Niektóre osoby upierają się przy użyciu spacji do tabel i wcięć.
W przypadku tabeli jest to bezsprzecznie złe. Z definicji tabulatory muszą być używane do tworzenia tabel.
Nawet w przypadku wcięć tabulatory są obiektywnie lepsze:
Społeczność Stack Exchange ma wyraźny konsensus .
Używanie pojedynczej przestrzeni do wcięcia jest wizualnie nieprzyjemne; używanie więcej niż jednego jest marnotrawstwem.
Ponieważ wszystkie cod
e golfowychers wiedzieć, programy powinny być jak najkrótsze. Nie tylko oszczędza miejsce na dysku twardym, ale także skraca czas kompilacji, jeśli trzeba przetworzyć mniej bajtów.Dostosowując szerokość zakładki 1 , ten sam plik wygląda inaczej na każdym komputerze, dzięki czemu każdy może użyć swojej ulubionej szerokości wcięcia bez modyfikowania rzeczywistego pliku.
Wszystkie dobre edytory tekstu domyślnie używają tabulatorów (i definicji).
Mówię tak i zawsze mam rację!
Niestety nie wszyscy słuchają rozsądku. Ktoś wysłał ci plik, który robi to źle TM i musisz go naprawić. Możesz to zrobić ręcznie, ale będą też inne.
Na tyle źle, że spacery marnują Twój cenny czas, więc decydujesz się napisać możliwie najkrótszy program, aby zająć się problemem.
Zadanie
Napisz program lub funkcję, która wykonuje następujące czynności:
Odczytaj pojedynczy ciąg znaków ze STDIN lub jako argument wiersza polecenia lub funkcji.
Zidentyfikuj wszystkie lokalizacje, w których spacje zostały użyte do tworzenia tabel lub wcięć.
Ciąg spacji jest wcięciem, jeśli występuje na początku linii.
Ciąg dwóch lub więcej spacji jest tabelą, jeśli nie jest wcięciem.
Pojedynczy przestrzeń, która nie jest wcięcie może być lub nie zostały wykorzystane na zestawianiu. Zgodnie z oczekiwaniami, gdy używasz tej samej postaci do różnych celów, nie ma łatwego sposobu, aby powiedzieć. Dlatego powiemy, że przestrzeń została wykorzystana do zamieszania .
Określ najdłuższą możliwą szerokość tabulatora 1, dla której wszystkie spacje używane do tabulacji lub wcięcia można zastąpić tabulatorami, bez zmiany wyglądu pliku.
Jeśli dane wejściowe nie zawierają tabulacji ani wcięcia, nie można określić szerokości tabulacji. W takim przypadku pomiń następny krok.
Używając wcześniej określonej szerokości tabulacji, zamień wszystkie spacje używane do tabelowania lub wcięcia na tabulatory.
Ponadto, o ile to możliwe, bez zmiany wyglądu pliku, zamień wszystkie spacje używane do pomyłek na tabulatory. (W razie wątpliwości pozbądź się spacji).
Zwróć zmodyfikowany ciąg z funkcji lub wydrukuj go do STDOUT.
Przykłady
Wszystkie spacje z
a bc def ghij
są tabelaryczne.
Każdy ciąg spacji dopełnia poprzedzający ciąg znaków spacji do szerokości 5, więc poprawna szerokość tabulacji wynosi 5, a poprawne wyjście 2 to
a--->bc-->def->ghij
Pierwsze dwie spacje z
ab cde f ghi jk lm
to tabulacja, inne zamieszanie.
Prawidłowa szerokość zakładki wynosi 4, więc poprawna wartość wyjściowa 2 to
ab->cde>f ghi>jk lm
Ostatnia spacja pozostaje nietknięta, ponieważ byłaby renderowana jako dwie spacje, gdyby została zastąpiona tabulatorem:
ab->cde>f ghi>jk->lm
Wszystkie oprócz jednego miejsca
int main( ) { puts("TABS!"); }
są wcięcia, drugie to zamieszanie.
Poziomy wcięcia wynoszą 0, 4 i 8 spacji, więc poprawna szerokość tabulacji wynosi 4, a poprawna wartość wyjściowa 2 to
int --->main( ) --->{ --->--->puts("TABS!"); --->}
Spacja w
( )
byłaby renderowana jako trzy spacje, gdyby została zastąpiona tabulatorem, więc pozostaje nietknięta.Pierwsze dwie spacje z
x yz w
są wcięcia, inne zamieszanie.
Prawidłowa szerokość zakładki wynosi 2, a poprawna wartość wyjściowa 2 to
->x>yz w
Ostatnia spacja byłaby renderowana jako dwie spacje, gdyby została zastąpiona tabulatorem, więc pozostaje nietknięta.
Pierwsze dwie spacje z
xy zw
są wcięcia, pozostałe trzy to tabulacje.
Tylko szerokość tabulatora 1 pozwala wyeliminować wszystkie spacje, więc poprawne wyjście 2 to
>>xy>>>zw
Wszystkie spacje z
a b c d
są zamieszaniem.
Nie ma najdłuższej możliwej szerokości tabulacji, więc poprawne wyjście 2 to
a b c d
Dodatkowe zasady
Dane wejściowe będą składały się wyłącznie z drukowalnych znaków ASCII i linii.
Możesz założyć, że w wierszu jest maksymalnie 100 wierszy tekstu i maksymalnie 100 znaków.
Jeśli wybierzesz STDOUT jako wyjście, możesz wydrukować jedno końcowe podawanie linii.
Obowiązują standardowe zasady gry w golfa .
1 Szerokość tabulacji jest definiowana jako odległość w znakach między dwoma kolejnymi tabulatorami przy użyciu czcionki o stałej szerokości .
2 Strzałki graficzne ASCII przedstawiają tabulatory Stack Exchange odmawia poprawnego renderowania, dla którego przesłałem raport o błędzie. Rzeczywiste wyjście musi zawierać rzeczywiste tabulatory.
źródło
programs should be as short as possible
Wydaje mi się, że znalazłem dawno zaginionego brata Artura Whitneya !!Odpowiedzi:
Pyth,
102103 bajtyWypróbuj online
Ciekawy pomysł, ale ponieważ zakładki na wejściu łamią koncepcję, niezbyt użyteczną.
Edycja: Naprawiono błąd. wielkie dzięki @aditsu
źródło
PowerShell,
414409 bajtówPoszedłem dalej i użyłem nowego wiersza zamiast,
;
gdzie to możliwe, aby ułatwić wyświetlanie. Używam końcówek linii uniksowych, więc nie powinno to wpływać na liczbę bajtów.Jak wykonać
Skopiuj kod do
SpaceMadness.ps1
pliku, a następnie potokuj dane wejściowe do skryptu. Zakładam, że plik wymagający konwersji nazywa siętaboo.txt
:Z PowerShell:
Z wiersza polecenia:
Testowałem to z PowerShell 5, ale powinno działać na 3 lub wyższej wersji.
Testowanie
Oto krótki skrypt PowerShell, który jest przydatny do testowania powyższego:
Umieść to w tym samym katalogu, co
SpaceMadness.ps1
ja nazywam tentester.ps1
, nazwij to tak:Masz pomysł. Po zakończeniu konwersji wyrzuca zawartość każdego pliku, przez
[RegEx]::Escape()
który przechodzi przez spacje i tabulatory, więc naprawdę wygodnie jest zobaczyć, co zostało zmienione.Dane wyjściowe wyglądają tak (ale z kolorami):
Wyjaśnienie
Pierwszy wiersz definiuje największą wspólną funkcję czynnik / dzielnik
g
tak zwięźle, jak potrafiłem, która przyjmuje tablicę (dowolną liczbę liczb) i oblicza rekurencyjnie GCD przy użyciu algorytmu euklidesowego .Celem tego było ustalenie „najdłuższej możliwej szerokości tabulatora” poprzez pobranie indeksu + długości każdego wcięcia i tabulacji zgodnie z definicją w pytaniu, a następnie przekazanie go do tej funkcji, aby uzyskać GCD, który moim zdaniem jest najlepszy, jaki możemy zrobić dla szerokości tabulacji. Długość pomyłki zawsze będzie wynosić 1, więc nie wnosi nic do tego obliczenia.
$b
definiuje blok skryptu, ponieważ irytujące muszę dwukrotnie wywołać ten fragment kodu, więc oszczędzam w ten sposób niektóre bajty. Ten blok pobiera ciąg (lub tablicę ciągów)$n
i uruchamia na nim wyrażenie regularne (sls
lubSelect-String
), zwracając obiekty dopasowania. Dostaję zarówno wcięcia, jak i tabulacje w jednym tutaj, co naprawdę zaoszczędziło mi dodatkowego przetwarzania, przechwytując je osobno.$n
jest używany do różnych rzeczy wewnątrz i na zewnątrz głównej pętli (naprawdę źle, ale jest to konieczne tutaj, aby móc osadzić ją w$b
bloku skryptowym i używać zarówno wewnątrz, jak i na zewnątrz pętli bez długiejparam()
deklaracji i przekazywania argumentów.$s
zostaje przypisana szerokość tabulatora, wywołując$b
blok na tablicy wierszy w pliku wejściowym, a następnie sumując indeks i długość każdego dopasowania, zwracając tablicę sum jako argument do funkcji GCD. Tak$s
ma wielkość naszej karcie zatrzymuje teraz.Następnie rozpoczyna się pętla. Iterujemy po każdej linii w tablicy linii wejściowych
$n
. Pierwszą rzeczą, którą robię w pętli, jest przypisanie$n
(zakres lokalny) wartości bieżącej linii z powyższego powodu.$w
pobiera wartość wywołania scriptblock tylko dla bieżącej linii (wcięcia i tabulacje dla bieżącej linii).$c
otrzymuje podobną wartość, ale zamiast tego znajdujemy wszystkie zamieszania .Sumuję
$w
i$c
które są tablicami, dając mi jedną tablicę ze wszystkimi potrzebnymi dopasowaniami spacji,sort
w kolejności malejącej według indeksu i rozpoczynam iterację po każdym dopasowaniu dla bieżącej linii.Rodzaj jest ważny. Na początku dowiedziałem się na własnej skórze, że zastępowanie części ciągu na podstawie wartości indeksu jest złym pomysłem, gdy zastępowany ciąg jest mniejszy i zmienia długość łańcucha! Pozostałe indeksy zostają unieważnione. Rozpoczynając od najwyższych indeksów w każdym wierszu, upewniam się, że zmniejszam ciąg tylko od końca i przesuwam się do tyłu, aby indeksy zawsze działały.
W tej pętli
$x
znajduje się w indeksie bieżącego dopasowania i$l
jest długością bieżącego dopasowania.$s
może być0
i to powoduje brzydki podział przez zero, więc sprawdzam jego poprawność, a następnie wykonuję matematykę.Chodzi
!(($x+$l)%$s)
o jeden punkt, w którym sprawdzam, czy zamieszanie należy zastąpić tabulatorem, czy nie. Jeśli indeks plus długość podzielona przez szerokość tabulatora nie ma już reszty, dobrze jest zastąpić to dopasowanie tabulatorem (matematyka zawsze będzie działać na wcięcia i tabulacje , ponieważ ich rozmiar określa szerokość tabulatora) najpierw).W przypadku zamiany każda iteracja pętli dopasowania działa w bieżącym wierszu danych wejściowych, więc jest to skumulowany zestaw zamienników. Wyrażenie regularne szuka
$l
spacji poprzedzonych$x
dowolną postacią. Zastępujemy go$l/$s
znakami tabulacji (lub 1, jeśli liczba ta jest mniejsza od zera).Ta część
(($l/$s),1-ge1)[0]
jest fantazyjnym, skomplikowanym sposobem powiedzeniaif (($l/$s) -lt 0) { 1 } else { $l/$s }
lub alternatywnie[Math]::Max(1,($l/$s))
. To sprawia, że tablicę$l/$s
i1
, a następnie wykorzystuje-ge 1
do powrotu tablicę zawierającą tylko te elementy, które są większe niż lub równe jeden, wówczas wybiera pierwszy element. Występuje w kilku bajtach krótszych niż[Math]::Max
wersja.Więc kiedy wszystkie zamiany zostaną wykonane, bieżąca linia jest zwracana z iteracji
ForEach-Object
(%
), a kiedy wszystkie są zwracane (tablica linii stałych), jest-join
edytowana z nowymi liniami (ponieważ na początku dzielimy na nowe linie).Wydaje mi się, że jest tu miejsce na ulepszenia, które jestem teraz zbyt wypalony, aby je złapać, ale może zobaczę coś później.
źródło
PHP -
278210 bajtówFunkcja działa poprzez przetestowanie każdej szerokości tabulatora, zaczynając od wartości 100, maksymalnej długości linii, a tym samym maksymalnej szerokości tabulatora.
Dla każdej szerokości tabulatora dzielimy każdą linię na „bloki” o tej długości. Dla każdego z tych bloków:
Po przeanalizowaniu każdego bloku linii zapamiętujemy wysuw linii. Jeśli wszystkie bloki wszystkich linii zostały z powodzeniem przeanalizowane, zwracamy zapamiętany ciąg. W przeciwnym razie, jeśli wypróbowano każdą ściśle dodatnią szerokość tabulatora, nie było ani tabulacji, ani wcięcia, i zwracamy oryginalny ciąg.
Oto wersja bez golfa:
Specjalne podziękowania dla DankMemes za zapisanie 2 bajtów.
źródło
for($t=101;--$t;)
zamiastfor($t=100;$t;--$t)
CJam, 112
Wypróbuj online
Musiałem odpowiedzieć na to wyzwanie, ponieważ muszę zrobić wszystko, aby pomóc uwolnić świat od tej obrzydliwości. Karty są oczywiście lepsze, ale niestety, niektórzy ludzie nie mogą być uzasadnieni.
Wyjaśnienie:
źródło
PowerShell ,
165160153152142 142138137 bajtówWypróbuj online!
Mniej golfa:
źródło