Wprowadzenie
To wyzwanie jest inspirowane przez Grime , mój język dopasowywania wzorów 2D. Zasadniczo otrzymujesz „gramatykę” opisującą dwuwymiarowe siatki znaków, a Twoim zadaniem jest wygenerowanie siatki zgodnie z gramatyką. Ponadto siatka powinna być jak najmniejsza w pewnym słabym znaczeniu.
Wejście
Wpisujesz ciąg zawierający małe znaki ASCII oraz symbole |
i -
. Dla uproszczenia dane wejściowe nie zawierają powtarzających się małych liter. Ciąg jest specyfikacją klasy prostokątnych siatek znaków i jest analizowany od lewej do prawej za pomocą stosu w następujący sposób.
- Biorąc pod uwagę małą literę
c
, przesuń na stosm×n
siatkę postacic
, dla dowolnejm, n ≥ 1
. - Biorąc pod uwagę fajkę
|
, przebij dwie siatkiA
iB
ze stosu (B
był na górze) i popchnij siatkęAB
uzyskaną przez konkatenacjęB
na prawo odA
. Wymaga toA
iB
mają jednakową wysokość. - Biorąc pod uwagę łącznik
-
, wysuń dwie siatkiA
iB
ze stosu (B
był na górze) i przesuń siatkęA/B
uzyskaną przez konkatenacjęB
na dółA
. Wymaga toA
iB
mają jednakową szerokość.
Jest pewne, że dla niektórych opcji m
in
dokonywanych podczas przetwarzania (które mogą być różne dla każdej litery) specyfikacja wejściowa poprawnie opisuje prostokąt, który pozostaje na stosie na końcu.
Wynik
Twój wynik jest prostokątną siatką znaków określonych przez dane wejściowe. Siatka musi być minimalna w tym sensie, że usunięcie dowolnego wiersza lub kolumny spowoduje, że będzie ona nieważna. Możesz zwrócić ciąg oddzielony znakiem nowej linii (z końcowym znakiem nowej linii lub bez), tablicę znaków 2D lub tablicę ciągów, w zależności od tego, który z nich jest najwygodniejszy.
Pamiętaj, że nie musisz przetwarzać danych wejściowych dokładnie tak, jak opisano powyżej; jedyną ważną rzeczą jest to, że wyniki są prawidłowe.
Przykład
Rozważ specyfikację
par-s||e-
Najpierw wybieramy pchnięcie 1×2
prostokąta p
i 1×1
prostokąty a
i r
(powód będzie wyjaśniony później). Następnie wyskakujemy a
i r
prostokąty i przesuwamy ich pionowe połączenie
a
r
Następnie wciskamy 1×2
prostokąt s
, pop go i powyższy prostokąt, i przesuwamy ich poziomą konkatenację
as
rs
Następnie przebijamy ten prostokąt i p
prostokąt i przesuwamy ich konkatenację
pas
prs
Na koniec wciskamy 3×1
prostokąt , przesuwamy e
go i powyższy prostokąt i przesuwamy pionową konkatenację
pas
prs
eee
To jest wynik programu lub przynajmniej jedna z możliwości. Zauważ, że mimo to
ppas
ppas
pprs
eeee
jest również generowany przez specyfikację, nie jest to poprawny wynik, ponieważ wiele wierszy i kolumn można usunąć.
Rozważ bardziej subtelny przykład
co|m|p|il|e|r|-
Ta specyfikacja generuje prostokąt
comp
iler
który jest prawidłowym wyjściem. Jednak generuje również
commp
iiler
co również jest ważne, ponieważ nie można usunąć pojedynczego wiersza ani kolumny bez unieważnienia go.
Zasady
Możesz podać pełny program lub funkcję. Wygrywa najniższa liczba bajtów, a standardowe luki są niedozwolone.
Dodatkowe przypadki testowe
Możesz użyć ich do przetestowania swojego programu.
Input:
a
Output:
a
Input:
co|mp|l|-ex|i|f|-y|
Example output:
cccoy
mplly
exify
Input:
ja-r|g-o|ni-|ze|d-|
Example output:
jronze
arondd
ggoidd
Input:
un|co|p-yr|i|gh-t-ab|-|le-||-
Example output:
unnnnnnn
coyriggl
ppyrihhe
ppyritte
ppyriabe
źródło
n
im
są wybierani niedeterministycznie. Gwarantujemy, że istnieją dla nich odpowiednie wartości, ale znalezienie ich jest zadaniem Twojego programu.un|co|p-|yr|i|gh--t-ab|-|le-||-
nie można być ważnym. Ostatni-
ma arity 2, podczas gdy na stosie jest tylko 1 element.Odpowiedzi:
K,
123110 bajtówZastosowałem podobne podejście do rozwiązania karton_box.
Ten program to seria definicji pomocników, po których następuje ukryta funkcja, która przyjmuje ciąg jako prawidłowy argument. Przeformatowanie pod kątem czytelności i przypisanie końcowej funkcji jako
f
:Użyj przykładu:
Testowane przy użyciu Kona, ale będzie działać również w OK, jeśli zastąpisz
:
w definicjif
na$
-k5 zmieniłem składnię „cond”.Kluczowym punktem jest uznanie, że wykonanie dołączenia pionowego jest transpozycją dołączenia poziomego transpozycji obu macierzy. (Zobacz definicję
v
.) Myślę, że wciąż jest miejsce na wyciśnięcie kilku znaków tu i tam. Jeśli ktoś jest zainteresowany bardziej szczegółowym wyjaśnieniem, mogę je przedstawić.edytować:
Zaktualizowano program u góry tego wpisu. Wersja bez golfa:
Znaczące optymalizacje długości obejmują użycie „kropki zastosuj” w
a
, zastąpienie „cond” indeksowaniem listy wf
(mniej wydajne, ale krótsze) i zastąpienie warunków formularzaa[b;c]
na,a[b]c
tam gdzie jest to dozwolone przez grupowanie. Ponieważ nie używam już „cond” ani żadnych prymitywów, które różnią się między k3 i k5, ta wersja działa teraz w ok bez modyfikacji.źródło
Prolog, 539 bajtów
Wyjaśnienie
Zaczynamy od predykatu
g
, który pobiera ciąg, konwertuje go jako listę znaków i wywołujep
predykat (parsuj) z pustym stosem jako drugim argumentem.Predykat
p
wywołuje się rekurencyjnie z odpowiednio zmodyfikowanym stosem (poszukaj[H|T]
wzorów destrukcyjnych i konstruktorskich). Po wywołaniu w przypadku podstawowym, gdzie lista wejściowa jest pusta,p
drukuje unikalny element stosu. Jeśli stos zawiera mniej niż jeden element w tym momencie, oznacza to, że mamy pusty ciąg wejściowy, zły ciąg wejściowy lub błąd (z pustym ciągiem predykat kończy się niepowodzeniem (mówi PrologNo
), ale nic nie jest drukowane, co jest w porządku, ponieważ nie powinniśmy nic drukować dla pustych ciągów).Rozwiązywanie
Stos zawiera opis zbudowanych prostokątów, oznaczony
S:W:H
, gdzieS
jest symboliczną reprezentacją prostokąta,W
jego szerokości iH
wysokości (uwaga,A:B
to cukier składniowy dla:(A,B)
krotki z nazwanym funktorem:
; jest tylko krótszy niż napisać krotkę z notacją przedrostkową).Z
A
B
specyfikacjami i pod-prostokątamiS
mogą być:h(A,B)
: concat poziomy A i Bv(A,B)
: concat pionowy A i Bf(C)
: wypełnij C, gdzie C jest kodem znakowymSzerokości i wysokości siatek są zmiennymi programującymi ograniczenia: podczas konkatenacji pionowej (odpowiednio. Poziomej) szerokość (odpowiednio. Wysokość) manipulowanych prostokątów jest ujednolicona, podczas gdy uzyskana wysokość (odpowiednio. Szerokość) jest ograniczona do sumy wysokość każdego podsiatki (lub szerokość).
Etap etykietowania na końcu procesu inicjuje zmienne przy jednoczesnym przestrzeganiu ograniczeń, przy użyciu minimalnych możliwych wartości (jest to właściwość kolejności, w której rozwiązania są wypróbowywane).
Mogłem uzyskać krótszą odpowiedź przy użyciu tego samego rozumowania, co w innych odpowiedziach, bez ograniczeń, ale teraz jest już za późno.
Zauważ również, że ponieważ domyślną domeną dla zmiennych jest ustawione
1..100
, istnieje ograniczenie co do możliwych rozmiarów siatek. W razie potrzeby górna granica może zostać zmieniona. Wpływ tego na wydajność polega na tym, że ustalenie, czy dane rozwiązanie nie dopuszcza żadnego rozwiązania, może zająć dużo czasu. Powiedziałem „ mógłbym ”, ponieważ ograniczenia prawdopodobnie drastycznie przycinają wyszukiwanie wykładnicze. Jeśli znajdziesz ciąg wejściowy, który jest trudny / kosztowny do odrzucenia, udostępnij.Druk
Część drukująca jest interesująca, ponieważ istnieje pewien algorytm rzutowania promieni nad strukturą: iteruję każdą komórkę wynikowej siatki, od punktu
(1,1)
do punktu(W,H)
iw
wywołuję predykat, aby wydrukować zawartość siatki w głównym drzewie, w ta lokalizacja (oczywiście nowa linia jest drukowana po przetworzeniu każdej linii).W
w
, pozycje są względem bieżącej siatki (siatka główna określa współrzędne bezwzględne).Podczas drukowania
h(A,B)
struktury w punkcie(X,Y)
bezwarunkowo drukuję w obu gałęziach:A
w punkcie(X,Y)
orazB
w punkcie(H,Y)
, gdzieH
jestX
minus szerokośćA
.Gałęzie liści drzewa siatki
f(C)
, w końcu albo wydrukują znakC
, jeśli względna lokalizacja znajduje się wewnątrz siatki, albo nic nie robią. W ten sposób mogę wydrukować zawartość siatki do strumienia wyjściowego, od góry do dołu, od lewej do prawej. Nie są generowane żadne rzeczywiste tablice.Testy
Uruchamianie testu:
źródło
No actual arrays are produced.
tak właśnie należy zrobić. W tym przypadku przesada, ponieważ gramatyka jest bardzo prosta i istnieją skróty.Python 2.7, 259
g
jest funkcją, która przyjmuje specyfikację i daje tablicę znaków 2D. Jeśli chcesz wersji bardziej przyjaznej dla użytkownika, dodaj ten wiersz, aby pobrać specyfikację ze standardowego wejścia i wydrukować tabelę:Przypadki testowe
Wyjaśnienie
Strategia jest prosta: jeśli siatka
G
jest poprawna dla specyfikacjiS
, to powtórzenie kolumny z prawej stronyG
również daje poprawną specyfikacjęS
, i to samo dotyczy powtórzenia dolnego rzędu (dowodem na to jest włączenie indukcji strukturalnejS
). Dlatego, gdy chcemy połączyć dwa prostokąty, możemy po prostu dołączyć ostatnią kolumnę / wiersz mniejszego, dopóki nie dopasują wielkości (to właśnie robi funkcja p).źródło
Haskell,
388367352 bajtówZastosowanie:
f "par-s||e-"
->["pas","prs","eee"]
Uruchomienie testowe z ładnym drukiem:
Jak to działa: funkcja
#
analizuje ciąg wejściowy w strukturę drzewa,C
która jest liściemL
zawierającym znak do wydrukowania lub węzłemN
.N
może być a) łączeniem obok siebie (t==2
), b) łączeniem góra-dół (t==1
) lub c) kwadratem z pojedynczą literą (t==0
). Wszystkie węzły mają pole szerokości i wysokości oraz lewe i prawe dziecko. Po analiziep
drukuje pozostały węzeł główny, rekurencyjnie dostosowując rozmiar (szerokość x wysokość) jego węzłów potomnych i łącząc je.Edycja: wyjście jako lista linii zamiast ładnego drukowania
źródło
JavaScript (ES6), 283
295Edytuj Teraz to (mocno golfowe) rozwiązanie JS jest co najmniej krótsze niż referencyjne (dość golfowe) rozwiązanie Python.
Podobnie jak w przypadku karton_powtarzania, wystarczy powtórzyć lewą kolumnę lub najwyższy rząd.
Niegolfowane To moje pierwsze, niegolfowane rozwiązanie.
Przetestuj w konsoli Firefox / FireBug
Wynik
źródło
Python 3, 251 bajtów
Oto obiecana odpowiedź, trochę dalej grałem w golfa.
Jest to pełny program, który pobiera ciąg ze STDIN i drukuje do STDOUT. Podejście jest takie samo, jak w przypadku karton_boksa: wciśnij tablicę 1x1 dla znaku i duplikuj wiersze, jeśli to konieczne do konkatenacji.
Szczegółowe wyjaśnienie
T
transponuje podaną listę list. Większość pracy polegazip(*m)
na zamianie wierszy na kolumny, reszta po prostu konwertuje wynik na listę list, ponieważzip
zwraca generator krotek.E(a,b)
zwracaa
z pierwszym elementem powtórzonym tyle razy, aby dopasować długośćb
. Zauważ, że pomnożenie listy przez liczbę ujemną daje pustą listę, więc jeślib
jest krótsza niża
, to zwracaa
.H(a,b)
zwraca łączenie w poziomiea
ib
, wE
razie potrzeby , krótsze jest przedłużane .s
to stos.for
pętli iterujemy ciąg wejściowy i zastępujemys
go nową wartością: jeśli jest|
(większa niżz
), wstawiamy dwie wartości i wypychamy ichH
, jeśli jest-
(mniejsza niża
), wstawiamy dwie wartości, transponujemy, przesyłamy doH
, transponuj ponownie i wypchnij wynik, a w przeciwnym razie wypchnij tablicę 1x1 z literą.s
.źródło