Цейлон 386 333 252 230 222 216 171 153 131 111
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Ungolfed Оригинал:
String truncate(String text, Integer length) {
if(text.size < length) {
return text;
}
Boolean spacePredicate(Character char) {
return char == ' ' || char == '-';
}
Integer? spaceIndex = text[0:length-2].lastIndexWhere(spacePredicate);
if(exists spaceIndex) {
return text[0:spaceIndex] + "...";
}
return text[0:length-3]+"...";
}
Это 386 байт / символов. Некоторые интересные особенности здесь:
x[y:z]
Синтаксис синтаксический x.measure(y, z)
, и возвращает поддиапазон , x
начиная y
с длиной z
- для строк, это подстрока. (Существует также x[y..z]
синтаксис, представляющий собой диапазон от индекса y до z, включительно, а также полуоткрытый диапазон x[...z]
и x[y...]
.)
List.lastIndexWhere
принимает предикат (т.е. функцию, принимающую элемент списка и возвращающую логическое значение, т. е. здесь a Callable<Boolean, [Character]>
), и дает индекс последнего элемента списка, где предикат выполнен (или ноль, если он никогда не выполняется). Поскольку строки являются списками, это работает и для строк.
Результат этого spaceIndex
типа Integer|Null
или Integer?
короткого типа , т. Е. Может быть целым числом или null
(единственным значением типа Null
). (Название spaceIndex
происходит от того, что я не осознавал, что -
это тоже было особенным - думаю breakIndex
, будет лучше.)
С помощью exists spaceIndex
мы можем проверить, не spaceIndex
является ли NULL, и сделать что-то другое. (Внутри этого блока if компилятор знает, что он не равен нулю ... без этого он бы пожаловался, если бы я использовал spaceIndex
для доступа к строке.)
Вместо локальной функции spacePredicate
мы также можем использовать анонимную функцию
(Character char) => char == ' ' || char == '-'
Это приводит нас к 333 символам:
String truncate(String text, Integer length) {
if(text.size < length) {
return text;
}
Integer? spaceIndex = text[0:length-2].lastIndexWhere(
(Character char) => char == ' ' || char == '-');
if(exists spaceIndex) {
return text[0:spaceIndex] + "...";
}
return text[0:length-3]+"...";
}
Следующая оптимизация заключается в использовании более коротких имен переменных и функций, что сокращает нас на 81 байт до 252:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
Integer? i = s[0:l-2].lastIndexWhere(
(Character e) => e == ' ' || e == '-');
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
Функция предиката фактически не нуждается в объявленном типе аргумента, который может быть выведен компилятором. То же самое для типа i
(где нам еще нужно написать, value
чтобы пометить его как объявление). Теперь эта декларация достаточно короткая, чтобы поместиться в одну строку, что приводит нас к 230:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere((e) => e == ' ' || e == '-');
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
Вместо этого e == ' ' || e == '-'
мы также можем написать e in [' ', '-']
(или e in {' ', '-'}
это итеративный конструктор вместо кортежа). in
Оператор переводит к методу Category.contains, который приводит нас к мысли , что мы можем передать этот кортеж contains
методы напрямую (это вызываемое принимая любой объект, так и принимать характер), без (e) => ...
шаблонных (222 байт):
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere([' ', '-'].contains);
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
На самом деле, другая категория, содержащая те же два символа, является двухсимвольной строкой " -"
. (Кроме того, он также содержит свои подстроки, но это не мешает здесь). 216 байт.
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere(" -".contains);
if(exists i) {
return s[0:i] + "...";
}
return s[0:l-3]+"...";
}
Я думаю, что мы получили максимальную отдачу от этой строки, давайте обратимся к другим ... последние два оператора return имеют некоторое сходство, которое мы можем использовать - они просто отличаются по i
сравнению с l-3
и используют i
только тогда, когда оно не равно нулю, в противном случае l-3
, К счастью, именно для этого и создан else
оператор!
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
value i = s[0:l-2].lastIndexWhere(" -".contains);
return s[0:(i else l-3)] + "...";
}
(Кажется, здесь нужны скобки, поскольку они else
имеют более низкий приоритет, чем [:]
.) Это 171 символ. Теперь i
используется только один раз, поэтому мы можем встроить его, доведя нас до 153 символов:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
return s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Мы также можем заменить эту if-return-return
комбинацию с помощью комбинации из then
и else
операторов в одном return
. ( then
return - второй операнд, если первый - true, в противном случае - null, который затем позволяет else
вернуть второй операнд.) 131 байт (хотя некоторые сбережения - это пробелы, которые мы в любом случае удалим)
String t(String s, Integer l) {
return s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Функция, которая содержит только одно возвращение с выражением, может альтернативно быть написана с помощью нотации «толстая стрелка», дающей 123:
String t(String s, Integer l) =>
s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
Удаление ненужных пробелов дает нам последние 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
которое используется после второго шага):
shared void testTruncate() {
value testInputs = {
["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]
};
for(input in testInputs) {
print(t(*input));
}
}