Płytki duodyadyczne są rodzajem kwadratowych bloków funkcyjnych które pobierają dwa dane wejściowe, jeden z góry i jeden z lewej strony, i mają dwa wyjścia, jeden po prawej stronie i jeden od spodu. Każde z ich wyjść stanowi osobną funkcję obu wejść.
Na przykład, jeśli #
reprezentuje płytki rodzajowe, prawo wyjściowy R
jest funkcją f
wejść T
i L
, a dno wyjście B
to kolejna funkcja g
of T
a L
:
T
L#R R = f(T, L)
B B = g(T, L)
(Kafelki są nazywane „duetem”, ponieważ istnieją dwie funkcje, i „dyadyczne”, ponieważ obie funkcje mają dwa argumenty .)
Płytki mogą być następnie składane razem na siatce, a wyjścia jednego kafelka przechodzą bezpośrednio do wejść sąsiadujących ze sobą kafelków. Tutaj, na przykład, prawe wyjście z lewej #
idzie do lewego wejścia z prawej #
:
AB D = f(f(A, C), B)
C##D E = g(A, C)
EF F = g(f(A, C), B)
Można sobie wyobrazić, że biorąc pod uwagę zestaw płytek duodyadycznych, z których każda ma określoną funkcjonalność, można tworzyć złożone (i potencjalnie przydatne) kompozycje.
W tym wyzwaniu zajmiemy się tylko tradycyjnym zestawem dziesięciu duodyadycznych płytek logicznych , w których wszystkie wejścia i wyjścia są jednobitowymi liczbami binarnymi (zerami lub jedynymi). Użyjemy osobnego znaku ASCII do oznaczenia każdego rodzaju kafelka.
Znaki kafelków i ich relacje wejścia-wyjścia są następujące:
( T
dotyczy górnego wejścia, L
lewego wejścia, R
prawego wyjścia, B
dolnego wyjścia).
- Zero:
0
lub(spacja) →
R = 0
,B = 0
- Jeden:
1
→R = 1
,B = 1
- Krzyż:
+
→R = L
,B = T
- Lustro:
\
→R = T
,B = L
- Tylko najlepsze:
U
→R = T
,B = T
- Tylko w lewo:
)
→R = L
,B = L
- Nie:
!
→R = not L
,B = not T
- I:
&
→R = L and T
,B = L and T
- Lub:
|
→R = L or T
,B = L or T
- Xor:
^
→R = L xor T
,B = L xor T
Wyzwanie
Napisz program lub funkcję, która przyjmuje prostokątną siatkę znaków 0 1+\U)!&|^
reprezentującą „obwód” wykonany przy użyciu dziesięciu logicznych płytek duodyadycznych. Musisz także wziąć dwa ciągi znaków 0
i 1
; jeden będzie lewą kolumną wejściową, a drugi będzie górnym wierszem wejściowym. Twój program / funkcja musi wydrukować / zwrócić dolny wiersz wyjściowy i prawą kolumnę wyjściową (także w 0
's i1
”).
Na przykład w tej siatce
+++
+++
wszystkie wejścia przepływają prosto przez siatkę do wyjść
ABC
D+++D
E+++E
ABC
więc wejście 010
/ 01
miałoby wynik 010
/ 01
:
010
0+++0
1+++1
010
Dokładna wyjście programu będzie [bottom output row]\n[right output column]
albo [bottom output row]/[right output column]
:
010
01
lub
010/01
Jeśli napisałeś funkcję, możesz zwrócić dwa ciągi w krotce lub liście (lub nadal je wydrukować).
Detale
- Weź trzy dane wejściowe jako ciągi znaków w jakikolwiek rozsądny sposób (najlepiej w tabeli kolejności, górnym rzędzie, lewej kolumnie): wiersz poleceń, plik tekstowy, sdtin, funkcja arg.
- Możesz założyć, że wejściowe długości wierszy i kolumn będą pasować do wymiarów siatki i będą zawierać tylko
0
„i1
”. - Twoja siatka musi używać odpowiednich znaków (
0 1+\U)!&|^
). Pamiętaj o tym0
ioznacz to samo.
Przypadki testowe
(Czytaj I / O jako top
/ left
→ bottom
/ right
.)
Nand:
&!
00
/ 0
→ 01
/ 1
00
/ 1
→ 01
/ 1
10
/ 0
→ 01
/ 1
10
/ 1
→ 11
/0
Wszystkie:
1111
1\+\
1+\+
1\+\
Każde wejście powinno skutkować 1111
/ 1111
.
Xor z Nand: (zwróć uwagę na kolumnę końcowych spacji)
\)+\
U&!&
+! !
\&!&
!
00000
/ 00000
→ 00000
/ 00000
00000
/ 10000
→ 00010
/ 00000
10000
/ 00000
→ 00010
/ 00000
10000
/ 10000
→ 00000
/00000
Zig zag:
+++\00000000
000\!!!!\000
00000000\+++
Pierwszy bit lewego wejścia staje się ostatnim bitem prawego wyjścia. Wszystko inne jest 0
.
000000000000
/ 000
→ 000000000000
/ 000
000000000000
/ 100
→ 000000000000
/001
Propagacja:
)))
UUU
U+U
U+U
UUU
Pierwszy bit lewego wejścia trafia do wszystkich wyjść.
000
/ 00000
→ 000
/ 00000
000
/ 10000
→ 111
/11111
Oto skrót wszystkich przypadków testowych siatki 1 × 1.
Punktacja
Najkrótsze przesłanie w bajtach wygrywa.
Bonus: Jakie fajne „obwody” możesz zrobić?
PS Nie przejmuj się Googlingiem „duodyadycznymi kafelkami”. Wymyśliłem je wczoraj; D
Jeśli chcesz porozmawiać o rozszerzeniu tego pomysłu na pełnoprawny język programowania, odwiedź ten czat .
źródło
Odpowiedzi:
Pyth, 122
Rodzaj potwora. Wykorzystuje po prostu rekurencję, nic fantazyjnego jak programowanie dynamiczne.
Demonstracja online .
Wprowadzanie odbywa się w następujący sposób: Najpierw siatka (bez ucieczki, bez dodatkowych symboli), a następnie dwie linie wprowadzania, np. (Zig zag)
źródło
Mathematica,
331276270267264262252250 bajtów
Jest prywatnym wykorzystanie znaków Unicode, który Mathematica używa jako indeks górnyT
, to znaczy, że to operator transpozycji.Oto bardziej czytelna wersja:
Jest to nienazwana funkcja, która pobiera trzy ciągi wejściowe grid, górny i lewy i drukuje dolne i prawe wyjścia.
Wyjaśnienie
Przejdźmy krok po kroku (postaram się nie zakładać żadnej wiedzy Mathematica). Trzeba trochę przeczytać kod od początku. Podstawowy algorytm omija linie obliczające każdą funkcję i zapisując wyniki
f
które będą dostępne dla kolejnych kafelków.Przetwarzanie wejściowe
To jest to:
To tylko dzieli siatkę na zagnieżdżoną listę znaków (zwróć uwagę, że zdefiniowałem
h
jako alias dlaCharacter
jakiegoś miejsca w kodzie), a następnie wstawia wiersz i kolumnę z danymi wejściowymi. Działa to, ponieważ1
i0
są również nazwami płytek o stałej funkcji, więc ich nałożenie ma taki sam efekt, jak ręczne wprowadzanie danych wejściowych. Ponieważ są to funkcje, technicznie będą pobierać dane spoza sieci, ale ponieważ są to funkcje stałe, nie ma to znaczenia. W lewym górnym rogu wyświetlany jest znak,0
ale jest to dość arbitralne, ponieważ wyniki tego kafelka nigdy nie są używane.Zwróć także uwagę na transpozycję. Dodawanie kolumn zajmuje więcej znaków niż dodawanie wierszy, więc transponuję siatkę po dodaniu górnego wiersza. Oznacza to, że górna / dolna i lewa / prawa są zamienione na główną część programu, ale są one całkowicie wymienne, więc to nie ma znaczenia. Muszę tylko zwrócić wyniki w prawidłowej kolejności.
Rozwiązywanie siatki
(Ta sekcja jest nieco nieaktualna. Naprawię ją, gdy będę naprawdę pewien, że skończyłem grać w golfa.)
Następnie przeglądamy
MapIndexed
wewnętrzny poziom tej zagnieżdżonej listy. Wywołuje to funkcję anonimową podaną jako pierwszy argument dla każdego znaku w siatce, dając również listę z bieżącymi dwoma współrzędnymi. Siatka jest przesuwana w kolejności, dzięki czemu możemy bezpiecznie obliczyć każdą komórkę na podstawie poprzednich.Używamy zmiennych
r
(ight) ib
(ottom) jako tabel wyszukiwania dla wyników każdej komórki. Nasza anonimowa funkcja ma bieżące współrzędne#2
, więc otrzymujemy dane wejściowe do dowolnej komórki za pomocąZauważ, że w pierwszym wierszu i kolumnie uzyska to dostęp do niezdefiniowanych wartości
r
ib
. Mathematica tak naprawdę nie ma z tym problemu i po prostu zwróci ci współrzędne, ale i tak odrzucamy ten wynik, ponieważ wszystkie kafelki w tym wierszu / kolumnie są funkcjami stałymi.Teraz ta rzecz:
Jest formą golfa
Która z kolei jest funkcją, która przy dwóch wejściowych kafelkach zwraca skojarzenie (nazwałbyś to hashapą lub tabelą w innych językach), która zawiera wszystkie możliwe wyniki kafelków dla tych dwóch danych wejściowych. Aby zrozumieć, w jaki sposób wszystkie funkcje są implementowane, musisz wiedzieć, że do pierwszego argumentu takiej funkcji można uzyskać dostęp,
#
a do drugiego za pomocą#2
. Ponadto##
udostępnia sekwencję obu argumentów, których można użyć do „splatania” argumentów.0
: jest prosty, po prostu zwracamy stałą,{0, 0}
a także przypisujemy jąz
do przyszłego użycia (np. w kafelku spacji).1
: jest w gruncie rzeczy słuszne{1,1}
, alez
skrócenie tego jest1+z
. Zapisujemy to również wo
, ponieważ przyda się dla wszystkich kafelków, w których oba wyjścia są identyczne.+
: Tutaj wykorzystujemy sekwencję.{##}
jest taki sam jak{#,#2}
i przekazuje oba dane wejściowe bez zmian.\
: My zamienić dwa argumenty{#2,#}
.U
: Teraz możemy skorzystać zo
.o#2
oznacza{1,1}*#2
, że umieściliśmy pierwszy argument w obu wynikach.)
Analogicznie dla lewego argumentu:o#
.!
: Bitowe nie jest irytujące w Mathematica, ale ponieważ mamy tylko kiedykolwiek0
i1
możemy po prostu odjąć od obu wejść1
(a tym samym ich odwrócenie) i przekazać je na:1-{##}
.&
: Ten jest całkiem fajny. Najpierw zauważamy, że bitowe i dla0
i1
jest identyczne z mnożeniem. Ponadtoo##
jest taki sam jako*#*#2
.|
: Ponownie używamy równoważnej funkcji. Bitowa lub jest taka sama jakMax
w tym przypadku, więc stosujemyMax
argumenty wejściowe i mnożymy wynik{1,1}
.^
: Najkrótsze, jakie znalazłem dla Xora, to wziąć różnicę i ją wyrównać (aby zapewnić pozytywność), więc mamyo(#-#2)^2
.Po zakończeniu tej funkcji i zwróceniu pełnego skojarzenia używamy znaku bieżącej komórki, aby wyciągnąć interesujący nas element i zapisać go w
r
orazb
. Zauważ, że jest to również wartość zwracana przez anonimową funkcję użytą wMapIndexed
, więc mapowanie da mi siatkę wszystkich wyników.Przetwarzanie wyjściowe
MapIndexed
zwraca siatkę 3D, w której pierwszy wymiar odpowiada poziomej współrzędnej siatki (pamiętaj o wcześniejszej transpozycji), drugi wymiar odpowiada pionowej współrzędnej siatki, a trzeci wskazuje, czy mamy wynik dolny, czy lewy. Zauważ, że zawiera on również wiersz wejściowy i kolumnę, których musimy się pozbyć. Tak więc uzyskujemy dostęp do dolnego wyjścia dolnego rzędu za pomocąi prawy wynik ostatniej kolumny za pomocą
Zauważ, że
2;;
jest to zakres od drugiego do ostatniego elementu.Wreszcie, stosujemy się
Print
do obu (wykorzystując@@@
jako cukier syntaktyczny dla drugiego poziomuApply
), który po prostu wypisuje wszystkie swoje argumenty jeden za drugim (a ponieważ stosuje się go do dwóch oddzielnych wyrażeń, pojawi się nowa linia między dolnym a dolnym właściwe wyjście).źródło
C,
332309272270266259247225 bajtówZobacz wyniki online tutaj!
Definiuje to funkcję
void f(char*, char*, char*)
, która powinna przyjąć tablicę jako swoje pierwsze wejście, potem górny rząd danych wejściowych, a następnie lewy rząd danych wejściowych.Oto, co testowałem:
Zatem, wprowadzając 2-bitowy mnożnik Sp3000:
Otrzymujemy:
Z drugiej strony, mając na uwadze pół sumatora Sp3000, chciałbym zobaczyć pełnego sumatora ...Jeden z was to zrobił! Nie sądzę, że system sam w sobie jest językiem programowania, ale był bardzo interesujący. Wydaje się to jednak doskonałym celem dla metagolfa!Krótkie wyjaśnienie:
Oto rozwikłany, skomentowany kod:
Powtarzamy
c
, od lewej do prawej (a następnie od góry do dołu), zat
każdym razem przepisując dane wejściowe i wypychając najbardziej prawy wynik, który jest wpychany dol
łańcucha. Możemy sobie wyobrazić, jak to zastąpienie górnym rzędziec
z1
„s oraz0
” S iteracyjnie i śledzenie bity, które są wypychane z prawej strony.Oto bardziej wizualna sekwencja, rząd po rzędzie:
To oczywiście komplikuje się przy różnych symbolach i rozmiarach, ale główna idea jest ważna. Działa to tylko dlatego, że dane nigdy nie płyną w górę ani w lewo.
źródło
f
naf(c,t,l)char*c,*t,*l
(nie przejmuj się typem zwrotu).f(c,t,l)char*c,*t,*l;
. Nie kompiluj w trybie C11, ponieważ niejawna reguła int, która pozwala nam upuścić typ zwracany, została usunięta w tej wersji.*l
? Kompiluje się w trybie C99 na moim komputerze.Python 2, 316 bajtów
Ta funkcja buduje 10 funkcji lambda kafelków, a następnie iteruje siatkę, aktualizując stany logiczne. Następnie drukowane są końcowe pionowe i poziome stany logiczne.
Nieskluczony kod zawierający testy:
test.txt
Pliku (w tym 2 innych testów według SP3000)Wyjście testowe:
źródło
Python 2,
384338325 bajtówPoważnie CH, jeśli to już nie jest zabawka, powinieneś zacząć dzwonić do niektórych fabryk zabawek.
Bardziej golfowi i znacznie mniej wydajni, ale wciąż nie dogonili CarpetPython. Dane wejściowe jak
f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010")
, wynik to krotka dwóch ciągów. Upewnij się jednak, że na planszy nie ma końcowego nowego wiersza, który to zepsuje.Program testowy
Możesz również przetestować wszystkie możliwe przypadki za pomocą
test_all()
.Dodatkowe przypadki testowe
Pół sumatora
Oto pół sumatora, który dodaje lewe górne bity, generując
<input bit> <carry> <sum>
:Testy:
Wyjście powinno być takie samo, nawet jeśli drugi / trzeci bit wejść zostanie zmieniony.
Prawa zmiana
Biorąc pod uwagę
abc / def
, wyniki tefab / cde
:Testy:
3-bitowy sortownik
Sortuje pierwsze trzy bity góry na ostatnie trzy bity dołu. Właściwe wyjście to śmieci.
Testy:
Mnożnik 2-bitowy na 2-bitowy
Traktuje pierwszy / drugi bit góry jako pierwszą liczbę, a trzeci / czwarty bit góry jako drugą liczbę. Wyjście do ostatnich czterech bitów dołu. Właściwe wyjście to śmieci.
Edycja: wyodrębniono kolumnę i dwa rzędy.
Testy:
źródło
R
524517Prawdopodobnie dużo miejsca na zmniejszenie tego w tej chwili, ale było to naprawdę interesujące. Istnieją dwie funkcje. Funkcja d jest pracownikiem, a f jest urządzeniem porównującym.
Funkcja d jest wywoływana z 3 ciągami znaków, bramkami, górnym i lewym. Bramy są umieszczane w matrycy określonej przez szerokość.
Trochę sformatowany
Niektóre testy
źródło