Sformatuj listę słów

16

Wyzwanie polega na sformatowaniu listy słów w wielu wierszach, które nie są dłuższe niż podana liczba znaków, tak aby każda linia zawierała jak najwięcej słów i żadne słowa nie były niepotrzebnie odcinane.

Wejście

Dane wejściowe będzie oddzieloną spacjami listą słów, a następnie liczbą co najmniej 4.

Wynik

Wynikiem powinny być słowa wejściowe pogrupowane w wiersze, aby żaden wiersz nie zawierał więcej znaków niż numer wejściowy. Słowa powinny być wypisywane w kolejności, w jakiej zostały wprowadzone. Słowa powinny być oddzielone przecinkiem, a następnie spacją, z wyjątkiem końca każdego wiersza, w którym spacja nie jest potrzebna. Jeśli słowo jest zbyt długie, aby zmieściło się w linii, należy je jak najmniej uciąć, przestrzegając pozostałych zasad, a na końcu dodać „…”.

Przypadki testowe

Input:
foo bar baz qux 12

Output:
foo, bar,
baz, qux


Input:
foo bar baz qux 5

Output:
foo,
bar,
baz,
qux


Input:
strength dexterity constitution intelligence wisdom charisma 10

Output:
strength,
dexterity,
consti...,
intell...,
wisdom,
charisma


Input:
quas wex exort 4

Output:
...,
wex,
e...
KSFT
źródło
Powiązane
Peter Taylor

Odpowiedzi:

10

Nieczytelny , 2559 bajtów

To wyzwanie jest niesamowicie odpowiednie dla Nieczytelnych.

Pierwsza wersja tego pliku miała 3379 bajtów, aby dać wyobrażenie o tym, jak bardzo grałem w golfa.

Program akceptuje dane wejściowe dokładnie tak, jak opisano w wyzwaniu: rozdzielona spacjami lista słów (która może również zawierać cyfry i znaki interpunkcyjne), po której następuje spacja i liczba całkowita o wartości co najmniej 4 (niższe liczby generują nieskończone pętle) .

„” „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „” „”„” „” „” „” „„ ”„ ”„ „” „” „” „” „” „” „„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ „” „” „” „” „” „„ ”„ „” „” „” „” „”„” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „„ ”„ ”„ ”„ ” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „” „”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „” „„ ”„ ”„ ”„ ” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „” „”„” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ „” „” „” „” „” „” „„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ ”„ „” „” „”„” „” „” „” „„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ „” „„ ”„ ”„ ” „” „„ ”„ ”„ „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ „” „” „” „” „„ ”„ „” „„ ”„ „” „„ ”„ ”„ ”„ ”„” „„ ”„ ”„ „” „” „„ ”„ „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ „” „” „” „”„” „” „” „” „„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „”„” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ „„ „” „„ ”„ „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„” „” „” „„ ”„ ”„ „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „„ ” „” „” „” „” „„ ”„ ”„ ”„ „” „” „„ ”„ ”„ „” „„ ”„ ”„ ”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ „”„” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ ”„ ”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ ”„ ”„ ”„ „” „” „” „” „” „” „” „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ „” „” „” „”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „„ ”„ „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ „” „” „” „” „” „” „”„” „” „” „” „„ ”„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „” „„ ”„ „” „” „” „„ ”„ ”„ „” „” „” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „” „” „„ ”„ „” „” „” „” „” „” „”„” „” „” „” „„ ”„ ”„ „” „” „” „„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „„ ”„ „” „” „” „” „” „” „” „” „” „” „” „„ ”„ ”„ ”„ „” „” „„ ”„ „” „” „”„” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ ”„ ”„ ” „” „” „” „” „„ ”„ ”„ „” „” „” „” „„ ”„ „” „” „” „” „” „” „” „” „„ ”„ „” „” „” „” „” „„ ”„ „” „” „” „” „” „” „”„” „” „” „” „„ ”„ ”„ ”„ ”„ ”„ ”„ „” „„ ”„ „” „” „„ ”„ ”„ ”„ ”

Wyjaśnienie

Przeprowadzę cię przez proces przetwarzania danych wejściowych przez program thyme horseradish peppermint 10 . Oczekiwany wynik to thyme,\nhorser...,\npeppermint.

Najpierw zaczynamy od komórki nr 7 i odczytujemy całe dane wejściowe, ale odejmujemy 32 od każdego znaku, aby spacje stały się zerami.

Z oczywistych powodów pozostawia to działający wskaźnik (o nazwie tutaj o p , przechowywany w komórce nr 0) na końcu. Używamy pętli while, aby znaleźć ostatnią przerwę, która jest początkiem liczby określającej szerokość wyniku (komórka nr 36 w tym przykładzie).

Chcemy teraz dekodować liczbę (tzn. Konwertować z dziesiętnego). Wynik końcowy będzie zarówno komórek T i r . Polegamy na tym, że zaczynają od zera.

Dla każdej cyfry w liczbie wykonaj następujące czynności:

  • Zestaw t na -15.
  • W pętli while zmniejszanie r (która zawiera dotychczasowy wynik) do -1 (ponieważ potrzebujemy dokładnie r iteracji, ale ponieważ zmniejszenie występuje zanim zostanie sprawdzone jako warunek pętli while, zmniejszenie do 0 dałoby o jedną iterację mniej) i dla każdej iteracji dodaj 10 do t . Teraz t zawiera 10-krotność poprzedniego wyniku minus 15.
  • Ponownie w pętli while zmniejsz * p do 0 i dla każdej iteracji dodaj 1 do t . Po tym t zawiera jak dotąd poprawny wynik pośredni: znaki, '0'które '9'mają kody ASCII 48–57, więc po wcześniejszym odjęciu 32 mają one 16–25, więc faktycznie dodajemy 15–24 do t , co anuluje się z -15 ustawiliśmy to na wcześniej. Ważne jest również, aby to zerowało komórki, które zawierały znaki cyfrowe, aby późniejszy kod mógł rozpoznać koniec listy słów.
  • Ustaw r na nowy wynik pośredni, aby następna iteracja znalazła go w r . (Uwaga: nie musimy czytać ponownie od t , możemy po prostu użyć ostatniej wartości z poprzedniej pętli while, ponieważ wiemy, że * p nie może wynosić zero, więc uruchomiło się co najmniej raz).

Na koniec używamy innej prostej pętli while (zmniejszającej t jako licznik) do konwersji obliczonej właśnie liczby na unarną. Przechowujemy ciąg 1s idących w lewo od komórki nr 0. Opiera się to na tym, że komórka nr 1, nasz działający wskaźnik dla tego ( q ), zaczyna się od 0. Dostajemy jeden mniej 1s, ponieważ podczas gdy pętle w Nieczytelnym są takie:

Po tym nie potrzebujemy już wartości wr , więc ponownie wykorzystujemy tę komórkę do czegoś innego. Resetujemy wskaźniki p i q i inicjalizujemy niektóre komórki za pomocą kodów ASCII znaków, których potrzebujemy później. Oznaczyłem również c i s, których użyjemy później i będziemy polegać na tym, że s zaczyna się od zera:

Hej, poczekaj chwilę. Dlaczego komórka nr 0 ma kolor czerwony? Cóż, ma to na celu podstępną sztuczkę. Pamiętasz, jak wyprodukowaliśmy jeden 1 za mało? Sztuka polega na tym, że używamy komórki nr 0 jako „rozszerzenia”, aby to poprawić. Działa to, ponieważ wiemy, że p nigdy nie będzie wynosić 0. W ten sposób czerwony blok ma teraz szerokość 10 komórek, dokładnie taką liczbę, jakiej chcemy. Zapisuje również 9 znaków, aby móc zainicjować q do 1 zamiast 0.

Teraz wchodzimy do pętli while, która przechodzi przez słowa i wypisuje je wszystkie.

Krok 1: Sprawdź, czy następne słowo będzie pasować do bieżącego wiersza. Robimy to po prostu przesuwając p w prawo i q w lewo za pomocą pętli while, aż p osiągnie następną przerwę:

Teraz, gdy p znajduje się po prawej stronie słowa, możemy sprawdzić, czy jest to ostatnie słowo na liście, sprawdzając, czy * (p + 1) wynosi zero. Przechowujemy również tę wartość (która w naszym przykładzie wynosi 72, ponieważ jest to „h” z „chrzanu” minus 32) c, ponieważ będziemy jej później potrzebować. W tym przypadku nie jest to zero, więc będziemy musieli wprowadzić przecinek wraz ze słowem, więc słowo jest dłuższe o jeden znak. Weź to pod uwagę, zmniejszając q jeszcze raz. Na koniec użyj innej pętli while, aby przenieść p z powrotem na początek słowa.

Wiemy teraz, że słowo zmieści się w bieżącym wierszu, ponieważ q wskazuje na niezerową wartość, więc wszystko, co musimy zrobić, to:

  • Przenieś s naprzód przez słowo znowu drukowania każdego znaku (plus 32, ponieważ wszystkie kody ASCII są wyłączone przez 32).
  • Jeśli c jest niezerowe, wydrukuj przecinek (używając wartości w komórce # 5).
  • Ustaw s na wartość niezerową, aby wskazać następnej iteracji, że nie jesteśmy już na początku wiersza i dlatego musimy wypisać znak spacji przed następnym słowem. (W tym celu ponownie wykorzystujemy wartość zwrotną powyższej instrukcji print, która wynosi 44 dla przecinka.)

Dotychczasowe wyniki: thyme,

Następnie rozpoczyna się kolejna iteracja dużej pętli. Tak jak poprzednio, sprawdzamy, czy następne słowo pasuje do reszty wiersza, zmniejszając q, gdy przechodzimy przez słowo od lewej do prawej. Zauważ, że q nadal wynosi -5 od poprzedniej iteracji, śledząc, ile znaków już wydrukowaliśmy w bieżącym wierszu. Po zliczeniu znaków w „chrzanie”, plus jeden dla przecinka, plus jeden, ponieważ s jest niezerowy, co oznacza, że ​​musimy również wypisać spację, q będzie miało przekroczenie końca bloku 1s:

Teraz q wskazuje na zerową komórkę, co oznacza, że ​​„chrzan” nie będzie pasował do bieżącej linii. To, co teraz robimy, zależy od tego, czy s jest niezerowe. W naszym przypadku tak jest, co oznacza, że ​​musimy przejść do następnej linii. Wszystko, co musimy zrobić, to:

  • Wydrukuj nową linię (używając komórki nr 3)
  • Ustaw q z powrotem na 1
  • Ustaw s na 0

Dotychczasowe wyniki: thyme,\n

W następnej iteracji p znajduje się w tym samym miejscu co poprzednio, więc ponownie przyjrzymy się temu samemu słowu. Tak jak poprzednio, liczymy znaki w „chrzanie”, ustawiamy ponownie c na 80, gdy zauważymy, że po nim jest inne słowo, zmniejszamy q przecinkiem i przewijamy p z powrotem do początku słowa:

Podobnie jak w poprzedniej iteracji, okazuje się, że „chrzan” nadal nie pasuje, ponieważ q kończy się na komórce, która ma zero. Jednak ten czas s wynosi zero, co oznacza, że ​​robimy coś innego niż ostatnim razem. Musimy wypisać część słowa, trzy kropki i przecinek. Nasza szerokość wynosi 10, więc musimy wypisać 6 znaków tego słowa. Zobaczmy, gdzie skończymy, jeśli:

  • Znajdź początek czerwonego bloku 1s. Możemy to zrobić, idąc w prawo, ponieważ wiemy, że q musi być po lewej stronie.
  • Zwiększ wartość q jeszcze raz, jeśli musimy również wprowadzić przecinek ( c ≠ 0).

Taśma wygląda teraz tak:

Zaznaczyłem tutaj rozpiętość 6 komórek. Jak widać, musimy wypisywać znaki, dopóki q = -1. Jest to bardzo efektywne pod względem kodu sprawdzanie (w zasadzie while ((++q)+1) { ... }). Więc:

  • Wydrukuj te znaki (plus 32, ponieważ wszystkie kody ASCII są wyłączone o 32), dopóki q nie osiągnie -1. p będzie wtedy w komórce 19, w środku słowa „chrzan”.
  • Wydrukuj trzy kropki. Ponieważ polecenie print zwraca własny argument, możemy efektywnie zagnieździć go kodem (w zasadzie print(print(print('.')))). Bierzemy wartość ASCII z komórki nr 5 i dodajemy 2 do niej, aby uzyskać kod ASCII kropki.
  • Przenieś s na koniec słowa. Ponieważ wiemy, że nie udało nam się dotrzeć do końca słowa (ponieważ słowo było zbyt długie i musieliśmy usunąć z niego co najmniej 3 znaki, aby pasowały do ​​kropek), ta pętla zdecydowanie ma co najmniej jedną iterację, więc jest krótszy w kodzie, aby ciało pętli while obliczało wartość ASCII dla kropki, a następnie przekazywało wartość zwrotną pętli while do funkcji drukowania.
  • Wydrukuj przecinek, jeśli c jest niezerowe.

Po tym wszystkim wypisujemy również nową linię (używając komórki nr 3) i ustawiamy q z powrotem na 1. Możemy również ustawić s na 0, nawet jeśli jest to już 0, co czyni to to samo, co poprzednio, kiedy zawijaliśmy do następny wiersz (gdy s było niezerowe), więc aby uniknąć powtórzenia kodu, robimy to po warunku, który sprawdza s .

Dotychczasowe wyniki: thyme,\nhorser...,\n

Pozostała tylko jedna iteracja. Tym razem po policzeniu liter słowa otrzymujemy:

Tym razem po p nie ma nic , więc ustawiamy c na 0, aby wskazać „brak przecinka”, a zatem nie zmniejszamy q ponownie. Ponieważ q wskazuje teraz na niezerową komórkę, wiemy, że słowo będzie pasować, więc wykonywany jest ten sam kod, co w pierwszej iteracji, z tym wyjątkiem, że tym razem c wynosi zero, więc po prostu nie wydrukuje przecinka.

Wynik: thyme,\nhorser...,\npeppermint

W tym przewodniku nie uwzględniłem przypadku, w którym kod wydrukowałby spację, ale myślę, że teraz powinno być dość jasne. Jeśli kod stwierdzi, że słowo pasuje ( * q ≠ 0), a s jest niezerowe, po prostu wyświetli spację przed słowem.

Timwi
źródło
3

JavaScript (ES6), 171

Jako anonimowa funkcja zwracająca dane wyjściowe jako tablicę

(ponieważ jest to ogólnie dozwolone, chyba że wyraźnie zabronione: meta meta )

s=>(s=s.split` `,n=s.pop()-1,t='',o=[],s.map((w,i)=>(w=w[n+=!s[i+1]]?w.slice(0,n-3)+'...':w,(t+w)[n-2]&&(t&&o.push(t.slice(1)),t=''),t+=` ${w},`)),o.push(t.slice(1,-1)),o)

f=s=>(s=s.split` `,n=s.pop()-1,t='',o=[],s.map((w,i)=>(w=w[n+=!s[i+1]]?w.slice(0,n-3)+'...':w,(t+w)[n-2]&&(t&&o.push(t.slice(1)),t=''),t+=` ${w},`)),o.push(t.slice(1,-1)),o)

// Less golfed
U=s=>(
  s=s.split` `,
  n=s.pop()-1,
  t='', // current line
  o=[], // output
  s.map( (w,i)=>(
    w=w[
      n+=!s[i+1] // space for 1 more char on the last line
    ]?w.slice(0,n-3)+'...':w, // change w if it is too long
    (t+w)[n-2]&& ( // if current line + w is too long, ouput t and reset current line
      t&&o.push(t.slice(1)),t=''
    ),
    t+=` ${w},`
  )),
  o.push(t.slice(1,-1)), // remove tailing comma on last line
  o
)

console.log=x=>O.textContent+=x+'\n\n';
  
console.log(f("foo bar baz qux 12").join`\n`)
console.log(f("foo bar baz qux 5").join`\n`)
console.log(f("strength dexterity constitution intelligence wisdom charisma 10").join`\n`)
console.log(f("quas wex exort 4").join`\n`)
<pre id=O></pre>

edc65
źródło
1

Python 2, 206 bajtów

i=input().split()
l=int(i.pop())
i=[[w[:l-4]+'...',w][len(w)<l]+','for w in i][:-1]+[[w,w[:l-3]+'...'][len(w)>l]]
r=[i.pop(0)]
for w in i:
 if len(r[-1])+len(w)<l:r[-1]+=' '+w
 else:r+=[w]
print'\n'.join(r)
TFeld
źródło