Któregoś dnia nasz zespół poszedł do pokoju ewakuacyjnego. Jedna z zagadek obejmowała tablicę sześciu mechanicznych przełączników, w której trzeba było znaleźć odpowiednią kombinację włączania i wyłączania, aby odblokować pudełko, mniej więcej tak:
-v-v-v-
-v-v-v-
Jako programiści postanowiliśmy, że bardziej efektywne będzie wypróbowanie każdej z 2 ^ 6 = 64 kombinacji niż rozwiązanie zagadki. Przydzieliliśmy więc jakiegoś biednego faceta do zliczenia binarnego:
-v-v-v-
-v-v-v-
-v-v-v-
-v-v-^-
-v-v-v-
-v-^-v-
-v-v-v-
-v-^-^-
i tak dalej.
Wyzwanie
Napisz program, który, biorąc pod uwagę wszystkie przełączniki w pozycji wyłączonej jako ciąg sformatowany jak powyżej, generuje wszystkie kombinacje włączania i wyłączania w dowolnej kolejności.
Możesz napisać pełny program lub funkcję. W ten sposób twój program może albo pobierać dane wejściowe przez stdin, plik, albo jako pojedynczy ciąg znaków i zwracać lub drukować dane wyjściowe. Jeśli zostanie zwrócone, dane wyjściowe mogą znajdować się w liście / tablicy / itp. zamiast jednego ciągu. Jeśli wynik jest pojedynczym ciągiem, tablice powinny być oddzielone znakami nowej linii (dozwolone są znaki nowej linii).
Ciągi wejściowe będą pasować do wyrażenia regularnego r'((-v)+-)(\n(-v)+-)*'
i będą reprezentować jedną płytkę ze wszystkimi wyłącznikami. Oznacza to brak zerowej wielkości liter, a przełączniki są wyrównane do lewej. Każdy wiersz może nie mieć takiej samej liczby przełączników.
Każda płytka wyjściowa powinna mieć dokładnie taki sam format jak wejście, z tym wyjątkiem, że v można w razie potrzeby zastąpić ^. Tablice wyjściowe można oddzielić dowolną liczbą nowych linii.
Ponieważ środowisko wykonawcze ma naturalnie wartość O (2 ^ n) pod względem liczby przełączników, kod nie będzie testowany na więcej niż 10 przełącznikach w dowolnym układzie.
To jest golf golfowy, więc wygrywa najkrótszy kod w liczbie bajtów.
Przykładowe wejścia i wyjścia
Wkład:
-v-
Możliwe wyjście:
-v-
-^-
Wkład:
-v-
-v-
Możliwe wyjście:
-^-
-^-
-^-
-v-
-v-
-^-
-v-
-v-
Ponieważ sprawdzanie odpowiedzi w przypadku większej liczby przełączników jest niezwykle uciążliwe, oto skrypt w języku Python jako narzędzie do sprawdzania czystości. (Dołączyłem obecnie skomentowany fragment kodu, aby wygenerować oczekiwane dane wyjściowe z danego pliku wejściowego na wypadek, gdybyś chciał więcej przypadków testowych.) Niestety, jest nieco mniej elastyczny pod względem danych wejściowych i wyjściowych niż specyfikacja; umieść ciąg wejściowy w pliku o nazwie „wejście”, a wyjście oddzielone znakiem nowej linii (przepraszam, brak formatowania listy) w pliku o nazwie „wyjście” w tym samym katalogu i uruchom python3 sanitycheck.py
.
źródło
Odpowiedzi:
Haskell ,
25242317 bajtówWypróbuj online!
-1 bajt dzięki @ H.PWiz
-1 bajt dzięki @nimi
Zwraca listę ciągów. TIO ma 2 dodatkowe bajty dla deklaracji funkcji - widziałem, jak inni ludzie ją wyłączają, gdy piszą funkcję bez punktów, więc robię to samo, chyba że powiedziano inaczej.
Poprzednia odpowiedź (25 bajtów)
Wyjaśnienia dotyczą poprzedniej odpowiedzi, która działa prawie w ten sam sposób, z tą różnicą, że wstawiłem definicję
g
. Sposób, w jakig
działa teraz jest za pomocą porównania leksykalnego zastąpił^v
zav
i zachować wszystko inne tak samo.Co ciekawe, działa to w przypadku dowolnych tablic rozdzielczych:
Wyjaśnienie (krótkie)
Objaśnienie (długie)
mapM
jest dość przerażającą funkcją dla tych, którzy nie znają Haskella. Ale nie jest trudno zrozumieć w tym kontekście. Ustawiając go naString
s (które w Haskell są listami postaci), wyspecjalizowałem się w jego definicji list. Więc w tym kontekście jego podpis typu toW rzeczywistości jest jeszcze bardziej wyspecjalizowany w moim użyciu -
a
ib
obaChar
- i możemy zobaczyć podpis typu jakoSzybko spójrzmy na to, co
g
robi, zanim wyjaśnimy, jak tomapM
działa.g
używa dopasowania wzorca do konwersji ciąguChar 'v'
na ciąg"v^"
; wszystko inne zostaje przekonwertowane na ciąg singletonu (pamiętaj, że ciągi to tylko listyChar
s, więc możemy umieścićx
listę singletonów). Testując REPL, stwierdzamy, że tak jestZauważ, że
g
jest to odpowiedni typ argumentumapM
(nic dziwnego!).Zbadamy, jak to
mapM
działa, podając gog
i argumentjako dane wejściowe.
mapM
pierwsze mapyg
nadString
, a ponieważg
konwertujeChar
s naStrings
, daje nam to listęStrings
Chociaż jest to prawidłowy typ wyjściowy,
mapM
robi nieco więcej. Możesz myśleć o tym jako o utworzeniu wszystkichString
liter, które możesz stworzyć z tej listy, jeśli będziesz musiał wybrać po jednym znaku z każdej z nichString
(w kolejności).Tak więc dla pierwszego elementu nie masz innego wyboru niż wybranie
Char '-'
. Dla drugiego elementu, można wybrać pomiędzy'v'
i'^'
tak dalej i tak dalej.Jest to mniej więcej odpowiednik tego kodu python:
Tyle, że ponieważ Haskell rozdziela
Char
s iString
s, kiedy umieszczaChar
s na liście, nie potrzebujejoin
ich.Tak więc końcowy wynik to
zgodnie z życzeniem.
źródło
mapM
pracowałem dla tego wyzwania, na początku miałem to sformułowane jako,sequence . map g
ale można to wyrazić zwięźle,mapM id . map g
a potem zobaczyłem, że mogęmapM g
=='v'
na>'-'
Perl 6 , 32 bajty
Wypróbuj online!
.comb
dzieli ciąg na znaki.».&{...}
odwzorowuje znaki zgodnie z funkcją między nawiasami klamrowymi.$_, ('^' if /v/)
tworzy listę alternatyw dla każdego znaku. Tylkov
ma zastępcę:^
.[X~]
zmniejsza tę listę za pomocą operatora krzyżowego łączenia produktówX~
.źródło
Galaretka , 7 bajtów
Wypróbuj online!
Dane wyjściowe to lista ciągów galaretki.
Wyjaśnienie:
źródło
Perl 5 , 29 bajtów
Wypróbuj online!
Moje pierwsze zgłoszenie!
Zwykle golfiści Perl 5 przesyłają programy zamiast funkcji, aby zaoszczędzić od konieczności dołączania
sub{}
co najmniej. Ale trzeba dodaćsay
,say␠
,say for
lubsay for␠
w zamian.Wybierając podejście podrzędne, mogłem skrócić
do
Wyjaśnienie jest dość proste. Perl 5 ma wbudowany
glob
operator, który akceptuje wzór globu podobny do powłoki, którego można użyć do wygenerowania list nazw plików (np.foo*.txt
) Lub listy ciągów (np{a,b,c}
.). Problem polega na tym, że nowa linia musi być zmieniona, co zrobiłem za pomocąquotemeta
(as\Q
).źródło
K (ngn / k) ,
2725 bajtówWypróbuj online!
"^"/"v"\
wymienić"v"
z"^"
x,'
zip z oryginalnymi znakami(,/,/:\:)/
produkt kartezjański zakończony?
uniqźródło
APL (Dyalog Classic) ,
21 1715 bajtówWypróbuj online!
podobne do mojego rozwiązania k
zwraca n-wymiarową tablicę ciągów (n = liczba przełączników)
w łatwiejszej do wyjaśnienia formie:
⊃(∘.,⌿ ⊢ ∪¨ 'v'⎕r'^')
'v'⎕r'^'
zamieńv
s na^
s⊢ ∪¨
... związki z każdą z oryginalnych postaci. jest to wektor ciągów o długości 1 lub 2∘.,⌿
redukcja produktu kartezjańskiego⊃
ujawniaćaby przejść do wersji w pełni golfowej, kierujemy się wzorem
f⌿ A g¨ B
->A f.g B
:∘.,⌿ ⊢ ∪¨ 'v'⎕r'^'
->⊢ ∘.,.∪ 'v'⎕r'^'
jako efekt uboczny nawiasy nie są już potrzebne
źródło
J , 42 bajty
Wypróbuj online!
wyjaśnienie
Niech weźmie
jako nasz przykładowy wkład.
('v^' {~ 2 #:@i.@^ 1 #. e.&'v')
tworzy wszystkie możliwe kombinacje samych przełączników, ignorując format wejściowy. w naszym przykładzie produkuje:1 #. e.&'v'
zlicza liczbyv
s na wejściu.2 #:@i.@^
podnosi 2 do tej potęgi, produkuje liczby całkowite od 0 do tej liczbyi.
i konwertuje je na binarne#:
'v^' {~
zmiany cyfr binarnych nav
i^
]`('v' I.@e.~ [)`[}"1
zmienia oryginalny wejściowy, tworząc jedną kopię dla każdego rzędu w wyniku opisanego w poprzednim etapie (czyli wszystkie możliwev
/^
combo). W każdej kopiiv
oryginalne wejście jest zastępowane jedną możliwą sekwencjąv
/^
.źródło
Java,
202197189191 bajtówTak, jest to dość szczegółowy język, ale to, co uważam za klasyczne golfa:
Myślałem, że „prosty” sposób radzenia sobie z podziałów wierszy, które są niezbędne do osiągnięcia celu prawidłowego układu było rzeczywiście ponownie użyć oryginalnego tablicę znaków wejściowych, a tylko wypełnić go z
'v'
S i'^'
S w odpowiednich pozycjach.Aktualizacje:
Okazało się, że nie przechowywania stanowisk pozwala na wodowania
int
i deklaracji zmiennych array (kosztem sprawdzanie każdej pozycji tablicy, czy zawiera onv
lub^
w locie), oszczędzając 5 bajtów.Kolejne 8 bajtów zaoszczędzonych dzięki
(1<<numberOfSwitches)
bardziej zwartemu obliczeniu górnej granicy .Zgodnie z regułą wymienioną w komentarzu należy policzyć deklarację funkcji, więc teraz jest to lambda ...
źródło
String generate(String s) {...}
) w swojej liczbie bajtów. Oto wersja fixed / lambda dla 191 bajtów . Zrobiłem trochę golfa, aby ogolić 3 bajty{ function body }
powinna być istotna, ponieważ nie ma znaczenia, czy umieścisz ją w funkcji, która jest,static
czy nie, i oczywiście, jeśli deklaracja liczy się do wyniku, można przekształcić ją w wyrażenie lambda. Ale tak się teraz dzieje, dziękuję za zwrócenie na to uwagi.d=94
). 2. Zainicjuj,i
kiedy to zadeklarujesz. 3. Użyji++<m
zamiast osobnego przyrostu (musisz zmodyfikować zawartość pętli w jednym miejscu, ale nie powoduje to żadnych kosztów). 4. Czy możesz uciec(i&1<<j++)>0
? 5. Nie sądzę, żebyś potrzebował{}
wewnętrznejfor
pętli. 6. Można wymienića[k]==d||a[k]==u
za[k]>45
, myślę. 7. Idź zj=k=0
. Wszystko to powinno usunąć 19 bajtów.{}
są konieczne, ale mogę mieć inny wygląd.a[k]>45
Może być schludny trik, jednak. Wprawdzie napisałem to tylko po to, by marnować trochę czasu na rozpoczęcie spotkania (stąd nazwa klasy - to było zamierzone ;-)), ale może jeszcze popatrzę - dzięki w każdym razie!J ,
41 4024 bajtówWypróbuj online!
źródło
{
. chociaż myślę[:>@,@{<@(,'^'$~'v'=])"0
, że byłoby to nieco bardziej sprawiedliwe, ponieważ „Każda płytka wyjściowa powinna mieć dokładnie taki sam format jak wejście”, a wejście nie jest zapakowane w ramkę.Python 2 , 87 bajtów
Wypróbuj online!
Podejście inne niż wyrażenia regularne.
źródło
C (gcc) ,
75 7470 bajtów-5 bajtów dzięki @ceilingcat
Wypróbuj online!
wymaga zapisywania
s
punktów pamięciźródło
Python 3.8 (wersja wstępna) ,
129 117 116 110106 bajtów-10 bajtów dzięki @Chas Brown
Wypróbuj online!
źródło
C (gcc) , 102 bajty
Wypróbuj online!
źródło
K4 , 44 bajty
Rozwiązanie:
Przykłady:
Wyjaśnienie:
Wymiana w miejscu
"^"
. Określić liczbę kombinacji przełączników (np. 2 ^ n), policzyć binarnie, wymienić przełączniki ...źródło
R , 116 bajtów
Wypróbuj online!
Funkcja zwracająca wektor tablic rozdzielonych znakiem nowej linii
źródło
"[<-"
!JavaScript, 88 bajtów
Wypróbuj online!
źródło
n>>=1
->n/=2
Retina 0.8.2 , 29 bajtów
Wypróbuj online! Wyjaśnienie:
Zmień znaki nowej linii na
;
s, av
s na#
markery.Wymień je
#
pojedynczo od lewej do prawej.Zmień każdą linię na dwie linie, jedną z
#
zastąpioną przez av
, jedną z zastąpioną przez a^
.Zmień
;
s z powrotem na nowe linie i rozdziel wyniki od siebie.źródło
Perl 5
-0
, 51 bajtówWypróbuj online!
źródło
-n
pozwoliłoby uniknąć potrzeby$_=<>;
JavaScript (Node.js) ,
80 7368 bajtówWypróbuj online!
źródło
Python 3 - konstrukcja, 203 bajty
Wypróbuj online!
Pierwsza próba, niezbyt mała, ale działa. W Pythonie nie ma eleganckiej zamiany napisów ...
Pierwsza pętla buduje odwzorowanie linii na indeksy bitów, tj. Dla każdej linii przechowywany jest indeks pierwszego bitu w liczniku bitów. Służy do indeksowania licznika bitów w następnej pętli.
Druga pętla uruchamia licznik binarny, wyodrębnia bity dla każdej linii i iteracji i łączy je. Po połączeniu wszystkich elementów jest on ponownie tłumaczony do formatu mapy przełączników, z wykorzystaniem zamiany napisów.
Sądzę, że istnieje bardziej elegancki sposób, poprzez ponowne użycie ciągu wejściowego zamiast jego przebudowywania w kółko.
Edycja: zainspirowana odpowiedzią Python 3.8 , tutaj jest znacznie krótsza wersja zastępująca
Python 3 - zamień, 123 bajty
Wypróbuj online!
źródło
Rubinowy , 64 bajty
W Ruby
i[j]
zwracaj
thi
zaczynający się od najmniej znaczącego bitu, czyli równoważny(i>>j)&1
.Wypróbuj online!
źródło
Węgiel drzewny , 28 bajtów
Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:
źródło
PHP , 93 bajty
Wypróbuj online!
Samodzielny program, wprowadzany z wiersza poleceń.
Zapętlić liczbę możliwych permutacji ciągu wejściowego na podstawie liczby
v
. Podczas liczenia w formacie binarnym zamień każdy plik binarny na „1
a”,^
a każdy plik binarny na „0
a”v
w ciągu wejściowym.źródło