Golf wszystkie 16 bramek logicznych z 2 wejściami i 1 wyjściem!


63

Na przykład bramka A and Bjest bramką logiczną z 2 wejściami i 1 wyjściem.

Jest ich dokładnie 16, ponieważ:

  • każda bramka logiczna przyjmuje dwa wejścia, które mogą być zgodne z prawdą lub falsey, co daje nam 4 możliwe dane wejściowe
  • z 4 możliwych danych wejściowych każdy może mieć wartość true i falsey
  • dlatego istnieją 2 ^ 4 możliwe bramki logiczne, czyli 16.

Twoim zadaniem jest napisanie 16 programów / funkcji, które implementują je wszystkie osobno.

Twoje funkcje / programy muszą być niezależne .

Są one ważne, o ile generują wartości true / falsey, co oznacza, że ​​można zaimplementować A or Bw Pythonie jako lambda a,b:a+b, nawet jeśli 2jest produkowany dla A=Truei B=True.

Wynik to całkowita liczba bajtów użytych dla każdej funkcji / programu.

Lista bramek logicznych

  1. 0,0,0,0 ( false)
  2. 0,0,0,1 ( and)
  3. 0,0,1,0 ( A and not B)
  4. 0,0,1,1 ( A)
  5. 0,1,0,0 ( not A and B)
  6. 0,1,0,1 ( B)
  7. 0,1,1,0 ( xor)
  8. 0,1,1,1 ( or)
  9. 1,0,0,0 ( nor)
  10. 1,0,0,1 ( xnor)
  11. 1,0,1,0 ( not B)
  12. 1,0,1,1 ( B implies A)
  13. 1,1,0,0 ( not A)
  14. 1,1,0,1 ( A implies B)
  15. 1,1,1,0 ( nand)
  16. 1,1,1,1 ( true)

Tam gdzie pierwsza liczba to wynik A=false, B=false, druga liczba to wynik A=false, B=true, trzecia liczba to wynik A=true, B=false, a czwarta to wynik A=true, B=true.

Tabela liderów


2
Twoje funkcje / programy mogą współdzielić kod. Co to znaczy? Ponadto, czy programy mogą być w różnych językach?
Lynn

2
Wyjaśnienie uważam za mylące: „z 4 możliwych danych wejściowych, które każdy może mieć, i danych wyjściowych prawdy i fałszu”. Czy nie oznacza to 8 (4 * 2) stanów?
DavidC

4
Nazwiska, których brakuje, to bramki AND-NOT (A AND NOT B i B AND NOT A).
Mego

14
To się powtórzyło. Istnieje 18 odpowiedzi, w większości prostych i poprawnych, a potem znikąd pytanie stało się „niejasne, o co pytasz”. Nie podoba ci się wyzwanie, kontynuuj, weź kolejne, nie zamykaj go!
edc65

4
@dorukayhan Zobacz: próżna prawda
Sp3000

Odpowiedzi:


110

Domino , 122 000 bajtów lub 72 płytki

Liczba bajtów to rozmiar zapisanego pliku, który wynosi 0.122 MB.

Inspiracją było domino . Przetestowałem to wszystko do symetrii (i nie tylko!) Za pomocą gry Steam w wirtualnej rzeczywistości o nazwie Tabletop Simulator .

Detale

  • I / O
    • Start - jest to uwzględnione dla przejrzystości (nie wliczane do sumy) i jest tym, co „wywołuje” lub „wykonuje” funkcję. Należy „nacisnąć” po wprowadzeniu danych wejściowych [Żółty] .
    • Wejście A - Uwzględniono to dla jasności (nie wlicza się do sumy całkowitej) i jest ono „wciśnięte”, aby wskazać „a”, 1a inaczej nie wciśnięte [zielone] .
    • Wejście B - Zostało to uwzględnione dla przejrzystości (nie liczone do całkowitej) i jest „wciśnięte”, aby wskazać a, 1a w innym przypadku nie jest wciśnięte [niebieski] .
    • Wyjście - jest liczone do sumy. To domino deklaruje wynik bramki logicznej [Czarny] .
  • T / F
    • Spadające wyjście domina reprezentuje wynik Truelub1
    • Stojący domino wyjściowy reprezentuje wynik Falselub0
  • Groźny
    • Aby dać wkład lub uruchomić łańcuch, spawn metalowy marmur
    • Ustaw siłę podnoszenia na 100%
    • Podnieś marmur powyżej pożądanego domina
    • Upuść marmur

wprowadź opis zdjęcia tutaj

Bramy

  • false, 1
    • wprowadź opis zdjęcia tutaj
  • oraz 6 4
    • wprowadź opis zdjęcia tutaj
  • A, a nie B, 4 3
    • wprowadź opis zdjęcia tutaj
  • A, 1
    • wprowadź opis zdjęcia tutaj
  • nie A i B, 4 3
    • wprowadź opis zdjęcia tutaj
  • B, 1
    • wprowadź opis zdjęcia tutaj
  • Xor, 15 11
    • wprowadź opis zdjęcia tutaj
  • lub 1
    • wprowadź opis zdjęcia tutaj
  • ani 3 2
    • wprowadź opis zdjęcia tutaj
  • xnor, 17 13
    • wprowadź opis zdjęcia tutaj
  • nie B, 2
    • wprowadź opis zdjęcia tutaj
  • B oznacza A, 7 6
    • wprowadź opis zdjęcia tutaj
  • nie A, 2
    • wprowadź opis zdjęcia tutaj
  • A implikuje B, 7 6
    • wprowadź opis zdjęcia tutaj
  • nand, 16 15
    • wprowadź opis zdjęcia tutaj
    • prawda, 1
    • wprowadź opis zdjęcia tutaj

TL; DR

Czekałem / chciałem wyzwanie przyjazne domino, a kiedy to zobaczyłem, nie mogłem tego przegapić. Jedyny problem polegał na tym, że najwyraźniej nikt nie ma już domino! W końcu poddałem się i kupiłem Double Twelve . Ten zestaw ma 91 kafelków, co podsunęło mi pomysł posiadania „wywołania funkcji” / uruchomienia domina zamiast zwykłej (długiej) metody „opóźnienia czasowego”. Kredyt za obrót o 90 stopni należy do kanału dominoesdouble07 .

Po zbudowaniu ich z fizycznymi domino, na meta orzeczono, że prawidłowe rozwiązania powinny być cyfrowe. Więc odtworzyłem te bramy w Tabletop Simulator . Niestety, TS i rzeczywistość nie zgadzają się co do fizyki domina. Wymagało to dodania 11 domino, ale zapisałem również 8. Ogólnie rzecz biorąc, wirtualne domino są około x150 bardziej efektywne pod względem budowy i testowania ( Ctrl+ Z).

Aktualizacja

  • -9 [17-03-13] Skróconoxor xnor nand
  • [17-03-04] Dodano link do pliku warsztatu
  • +11 [17-03-03] Dodano cyfrowe xnorixor
  • -8 [17-03-03] Digitalizacja wszystkich bram (oprócz xori xnor). Blokowanie na Tabletop wymaga tylko 1 domina zamiast 2.
  • [16-09-23] Zmniejszone obrazy
  • -11 [16-09-18] Ponownie prawie pociął xor na pół. Dzięki @DJMcMayhem dla xnor i Joe dla xor.
  • -31 [16-08-31] Zaktualizowano kilka zdjęć, ogoliłem płytki i przeciąłem xor na pół
  • [16-08-28] Dodano zdjęcia

43
+1 Potrzebujemy więcej gry w domino na PPCG
Beta Decay


7
Łał. To jedna z najbardziej oryginalnych odpowiedzi, jakie kiedykolwiek widziałem na tej stronie.
DJMcMayhem

3
Wygląda na to, że możesz zdjąć jedno domino, jeśli ściśniesz xnor razem i masz 4 na górze, a nie 5. Z drugiej strony, wcale tego nie testowałem.
DJMcMayhem

2
Dziękujemy za poświęcenie czasu, aby uczynić to prawidłową odpowiedzią. Jednak link do pliku źródłowego jest nieco trudny do znalezienia. Zwykle link w nagłówku prowadzi do samego języka. Chciałbym więc połączyć ten link z grą Steam, a następnie umieścić link do rzeczywistego „pliku źródłowego” w osobnym, wyraźnie oznaczonym linku gdzieś w treści odpowiedzi.
Martin Ender,

45

Sześciokąt , 89 bajtów

Dziękujemy FryAmTheEggman za niezbędną inspirację dla rozwiązania XOR.

0000 !@
0001 ?.|@!
0010 #?#!)@
0011 ?!@
0100 +?|@!?
0101 ??!@
0110 ?<@!!<_\~(
0111 ?<<@!
1000 )\!#?@{
1001 (~?/@#!
1010 ??|@!)
1011 \#??!1@
1100 ?(~!@
1101 ?.|@!)
1110 ?$@#)!<
1111 1!@

Wszystkie programy używają wartości 0false i 1true.

Wypróbuj online! To nie jest zestaw testowy, musisz sam skopiować w różnych programach i danych wejściowych.

Powyższe rozwiązanie mieści się w granicach 2 bajtów optymalności (chyba, że ​​rozluźnimy interpretację prawdy / fałszu, jak sądzę). Pozwoliłem, by wyszukiwanie siłowe trwało prawie dwa dni we wszystkich programach, które pasują do długości 2, tj. Do 7 bajtów (nie do końca wszystkie programy - poczyniłem kilka założeń na temat tego, czego potrzebuje każdy prawidłowy program, a czego nie prawidłowy program może mieć). Wyszukiwanie znalazło rozwiązania dla 15 z 16 możliwych bramek - i często o wiele więcej niż tylko jednej. Możesz znaleźć listę wszystkich alternatywnych rozwiązań w tym pastebinie, gdzie pogrupowałem je według równoważnych zachowań. Te, które pokazuję powyżej, wybrałem, ponieważ są albo najprostszym, albo najciekawszym rozwiązaniem, i dodam je jutro.

Jeśli chodzi o 16. bramę: XOR jest jedyną bramą, która najwyraźniej nie może być zaimplementowana w 7 bajtach. Wyszukiwanie przy użyciu brutalnej siły nad większymi programami jest niestety niemożliwe przy użyciu kodu, który mam obecnie. Więc XOR musiał być napisany ręcznie. Najkrótszy, jaki do tej pory znalazłem, to powyższy 10-bajtowy program, który jest oparty na nieudanej (ale bardzo bliskiej) próbie FryAmTheEggman. Możliwe, że istnieje rozwiązanie 8-bajtowe lub 9-bajtowe, ale poza tym wszystkie rozwiązania powinny być rzeczywiście optymalne.

Objaśnienia

Ostrzeżenie: ściana tekstu. Na wszelki wypadek, gdy ktoś jest zainteresowany tym, jak działają te wysoce skompresowane programy Hexagony, zamieściłem objaśnienia do każdego z nich poniżej. Próbowałem wybrać najprostsze rozwiązanie dla każdej bramki w przypadkach, gdy istnieje więcej niż jeden optymalny program, aby wyjaśnienia były dość krótkie. Jednak niektóre z nich wciąż psują umysł, więc pomyślałem, że zasługują na nieco więcej rozwinięcia.

0000: Fałszywe

Nie sądzę, że potrzebujemy diagramu dla tego:

 ! @
. . .
 . .

Ponieważ cała siatka pamięci jest inicjowana na zera, !po prostu drukuje zero i @kończy działanie programu.

Jest to również jedyne rozwiązanie 2-bajtowe.

0001: I

 ? .
| @ !
 . .

To w zasadzie powoduje zwarcie . Szary schemat poniżej pokazuje początek programu, w którym czytane jest pierwsze wejście, ?a wskaźnik instrukcji (IP) otacza lewy róg, w którym |odbija go lustro. Teraz narożnik działa jako warunek, na przykład istnieją dwie różne ścieżki wykonania w zależności od wartości pierwszego wejścia. Czerwony schemat pokazuje przepływ sterowania dla, A = 0a zielony schemat dla A = 1:

ja ja ja

Jak widać, kiedy Ajest 0, to po prostu go drukujemy i kończymy (pamiętaj, że .nie ma żadnych operacji). Ale kiedy Ajest 1, adres IP ponownie przechodzi do pierwszego wiersza, Bzamiast tego odczytując i drukując.

W sumie dla tej bramki istnieje szesnaście 5-bajtowych rozwiązań. Czternaście z nich jest zasadniczo takich samych, jak powyższe, albo używając >zamiast, |albo zastępując .komendą, która faktycznie nie działa, lub umieszczając ?na drugiej pozycji:

?.|@!    .?|@!    ?=|@!    =?|@!    ?_|@!    _?|@!    ?0|@!
?.>@!    .?>@!    ?=>@!    =?>@!    ?_>@!    _?>@!    ?0>@!

A potem są dwa inne rozwiązania (które są sobie równoważne). Implementują one również tę samą logikę zwarć, ale ścieżki wykonania są nieco bardziej szalone (i pozostawione jako ćwiczenie dla czytelnika):

?<!@|
?<!@<

0010: A, a nie B

 # ?
# ! )
 @ .

Wprowadza to również formę zwarcia, ale ze względu na użycie #przepływu sterującego jest znacznie trudniejsze. #jest warunkowym przełącznikiem IP. Sześciokąty faktycznie ma sześć adresów IP oznaczonych 0na 5, które zaczynają się w sześciu rogach siatki, wskazując wzdłuż ich krawędzi zgodnej z ruchem wskazówek zegara (a program zawsze zaczyna się od IP 0). Gdy #napotkamy a, bieżąca wartość jest pobierana modulo 6, a przepływ sterowania jest kontynuowany z odpowiednim adresem IP. Nie jestem pewien, jaki przypływ szaleństwa zmusił mnie do dodania tej funkcji, ale na pewno pozwala ona na niektóre zaskakujące programy (takie jak ten).

Rozróżnimy trzy przypadki. Gdy A = 0program jest dość prosty, ponieważ wartość jest zawsze 0, kiedy #jest taka, że nie napotkał IP przełączanie odbywa się:

ja

#nic nie robi, ?czyta A(tzn. też nic nie robi), #nadal nic nie robi, !drukuje 0, )inkrementuje to (jest to ważne, w przeciwnym razie IP nie przeskakuje do trzeciej linii), @kończy działanie programu. Wystarczająco proste. Rozważmy teraz przypadek (A, B) = (1, 0):

ja

Czerwona ścieżka nadal odpowiada IP 0, a ja dodałem zieloną ścieżkę dla IP 1. Widzimy, że po ?odczytach A( 1tym razem) #przełącza się na adres IP, który zaczyna się w prawym górnym rogu. Oznacza to, że ?można przeczytać B( 0). Teraz )zwiększa to 1, aby #w lewym górnym rogu nic nie robi i pozostajemy z IP 1. W !drukuje 1i OD otacza lewy przekątnej. #nadal nic nie robi i @kończy działanie programu.

Wreszcie, naprawdę dziwny przypadek, w którym oba dane wejściowe to 1:

ja

Tym razem, drugie wejście jest również 1i )powiększa go 2. Oznacza to, że #w lewym górnym rogu powoduje kolejną zmianę adresu IP na IP 2, oznaczoną kolorem niebieskim. Na tej ścieżce najpierw zwiększamy ją 3(choć nie ma to znaczenia), a następnie przechodzimy ?po raz trzeci. Ponieważ mamy teraz wciśnięty EOF (tzn. Dane wejściowe są wyczerpane), ?zwraca 0, !drukuje to i @kończy działanie programu.

Warto zauważyć, że jest to jedyne 6-bajtowe rozwiązanie dla tej bramki.

0011: A

 ? !
@ . .
 . .

Jest to na tyle proste, że nie potrzebujemy diagramu: ?odczytuje A, !drukuje go, @kończy.

Jest to jedyne 3-bajtowe rozwiązanie dla tej bramki. (Zasadniczo byłoby to również możliwe ,;@, ale wyszukiwanie nie obejmowało ;, ponieważ nie sądzę, że może kiedykolwiek zaoszczędzić bajty !dla tego zadania).

0100: B, a nie A

 + ?
| @ !
 ? .

Ten jest o wiele prostszy niż jego „brat” 0010. Przepływ sterowania jest w rzeczywistości taki sam, jak widzieliśmy powyżej dla 0001(I). Jeśli A = 0, to IP przechodzi przez dolną linię, odczytując Bi drukując ją przed zakończeniem. Jeśli A = 1następnie IP ponownie przechodzi do pierwszego wiersza, również odczytuje B, ale +dodaje dwie nieużywane krawędzie pamięci, więc wszystko, co robi, to resetuje bieżącą wartość do 0, aby !zawsze drukować 0.

Istnieje całkiem sporo 6-bajtowych alternatyw (w sumie 42). Po pierwsze, istnieje mnóstwo rozwiązań równoważnych powyższym. Możemy ponownie swobodnie wybierać między |i >, i +możemy je zastąpić dowolnym innym poleceniem, które daje nam pustą przewagę:

"?|@!?    &?|@!?    '?|@!?    *?|@!?    +?|@!?    -?|@!?    ^?|@!?    {?|@!?    }?|@!?
"?>@!?    &?>@!?    '?>@!?    *?>@!?    +?>@!?    -?>@!?    ^?>@!?    {?>@!?    }?>@!?

Ponadto możemy również użyć ]zamiast ?. ]przenosi do następnego adresu IP (tzn. wybiera adres IP 1), dzięki czemu gałąź ta zamiast tego ponownie wykorzystuje ?w prawym górnym rogu. To daje kolejne 18 rozwiązań:

"?|@!]    &?|@!]    '?|@!]    *?|@!]    +?|@!]    -?|@!]    ^?|@!]    {?|@!]    }?|@!]
"?>@!]    &?>@!]    '?>@!]    *?>@!]    +?>@!]    -?>@!]    ^?>@!]    {?>@!]    }?>@!]

I jest jeszcze sześć innych rozwiązań, które działają inaczej z różnym poziomem szaleństwa:

/[<@!?    ?(#!@]    ?(#>@!    ?/@#/!    [<<@!?    [@$\!?

0101: B

 ? ?
! @ .
 . .

Woohoo, kolejny prosty: czytaj A, czytaj B, drukuj B, zakończ. Istnieją jednak alternatywy dla tego. Ponieważ Ajest to tylko jeden znak, możemy go również odczytać za pomocą ,:

,?!@

Istnieje również opcja użycia pojedynczego ?i dwukrotnego uruchomienia lustra:

?|@!    ?>@!

0110: Xor

  ? < @
 ! ! < _
\ ~ ( . .
 . . . .
  . . .

Jak powiedziałem powyżej, była to jedyna brama, która nie zmieściłaby się w boku o długości 2, więc jest to odręczne rozwiązanie FryAmTheEggman i mnie, i istnieje duża szansa, że ​​nie jest optymalna. Istnieją dwa przypadki do rozróżnienia. Jeśli A = 0przepływ kontrolny jest dość prosty (ponieważ w takim przypadku wystarczy wydrukować B):

ja

Zaczynamy czerwoną ścieżką. ?czyta A, <to gałąź, która odchyla zero w lewo. IP zawija się w dół, a następnie _jest kolejnym lustrem, a kiedy IP uderza w narożnik, zawija się w lewym górnym rogu i kontynuuje na niebieskiej ścieżce. ?czyta B, !drukuje. Teraz (to zmniejsza. Jest to ważne, ponieważ zapewnia, że ​​wartość nie będzie dodatnia (ani jedna, 0ani -1teraz). To powoduje, że IP zawija się w prawy róg, gdzie @kończy program.

Kiedy A = 1sprawy stają się trochę trudniejsze. W takim przypadku chcemy wydrukować not B, co samo w sobie nie jest zbyt trudne, ale ścieżka wykonania jest nieco trippy.

ja

Tym razem <odchyla adres IP w prawo, a następnie <działa jak lustro. Tak więc IP przemierza tę samą ścieżkę w odwrotnej kolejności, czytając, Bgdy napotka ?ponownie. Adres IP zawija się w prawym rogu i kontynuuje zieloną ścieżkę. Również kolejne spotkania (~, która jest „dekrementuj mnożenie przez -1”, który swapy 0i 1i oblicza zatem not B. \jest tylko lustrem i !drukuje pożądany rezultat. Następnie ?próbuje zwrócić inną liczbę, ale zwraca zero. Adres IP jest teraz kontynuowany w lewym dolnym rogu na niebieskiej ścieżce. (zmniejsza, <odzwierciedla,(ponownie się zmniejsza, tak że bieżąca wartość jest ujemna, gdy IP uderza w narożnik. Porusza się po prawej dolnej przekątnej, a następnie w końcu uderza, @aby zakończyć program.

0111: Lub

 ? <
< @ !
 . .

Więcej zwarć.

ja ja

A = 0Przypadek (czerwona ścieżka) jest nieco mylące tutaj. Adres IP jest odchylany w lewo, zawija się do lewego dolnego rogu, natychmiast jest odzwierciedlany przez <i wraca ?do odczytu B. Następnie zawija do rigt rogu, drukuje Bsię !i kończy.

Obudowa A = 1(zielona ścieżka) jest nieco prostsza. <Gałąź ugina IP rację, więc po prostu wydrukować !, zawinąć z powrotem do góry po lewej, a kończą się @.

Jest tylko jedno 5-bajtowe rozwiązanie:

\>?@!

Działa zasadniczo tak samo, ale rzeczywiste ścieżki wykonania są zupełnie inne i używa rozgałęzienia zamiast rozgałęzienia <.

1000: Nor

 ) \
! # ?
 @ {

To może być mój ulubiony program znaleziony podczas tego wyszukiwania. Najfajniejsze jest to, że ta implementacja norfaktycznie działa dla maksymalnie 5 wejść. Będę musiał trochę zagłębić się w szczegóły modelu pamięci, aby to wyjaśnić. Tak więc, jako szybki odświeżacz, model pamięci Hexagony jest oddzielną heksagonalną siatką, w której każda krawędź zawiera wartość całkowitą (początkowo wszystkie zero). Istnieje wskaźnik pamięci (MP), który wskazuje krawędź i kierunek wzdłuż tej krawędzi (tak, że przed i za bieżącą krawędzią znajdują się dwie sąsiednie krawędzie, z wyraźnymi lewymi i prawymi sąsiadami). Oto schemat krawędzi, których będziemy używać, a MP zacznie się jak pokazano na czerwono:

ja

Rozważmy najpierw przypadek, w którym oba dane wejściowe to 0:

ja

Zaczynamy od szarej ścieżki, która po prostu zwiększa krawędź A do, 1tak aby #przełącza się na IP, 1która jest niebieską ścieżką, zaczynając od prawego górnego rogu. \nic tam nie robi i ?czyta dane wejściowe. Zawijamy do lewego górnego rogu, gdzie )inkrementuje to wejście. Teraz, dopóki dane wejściowe są równe zero, spowoduje to 1, że #nic nie zrobi. Następnie {przesuwa MP w lewo, czyli na pierwszej iteracji z do B . Ponieważ ta krawędź wciąż ma swoje początkowe zero, IP zawija się z powrotem w prawy górny róg i na nowej krawędzi pamięci. Tak więc ta pętla będzie kontynuowana tak długo, jak odczyta zera, przesuwając MP wokół sześciokąta od B?do C do D i tak dalej. Nie ma znaczenia, czy ?zwraca zero, ponieważ było to dane wejściowe, czy dlatego, że było to EOF.

Po sześciu powtórzeń przez tę pętlę, {powraca do . Tym razem krawędź przechowuje już wartość z pierwszej iteracji, więc IP zawija się do lewego rogu i kontynuuje na zielonej ścieżce. po prostu drukuje to i kończy program.1!1@

A co jeśli jakieś dane wejściowe są 1?

ja

Następnie ?czyta to 1w pewnym momencie i )zwiększa to 2. Oznacza to, #że teraz zmieni ponownie adresy IP i będziemy kontynuować w prawym rogu na czerwonej ścieżce. ?odczytuje kolejne dane wejściowe (jeśli takie są), które tak naprawdę nie mają znaczenia i {przesuwa się o jedną krawędź dalej. To musi być niewykorzystane zbocze, dlatego działa dla maksymalnie 5 wejść. Adres IP zawija się w prawym górnym rogu, gdzie jest natychmiast odbijany i zawija się w lewym rogu. !drukuje 0nieużywaną krawędź i #przełącza z powrotem na IP 0. To IP wciąż czekało na #południowo-zachodniej (szara ścieżka), więc natychmiast trafia @i kończy program.

W sumie dla tej bramki istnieje siedem 7-bajtowych rozwiązań. 5 z nich działa tak samo jak to i po prostu użyj innych poleceń, aby przejść do nieużywanej krawędzi (i może chodzić po innym sześciokącie lub w innym kierunku):

)\!#?@"    )\!#?@'    )\!#?@^    )\!#?@{    )\!#?@}

Jest jeszcze jedna klasa rozwiązań, która działa tylko z dwoma danymi wejściowymi, ale których ścieżki wykonania są w rzeczywistości jeszcze bardziej bałagan:

?]!|<)@    ?]!|<1@

1001: Równość

 ( ~
? / @
 # !

To również bardzo sprytnie wykorzystuje warunkowy wybór adresu IP. Musimy ponownie rozróżnić między A = 0i A = 1. W pierwszym przypadku chcemy wydrukować not B, w drugim chcemy wydrukować B. Dla A = 0nas również rozróżnić dwa przypadki dla B. Zacznijmy od A = B = 0:

ja

Zaczynamy na szarej ścieżce. (~można zignorować, IP zawija się w lewym rogu (wciąż na szarej ścieżce) i czyta za Apomocą ?. (zmniejsza to, więc otrzymujemy -1i IP zawijamy do lewego dolnego rogu. Teraz, jak powiedziałem wcześniej, #bierze wartość modulo 6przed wyborem jego IP, więc wartość -1faktycznie wychodzi z IP 5, która zaczyna się w lewym rogu na czerwonej ścieżce. ?czyta B, również to (zmniejsza, abyśmy pozostali na IP, 5kiedy uderzymy #ponownie. ~neguje -1tak, że IP zawija się w prawym dolnym rogu, drukuje 1i kończy.

ja

Teraz, jeśli Bjest 1, obecna wartość będzie, 0gdy uderzymy #drugi raz, więc przełączamy się z powrotem na IP 0(teraz na zielonej ścieżce). To uderza ?po raz trzeci, ustępując 0, !drukuje i @kończy.

ja

Wreszcie przypadek, w którym A = 1. Tym razem obecna wartość jest już zerowa, gdy uderzamy #po raz pierwszy, więc nigdy nie przełącza się ona na IP 5. Po prostu kontynuujemy natychmiast zieloną ścieżkę. ?teraz nie tylko podaje zero, ale zwraca B. !drukuje i @kończy ponownie.

W sumie istnieją trzy 7-bajtowe rozwiązania dla tej bramki. Pozostałe dwa działają bardzo odmiennie (nawet od siebie) i jeszcze dziwniej je wykorzystują #. W szczególności odczytują jedną lub więcej wartości za pomocą ,(odczytuje kod znakowy zamiast liczby całkowitej), a następnie używają tej wartości modulo 6, aby wybrać adres IP. To całkiem szalone.

),)#?@!

?~#,~!@

1010: Nie b

 ? ?
| @ !
 ) .

Ten jest dość prosty. Ścieżka wykonania jest gałęzią poziomą, którą znamy andwcześniej. ??czyta, Aa potem natychmiast B. Po odbiciu |i rozgałęzieniu B = 0wykonamy dolną gałąź, w której )zwiększa się wartość, do 1której jest następnie drukowany !. Na górnej gałęzi (jeśli B = 1) po ?prostu zresetuj krawędź, do 0której jest następnie drukowane !.

Istnieje osiem 6-bajtowych programów dla tej bramki. Cztery z nich są prawie takie same, używając albo >zamiast |albo 1zamiast )(lub obu):

??>@!)    ??>@!1    ??|@!)    ??|@!1

Dwa używają jednego, ?który jest używany dwa razy z powodu lustra. Negacja dzieje się wtedy tak, jak w xorprzypadku jednego z nich (~lub ~).

?>!)~@    ?>!~(@

I na koniec, dwa rozwiązania używają warunkowego przełącznika IP, ponieważ po co korzystać z prostego sposobu, jeśli zawiłe również działa:

??#)!@    ??#1!@

1011: B oznacza A

 \ #
? ? !
 1 @

Wykorzystuje to dość skomplikowane przełączanie adresów IP. A = 1Tym razem zacznę od przypadku, ponieważ jest to prostsze:

wprowadź opis zdjęcia tutaj

Zaczynamy na szarym drogi, który odczytuje Az ?czym uderza #. Ponieważ Ajest 1to przełącza się na IP 1(zielona ścieżka). !Natychmiast drukuje, że IP zawija się w lewym górnym rogu, czyta B(niepotrzebnie) i kończy.

Kiedy A = 0sprawy stają się bardziej interesujące. Najpierw zastanówmy się A = B = 0:

wprowadź opis zdjęcia tutaj

Tym razem #nic nie robi i pozostajemy na IP 0(czerwona ścieżka od tego momentu). ?czyta Bi 1zamienia go w 1. Po owinięciu w lewym górnym rogu, uderzamy #ponownie, więc ostatecznie trafiamy na zieloną ścieżkę i drukujemy 1jak poprzednio, przed zakończeniem.

Wreszcie, oto (A, B) = (0, 1)fałszywy przypadek:

wprowadź opis zdjęcia tutaj

Zauważ, że usunąłem początkową szarą ścieżkę dla przejrzystości, ale program zaczyna się w ten sam sposób i kończymy na czerwonej ścieżce jak poprzednio. Tym razem drugi ?powraca 1. Teraz spotykamy 1. W tym momencie ważne jest, aby zrozumieć, co faktycznie robią cyfry w Heksagonii (do tej pory używaliśmy ich tylko na zerach): gdy napotkasz cyfrę, bieżąca wartość zostanie pomnożona przez 10, a następnie cyfra zostanie dodana. Zwykle jest to używane do zapisywania liczb dziesiętnych dosłownie w kodzie źródłowym, ale oznacza to, że B = 1faktycznie jest odwzorowane na wartość 11. Więc kiedy trafiliśmy #, to jest brane modulo 6do orzekania 5, a więc możemy przejść do IP 5(zamiast 1, jak poprzednio) i dalej na niebieskiej ścieżce. Uderzenie?trzeci raz zwraca zero, więc !drukuje to, a po kolejnych dwóch ?IP zawija się w dolnym prawym rogu, gdzie kończy się program.

Istnieją cztery 7-bajtowe rozwiązania tego problemu i wszystkie działają inaczej:

#)/!?@$    <!?_@#1    \#??!1@    |/)#?@!

1100: Nie A

 ? (
~ ! @
 . .

Wystarczy jeden prosty liniowy: czytaj Az ?, neguje się (~, drukować !, kończą się @.

Istnieje jedno alternatywne rozwiązanie, a ~)zamiast tego neguje się :

?~)!@

1101: A oznacza B

 ? .
| @ !
 ) .

Jest to o wiele prostsze niż przeciwna implikacja, o której właśnie mówiliśmy. To znowu jeden z tych horyzontalnych programów branżowych, jak ten dla and. Jeśli Atak 0, po prostu zwiększa się 1na dolnej gałęzi i drukuje. W przeciwnym razie górna gałąź jest wykonywana ponownie tam, gdzie ?czyta, Ba następnie ją !drukuje.

Jest tu mnóstwo alternatyw (w sumie 66 rozwiązań), głównie ze względu na swobodny wybór skutecznych no-opów. Na początek możemy zmieniać powyższe rozwiązanie we wszystkich taki sam sposób moglibyśmy za andi możemy również wybierać pomiędzy )i 1:

?.|@!)    .?|@!)    ?=|@!)    =?|@!)    ?_|@!)    _?|@!)    ?0|@!)
?.|@!1    .?|@!1    ?=|@!1    =?|@!1    ?_|@!1    _?|@!1    ?0|@!1
?.>@!)    .?>@!)    ?=>@!)    =?>@!)    ?_>@!)    _?>@!)    ?0>@!)
?.>@!1    .?>@!1    ?=>@!1    =?>@!1    ?_>@!1    _?>@!1    ?0>@!1

A potem jest inna wersja wykorzystująca warunkowy wybór adresu IP, w którym pierwsze polecenie można wybrać prawie arbitralnie, a także istnieje wybór pomiędzy )i 1dla niektórych z tych opcji:

"?#1!@    &?#1!@    '?#1!@    )?#1!@    *?#1!@    +?#1!@    -?#1!@    .?#1!@    
0?#1!@    1?#1!@    2?#1!@    3?#1!@    4?#1!@    5?#1!@    6?#1!@    7?#1!@    
8?#1!@    9?#1!@    =?#1!@    ^?#1!@    _?#1!@    {?#1!@    }?#1!@

"?#)!@    &?#)!@    '?#)!@              *?#)!@    +?#)!@    -?#)!@    
0?#)!@              2?#)!@              4?#)!@              6?#)!@    
8?#)!@                        ^?#)!@    _?#)!@    {?#)!@    }?#)!@

1110: Nand

 ? $
@ # )
 ! <

Ostatni skomplikowany. Jeśli nadal czytasz, prawie to zrobiłeś. :) Spójrzmy A = 0najpierw:

wprowadź opis zdjęcia tutaj

?czyta, Aa potem trafiamy $. Jest to polecenie skoku (takie jak Befunge #), które pomija kolejną instrukcję, abyśmy nie zakończyli na @. Zamiast tego adres IP jest kontynuowany w #. Jednak ponieważ Aznaczy 0, to nie robi nic. )zwiększa ją, aby 1adres IP był kontynuowany na dolnej ścieżce, w której 1drukowany jest. W <odchyla IP w prawo, gdzie owija się w lewym rogu i program kończy.

Następnie, gdy dane wejściowe są (A, B) = (1, 0), otrzymujemy tę sytuację:

wprowadź opis zdjęcia tutaj

Jest to w zasadzie takie same jak przed tą różnicą, że u #nas włączyć do OD 1(zielony ścieżka), ale ponieważ Bjest 0nam wrócić do OD 0, kiedy uderzył #po raz drugi (teraz niebieski ścieżki), gdzie drukuje 1jak poprzednio.

Wreszcie A = B = 1sprawa:

wprowadź opis zdjęcia tutaj

Tym razem, gdy my #po raz drugi, bieżąca wartość jest nadal 1, abyśmy nie zmienili IP ponownie. <Odzwierciedla to i trzeci raz trafiliśmy ?otrzymujemy zero. Dlatego IP zawija się w lewym dolnym rogu, gdzie !wypisuje zero i program się kończy.

Łącznie jest na to dziewięć 7-bajtowych rozwiązań. Pierwsza alternatywa po prostu używa 1zamiast ):

?$@#1!<

Są też dwa rozwiązania, które pozwolą ci zmierzyć się z ilością przełączanych adresów IP:

)?#_[!@    1?#_[!@

To naprawdę zadziwiło mnie: interesującą częścią jest to, że przełączanie adresów IP może być używane jako odroczony warunek. Reguły przełączania adresów IP w języku są takie, że bieżący adres IP robi kolejny krok przed przełączeniem. Jeśli ten krok zdarzy się przejść przez róg, to bieżąca wartość decyduje o tym, w której gałęzi adres IP będzie kontynuowany, jeśli kiedykolwiek wrócimy do niego. Dokładnie dzieje się tak, gdy wejście jest A = B = 1. Chociaż wszystko to jest spójne z tym, jak zaprojektowałem język, nigdy nie zdawałem sobie sprawy z tego wpływu specyfikacji, więc miło jest, gdy mój język uczy mnie nowych sztuczek: D.

Jest też trzecie rozwiązanie, którego przełączanie adresów IP jest jeszcze gorsze (chociaż nie wykorzystuje tego odroczonego efektu warunkowego):

>?1]#!@

A potem jeszcze jeden:

?$@#)!<

A potem są te cztery równoważne rozwiązania, które wykorzystują pewne bezwarunkowe przełączanie adresów IP i zamiast tego implementują całą logikę za pośrednictwem gałęzi i narożników:

]<?<@!)    ]<?<@!1    ]|?<@!)    ]|?<@!1

1111: Prawdziwe

 1 !
@ . .
 . .

Na koniec zasłużyłeś sobie na coś prostego: ustaw krawędź na 1, drukuj !, zakończ z @. :)

Oczywiście istnieje jedna alternatywa:

)!@

Jak zwykle wszystkie diagramy kontrolne utworzone za pomocą HexagonyColorer Timwi i diagram pamięci z jego EsotericIDE .


9
Aaaaa i tl; dr nagroda idzie do ... (żartuje oczywiście, świetna odpowiedź i bardzo dobrze napisana, +1)
Bassdrop Cumberwubwubwub

4
To jest powód, dla którego nie jesteś już aktywny na czacie?
Optymalizator

Trochę późno, ale czy możesz dodać link do kodu brutalnej siły?
nedla2004

@ nedla2004 Zwykle ich nie trzymam, ale zawsze jest to zmodyfikowana wersja tego skryptu .
Martin Ender

40

APL, 22 20 18 bajtów

Prawda i fałsz to kompletne programy, a pozostałe 14 to funkcje. (Dzięki Adám.)

0000 false              0 (complete program)
0001 p and q            ∧
0010 p and not q        >
0011 p                  ⊣
0100 not p and q        <
0101 q                  ⊢
0110 xor                ≠
0111 p or q             ∨
1000 not p and not q    ⍱
1001 eq                 =
1010 not q              ~⊢
1011 p or not q         ≥
1100 not p              ~⊣
1101 not p or q         ≤
1110 not p or not q     ⍲
1111 true               1 (complete program)

Wypróbuj tutaj.


1
+1 Ładne wykorzystanie atops! Możesz zapisać dwa bajty, zmieniając 0000 i 1111 w trad-fns 0i 1.
Adám

Istnieje zgoda, aby zezwolić na tfns, ale nie liczyć pierwszej linii. Odpowiada to nie liczeniu nazwy pliku w językach, w których pliki są używane jako kontenery programu z nazwą programu = nazwa pliku.
Adám


10
Galaretka: 19 bajtów. To: 18 bajtów. Czy to nie znaczy, że wygraliście Dennisa ? +1 za to.
NoOneIsHere

29

Szachy / mierny szachista w grze końcowej, 70 sztuk

Zainspirowany odpowiedzią domina, zdecydowałem, że kolejna gra powinna mieć ten zaszczyt.

Pamiętaj, że wziąłem kilka zasad dotyczących ruchu elementów. Ponieważ nie mam ochoty studiować optymalnych ruchów w każdej sytuacji, zasady dotyczące białych ruchów są proste: trzymaj się z daleka, złap najwyższy kawałek, który może obrócić, tracąc jednocześnie jak najmniej materiału i zatrzymaj pionka od promowania, w tej kolejności pierwszeństwa. Jeśli są dwa pola, na które może się poruszać, z równą uprzywilejowaniem, może przejść do jednego z nich (stąd na nich, jeśli może przejść do więcej niż jednego kwadratu, mają ten sam kolor). Zauważ, że biały złapie coś, nawet jeśli zostanie złapany, jeśli atakowany element ma większą wartość niż utracony. Wartości są tutaj:pawn<knight=bishop<rook<queen

Dane wejściowe określają, czy wieża jest obecna, czy nie. Zauważ, że wieże są oznaczone tylko nazwami A i B, gdy ma to znaczenie: jeśli brama zachowuje się tak samo, gdy wieże są przełączane, nie są one oznaczone.

Wyjście ma kolor kwadratowego białego króla, który kończy się na: Biały = 1, czarny = 0

Przed zdjęciami chcę przeprosić za słabe obrazy. Nie jestem zbyt dobry w trzymaniu aparatu nieruchomo.

Fałsz, 4:

Fałszywe

ORAZ 4:

wprowadź opis zdjęcia tutaj

A, a nie B, 5 (myślę, że mogę sprowadzić to do trzech, ale nie mam teraz wyżywienia):

wprowadź opis zdjęcia tutaj

A, 4:

wprowadź opis zdjęcia tutaj

Nie A i B, 5 (myślę, że mogę sprowadzić to do trzech, ale nie mam teraz wyżywienia):

wprowadź opis zdjęcia tutaj

B, 4:

wprowadź opis zdjęcia tutaj

Xor, 5 (znam sposób, aby zrobić 4, ale nie mam teraz planszy):

wprowadź opis zdjęcia tutaj

Lub 4:

wprowadź opis zdjęcia tutaj

Ani 4:

wprowadź opis zdjęcia tutaj

Xnor, 5 (Znam sposób, aby zrobić 4, ale nie mam teraz planszy):

wprowadź opis zdjęcia tutaj

Nie B, 4:

wprowadź opis zdjęcia tutaj

B oznacza A, 5 (myślę, że mogę sprowadzić to do trzech, ale nie mam w tej chwili wyżywienia):

wprowadź opis zdjęcia tutaj

Nie A, 4:

wprowadź opis zdjęcia tutaj

A implikuje B, 5 (myślę, że mogę sprowadzić to do trzech, ale nie mam teraz wyżywienia):

wprowadź opis zdjęcia tutaj

Nand, 4:

wprowadź opis zdjęcia tutaj

Prawda 4:

wprowadź opis zdjęcia tutaj


1
Wow, nie miałem pojęcia, że ​​programowanie w szachach jest możliwe ... Czy możesz zamieścić wideo / symulację kilku z nich w akcji?
Beta Decay

2
hmmm, obecnie nie mam dostępu do szachownicy. Prawdopodobnie powiedziałbym, że A oznacza, że ​​B / B oznacza, że ​​A / itp. Są najtrudniejsze do zrozumienia ze względu na wpływ pionków na ruch królów. Prawdopodobnie powinienem dodać lepsze wyjaśnienie tych dwóch
Destructible Lemon

Cieszę się, że inspiruję: D Jeśli dobrze rozumiem, położenie planszy i elementów jest równoważne z programem. Wieże są wkładem, więc mogę umieścić je na dowolnym kwadracie, o ile ma odpowiedni kolor?
NielinioweOwoce

Nie, wejście wież polega na tym, czy są one obecne, czy nieobecne na planszy. Są oznaczone a i b, gdy nie są bramkami symetrycznymi (gdy ma to znaczenie dla różnych a i b). Uświadomiłem sobie również, jak mogę grać w golfa z 2 elementów, ale nie mam teraz planszy. Pędzel musi zostać użyty :)
Destructible Lemon

W przypadku „I”, jeśli usuniesz prawą wieżę, co powstrzymuje króla przed zejściem w dół (do białego)?
Nathan Merrill,

27

Galaretka , 19 bajtów

0 0 0 0 ¤  1 byte  Empty niladic chain. Returns default argument 0.
0 0 0 1 &  1 byte  Bitwise AND.
0 0 1 0 >  1 byte  Greater than.
0 0 1 1    0 bytes Empty link. Returns left argument.
0 1 0 0 <  1 byte  Less than.
0 1 0 1 ị  1 byte  At-index (x,y -> [y][x]). Returns right argument.
0 1 1 0 ^  1 byte  Bitwise XOR.
0 1 1 1 |  1 byte  Bitwise OR.
1 0 0 0 |¬ 2 byte  Logical NOT of bitwise OR.
1 0 0 1 =  1 byte  Equals.
1 0 1 0 ¬} 2 bytes Logical NOT of right argument.
1 0 1 1 *  1 byte  Exponentiation.
1 1 0 0 ¬  1 byte  Logical NOT of left argument.
1 1 0 1 >¬ 2 bytes Logical NOT of greater than.
1 1 1 0 &¬ 2 bytes Logical NOT of bitwise AND.
1 1 1 1 !  1 byte  Factorial.

Wypróbuj online!


13
Uwielbiam używać Factorial do konwertowania 0 lub 1 na 1.
Neil

Czy Jelly UTF-8? Jeśli tak, to ¤i ¬są 2 bajty, a nie 1.
VI.

1
@Vi. Galaretka obsługuje UTF-8, ale obsługuje także niestandardową stronę kodową, która koduje każdy z 256 znaków, które rozumie jako pojedynczy bajt. Te bajty odwołuje się w punktach głowicy do niego.
Dennis

0 0 1 0 > 1 byte Greater than.czy to nie zawiedzie, jeśli drugie wejście będzie ujemne?
MD XF,

@MFXF Możemy wybrać, którą wartość prawdy i jaką wartość fałszowania popieramy.
Dennis

24

Bramy logiczne NAND - 31 bramek

Jako twórcy oryginalnej serii z NAND bramy pytania , nie mogłem przepuścić okazji do korzystania z tych bram rozwiązać inny problem logika bramy.

wprowadź opis zdjęcia tutaj

Na każdym z tych schematów górne wejście to A, a dolne wejście to B.


5
@xnor może pochlebiać, wiedząc, że jego brama logiczna wymaga takich bram NAND, aby D:
Joe Z.

Czy możesz przynajmniej użyć Logisim do sformatowania kodu?
mbomb007

1
@ mbomb007 Zmienię to później. Nie mam takiego doświadczenia z Logisim, więc może to chwilę potrwać.
Joe Z.

3
Ale bardziej lubię pismo ręczne.
Leaky Nun

1
Ewentualnie można przełączyć się ani bramy i sformatować go przy użyciu Redstone ...
jimmy23013

22

Bitowy cykliczny znacznik , 118 bitów = 14,75 bajtów

Bitowy cykliczny tag jest prawdopodobnie najprostszym językiem Turinga, jaki kiedykolwiek wymyślono. Istnieje taśma programowa i taśma danych, obie składające się z listy bitów. Taśma programu jest interpretowana cyklicznie, dopóki taśma danych nie będzie pusta, w następujący sposób:

  • 0: usuń pierwszy bit z taśmy danych.
  • 1x: jeśli pierwszy bit taśmy danych ma wartość 1, dołącz bit xdo taśmy danych.

Inicjalizujemy taśmę danych za pomocą 1, po której następują dwa bity wejściowe (1 jest konieczne, ponieważ nie ma możliwości utworzenia 1, jeśli taśma danych składa się w całości z 0) i używamy końcowego usuniętego bitu danych jako wyjścia bramki .

  • 0,0,0,0 ( false):001
  • 0,0,0,1 ( and):1001001
  • 0,0,1,0 ( A and not B):0110100
  • 0,0,1,1 ( A):1001
  • 0,1,0,0 ( not A and B):0100
  • 0,1,0,1 ( B):0
  • 0,1,1,0 ( xor):0110110010
  • 0,1,1,1 ( or):0110
  • 1,0,0,0 ( nor):1101001000
  • 1,0,0,1 ( xnor):110101001100
  • 1,0,1,0 ( not B):1100100
  • 1,0,1,1 ( B implies A):110101101000
  • 1,1,0,0 ( not A):11010000
  • 1,1,0,1 ( A implies B):11010011001
  • 1,1,1,0 ( nand):10110100100010
  • 1,1,1,1 ( true):1100

Gratulacje!
Leaky Nun

Czy spływu 1na falsewymagane?
CalculatorFeline,

@CalculatorFeline Tak, musimy dołączyć a 0do taśmy, aby można ją było usunąć jako ostatnią.
Anders Kaseorg,

Ach Zapomniałem o tym + pakowaniu. Sprytny!
CalculatorFeline

20

Python 2, 137 bajtów

[].sort
min
int.__rshift__
round
range
{}.get
cmp
max
lambda a,b:a<1>b
lambda a,b:a==b
lambda a,b:b<1
pow
{0:1,1:0}.get
{0:1}.get
lambda a,b:a+b<2
slice

Pobiera dane wejściowe takie jak min(True,False)(lub jako min(1,0)). Ma dużą przewagę nad wyjściami, które muszą mieć tylko odpowiednią wartość Truthy-Falsey. O ile to możliwe, wykorzystuje wbudowany system, aby uniknąć kosztowności lambda. Użyłem kodu, aby wyszukać wbudowane działające.

Moim ulubionym jest to {0:1}.get, o czym myślałem ręcznie. Słownik {0:1}mapuje klucz 0na wartość 1. Ta getmetoda przyjmuje klucz i domyślną wartość wyjściową odpowiadającą kluczowi lub wartość domyślną, jeśli nie ma takiego klucza. Zatem jedynym sposobem na wyprowadzenie a 0jest as {0:1}.get(1,0), z brakującym kluczem 1i wartością domyślną 0. Można uzyskać inne warianty z różnymi słownikami, ale tylko ten był najkrótszy.

built_in_names = list(__builtins__) 

object_names = ["int","(0)","(1)"] + \
["True","False","0L","1L","0j","1j"] + \
["str", "''", "'0'","'1'","'a'"] + \
["list", "[]", "[0]", "[1]","['']","[[]]","[{}]"] + \
["set","set()","{0}","{1}","{''}"] + \
["dict","{}","{0:0}","{0:1}","{1:0}","{1:1}","{0:0,1:0}", "{0:0,1:1}","{0:1,1:0}","{0:1,1:1}"] + \
["id"]

object_method_names = [object_name+"."+method_name 
for object_name in object_names 
for method_name in dir(eval(object_name))]

additional_func_names = [
"lambda a,b:0",
"lambda a,b:1",
"lambda a,b:a",
"lambda a,b:b",
"lambda a,b:b<1",
"lambda a,b:a<1",
"lambda a,b:a+b",
"lambda a,b:a*b",
"lambda a,b:a==b",
"lambda a,b:a-b",
"lambda a,b:a<=b",
"lambda a,b:a>=b", 
"lambda a,b:a>b", 
"lambda a,b:a<b", 
"lambda a,b:a<1>b", 
"lambda a,b:a+b<2"]

func_names = built_in_names + object_method_names + additional_func_names

t=True
f=False

cases = [(f,f),(f,t),(t,f),(t,t)]

def signature(func):
    table = [bool(func(x,y)) for x,y in cases]
    table_string = ''.join([str(int(val)) for val in table])
    return table_string

d={}

for func_name in func_names:
    try:
        func = eval(func_name) 
        result = signature(func)
        if result not in d or len(func_name)<len(d[result]):
            d[result]=func_name
    except:
        pass

total_length = sum(len(func) for sig,func in d.items())

print total_length
print

for sig in sorted(d):
    print d[sig]

Nie możesz używać metod wbudowanych takich jak int __lt__lub __eq__? Spowoduje to dalsze zmniejszenie liczby bajtów: int.__gt__zamiast lambda a,b:b<1, int.__eq__zamiast, lambda a,b:a==bi tak dalej
Gábor Fekete

@ GáborFekete Nie istnieją w Pythonie 2, ponieważ intporównują odciążenia cmp. Nie próbowałem tego w Pythonie 3.
xnor

Och, teraz rozumiem!
Gábor Fekete

Zaoszczędź 4 bajty, używając funkcji notfor 0001, False- ideone
Jonathan Allan

1
@JonathanAllan To sprytne, ale myślę, że notnie spełnia wymagań funkcji, ponieważ nie możesz tego zrobić f=not;f(3,4). Ciąg notzdarza się działać, ponieważ rzekome argumenty funkcji wyglądają jak krotka, tak samo 3+działałoby, 3+(4)jakby 3+nie była funkcją, którą można przyjąć 4jako dane wejściowe.
xnor

20

Go (gra), 33 kamienie, 73 skrzyżowania

Jeśli domino i szachy są dopuszczalne, to jest to. Na pełnej planszy 19x19 Go nie może być zbyt golfowy. Użyłem więc małych prostokątnych desek. Dane wejściowe dotyczą tego, czy kamienie oznaczone 1 i 2 są obecne. Wynik jest taki, czy czarny wygrywa. Wykorzystuje ocenę punktową, 0,5 komi, superko sytuacyjne, bez samobójstw. Cały czarny do gry. Niektóre mają wiele rozwiązań.

Białe wygrane (2, 1x5):

➊━━━➋

1 i 2 (3, 2x3):

➊◯➋
┗┷┛

1, a nie 2 (2, 1x5):

╺➊━➁╸

1 (2, 1x5):

╺➊➁━╸ 
╺➊━━➁
➀━➁━╸

Nie 1 i 2 (2, 1x5):

╺➋━➀╸

2 (2, 1x5):

╺➋➀━╸

1 x lub 2 (2, 2x3):

➀┯➁
┗┷┛

1 lub 2 (2, 1x5):

╺➊━➋╸
➀━━━➁

1 ani 2 (2, 1x4):

➊━━➋
╺➀➁╸

1 = 2 (2, 1x7):

╺━➀━➁━╸

Nie 2 (2, 1x3):

➀➁╸

1 lub nie 2 (2, 1x4):

➀➁━╸
➀━➁╸
╺➊➁╸
➋➊━╸
➋━➊╸

Nie 1 (2, 1x3)

➁➀╸

Nie 1 lub 2 (2, 1x4):

➁➀━╸

1 i 2 (2, 1x3):

➊━➋

Czarne wygrane (2, 1x3):

➊➋╸
➀━➁
➊━➁

Ta strona pomogła mi trochę: http://www.mathpuzzle.com/go.html

Może ktoś mógłby znaleźć rozwiązanie 2 kamieni dla 1 i 2 na planszy 1x9 ...


1
Jakie są twoje zasady dotyczące samobójstwa? Niedozwolone? A co się stanie, gdy jedna strona zapełni całą planszę? Czy to uważa się za samobójstwo?
Martin Ender

@MartinEnder Niedozwolone. I tak, to jest uważane za samobójstwo.
jimmy23013

Rozwiązanie 1x7 wydawało się złe. Próbuję to naprawić ...
jimmy23013

15

JavaScript ES6, 124 bajty

a=>0
Math.min
parseInt
a=>a
a=>b=>a<b
a=>b=>b
a=>b=>a^b
Math.max
a=>b=>~a&~b
a=>b=>a==b
a=>b=>~b
Math.pow
a=>~a
a=>b=>a<=b
a=>b=>~a|~b
a=>1

Poważnie nienawidzę teraz lambdów.


1
Jeśli wolno mi napisać kilka programów, a niektóre funkcje ... Myślę, że można zmienić a=>b=>0, aby a=>0i powiedzieć gramatyka nazywając to jest (a=>0)(a,b)tylko dla tych 4 wpisy.
jimmy23013

O tak, dzięki!
Mama Fun Roll

2
Math.minzamiast a=>b=>a&b. Math.maxzamiast a=>b=>a|b. Math.powzamiast a=>b=>a>=b.
Conor O'Brien

1
Ponieważ NaN to falsey, możesz to zrobić parseIntzamiast a=>b=>a>b.
Conor O'Brien

1
@algmyr !NaN=> true, !!NaN=>false
Mama Fun Roll

14

Siatkówka , 62 39 bajtów

23 bajty dzięki @MartinEnder !

0000 false              1 byte : 2
0001 p and q            2 bytes: 11
0010 p and not q        2 bytes: 10
0011 p                  2 bytes: ^1
0100 not p and q        2 bytes: 01
0101 q                  2 bytes: 1$
0110 xor                5 bytes: 01|10
0111 p or q             1 byte : 1
1000 not p and not q    2 bytes: 00
1001 xnor               5 bytes: (.)\1
1010 not q              2 bytes: 0$
1011 p or not q         5 bytes: ^1|0$
1100 not p              2 bytes: ^0
1101 not p or q         5 bytes: ^0|1$
1110 not p or not q     1 byte : 0
1111 true               0 bytes: 

Pobiera dane wejściowe jako PQ.

Zwraca liczbę całkowitą między 0do 3. 0jest falsey, inni są prawdomówni.

Wyjaśnienie

Wszystkie są tylko wyrażeniami regularnymi .

Na przykład 01|10po prostu pasuje 01lub 10.

W 0000, 2nigdy nie będzie na wejściu, więc nigdy nie pasuje.

W 1111dopasowuje pusty ciąg znaków, który istnieje 4.


^1|0$powinien pasować tylko 1 ciąg znaków. Co tu się dzieje?
CalculatorFeline

@CalculatorFeline Dopasowuje [ 1na początku wprowadzania] LUB [ 0na końcu wprowadzania]. Zajęło mi to również chwilę, aby go zdobyć ...
ETHproductions

Pierwszeństwo, chłopaki ...
Leaky Nun

Sądzę, że ^1|0$jest trudniejszy do odczytania niż 1.|.0. Wydaje się, że czytanie jest trudniejsze
l4m2

10

Stack Cats , 67 + 64 = 131 bajtów

Zauważ, że +64 wynika z zastosowania -nmflag do każdego programu. -nwskazuje numeryczne we / wy i -modzwierciedla kod źródłowy ostatniego znaku - nie wszystkie zgłoszenia wymagają tych flag technicznie, ale dla spójności i prostoty oceniam je w ten sam sposób.

-2 -2 -3 -3     !I                0 0 0 0     <I!+
-4 -4 -4  1     |!T*I             0 0 0 1     [>I=I_
-4 -4  3 -2     *I*_              0 0 1 0     :I*=I:
-2 -2  3  3     T*I               0 0 1 1     [<!>X
-2  1 -2 -2     _*T*I             0 1 0 0     *|!TI:
-2  1 -3  1     !-|_I             0 1 0 1     <!I!>X
-2  3  3 -2     ^T*I              0 1 1 0     ^:]<_I
-2  3  3  3     -_T*I             0 1 1 1     *I<-I!
 2 -3 -3 -3     -*|_I             1 0 0 0     ^{!:}I_
 2 -3 -3  2     _|*I              1 0 0 1     _|[<I!:
 1 -2  1 -2     :]I*:             1 0 1 0     _!:|]X
 1 -2  1  1     *I\<X             1 0 1 1     *>I>!I
 2  2 -3 -3     -*I               1 1 0 0     I^:!
 2  2 -3  2     _*I_              1 1 0 1     |I|^:!
 1  2  2 -1     |!:^I             1 1 1 0     -I*<*I
 1  1  1  1     *<X               1 1 1 1     +I+

()w Stack Cats sprawdza, czy element jest dodatni czy dodatni (tj. 0 lub ujemny), więc używamy go odpowiednio do prawdy / fałszu. Druga kolumna jest tylko dla zainteresowania i zawiera najlepsze bramki z 0/ 1s jako dane wyjściowe (z łącznym wynikiem 90).

Dane wejściowe to bity oddzielone separatorem przez STDIN. Wypróbuj online!


Stack Cats to odwracalny ezoteryczny język, w którym programy mają odblaskową symetrię. Biorąc pod uwagę fragment kodu f(np. >[[(!-)/), Odbicie lustrzane (np. \(-!)]]<) Oblicza odwrotność f^-1. Jako takie, nawet programy długości nic nie robią (lub utkną w nieskończonej pętli), a jedyne nietrywialne programy mają nieparzystą długość, obliczając f g f^-1gdzie gjest operator centralny.

Ponieważ połowa kodu źródłowego jest zawsze nadmiarowa, można go pominąć, a uruchomienie kodu z -mflagą wskazuje, że kod źródłowy powinien być dublowany nad ostatnim znakiem, aby pobrać rzeczywisty kod źródłowy. Na przykład program *<Xjest w rzeczywistości *<X>*symetryczny.

Gra w golfa w Stack Cats jest bardzo nieintuicyjna, więc powyższe programy musiały zostać znalezione brutalną siłą. Większość z nich jest zaskakująco skomplikowana, ale wyjaśnię kilka i dodam do tej odpowiedzi, kiedy będę miał czas. Na razie niektóre objaśnienia i alternatywne rozwiązania dla wersji 0/ 1można znaleźć w repozytorium Github tutaj .


1
Note that the +64 is from applying the -nm flags to each program.3 * 16 = 48 lub 2 * 16 = 32, w obie strony 64 to droga hai
kot

@cat Flagi kosztują 4 za program, ponieważ musisz liczyć również miejsce.
FryAmTheEggman


Minęło ponad rok. Czy masz już czas?
CalculatorFeline,

8

Haskell, 78 76 75 bajtów

  1. _#_=2<1
  2. &&
  3. >
  4. pure
  5. <
  6. _#b=b
  7. /=
  8. ||
  9. (not.).max
  10. ==
  11. _#b=not b
  12. >=
  13. a#_=not a
  14. <=
  15. (not.).min
  16. _#_=1<2

Edycja: -1 bajt dzięki @cole.


Właśnie miałem skomentować „koleś, _#_nie jest standardowym operatorem!” I wtedy zrozumiałem ... Dobra robota.
MathematicalOrchid

4 może byćpure
cole

@cole: Dzięki. Wow, purezostał wprowadzony Preludew 2015 roku, więc był dostępny w czasie tego wyzwania.
nimi

6

Brachylog , 36 34 bajtów

0000 false              \     Backtrack (always false)
0001 p and q            1.    Unify input and output with 1
0010 p and not q        >.    Input > Output
0011 p                  1     Unify input with 1
0100 not p and q        <.    Input < Output
0101 q                  ,1.   Unify output with 1
0110 xor                '.    Input and output cannot unify
0111 p or q             1;1.  Unify input with 1 or unify output with 1
1000 not p and not q    0.    Unify input and output with 0
1001 eq                 .     Unify input with output
1010 not q              ,0.   Unify output with 0
1011 p or not q         >=.   Input >= Output
1100 not p              0     Unify input with 0
1101 not p or q         <=.   Input <= Output
1110 not p or not q     0;0.  Unify input with 0 or unify output with 0
1111 true                     Empty program (always true)

Oczekuje się, 0że będzie to wartość fałszywa i 1prawdziwa. Zwraca truelub false. p oznacza Inputq oznacza Output.


Jak wprowadzić dane wyjściowe?
Leaky Nun

1
@LeakyNun Podobnie jak wejście. Główny predykat, którego dotyczy zapytanie, ma dwa argumenty, wywoływany Inputi Outputzgodnie z konwencją, ale można ustawić wartości na oba lub zwrócić wartości z obu.
Fatalize

1
To właściwe narzędzie do pracy: P
Conor O'Brien

6

Prolog, 147 145 bajtów

Zdobył 2 bajty dzięki @SQB

a(a,a).       % 0000 false
b(1,1).       % 0001 P and Q
c(1,0).       % 0010 P and not Q
d(1,_).       % 0011 P
e(0,1).       % 0100 not P and Q
f(_,1).       % 0101 Q
g(P,Q):-P\=Q. % 0110 P xor Q
h(1,_).       % 0111 P or Q
h(0,1).
i(0,0).       % 1000 not P and not Q
j(P,P).       % 1001 P == Q                 
k(_,0).       % 1010 not Q
m(P,Q):-P>=Q. % 1011 P or not Q
n(0,_).       % 1100 not P              
r(P,Q):-P=<Q. % 1101 not P or Q         
s(0,_).       % 1110 not P or not Q
s(1,0).
t(_,_).       % 1111 true

Zapytanie x(P,Q).o xbycie odpowiednią literę a Pi Qustawiony na 0 lub 1.
Zwraca truelub false.

SZWAJCOWY przykład z testami - enter, runTest.aby uruchomić.


Czy obsługuje a(2,2).fałsz?
jimmy23013

@ jimmy23013 Chyba tak, jeśli założę, że 2 to fałsz. Nie jestem pewien, czy to dopuszczalne.
Fatalize

@ jimmy23013 W rzeczywistości a(a,a).(lub jakikolwiek inny list) również działa i anie jest akceptowalnym wkładem do prawdy, więc to dobrze. Dzieki za sugestie.
Fatalize

6

NTFJ, 86 bajtów

0000 false              ~
0001 p and q            |:|
0010 p and not q        :||:|
0011 p                  $
0100 not p and q        #{:||:|
0101 q                  #{$
0110 xor                :#{:#{:||#}:|||
0111 p or q             :|#{:||
1000 not p and not q    :|#{:||:|
1001 eq                 :#{:#{:||#}:|||:|
1010 not q              #{$:|
1011 p or not q         #{:||
1100 not p              $:|
1101 not p or q         :||
1110 not p or not q     |
1111 true               #

Wypróbuj tutaj! Ale najpierw przeczytaj poniżej.

Dane wejściowe są niejawne na stosie. Wynik zostaje pozostawiony na stosie. Dodaj 16 bajtów (jeden *na końcu każdego z nich), jeśli chcesz 0x00lub 0x01do wyjścia reprezentującego 0 i 1. dodać dodatkowe 160 bajtów, jeśli chcesz 0lub 1wydrukowany. (Umieść ~~##~~~#{@przed każdym *.)

Jedynym operatorem binarnym NTFJ jest NAND, więc każdy z nich jest zapisany w formie NAND.

Przejrzyjmy każdy z nich.

0: fałsz

~

~reprezentuje fałszywy bit. Wystarczająco proste. Ponieważ dane wejściowe są niejawne u dołu stosu, pozostawia się je u góry stosu.

1: p i q

|:|

NTFJ działa na stosie. :to polecenie duplikowania. Obserwuj to p and qnot (p nand q)i tamto not q = q nand q.

Command | Stack
        | p q
   |    | (p nand q)
   :    | (p nand q) (p nand q)
   |    | (p nand q) nand (p nand q)
        | => not (p nand q)
        | => p and q

(Uwaga: :|można zatem powiedzieć, że to negacja i |:|można powiedzieć, że to koniunkcja )

2: p, a nie q

:||:|

Zauważ, że to tylko negacja :|i koniunkcja |:|.

Command | Stack
        | p q
  :|    | p (not q)
  |:|   | p and (not q)

3: s

$

$wyskakuje przedmiot ze stosu. Więc tak.

4: nie p i q

#{:||:|

To jest to samo, co 2, z wyjątkiem #{na początku. #przesuwa 1 (prawdziwy bit) i raz {obraca stos w lewo. Wystarczająco proste.

5: q

#{$

Obróć raz w lewo, upuść.

6: xor

:#{:#{:||#}:|||

Przestrzegać:

p xor q = (p and (not q)) or ((not p) and q)                ; by experimentation (trust me)
        = (not ((not p) nand q)) or (not (p nand (not q)))  ; by definition of nand
        = not (((not p) nand q) and (p nand (not q)))       ; by De Morgan's laws
        = ((not p) nand q) nand (p nand (not q))            ; by definition of nand

Nie ma jednak możliwości całkowitego skopiowania stosu. Więc będziemy musieli wnieść każda p, qdo góry i powielić go.

Command | Stack
        | p q
   :    | p q q
  #{    | q q p
   :    | q q p p
  #{    | q p p q
  :|    | q p p (not q)
   |    | q p (p nand (not q))
  #}    | (p nand (not q)) q p
  :|    | (p nand (not q)) q (not p)
   |    | (p nand (not q)) (q nand (not p))
   |    | (p nand (not q)) nand (q nand (not p))

I tak mamy nasz XOR.

7: p lub q

:|#{:||

Neguj górę, zbliż od dołu do góry, neguj to i połącz je razem. Zasadniczo p or q = (not p) nand (not q).

8: nie p i nie q

:|#{:||:|

Jest to po prostu negacja 7. Łatwa.

9: równ

:#{:#{:||#}:|||:|

To tylko xnor lub nie xor. Znowu proste.

10: nie q

#{$:|

Negacja 5.

11: p lub nie q

#{:||

Neguj p, nand. (not p) nand q = not ((not p) and q) = p or (not q) (by De Morgan's laws).

12: nie p

$:|

Upuszczaj, zatrzymuj i neguj.

13: nie p lub q

:||

Prawa De Morgana, by znów uratować dzień! Taki sam proces jak w przypadku 11, tylko negowanie qzamiast p.

14: nie p lub nie q

|

To tylko mimika.

15: prawda

#

# to prawda.


tylko dlaczego ...> _>
Rɪᴋᴇʀ

Nie wiem dokładnie, jak to działa, ale wydaje się całkiem fajne +1
Downgoat

Dlaczego 5 nie jest pustym programem, a 10 tylko :|?
Joffan

6

Minecraft, 89 bloków

Na wszystkich poniższych zdjęciach niebieskie bloki dotyczą wejścia A, a pomarańczowe bloki dotyczą wejścia B.

16. PRAWDA brama - 1 bloki

wprowadź opis zdjęcia tutaj

15. Bramka NAND - 1x2x3 = 6 bloków

wprowadź opis zdjęcia tutaj

14. A => B - 1x2x3 = 6 blokówwprowadź opis zdjęcia tutaj

13. NOT A - 2 bloki wprowadź opis zdjęcia tutaj

12. B => A - 1x2x3 = 6 blokówwprowadź opis zdjęcia tutaj

11. NOT B - 2 bloki wprowadź opis zdjęcia tutaj

10. XNOR - 1x3x4 = 12 bloków wprowadź opis zdjęcia tutaj

9. NOR - 1x2x3 = 6 blokówwprowadź opis zdjęcia tutaj

8. LUB - 1 bloki wprowadź opis zdjęcia tutaj

7. XOR - 1x3x4 = 12 bloków wprowadź opis zdjęcia tutaj

6. B - 1 bloki wprowadź opis zdjęcia tutaj

5.! A&B - 1x2x5 = 10 bloków wprowadź opis zdjęcia tutaj

4. A - 1 bloki wprowadź opis zdjęcia tutaj

3. A &! B - 1x2x5 = 10 bloków wprowadź opis zdjęcia tutaj

2. I - 2x2x3 = 12 bloków wprowadź opis zdjęcia tutaj

1. FAŁSZ - 1 bloki wprowadź opis zdjęcia tutaj


2
W obrazie od drugiego do ostatniego (ORAZ) możesz zapisać 6 bloków, umieszczając pochodnie u góry bloków, tj. Naprzeciwko dźwigni. Zamień pochodnię na środku na kurz i usuń kurz u góry, sprowadzając go do 1x2x3 = 6 bloków.
Luca H,

5

Mathematica, 67 bajtów

0>1&
And
#&&!#2&
#&
!#&&#2&
#2&
Xor
Or
Nor
Xnor
!#2&
#||!#2&
!#&
!#||#2&
Nand
1>0&

Każda z nich ocenia się na funkcję, więc możesz ich używać w podobny sposób

#&&!#2&[True, False]
Xor[True, False]

Ach, gdyby tylko liczby całkowite były zgodne z prawdą / fałszem w Mathematica, te cztery dłuższe mogłyby zostać znacznie skrócone.


Jeśli liczby całkowite nie są zgodne z prawdą / falseyem, co się stanie, gdy umieścisz je w instrukcji if?
Conor O'Brien

3
@ CᴏɴᴏʀO'Bʀɪᴇɴ pozostaje nieoceniony.
Martin Ender

5

MATL, 34 23 bajtów

Mam nadzieję, że wszystko w porządku! Zero to falsey, niezerowe to prawda. Każda funkcja pobiera dwa niejawne dane wejściowe (chociaż może ignorować niektóre dane wejściowe). Pierwsze wejście to A, a drugie B. Możesz wpisać 0/ 1dla true / false lub T/ F.

Oto przykład TryItOnline dla przypadku testowego 3.

Zaoszczędziłem 4 bajty za pomocą *for and, a kolejne 4 za pomocą >/ <zamiast ~wY&/ w~Y&po tym, jak zobaczyłem odpowiedź Dennisa!

1.  0,0,0,0 0 (ignores input, just returns a zero)
2.  0,0,0,1 * (and)
3.  0,0,1,0 < (not-A and B)
4.  0,0,1,1 D (A)
5.  0,1,0,0 > (not-B and A)
6.  0,1,0,1 xD (discard A, display B)
7.  0,1,1,0 Y~ (xor)
8.  0,1,1,1 + (or)
9.  1,0,0,0 +~ (not-or)
10. 1,0,0,1 = (A=B)
11. 1,0,1,0 x~ (not-B)
12. 1,0,1,1 <~ (not-B or A)
13. 1,1,0,0 ~ (not-A)
14. 1,1,0,1 ~+ (not-A or B)
15. 1,1,1,0 *~ (not(A and B))
16. 1,1,1,1 1 (just returns 1)

10
Numer sześć uważa, że ​​to zabawne.
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Numer 6 jest najlepszy, lubię też numer 12! xD!
David

Nie masz funkcji „nierównej”?
Leaky Nun

Nie (przynajmniej tak mi się nie wydaje)
David

2
@David Myślę, że numer 7 można zastąpić-
Luis Mendo

5

dc, 37 bajtów

dc(„kalkulator biurkowy”) to standardowe polecenie unixowe, kalkulator pocztowy oparty na stosie. Brakuje operacji bitowych, a operatorów porównania można używać tylko do wykonywania makr (co nie jest warte bajtów). Podział na liczby całkowite to odrobina.

Skrypty te oczekują 0i 1wartości na stosie, i pozostawić wynik na stosie.

0,0,0,0 (false)              0
0,0,0,1 (and)                *         a*b
0,0,1,0                      -1+2/     (a-b+1)/2
0,0,1,1 (A)                  r         reverse a, b: a now on top
0,1,0,0                      -1-2/     (a-b-1)/2
0,1,0,1 (B)                            (0 bytes) do nothing: b on top
0,1,1,0 (xor)                -         a-b
0,1,1,1 (or)                 +         a+b                  
1,0,0,0 (nor)                +v1-      sqrt(a+b) -1
1,0,0,1 (xnor)               +1-       a+b-1
1,0,1,0 (not B)              1-        b-1
1,0,1,1 (if B then A)        -1+       a-b+1
1,1,0,0 (not A)              r1-       a-1
1,1,0,1 (if A then B)        -1-       a-b-1            
1,1,1,0 (nand)               *1-       a*b - 1
1,1,1,1 (true)               1

5

Labirynt , 85 bajtów

Dzięki Sp3000 za oszczędność 2 bajtów.

!@
??&!@
??~&!@
?!@
?~?&!@
??!@
??$!@
??|!@
??|#$!@
??$#$!@
?#?$!@
?#?$|!@
?#$!@
?#$?|!@
??&#$!@
1!@

Wszystkie są pełnymi programami, odczytują dwie liczby całkowite 0lub 1ze STDIN (przy użyciu dowolnego separatora niecałkowitego) i wypisują wynik jako 0lub 1do STDOUT.

Wypróbuj online!(Nie jest to zestaw testowy, więc będziesz musiał ręcznie wypróbować różne programy i dane wejściowe).

Jeśli chodzi o wyjaśnienia, wszystkie są dość proste. Wszystkie programy są liniowe, a używane polecenia wykonują następujące czynności:

?   Read integer from STDIN and push.
!   Pop integer and write to STDOUT.
@   Terminate program.
&   Bitwise AND of top two stack items.
|   Bitwise OR of top two stack items.
$   Bitwise XOR of top two stack items.
~   Bitwise NOT of top stack item.
#   Push stack depth (which is always 1 when I use it in the above programs).
1   On an empty stack, this pushes 1.

Zauważ, że używam #jest zawsze używany do łączenia go $, tj. Do obliczania XOR 1, lub innymi słowy do logicznej negacji. Tylko w kilku przypadkach mogłem użyć ~zamiast tego, ponieważ kolejne &odrzucają wszystkie niechciane bity z wynikowego -1lub -2.


5

Kod maszynowy IA-32, 63 bajty

Hexdump kodu z dezasemblacją:

0000  33 c0     xor eax, eax;
      c3        ret;

0001  91        xchg eax, ecx;
      23 c2     and eax, edx;
      c3        ret;

0010  3b d1     cmp edx, ecx;
      d6        _emit 0xd6;
      c3        ret;

0011  91        xchg eax, ecx;
      c3        ret;

0100  3b ca     cmp ecx, edx;
      d6        _emit 0xd6;
      c3        ret;

0101  92        xchg eax, edx;
      c3        ret;

0110  91        xchg eax, ecx;
      33 c2     xor eax, edx;
      c3        ret;

0111  8d 04 11  lea eax, [ecx + edx];
      c3        ret;

1000  91        xchg eax, ecx; // code provided by l4m2
      09 d0     or eax, edx;
      48        dec eax;
      c3        ret;

1001  3b ca     cmp ecx, edx;
      0f 94 c0  sete al;
      c3        ret;

1010  92        xchg eax, edx;
      48        dec eax;
      c3        ret;

1011  39 d1     cmp ecx, edx; // code provided by l4m2
      d6        _emit 0xd6;
      40        inc aex;
      c3        ret;

1100  91        xchg eax, ecx;
      48        dec eax;
      c3        ret;

1101  3b d1     cmp edx, ecx; // code inspired by l4m2
      d6        _emit 0xd6;
      40        inc aex;
      c3        ret;

1110  8d 44 11 fe   lea eax, [ecx+edx-2] // code provided by l4m2
      c3        ret;

1111  91        xchg eax, ecx;
      40        inc eax;
      c3        ret;

Kod jest dłuższy niż mógłby być, ponieważ używa się standardowej konwencji kodowania: wejście w ecxi edxi wyjście w al. Można to wyrazić w C jako

unsigned char __fastcall func(int, int);

Wygląda na to, że MS Visual Studio nie rozumie nieudokumentowanego SALCopcode, więc musiałem użyć jego kodu zamiast nazwy.

Dziękuję l4m2 za ulepszenie niektórych próbek kodu!


1
1110 8D4411FE LEA EAX, [ECX+EDX-2]
l4m2

5

C 34 bajty

#define g(n,a,b)((n-1)>>3-b-2*a)&1

Gdzie n to numer funkcji do użycia, ale myślę, że zostałby odrzucony, więc proponuję inną:

C 244 bajty (przy użyciu pamięci)

typedef int z[2][2];
z a={0,0,0,0};
z b={0,0,0,1};
z c={0,0,1,0};
z d={0,0,1,1};
z e={0,1,0,0};
z f={0,1,0,1};
z g={0,1,1,0};
z h={0,1,1,1};
z i={1,0,0,0};
z j={1,0,0,1};
z k={1,0,1,0};
z l={1,0,1,1};
z m={1,1,0,0};
z n={1,1,0,1};
z o={1,1,1,0};
z p={1,1,1,1};

używa podwójnie indeksowanej tablicy. n[0][1]jest(A implies B)(0,1)

Dalej 138 bajtów

Właśnie nauczyłem się Fortha. Przypuszczam, że jest kompatybilny z Ansi Forth, ponieważ działa również na gforth.

: z create dup , 1+ does> @ -rot 3 swap - swap 2* - rshift 1 and ; 
0 
z a z b z c z d z e z f z g z h z i z j z k z l z m z n z o z p 
drop

Funkcja z utwórz nową funkcję o podanej nazwie, a następnie umieść numer bramki logicznej z góry stosu na nowy adres funkcji. Pozostawia następną (n + 1) funkcję bramki logicznej na stosie do następnej deklaracji.

możesz to przetestować:
i AB

0 0 b . cr 
0 1 b . cr
1 0 b . cr 
1 1 b . cr   

(„.” drukuj górę stosu „cr” oznacza powrót wózka)


Musisz tylko podać fragmenty kodu dla każdej funkcji.
CalculatorFeline

4

C, 268 bajtów

#define c(a,b)0      // 0000 
#define d(a,b)a&b    // 0001 
#define e(a,b)a>b    // 0010 
#define f(a,b)a      // 0011 
#define g(a,b)a<b    // 0100 
#define h(a,b)b      // 0101 
#define i(a,b)a^b    // 0110 
#define j(a,b)a|b    // 0111 
#define k(a,b)!b>a   // 1000 
#define l(a,b)a==b   // 1001 
#define m(a,b)!b     // 1010 
#define n(a,b)!b|a   // 1011 
#define o(a,b)!a     // 1100 
#define p(a,b)!a|b   // 1101 
#define q(a,b)!b|!a  // 1110 
#define r(a,b)1      // 1111 

Makra wydają się krótsze niż funkcje.


4

Brian & Chuck , 183 bajtów

Dzięki Sp3000 za oszczędność 4 bajtów.

Niektóre programy zawierają znak niezadrukowany. W szczególności każdy \x01powinien zostać zastąpiony <SOH>znakiem kontrolnym (0x01):

0000
?
#>.
0001
,-?,-?>?\x01
#}>.
0010
,-?,?>?\x01
#}>.
0011
,?\x01+?
#>.
0100
,?,-?>?\x01
#}>.
0101
,,?\x01+?
#>.
0110
,?>},?>?_\x01
#}+{>?_}>.
0111
,\x01?,?>?
#{>.
1000
,?,?>?\x01
#}>.
1001
,-?>},?>?_\x01
#}+{>>?_}>.
1010
,,-?\x01+?
#>.
1011
,\x01?,-?>?
#{>.
1100
,-?\x01+?
#>.
1101
,\x01-?,?>?
#{>.
1110
,\x01-?,-?>?
#{>.
1111
?
#>+.

Wartości wejściowe i wyjściowe wykorzystują bajty , więc dane wejściowe powinny wynosić dwa bajty 0x00 lub 0x01 (bez separatora), a dane wyjściowe będą jednym takim bajtem. Jest to tak naprawdę najbardziej sensowna definicja prawdy / fałszu dla B&C, ponieważ jest to jedyne polecenie sterowania przepływem? traktuje zera jako fałsz i wszystko inne prawdziwe.

Objaśnienia

Najpierw szybki podkład B&C:

  • Każdy program składa się z dwóch instancji typu Brainfuck, każda napisana w osobnej linii. Pierwszego nazywamy Brianem, a drugiego Chuckiem . Egzekucja rozpoczyna się na Brianie.
  • Taśma każdego programu jest kodem źródłowym drugiego programu, a wskaźnikiem instrukcji każdego programu jest głowa taśmy drugiego programu.
  • Tylko Brian może używać polecenia ,(bajt wejściowy), a tylko Chuck może używać polecenia .(bajt wyjściowy).
  • []Pętla Brainfuck nie istnieje. Zamiast tego jedynym przepływem kontrolnym, jaki masz, jest ?przełączenie sterowania na inne wystąpienie, jeśli bieżąca wartość pod głowicą taśmy jest niezerowa.
  • Oprócz >i <, istnieją {i }które są zasadniczo równoważne fragmentom Brainfuck [<]i [>], to znaczy, przesuwają głowicę taśmy do następnej pozycji zerowej w tym kierunku. Główną różnicą jest to, że {można ją również zatrzymać na lewym końcu taśmy, niezależnie od jej wartości.
  • Dla wygody wszelkie _znaki w kodzie źródłowym są zastępowane zerowymi bajtami (ponieważ są one bardzo przydatne w nietradycyjnych programach w celu przechwytywania {i }).

Zauważ, że we wszystkich programach taśma Chucka zaczyna się od #. To może być naprawdę wszystko. ?działa tak, że głowa taśmy przesuwa się o jedną komórkę przed rozpoczęciem wykonywania (tak, że sam warunek nie jest wykonywany, jeśli zdarzy się, że jest prawidłowym poleceniem). Więc nigdy nie możemy użyć pierwszej komórki Chucka do kodu.

Istnieje pięć klas programów, które wyjaśnię szczegółowo później. Na razie wymieniam je tutaj w kolejności rosnącej złożoności.

0000, 1111: Funkcje stałe

?
#>.
?
#>+.

To są bardzo proste. Przechodzimy na Chucka bezwarunkowo. Chuck przesuwa głowicę taśmy do nieużywanej komórki w prawo i albo drukuje ją bezpośrednio, albo zwiększa ją najpierw, aby wydrukować 1.

0011, 0101, 1010, 1100: Funkcje zależności tylko jedno wejście

,?\x01+?
#>.
,,?\x01+?
#>.
,,-?\x01+?
#>.
,-?\x01+?
#>.

W zależności od tego, czy zaczynamy od, ,czy ,,pracujemy z Alub B. Spójrzmy na pierwszy przykład 0011(tj A.). Po odczytaniu wartości używamy ?jej warunkowo. Jeśli A = 1, to przełącza się na Chucka, który przesuwa głowicę taśmy w prawo i drukuje dosłownie osadzony 1bajt. W przeciwnym razie kontrola pozostaje na Brianie. W tym przypadku 1-bajt to brak operacji. Następnie zwiększamy dobrze wartość wejściową, +aby upewnić się, że jest niezerowa, a następnie przełączamy na Chuck za pomocą ?. Tym razem >przechodzi do nieużywanej komórki po prawej stronie, która jest następnie drukowana jako0 .

Aby zanegować jedną z wartości, po prostu ją zmniejszamy -. Włącza 1się 0i 0na -1, która jest różna od zera, a więc truthy o ile ?dotyczy.

0001, 0010, 0100, 1000: Funkcje binarne z jednej wyniku truthy

,-?,-?>?\x01
#}>.
,-?,?>?\x01
#}>.
,?,-?>?\x01
#}>.
,?,?>?\x01
#}>.

Jest to rozszerzenie poprzedniego pomysłu w celu pracy z dwoma wejściami. Spójrzmy na przykład 1000(NOR). (Potencjalnie) czytamy oba dane wejściowe za pomocą ,?. Jeśli tak 1, ?przełącza się na Chucka. Przesuwa głowę taśmy do końca za pomocą }(na pustą komórkę po kodzie Briana), przesuwa kolejną komórkę za pomocą >(wciąż zero) i drukuje ją ..

Jednak jeśli oba wejścia są zerowe, kontrola jest nadal z Brianem. >następnie przesuwa głowicę taśmy w }taki sposób, że to polecenie nie jest wykonywane po przełączeniu na Chucka za pomocą ?. Teraz wszystko, co robi Chuck, >.przesuwa się tylko na 1komórkę i drukuje to.

Możemy łatwo uzyskać pozostałe trzy funkcje, negując jeden lub oba wejścia zgodnie z wymaganiami.

0111, 1011, 1101, 1110: Funkcje binarne z trzech wyników truthy

,\x01?,?>?
#{>.
,\x01?,-?>?
#{>.
,\x01-?,?>?
#{>.
,\x01-?,-?>?
#{>.

Drobna modyfikacja poprzedniego pomysłu, aby zignorować wynik (tj. Wydrukować, 0gdy przejdziemy przez cały Brian i 1nie tylko). Spójrzmy na 0111(LUB) jako przykład. Zauważ, że wbudowany- 1bajt nie działa, więc nadal zaczyna się od ,?,?. Jeśli którekolwiek z tych danych wejściowych 1, przełączamy na Chucka, który przesuwa głowicę z powrotem na początek {. >.przesuwa głowicę taśmy na ten 1bajt i drukuje ją.

Jeśli oba wejścia są równe zero, pozostajemy z Brianem, przesuń głowicę taśmy, {aby ją pominąć, a następnie przełącz na Chucka. Kiedy wykonuje >.ten czas, przechodzi do pustej komórki po kodzie Briana i drukuje 0.

Ponownie łatwo uzyskujemy inne funkcje, negując jedno lub oba dane wejściowe.

0110, 1001: Funkcje binarne z dwoma prawdziwymi wynikami

,?>},?>?_\x01
#}+{>?_}>.
,-?>},?>?_\x01
#}+{>>?_}>.

Ten jest nieco trudniejszy. Poprzednie funkcje były dość proste, ponieważ mogą być zwarte - wartość pierwszego wejścia może decydować o wyjściu, a jeśli nie, to patrzymy na inne wejście. W przypadku tych dwóch funkcji zawsze musimy przyjrzeć się obu wejściom.

Podstawową ideą jest użycie pierwszego wejścia do podjęcia decyzji, czy drugie wejście wybierze pomiędzy 0i 1czy pomiędzy 1i 0. Weźmy 0110jako przykład (XOR):

Zastanów się A = 0. W tym przypadku chcemy uzyskać dane wyjściowe bez Bzmian. ,czyta A, ?nic nie robi. >przechodzi do następnej (niezerowej) komórki, dzięki czemu }dochodzimy do _Chucka. Oto czytamy, Bze ,i użyć ?ponownie. Jeśli tak Bbyło 0, wciąż jesteśmy na Brianie. >pomija }on Chucka i ?przełącza, aby >.drukować 0osadzony w kodzie źródłowym Briana. Jeśli Bbyło 1z drugiej strony, Chuck już wykonuje polecenie, }które przechodzi do _kodu Briana, więc >.wtedy wypisuje 1-byte.

Jeśli A = 1, to od razu zmienimy na Chucka, który wykona polecenie }+{>?. To powoduje przejście do _kodu źródłowego Briana, zmienia go 1również w +, a następnie przesuwa się z powrotem na początek {i przeskakuje Briana, ?przesuwając jedną komórkę w prawo >przed przekazaniem mu kontroli. Tym razem, po Brian czytać-tych B, czy B = 0i Chuck wykorzystuje >.komórkę obok Briana ?będzie 1zamiast 0. Ponadto, kiedy B = 1Chuck }przeskakuje nad tym, co kiedyś było przerwą, i przesuwa się aż do końca taśmy, więc >.zamiast tego drukuje zero. W ten sposób drukujemy not B.

Aby wprowadzić równoważność, po prostu zanegowaliśmy, Azanim użyliśmy go jako warunku. Zauważ, że z tego powodu musimy również dodać kolejny >do Chucka, aby pominąć to -również podczas powrotu do początku.


4

ClojureScript, 88 84 76 74 bajty

nili falsesą fałszywe, wszystkie inne wartości są prawdziwe. Booleany przymuszają do 0/1 za arytmetykę i nierówności. Funkcje mogą przyjmować niewłaściwą liczbę argumentów.

0000   nil?            ; previously: (fn[]nil)
0001   and
0010   <
0011   true?           ; previously: (fn[x]x)
0100   >
0101   (fn[x y]y)
0110   not=
0111   or
1000   #(= 0(+ % %2))
1001   =
1010   #(not %2)
1011   <=
1100   not
1101   >=
1110   #(= 0(* % %2))
1111   /               ; previously: (fn[]4), inc

Czy to nie 0fałsz?
Leaky Nun

2
Nie w ClojureScript.
MattPutnam

@LeakyNun Nie w większości LISP-ów ani funkcjonalnych języków programowania, którymi zdecydowanie jest Clojure
cat

@cat Tak w większości funkcjonalnych języków programowania! Na przykład Python ocenia not not(0)na Falsewartość falsey.
Erik the Outgolfer,

3
@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Er ... Python nie jest ani funkcjonalnym, ani rodzajem funkcjonalnego języka, o którym mówię. Python jest w większości konieczny i ma pewne mniejsze (źle wykonane) aspekty funkcjonalne. Erlang, Haskell (myślę), Common LISP, Clojure, rakieta, Schemat, Factor, Standard ML, Objective CAML itp 0 jest tylko inną wartość i jest w wyniku truthy i symbol false ( #f, f, false, etc) jest fałszywe. Wszystkie pozostałe wartości są prawdziwe w większości języków funkcjonalnych.
kot

4

Brainfuck , 184 178 174 bajtów

Wejścia / wyjścia używają U + 0000 i U + 0001.

0000 .
0001 ,[,[->+<]]>.
0010 ,[,-[+>+<]]>.
0011 ,.
0100 ,-[,[->+<]]>.
0101 ,,.
0110 ,>,[-<->]<[>>+<]>.
0111 ,-[,-[+>-<]]>+.
1000 ,-[,-[+>+<]]>.
1001 ,>,[-<->]<[>>-<]>+.
1010 ,,-[+>+<]>.
1011 ,-[,[->-<]]>+.
1100 ,-[+>+<]>.
1101 ,[,-[+>-<]]>+.
1110 ,[,[->-<]]>+.
1111 +.

Czytanie drugiego warunkowego wpisu wygląda na drogie. Np. 0001Czy nie możesz tego zrobić ,[,>]<.(biorąc pod uwagę tłumacza, który pozwala ci przejść na lewo od komórki początkowej)?
Martin Ender

@MartinEnder Doszedłem do wniosku, że nie skopiuję tutaj odpowiedzi Dennisa.
Leaky Nun

4

Brain-Flak , 418 , 316 bajtów

Wypróbuj online!

Niech dane wejściowe będą górnymi dwiema liczbami na stosie na początku programu (zero dla fałszu dla prawdy), a dane wyjściowe będą górą stosu na końcu programu (zero dla fałdu dla prawdy).

false, 4 bajty (dzięki uprzejmości Leaky Nun )

(<>)

i 36 bajtów

(({}{}[(())()])){{}{}(((<{}>)))}{}{}

A, a nie B, 40 bajtów

((({}){}{}[(())()])){{}{}(((<{}>)))}{}{}

A, 6 bajtów

({}<>)

nie A i B, 38 bajtów

((({}){}{}[(())])){{}{}(((<{}>)))}{}{}

B, 2 bajty

{}

xor, 34 bajty

(({}{}[(())])){{}{}(((<{}>)))}{}{}

lub 6 bajtów

({}{})

ani 34 bajty

(({}{}<(())>)){{}{}(((<{}>)))}{}{}

xnor, 10 bajtów

({}{}[()])

nie B, 34 bajty

{}(({}<(())>)){{}{}(((<{}>)))}{}{}

B oznacza A, 14 bajtów

(({}){}{}[()])

nie A, 34 bajty

(({}<{}(())>)){{}{}(((<{}>)))}{}{}

A oznacza B, 16 bajtów

(({}){}{}[()()])

nand, 12 bajtów

({}{}[()()])

prawda, 6 bajtów

<>(())

Wyjaśnienie

Ponieważ większość z nich jest bardzo podobnych, nie zamierzam dokładnie wyjaśniać, jak działa każdy z nich. Staram się jednak wyjaśnić, jak działa cała szesnaście osób.

Po pierwsze, bramki, które zwracają trzy o tej samej wartości (tj. 2, 3, 5, 8, 9, 12, 14 i 15). Wszystkie one mają ten sam wzór. Najpierw konwertujesz dane wejściowe na liczbę dwubitową z miejscem jako dwójkami i B jako jednością. Odbywa się to za pomocą tego fragmentu (({}){}{}). Następnie odejmij wartość dwubitowego wejścia, które chcesz izolować ({}[value]). (W rzeczywistym kodzie odejmowanie i konwersja są wykonywane w jednym kroku, aby zapisać bajty). W razie potrzeby można to połączyć z nie (({}<(())>)){{}{}(((<{}>)))}{}{}.

Dalej: i, nor, lub, xor i xnor. Działają one podobnie do powyższych. W rzeczywistości niektóre z nich są uwzględnione powyżej, jednak ta metoda jest krótsza. Sztuczka, której tu użyłem, polega na tym, że każda z nich odpowiada sumie A B. Np. Xor ocenia na prawda, jeśli A + B = 1, a fałsz w przeciwnym razie. Najpierw dodajesz AB i odejmujesz odpowiednią kwotę. Wyrażony jako ({}{}[0,1,2 or 3]). Następnie w razie potrzeby przeprowadź nie

Dalej: A, B, nie A i nie B. Są one dość oczywiste. Zaczynamy od usunięcia niepotrzebnej wartości, a następnie albo negujemy, albo kończymy.

Wreszcie są dwie prostoty: prawda i fałsz. W tym celu wypychamy prawidłową wartość na stos. W <>nilad zwraca zero, dzięki czemu możemy zaoszczędzić dwa bajty przy użyciu przełącznika jako wartość zerową.

Nie jest to najskuteczniejsze rozwiązanie (być może najskuteczniejsze w Brain-Flak), ale pisanie ich sprawiało mi wiele radości i błagam, abyś spróbował je skrócić.


(<>)wystarczy dla false; również (<{}{}>)ma 8 bajtów
Leaky Nun

Wow, miałem znacznie bardziej rygorystyczną definicję wyzwania. Dziękuję Ci. Zmniejszę to znacznie
Wheat Wizard

Co masz na myśli?
Leaky Nun

Pomyślałem, że muszę usunąć istniejące dane wejściowe i umieścić wynik na jego miejscu. (<>)pozostawi wejścia i umieści zero na drugim stosie.
Wheat Wizard

1
Czy nie <>wystarczy ze falsewzględu na domniemane zera? Myślę też, że amoże to być pusty program. truemoże być <>[][](nie zapisuje bajtów, ale wygląda świetnie: P).
CalculatorFeline

4

ProgFk , 18,5 17,5 bajtów

Ponieważ instrukcje ProgFk są określone w skubkach, poniższy kod jest podany w systemie szesnastkowym, jedna bramka logiczna na linię i ze spacjami między bajtami.

3
E1
DE 2D
<empty>
DE 1
1
E3
E2
E2 D
E3 D
1D
DE 2
D
DE 1D
E1 D
4

Wyjaśnienie

ProgFk jest opartym na taśmie esolangiem (podobnym do Brainfuck), w którym każda komórka jest trochę, a instrukcje są podawane w postaci skubków (4 bajty). Instrukcje działają na komórce wskazanej wskaźnikiem instrukcji. Dane wejściowe są podawane w pierwszej i drugiej komórce (z odpowiednio Ai Bpierwszą i drugą komórką), a wskaźnik instrukcji zaczyna się od pierwszej komórki. Dane wyjściowe są przechowywane w pierwszej komórce.

Każda zastosowana instrukcja jest wyjaśniona poniżej.

1   Increment the instruction pointer.
2   Decrement the instruction pointer.
3   Set the current bit to 0.
4   Set the current bit to 1.
D   Perform a NOT on the current bit.
E   The next instruction is an extended instruction.

Extended instructions:
1   Set the current bit to the current bit AND the next bit.
2   Set the current bit to the current bit OR the next bit.
3   Set the current bit to the current bit XOR the next bit.
6   Swap the current bit and the next bit.

Zapisano bajt dzięki @LeakyNun!


4

Właściwie 24 bajty

Programy te przyjmują dane wejściowe jako A\nB(z \nreprezentacją nowej linii), co pozostawia B na górze stosu, z A poniżej. Falsejest reprezentowany przez 0i Truejest reprezentowany przez dowolną dodatnią liczbę całkowitą.

é0  (false: clear stack, push 0)
*   (and: multiply)
<   (A and not B: less-than)
X   (A: discard B)
>   (B and not A: greater-than)
@X  (B: discard A)
^   (A xor B: xor)
|   (A or B: or)
|Y  (A nor B: or, boolean negate)
=   (A xnor B: equals)
@XY (not B: discard A, boolean negate B)
≤   (if B then A: less-than-or-equal)
XY  (not A: discard B, boolean negate)
≥   (if A then B: greater-than-or-equal)
*Y  (A nand B: multiply, boolean negate)
é1  (true: clear stack, push 1)

Dzięki Leaky Nun za 3 bajty

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.