Мини-гольф по понедельникам: серия коротких соревнований по коду , публикуемых (надеюсь!) Каждый понедельник.
Многие веб-приложения (особенно социальные сети) автоматически обрезают длинные отрывки текста, чтобы они соответствовали форматированию приложения. В этой задаче мы собираемся создать алгоритм для автоматической обрезки фрагмента текста до определенной длины.
Вызов
Цель задачи - написать программу или функцию, которая принимает два аргумента:
- T , текст для усечения.
- L , максимальная длина для возврата.
И возвращает T , усеченный со следующей логикой:
- Если длина T меньше или равна L , усечение не требуется. Вернуть оригинальную строку.
- Усечь T до длины L -2. Если в нем нет пробелов или дефисов, верните T, усеченный до L- 3 символов, а затем многоточие
...
. - В противном случае обрежьте конец результата до последнего пробела или дефиса. Добавьте многоточие
...
и верните результат.
Детали
- T и L могут быть взяты в любом порядке и в любом формате.
- Вы можете предположить, что 3 < L <2 31 .
- Вы не можете использовать U + 2026 Горизонтальный многоточие
…
; Вы должны использовать три периода. - Ввод не будет начинаться с пробела или дефиса.
- На входе не будет никаких пробелов, кроме обычных. (Без вкладок, новых строк и т. Д.)
Тест-кейсы
Входы:
"This is some very long text." 25
"This-is-some-long-hyphen-separated-text." 33
"Programming Puzzles & Code Golf is a question and answer site for programming puzzle enthusiasts and code golfers." 55
"abcdefghijklmnopqrstuvwxyz" 20
"a b c" 4
"Very long." 100
Выходы:
"This is some very long..."
"This-is-some-long-hyphen..."
"Programming Puzzles & Code Golf is a question and..."
"abcdefghijklmnopq..."
"a..."
"Very long."
(Обратите внимание, что кавычки просто указывают на то, что это строки; их не нужно включать.)
счет
Это код-гольф , поэтому выигрывает самый короткий действительный код в байтах. Tiebreaker переходит к представлению, которое первым достигло конечного числа байтов. Победитель будет выбран в следующий понедельник, 5 октября. Удачи!
Изменить: Поздравляем вашего победителя, @Jakube с Pyth снова, с 25 байтами!
Ответы:
Pyth, 25 байт
Попробуйте онлайн: демонстрация или тестовый набор
Объяснение:
источник
Perl,
695952 байта51 байтовый код + 1 байтовая командная строка. Предполагается, что числовой ввод может быть задан с параметром -i.
Использование:
источник
Python 2,
7873 байтаФормат ввода соответствует примеру ввода.
источник
JavaScript (ES6),
123786761 байтЯ не ожидал, что смогу сократить это так сильно, но оказывается, что комбинация сращивания / замены способна охватить каждый случай, когда необходимо усечение.
Первый аргумент - это строка, второй - длина. Отдельное спасибо edc65 за оптимизацию проверки длины!
Вот оригинальный код (123 байта):
источник
.length
проверять длину(T,L)=>T[L]?T.slice(0,L-2).replace(/([ -][^ -]*|.)$/,'...'):T
партитуры 61[ -][^ -]
на,\s\S
чтобы сохранить еще 5 байтовTI-BASIC, 87 байт
TI-BASIC не имеет много команд для работы со строками, поэтому нам нужно найти последний индекс вручную: если строка не содержит строку для поиска,
inString(
возвращает 0. Мы ищем дефисы и пробелы, начиная с каждой позиции от 1 чтобыL
и записать наибольшее число меньше или равноL-3
. Если это числоI
все еще равно 0, мы используемL-3
вместо этого конечный индекс.Из-за ограничений калькулятора самый большой адресуемый индекс строки - 9999; следовательно, это не удастся для больших строк.
Я полагаюсь на поведение калькулятора при автоматической инициализации переменной
I
на 0, поэтомуI
перед запуском удалите или очистите память вашего калькулятора.источник
C # .NET,
187169 байтХм ...
источник
Python 2, 105 байт
Вызывается с
источник
Groovy, 95 байт
Довольно просто, вероятно, можно играть в гольф дальше
источник
CJam, 34 байта
Попробуйте онлайн: Chrome | Fire Fox
источник
T-SQL, 145 байт
использование:
exec a("This is some very long text.", 25) exec a("This-is-some-long-hyphen-separated-text.", 33)
источник
RS 116
По крайней мере, это короче, чем C # ...
Живая демоверсия и тестовые случаи.
источник
Цейлон
386333252230222216171153131111Ungolfed Оригинал:
Это 386 байт / символов. Некоторые интересные особенности здесь:
x[y:z]
Синтаксис синтаксическийx.measure(y, z)
, и возвращает поддиапазон ,x
начинаяy
с длинойz
- для строк, это подстрока. (Существует такжеx[y..z]
синтаксис, представляющий собой диапазон от индекса y до z, включительно, а также полуоткрытый диапазонx[...z]
иx[y...]
.)List.lastIndexWhere
принимает предикат (т.е. функцию, принимающую элемент списка и возвращающую логическое значение, т. е. здесь aCallable<Boolean, [Character]>
), и дает индекс последнего элемента списка, где предикат выполнен (или ноль, если он никогда не выполняется). Поскольку строки являются списками, это работает и для строк.Результат этого
spaceIndex
типаInteger|Null
илиInteger?
короткого типа , т. Е. Может быть целым числом илиnull
(единственным значением типаNull
). (НазваниеspaceIndex
происходит от того, что я не осознавал, что-
это тоже было особенным - думаюbreakIndex
, будет лучше.)С помощью
exists spaceIndex
мы можем проверить, неspaceIndex
является ли NULL, и сделать что-то другое. (Внутри этого блока if компилятор знает, что он не равен нулю ... без этого он бы пожаловался, если бы я использовалspaceIndex
для доступа к строке.)Вместо локальной функции
spacePredicate
мы также можем использовать анонимную функциюЭто приводит нас к 333 символам:
Следующая оптимизация заключается в использовании более коротких имен переменных и функций, что сокращает нас на 81 байт до 252:
Функция предиката фактически не нуждается в объявленном типе аргумента, который может быть выведен компилятором. То же самое для типа
i
(где нам еще нужно написать,value
чтобы пометить его как объявление). Теперь эта декларация достаточно короткая, чтобы поместиться в одну строку, что приводит нас к 230:Вместо этого
e == ' ' || e == '-'
мы также можем написатьe in [' ', '-']
(илиe in {' ', '-'}
это итеративный конструктор вместо кортежа).in
Оператор переводит к методу Category.contains, который приводит нас к мысли , что мы можем передать этот кортежcontains
методы напрямую (это вызываемое принимая любой объект, так и принимать характер), без(e) => ...
шаблонных (222 байт):На самом деле, другая категория, содержащая те же два символа, является двухсимвольной строкой
" -"
. (Кроме того, он также содержит свои подстроки, но это не мешает здесь). 216 байт.Я думаю, что мы получили максимальную отдачу от этой строки, давайте обратимся к другим ... последние два оператора return имеют некоторое сходство, которое мы можем использовать - они просто отличаются по
i
сравнению сl-3
и используютi
только тогда, когда оно не равно нулю, в противном случаеl-3
, К счастью, именно для этого и созданelse
оператор!(Кажется, здесь нужны скобки, поскольку они
else
имеют более низкий приоритет, чем[:]
.) Это 171 символ. Теперьi
используется только один раз, поэтому мы можем встроить его, доведя нас до 153 символов:Мы также можем заменить эту
if-return-return
комбинацию с помощью комбинации изthen
иelse
операторов в одномreturn
. (then
return - второй операнд, если первый - true, в противном случае - null, который затем позволяетelse
вернуть второй операнд.) 131 байт (хотя некоторые сбережения - это пробелы, которые мы в любом случае удалим)Функция, которая содержит только одно возвращение с выражением, может альтернативно быть написана с помощью нотации «толстая стрелка», дающей 123:
Удаление ненужных пробелов дает нам последние 111 байтов:
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Кроме того, вот функция, которая печатает примеры из вопроса (используя имя,
t
которое используется после второго шага):источник
POSIX shell + GNU sed, 65 байт
Это работа для седа! Но мне нужен shell, чтобы получить ограничение длины (возможно, Perl был бы лучше). Часть sed расширяется до довольно простой последовательности с условными переходами, когда мы заканчиваем:
источник
Mathematica 192 байта
Называется как
источник
> <>, 74 байта
Это решение требует, чтобы строка была усечена и
L
уже находилась в стеке в указанном порядке.Там 7 потраченных впустую байтов, вызванных проблемами выравнивания, все еще пытающимися вывести их из строя.
источник
C # (157):
На основании ответа Салаха Алами , но короче. Класс string происходит от
IEnumerable<char>
, поэтому вместо негоT.Contains(" ")||T.Contains("-")
я использую" -".Any(x=>T.Contains(x))
.Решение:
Ungolfed:
Обновить:
Сохранено 6 байт благодаря комментарию SLuck49, использующему
Any(T.Contains)
вместоAny(x=>T.Contains(x))
.источник
.Any(x=>T.Contains(x))
вы можете напрямую использовать метод вместо лямбды, как.Any(T.Contains)
для сохранения 6 байтовGS2 , 29 байт
Эта программа принимает стандартный ввод. Первая строка - это строка, а вторая - номер целевой длины.
Код GS2 иногда бывает трудно читать. :) Вот некоторые комментарии.
источник
Groovy, 56 байт
Сначала скопировал ответ Клейгерта, отсюда и те же имена переменных ...
Обрежьте строку на 2 символа, затем большую часть работы выполняет регулярное выражение, замените тире или пробел, а затем любое количество символов, которые не являются тире или пробел в конце строки, с "." ИЛИ замените любой символ в конце строки, если все символы перед ним не являются ни чертой, ни пробелом с «.». Труднее выразить словами, чем написать регулярное выражение ...
Изменить: На самом деле, можно просто удалить часть строки, которая соответствует регулярному выражению и добавить "..." в конце:
источник
Желе , 29 байт
Попробуйте онлайн!
Полная программа.
источник
Чисто , 89 байт
Попробуйте онлайн!
Как функция
$ :: Int String -> String
источник
C # (интерактивный компилятор Visual C #) , 117 байт
Основано на @ Abba's, которое основано на ответе @Salah Alami. Вместо использования
Contains
и ненужногоSubstring
вызова он использует IndexOf для проверки наличия дефиса или пробела в усеченной строке.Попробуйте онлайн!
источник