Monday Mini-Golf: Seria krótkich golfowych wyzwań, opublikowanych (miejmy nadzieję!) W każdy poniedziałek.
Wiele aplikacji internetowych (zwłaszcza mediów społecznościowych) automatycznie obcina długie fragmenty tekstu, aby pasowały do formatowania aplikacji. W tym wyzwaniu stworzymy algorytm do automatycznego przycinania fragmentu tekstu do określonej długości.
Wyzwanie
Celem wyzwania jest napisanie programu lub funkcji, która przyjmuje dwa argumenty:
- T , tekst do obcięcia.
- L , maksymalna długość zwrotu.
I zwraca T , obcięty za pomocą następującej logiki:
- Jeśli długość T jest mniejsza lub równa L , obcięcie nie jest konieczne. Zwraca oryginalny ciąg.
- Obetnij T do długości L -2. Jeśli nie zawiera spacji ani łączników, zwróć literę T obciętą do dokładnie L -3 znaków, a następnie elipsę
...
. - W przeciwnym razie przytnij koniec wyniku do ostatniej spacji lub łącznika. Dodaj elipsę
...
i zwróć wynik.
Detale
- T i L mogą być przyjmowane w dowolnej kolejności i dowolnym formacie.
- Możesz założyć, że 3 < L <2 31 .
- Nie możesz używać poziomej elipsy U + 2026
…
; musisz użyć trzech kropek. - Dane wejściowe nie będą zaczynać się od spacji ani myślnika.
- Dane wejściowe nie będą zawierać żadnych białych znaków oprócz zwykłych spacji. (Bez kart, nowych linii itp.)
Przypadki testowe
Wejścia:
"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
Wyjścia:
"This is some very long..."
"This-is-some-long-hyphen..."
"Programming Puzzles & Code Golf is a question and..."
"abcdefghijklmnopq..."
"a..."
"Very long."
(Uwaga: cudzysłowy mają jedynie na celu określenie, że są to ciągi znaków; nie trzeba ich uwzględniać).
Punktacja
To jest golf golfowy , więc wygrywa najkrótszy prawidłowy kod w bajtach. Tiebreaker przechodzi do przesyłania, które jako pierwsze osiągnęło końcową liczbę bajtów. Zwycięzca zostanie wybrany w poniedziałek, 5 października. Powodzenia!
Edycja: Gratulacje dla zwycięzcy, ponownie @Jakube with Pyth, z 25 bajtami!
Odpowiedzi:
Pyth, 25 bajtów
Wypróbuj online: pakiet demonstracyjny lub testowy
Wyjaśnienie:
źródło
Perl,
695952 bajtówKod 51 bajtów + wiersz poleceń 1 bajt. Zakłada, że dane liczbowe można podawać za pomocą parametru -i.
Stosowanie:
źródło
Python 2,
7873 bajtówFormat wejściowy jest zgodny z przykładowym wejściem.
źródło
JavaScript (ES6),
123786761 bajtówNie spodziewałem się, że będę w stanie tak bardzo to ograniczyć, ale okazuje się, że kombinacja łączenia / zamiany jest w stanie pokryć każdy przypadek, w którym potrzebne jest obcięcie.
Pierwszy argument to ciąg, drugi to długość. Specjalne podziękowania dla edc65 za optymalizację sprawdzania długości!
Oto oryginalny kod (123 bajty):
źródło
.length
sprawdzać długości wyniku struny(T,L)=>T[L]?T.slice(0,L-2).replace(/([ -][^ -]*|.)$/,'...'):T
61[ -][^ -]
ze\s\S
aby zapisać 5 więcej bajtówTI-BASIC, 87 bajtów
TI-BASIC nie ma wielu poleceń manipulacji ciągami, dlatego musimy ręcznie znaleźć ostatni indeks: jeśli ciąg nie zawiera szukanego ciągu,
inString(
zwraca 0. Szukamy łączników i spacji zaczynając od każdej pozycji od 1 doL
i nagrywać największą liczbę mniejszą niż lub równyL-3
. Jeśli liczbaI
ta nadal wynosi 0,L-3
zamiast tego używamy indeksu końcowego.Ze względu na ograniczenia kalkulatora największy adresowalny indeks ciągu wynosi 9999; dlatego nie powiedzie się to w przypadku większych ciągów.
Opieram się na zachowaniu kalkulatora podczas automatycznej inicjalizacji zmiennej
I
na 0, więc usuńI
lub wyczyść pamięć kalkulatora przed uruchomieniem.źródło
C # .NET,
187169 bajtówHmm ...
źródło
Python 2, 105 bajtów
Zadzwoniłem z
źródło
Groovy, 95 bajtów
Całkiem proste, prawdopodobnie można dalej grać w golfa
źródło
CJam, 34 bajty
Wypróbuj online: Chrome | Firefox
źródło
T-SQL, 145 bajtów
stosowanie:
exec a("This is some very long text.", 25) exec a("This-is-some-long-hyphen-separated-text.", 33)
źródło
rs , 116
Przynajmniej jest krótszy niż C # ...
Prezentacje na żywo i przypadki testowe.
źródło
Cejlon
386333252230222216171153131111Niegolfowany oryginał:
To jest 386 bajtów / znaków. Kilka interesujących funkcji tutaj:
x[y:z]
Składnia jest cukier syntaktyczny dlax.measure(y, z)
i zwraca podzakresu zx
zaczynający
o długościz
- 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 zakresamix[...z]
ix[y...]
.)List.lastIndexWhere
pobiera predykat (tj. funkcję przyjmującą element listy i zwracającą wartość logiczną, tj. tutaj aCallable<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
spaceIndex
jest rodzajInteger|Null
lubInteger?
w skrócie - tzn. Może to być liczba całkowita lubnull
(jedyna wartość typuNull
). (NazwaspaceIndex
pochodzi od tego, kiedy nie zdawałem sobie sprawy, że-
to również było specjalne - myślę, żebreakIndex
byłoby lepiej.)Za pomocą
exists spaceIndex
możemy sprawdzić, czyspaceIndex
wartość 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łspaceIndex
dostępu do ciągu.)Zamiast funkcji lokalnej
spacePredicate
możemy również użyć funkcji anonimowejTo prowadzi nas do 333 znaków:
Następną optymalizacją jest użycie krótszych nazw zmiennych i funkcji, co obniża nas o 81 bajtów do 252:
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:Zamiast tego
e == ' ' || e == '-'
możemy również pisaće in [' ', '-']
(lube in {' ', '-'}
, to jest konstruktowalny iteracyjny zamiast krotkowego).in
Operator odwzorowuje metody Category.contains, która prowadzi nas do tego, że możemy przekazać tę krotka wcontains
sposób bezpośredni (to jest wymagalne zastosowaniem jakiegokolwiek przedmiotu, tak też przyjmując postać), bez(e) => ...
boilerplate (222 bajtów):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.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
i
wersetachl-3
, a są przy użyciui
tylko wtedy, gdy nie jest null, inaczejl-3
. Na szczęście właśnie toelse
służy operator!(Nawiasy wydają się być tutaj potrzebne, ponieważ
else
mają niższy priorytet niż[:]
.) To jest 171 znaków. Terazi
jest używany tylko raz, więc możemy go wstawić, doprowadzając nas do 153 znaków:Możemy również zastąpić tę
if-return-return
kombinację kombinacją operatorówthen
ielse
w jednymreturn
. (then
zwraca 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ć):Funkcja zawierająca tylko jeden zwrot z wyrażeniem może być alternatywnie zapisana za pomocą notacji „gruba strzałka”, co daje 123:
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,
t
która jest używana po kroku drugim):źródło
Powłoka POSIX + GNU sed, 65 bajtów
To jest praca dla sed! Ale potrzebowałem powłoki, aby uzyskać limit długości (być może Perl byłby lepszy). Część sed rozwija się do dość prostej sekwencji, z warunkowymi skokami po zakończeniu:
źródło
Mathematica 192 bajty
Nazywany jako
źródło
> <>, 74 bajty
To rozwiązanie wymaga obcięcia łańcucha i
L
go na stosie w tej kolejności.Jest 7 zmarnowanych bajtów spowodowanych problemami z wyrównaniem, wciąż próbujących je rozegrać.
źródło
C # (157):
Na podstawie odpowiedzi Salah Alami , ale krótszy. W ciąg klasy wywodzi
IEnumerable<char>
, więc zamiastT.Contains(" ")||T.Contains("-")
używam" -".Any(x=>T.Contains(x))
.Rozwiązanie:
Nie golfowany:
Aktualizacja:
Zaoszczędziłem 6 bajtów dzięki komentarzowi SLuck49, używając
Any(T.Contains)
zamiastAny(x=>T.Contains(x))
.źródło
.Any(x=>T.Contains(x))
możesz bezpośrednio użyć metody zamiast lambda, jak.Any(T.Contains)
zapisać 6 bajtówGS2 , 29 bajtów
Ten program pobiera standardowe dane wejściowe. Pierwszy wiersz to ciąg, a drugi to liczba długości docelowej.
Czasami kod GS2 może być trudny do odczytania. :) Oto komentarz.
źródło
Groovy, 56 bajtów
Najpierw skopiowałem odpowiedź Kleyguertha, stąd te same nazwy zmiennych ...
Przytnij ciąg znaków w dół o 2 znaki, następnie większość pracy jest wykonywana przez wyrażenie regularne, zamień myślnik lub spację, a następnie dowolną liczbę znaków, które nie są myślnikiem ani spacją na końcu łańcucha na „.” LUB zamień dowolny znak na końcu łańcucha, jeśli wszystkie znaki przed nim nie są kreską ani spacją z „.”. Trudniej jest wyrazić słowami niż napisać wyrażenie regularne ...
Edycja: W rzeczywistości można po prostu usunąć część ciągu pasującą do wyrażenia regularnego i dodać „...” na końcu:
źródło
Galaretka , 29 bajtów
Wypróbuj online!
Pełny program
źródło
Czysty , 89 bajtów
Wypróbuj online!
Jako funkcja
$ :: Int String -> String
źródło
C # (interaktywny kompilator Visual C #) , 117 bajtów
Oparty na @ Abba's, który jest oparty na odpowiedzi @Salah Alami. Zamiast używać
Contains
i niepotrzebnegoSubstring
wywołania używa IndexOf, aby sprawdzić, czy w skrócie znajduje się myślnik lub spacja.Wypróbuj online!
źródło