Цейлон 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)]+"...";
Оригінальний оригінал:
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]>), і дає індекс останнього елемента списку, де виконується предикат (або null, якщо він ніколи не виконується). Оскільки рядки є списками, це працює і для рядків.
Результат цього spaceIndexмає тип Integer|Nullабо Integer?короткий - тобто він може бути або цілим чи null(єдиним значенням типу Null). (Назва spaceIndexпоходить, коли я не усвідомлював, що -це також було особливим - я думаю, breakIndexбуло б краще.)
З exists spaceIndexми можемо перевірити , якщо spaceIndexне дорівнює нулю, і зробити що - то інше , то. (Всередині цього if-block компілятор знає, що він не є нульовим ... без цього він скаржився б, якби я використовував 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]+"...";
}
Я думаю, що ми отримали максимум користі з цього рядка, давайте звернемось до інших ... останні два повернення заяви мають деяку схожість, яку ми можемо використати - вони просто відрізняються 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повертає другий операнд, коли перший істинний, інакше нульовий, що потім дозволяє 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));
}
}