Cejlon 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)]+"...";
Niegolfowany oryginał:
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]+"...";
}
To jest 386 bajtów / znaków. Kilka interesujących funkcji tutaj:
x[y:z]Składnia jest cukier syntaktyczny dla x.measure(y, z)i zwraca podzakresu z xzaczynając yo długości z- na smyczki, to podciąg. (Jest równieżx[y..z] składnia, która jest rozpiętością od indeksu y do z, zarówno obejmującymi, jak i półotwartymi zakresami x[...z]i x[y...].)
List.lastIndexWherepobiera predykat (tj. funkcję przyjmującą element listy i zwracającą wartość logiczną, tj. tutaj a Callable<Boolean, [Character]>), i podaje indeks ostatniego elementu listy, w którym predykat jest spełniony (lub null, jeśli nigdy nie jest spełniony). Ponieważ ciągi są listami, działa to również w przypadku ciągów.
Wynikiem tego spaceIndexjest rodzaj Integer|Nulllub Integer?w skrócie - tzn. Może to być liczba całkowita lubnull (jedyna wartość typu Null). (Nazwa spaceIndexpochodzi od tego, kiedy nie zdawałem sobie sprawy, że -to również było specjalne - myślę, że breakIndexbyłoby lepiej.)
Za pomocą exists spaceIndexmożemy sprawdzić, czy spaceIndexwartość nie jest zerowa, i zrobić coś innego. (Wewnątrz tego if-bloku kompilator wie, że nie ma wartości null ... bez tego narzekałby, gdybym użył spaceIndexdostępu do ciągu.)
Zamiast funkcji lokalnej spacePredicate możemy również użyć funkcji anonimowej
(Character char) => char == ' ' || char == '-'
To prowadzi nas do 333 znaków:
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]+"...";
}
Następną optymalizacją jest użycie krótszych nazw zmiennych i funkcji, co obniża nas o 81 bajtów do 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]+"...";
}
Funkcja predykatu faktycznie nie wymaga zadeklarowania typu argumentu, co może wywnioskować kompilator. To samo dotyczy rodzaju i(gdzie wciąż musimy pisaćvalue aby oznaczyć go jako deklarację). Teraz deklaracja jest wystarczająco krótka, aby zmieścić się w jednej linii, co prowadzi nas do 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]+"...";
}
Zamiast tego e == ' ' || e == '-'możemy również pisać e in [' ', '-'](lub e in {' ', '-'}, to jest konstruktowalny iteracyjny zamiast krotkowego). inOperator odwzorowuje metody Category.contains, która prowadzi nas do tego, że możemy przekazać tę krotka w containssposób bezpośredni (to jest wymagalne zastosowaniem jakiegokolwiek przedmiotu, tak też przyjmując postać), bez (e) => ...boilerplate (222 bajtów):
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]+"...";
}
W rzeczywistości inną kategorią zawierającą te same dwa znaki jest ciąg dwóch znaków " -". (Dodatkowo zawiera także podciągi, ale tutaj nie boli). 216 bajtów.
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]+"...";
}
Chyba mamy najwięcej z tej linii, wróćmy do innych ... dwie ostatnie wypowiedzi powrotne mają pewne podobieństwo, które możemy wykorzystać - po prostu różnią się w iwersetach l-3, a są przy użyciu itylko wtedy, gdy nie jest null, inaczej l-3. Na szczęście właśnie toelse służy operator!
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)] + "...";
}
(Nawiasy wydają się być tutaj potrzebne, ponieważ elsemają niższy priorytet niż [:].) To jest 171 znaków. Teraz ijest używany tylko raz, więc możemy go wstawić, doprowadzając nas do 153 znaków:
String t(String s, Integer l) {
if(s.size < l) {
return s;
}
return s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Możemy również zastąpić tę if-return-returnkombinację kombinacją operatorów theni elsew jednym return. ( thenzwraca drugi argument, gdy pierwszy jest prawdziwy, w przeciwnym razie jest pusty, co pozwalaelse return na zwrócenie drugiego operandu.) 131 bajtów (chociaż niektóre oszczędności to białe przestrzenie, które i tak będziemy się pozbywać):
String t(String s, Integer l) {
return s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
}
Funkcja zawierająca tylko jeden zwrot z wyrażeniem może być alternatywnie zapisana za pomocą notacji „gruba strzałka”, co daje 123:
String t(String s, Integer l) =>
s.size < l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains) else l-3)] + "...";
Usunięcie niepotrzebnych białych znaków daje nam ostatnie 111 bajtów:
String t(String s,Integer l)=>s.size<l then s else s[0:(s[0:l-2].lastIndexWhere(" -".contains)else l-3)]+"...";
Jako dodatek, tutaj jest funkcja, która drukuje przykłady z pytania (używając nazwy, tktóra jest używana po kroku drugim):
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));
}
}