Golf tutte le 16 porte logiche con 2 ingressi e 1 uscita!


63

Ad esempio, il gate A and Bè un gate logico con 2 ingressi e 1 uscita.

Ce ne sono esattamente 16, perché:

  • ogni porta logica accetta due ingressi, che possono essere verità o falsa, dandoci 4 possibili ingressi
  • dei 4 possibili input, ognuno può avere un output di verità e falsità
  • pertanto, ci sono 2 ^ 4 possibili porte logiche, che è 16.

Il tuo compito è scrivere 16 programmi / funzioni che li implementano separatamente.

Le tue funzioni / programmi devono essere indipendenti .

Sono validi fintanto che generano valori di verità / falsità, il che significa che è possibile implementare A or Bin Python come lambda a,b:a+b, anche se 2è prodotto per A=Truee B=True.

Il punteggio è il totale dei byte utilizzati per ciascuna funzione / programma.

Elenco di porte logiche

  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)

Dove il primo numero è l'output per A=false, B=false, il secondo numero è l'output per A=false, B=true, il terzo numero è l'output per A=true, B=false, il quarto numero è l'output per A=true, B=true.

Classifica


2
Le tue funzioni / programmi possono condividere il codice. Cosa significa questo? Inoltre, i programmi possono essere in diverse lingue?
Lynn,

2
Trovo la spiegazione confusa: "dei 4 possibili input ciascuno può avere e output di verità e falsità". Questo non implica 8 (4 * 2) stati?
DavidC

4
I nomi che ti mancano sono le porte AND-NOT (A AND NOT B e B AND NOT A).
Mego

14
Quindi è successo di nuovo. Ci sono 18 risposte, per lo più semplici e corrette, quindi dal nulla la domanda è diventata "poco chiara cosa stai chiedendo". Io non ti piace una sfida, dai, prendine un'altra, non chiuderla!
edc65,

4
@dorukayhan See: verità vacua
Sp3000,

Risposte:


110

Domino , 122.000 byte o 72 tessere

Il conteggio dei byte è la dimensione del file salvato che è 0.122 MB.

L'elaborazione del domino è stata l'ispirazione. Ho provato tutti questi fino alla simmetria (e oltre!) Tramite un gioco Steam di realtà virtuale chiamato Tabletop Simulator .

Dettagli

  • I / O
    • Avvio : è incluso per chiarezza (non conteggiato per il totale) ed è ciò che 'chiama' o 'esegue' la funzione. Dovrebbe essere 'premuto' dopo che è stato immesso [Giallo] .
    • Ingresso A - Questo è incluso per chiarezza (non conteggiato per il totale) ed è 'premuto' per indicare a 1e non premuto altrimenti [Verde] .
    • Ingresso B - Questo è incluso per chiarezza (non conteggiato per il totale) ed è 'premuto' per indicare a 1e non premuto altrimenti [Blu] .
    • Output : viene conteggiato per il totale. È il domino che dichiara il risultato della porta logica [Nero] .
  • T / F
    • Un domino di output decaduto rappresenta il risultato di Trueo1
    • Un domino di output permanente rappresenta un risultato di Falseo0
  • urgente
    • Per dare input o avviare la catena, spawn il marmo metallico
    • Impostare la forza di sollevamento su 100%
    • Solleva il marmo sopra il domino desiderato
    • Lascia cadere il marmo

inserisci qui la descrizione dell'immagine

Gates

  • falso, 1
    • inserisci qui la descrizione dell'immagine
  • e, 6 4
    • inserisci qui la descrizione dell'immagine
  • A e non B, 4 3
    • inserisci qui la descrizione dell'immagine
  • A, 1
    • inserisci qui la descrizione dell'immagine
  • non A e B, 4 3
    • inserisci qui la descrizione dell'immagine
  • B, 1
    • inserisci qui la descrizione dell'immagine
  • xor, 15 11
    • inserisci qui la descrizione dell'immagine
  • oppure, 1
    • inserisci qui la descrizione dell'immagine
  • 3 2
    • inserisci qui la descrizione dell'immagine
  • xnor, 17 13
    • inserisci qui la descrizione dell'immagine
  • non B, 2
    • inserisci qui la descrizione dell'immagine
  • B implica A, 7 6
    • inserisci qui la descrizione dell'immagine
  • non A, 2
    • inserisci qui la descrizione dell'immagine
  • A implica B, 7 6
    • inserisci qui la descrizione dell'immagine
  • nand, 16 15
    • inserisci qui la descrizione dell'immagine
    • vero, 1
    • inserisci qui la descrizione dell'immagine

TL; DR

Stavo aspettando / volendo una sfida amichevole per il domino e quando l'ho vista, non sono riuscita a superarla. L'unico problema era che apparentemente nessuno possiede più il domino! Quindi alla fine ho ceduto e comprato un doppio dodici . Questo set ha 91 tessere, che mi hanno dato l'idea di avere una "funzione chiamata" / avvio domino invece del normale (lungo) metodo "ritardo". Il merito della svolta di 90 gradi appartiene al canale di dominoesdouble07 .

Dopo aver costruito questi con domino fisici, è stato stabilito in meta che le soluzioni valide dovrebbero essere digitali. Così ho ricreato queste porte in Simulatore da tavolo . Purtroppo, TS e realtà non sono d'accordo sulla fisica del domino. Ciò ha richiesto l'aggiunta di 11 domino, ma ho anche salvato 8. Complessivamente, i domino virtuali sono circa x150 più efficaci in termini di costruzione e test ( Ctrl+ Z).

Aggiornare

  • -9 [17-03-13] Ridottoxor xnor nand
  • [17-03-04] Aggiunto link al file dell'officina
  • +11 [17-03-03] Aggiunti digitali xnorexor
  • -8 [17-03-03] Digitalizzato tutte le porte (tranne xore xnor). Il blocco su Tabletop richiede solo 1 domino, anziché 2.
  • [16-09-23] Immagini ristrette
  • -11 [16-09-18] Quasi nuovamente xor a metà. Grazie a @DJMcMayhem per xnor e Joe per xor.
  • -31 [16-08-31] Aggiornate alcune foto e rasato alcune piastrelle e tagliate xor a metà
  • [16-08-28] Aggiunte immagini

43
+1 Abbiamo bisogno di più golf a domino su PPCG
Decadimento beta


7
Wow. Questa è una delle risposte più originali che abbia mai visto su questo sito.
DJMcMayhem

3
Sembra che potresti togliere un domino se schiacci lo xnor insieme e ne hai 4 nella parte superiore, anziché 5. Quindi, di nuovo, non l'ho provato affatto.
DJMcMayhem

2
Grazie per aver dedicato del tempo a rendere questa una risposta valida. Tuttavia, il collegamento al file di origine è un po 'difficile da trovare. Normalmente, il collegamento nell'intestazione porta alla lingua stessa. Quindi collegerei quello al gioco Steam e poi inserivo il collegamento al "file sorgente" reale in un collegamento separato, chiaramente etichettato da qualche parte nel corpo della risposta.
Martin Ender,

45

Esagonia , 89 byte

Grazie a FryAmTheEggman per l'ispirazione necessaria per la soluzione XOR.

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

Tutti i programmi usano 0per falso e 1per vero.

Provalo online! Questa non è una suite di test, dovrai copiare i vari programmi e input da solo.

La soluzione sopra è entro 2 byte di ottimalità (a meno che non rilassiamo l'interpretazione verità / falsa, immagino). Ho lasciato un bruto corsa di ricerca forza per quasi due giorni più di tutti i programmi che rientrano in parte di lunghezza 2, vale a dire fino a 7 byte (non abbastanza tutti i programmi - ho fatto un paio di ipotesi su ciò che ogni esigenza programma valido e cosa no programma valido potrebbe avere). La ricerca ha trovato soluzioni per 15 delle 16 possibili porte - e spesso molto più di una sola. Puoi trovare un elenco di tutte le soluzioni alternative in questo pastebin in cui le ho anche raggruppate per comportamento equivalente. Quelli che sto mostrando sopra li ho selezionati perché sono la soluzione più semplice o più interessante e domani aggiungerò spiegazioni per loro.

Per quanto riguarda la 16a porta: XOR è l'unica porta che apparentemente non può essere implementata in 7 byte. Sfortunatamente una ricerca di forza bruta su programmi più grandi non è fattibile con il codice che ho attualmente. Quindi XOR doveva essere scritto a mano. Il più breve che ho trovato finora è il programma da 10 byte sopra, che si basa su un tentativo fallito (ma molto vicino) di FryAmTheEggman. È possibile che esista una soluzione a 8 o 9 byte, ma a parte ciò, tutte le soluzioni dovrebbero essere effettivamente ottimali.

spiegazioni

Attenzione: muro di testo. Per caso qualcuno è interessato a come funzionano questi programmi Hexagony altamente compressi, ho incluso spiegazioni per ciascuno di essi di seguito. Ho cercato di scegliere la soluzione più semplice per ogni gate nei casi in cui esiste più di un programma ottimale, al fine di mantenere le spiegazioni ragionevolmente brevi. Tuttavia, alcuni di loro continuano a confondere la mente, quindi ho pensato che meritassero un po 'più di elaborazione.

0000: Falso

Non credo che avremo bisogno di un diagramma per questo:

 ! @
. . .
 . .

Poiché l'intera griglia di memoria è inizializzata su zero, !stampa semplicemente uno zero e @termina il programma.

Questa è anche l'unica soluzione a 2 byte.

0001: E

 ? .
| @ !
 . .

Questo in pratica implementa il corto circuito . Il diagramma grigio in basso mostra l'inizio del programma, in cui viene letto il primo input ?e il puntatore dell'istruzione (IP) si avvolge nell'angolo sinistro dove lo |specchio lo riflette. Ora l'angolo funge da condizionale, quindi esistono due diversi percorsi di esecuzione a seconda del valore del primo input. Il diagramma rosso mostra il flusso di controllo per A = 0e il diagramma verde per A = 1:

io io io

Come puoi vedere, quando lo Aè 0, lo stampiamo e terminiamo semplicemente (ricorda che tutti .sono vietati). Ma quando lo Aè 1, l'IP attraversa di nuovo la prima riga, leggendola Be stampandola invece.

In totale ci sono sedici soluzioni a 5 byte per questo gate. Quattordici di questi sono essenzialmente gli stessi di cui sopra, o usando >invece |o sostituendo il .con un comando che è effettivamente un no-op, o mettendo ?in seconda posizione:

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

E poi ci sono altre due soluzioni (che sono equivalenti tra loro). Questi implementano anche la stessa logica di corto circuito, ma i percorsi di esecuzione sono un po 'più folli (e lasciati come esercizio al lettore):

?<!@|
?<!@<

0010: A e non B

 # ?
# ! )
 @ .

Questo implementa anche una forma di corto circuito, ma a causa dell'uso del #flusso di controllo è molto più complicato. #è uno switch IP condizionale. Hexagony in realtà è dotato di sei indirizzi IP etichettati 0a 5, che partono nei sei angoli della griglia, indicando lungo il loro bordo in senso orario (e il programma inizia sempre con IP 0). Quando #viene rilevato un, il valore corrente viene assunto modulo 6e il flusso di controllo continua con l'IP corrispondente. Non sono sicuro di quale forma di follia mi abbia fatto aggiungere questa funzionalità, ma certamente consente alcuni programmi sorprendenti (come questo).

Distingueremo tre casi. Quando A = 0, il programma è abbastanza semplice, perché il valore è sempre 0quando #viene rilevato in modo tale che non avvenga alcuna commutazione IP:

io

#non fa nulla, ?legge A(cioè non fa nulla), #non fa ancora nulla, !stampa il 0, lo )incrementa (questo è importante, altrimenti l'IP non salterebbe alla terza riga), @termina il programma. Abbastanza semplice. Consideriamo ora il caso (A, B) = (1, 0):

io

Il percorso rosso corrisponde ancora a IP 0e ho aggiunto il percorso verde per IP 1. Vediamo che dopo le ?letture A( 1questa volta), #passa all'IP che inizia nell'angolo in alto a destra. Ciò significa che ?può leggere B( 0). Ora lo )incrementa a 1, in modo tale che #nell'angolo in alto a sinistra non faccia nulla e rimaniamo con IP 1. La !stampa 1e l'IP si avvolgono attorno alla diagonale sinistra. #continua a non fare nulla e @termina il programma.

Infine, il caso davvero strano in cui entrambi gli input sono 1:

io

Questa volta, anche il secondo input è 1e lo )incrementa a 2. Ciò significa che #nell'angolo in alto a sinistra provoca un altro IP switch su IP 2, indicato in blu. Su quel percorso, prima lo incrementiamo ulteriormente 3(anche se questo è irrilevante) e quindi passiamo la ?terza volta. Dato che ora abbiamo premuto EOF (ovvero l'input è esaurito), ?ritorna 0, lo !stampa e @termina il programma.

In particolare, questa è l'unica soluzione a 6 byte per questo gate.

0011: A

 ? !
@ . .
 . .

Questo è abbastanza semplice che non avremo bisogno di un diagramma: ?legge A, !stampa, @termina.

Questa è l'unica soluzione a 3 byte per questo gate. (In linea di principio, sarebbe anche possibile farlo ,;@, ma la ricerca non ha incluso ;, perché non credo che potrà mai salvare byte !per questa attività.)

0100: B e non A

 + ?
| @ !
 ? .

Questo è molto più semplice del suo "fratello" 0010. Il flusso di controllo è in realtà lo stesso che abbiamo visto sopra per 0001(And). Se A = 0, quindi l'IP attraversa la riga inferiore, leggendola Be stampandola prima di terminare. Se A = 1poi l'IP attraversa di nuovo la prima riga, leggendo anche B, ma +aggiunge due bordi di memoria inutilizzati, quindi tutto ciò che fa è resettare il valore corrente 0, in modo che venga !sempre stampato 0.

Ci sono molte alternative a 6 byte (42 in totale). Innanzitutto, ci sono un sacco di soluzioni equivalenti a quanto sopra. Possiamo di nuovo scegliere liberamente tra |e >e +può essere sostituito con qualsiasi altro comando che ci dia un bordo vuoto:

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

Inoltre, possiamo anche usare al ]posto di ?. ]passa all'IP successivo (ovvero seleziona l'IP 1), in modo che questo ramo riutilizzi invece l' ?angolo superiore destro. Questo offre altre 18 soluzioni:

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

E poi ci sono altre sei soluzioni che funzionano in modo diverso con vari livelli di follia:

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

0101: B

 ? ?
! @ .
 . .

Woohoo, un altro semplice: leggi A, leggi B, stampa B, termina. In realtà ci sono alternative a questo però. Dato che Aè solo un singolo personaggio, possiamo anche leggerlo con ,:

,?!@

E c'è anche la possibilità di utilizzare un singolo ?e utilizzare un mirror per eseguirlo due volte:

?|@!    ?>@!

0110: Xor

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

Come ho detto sopra, questo era l'unico cancello che non si adattava alla lunghezza laterale 2, quindi questa è una soluzione scritta a mano da FryAmTheEggman e da me, e c'è una buona probabilità che non sia ottimale. Vi sono due casi da distinguere. Se A = 0il flusso di controllo è abbastanza semplice (perché in quel caso dobbiamo solo stampare B):

io

Iniziamo sul sentiero rosso. ?legge A, <è un ramo che devia lo zero sinistro. L'IP si sposta in basso, quindi _è un altro mirror e quando l'IP colpisce l'angolo, si sposta nell'angolo in alto a sinistra e continua sul percorso blu. ?legge B, !stampa. Ora lo (diminuisce. Questo è importante perché garantisce che il valore non sia positivo (sia 0o sia -1adesso). Ciò fa avvolgere l'IP nell'angolo destro, dove @termina il programma.

Quando le A = 1cose si fanno un po 'più complicate. In tal caso, vogliamo stampare not B, che di per sé non è troppo difficile, ma il percorso di esecuzione è un po 'lento.

io

Questa volta, <devia l'IP a destra e poi <agisce solo come mirror. Quindi l'IP percorre lo stesso percorso al contrario, leggendo Bquando si incontra di ?nuovo. L'IP si avvolge nell'angolo destro e continua sul percorso verde. It prossimi incontri (~che è "decremento, moltiplicare per -1", quali swap 0e 1e calcola quindi not B. \è solo uno specchio e !stampa il risultato desiderato. Quindi ?tenta di restituire un altro numero ma restituisce zero. L'IP ora continua nell'angolo in basso a sinistra sul percorso blu. (diminuisce, <riflette,(diminuisce nuovamente, in modo che il valore corrente sia negativo quando l'IP colpisce l'angolo. Si sposta attraverso la diagonale in basso a destra e infine colpisce @per terminare il programma.

0111: O

 ? <
< @ !
 . .

Più corto circuito.

io io

Il A = 0caso (il percorso rosso) è un po 'confuso qui. L'IP viene deviato a sinistra, si avvolge nell'angolo in basso a sinistra, viene immediatamente riflesso da <e torna ?alla lettura B. Si avvolge poi verso l'angolo rigt, stampa Bcon !e termina.

Il A = 1caso (il percorso verde) è un po 'più semplice. Il <ramo devia l'IP a destra, quindi stampiamo semplicemente !, torniamo in alto a sinistra e terminiamo a @.

Esiste solo un'altra soluzione a 5 byte:

\>?@!

Funziona essenzialmente allo stesso modo, ma i percorsi di esecuzione effettivi sono piuttosto diversi e utilizza un angolo per la ramificazione anziché a <.

1000: Né

 ) \
! # ?
 @ {

Questo potrebbe essere il mio programma preferito trovato in questa ricerca. La cosa più interessante è che questa implementazione norfunziona fino a 5 input. Dovrò entrare un po 'nei dettagli del modello di memoria per spiegarlo. Così come un rapido aggiornamento, modello di memoria di Hexagony è una griglia esagonale separata, dove ogni bordo conserva un valore intero (inizialmente tutti zero). C'è un puntatore di memoria (MP) che indica un bordo e una direzione lungo quel bordo (in modo tale che ci siano due bordi vicini davanti e dietro il bordo corrente, con i vicini significativi sinistro e destro). Ecco un diagramma dei bordi che useremo, con la MP che inizia come mostrato in rosso:

io

Consideriamo innanzitutto il caso in cui entrambi gli input sono 0:

io

Iniziamo sul percorso grigio, che semplicemente incrementa il bordo A in 1modo che passi #a IP 1che è il percorso blu, iniziando nell'angolo in alto a destra. \non fa nulla lì e ?legge un input. Si avvolge nell'angolo in alto a sinistra dove )incrementa tale input. Ora fino a quando l'input è zero, questo si tradurrà in a 1, quindi #non fa nulla. Poi {sposta il MP a fianco, cioè alla prima iterazione da A a B . Poiché questo fronte ha ancora il suo zero iniziale, l'IP torna all'angolo in alto a destra e su un nuovo bordo di memoria. Quindi questo ciclo continuerà finché ?legge zero, spostando il MP attorno all'esagono da Ba C a D e così via. Non importa se ?restituisce uno zero perché era un input o perché era EOF.

Dopo sei iterazioni attraverso questo ciclo, {torna a A . Questa volta, il bordo contiene già il valore 1sin dalla prima iterazione, quindi l'IP si sposta nell'angolo sinistro e continua invece sul percorso verde. !semplicemente lo stampa 1e @termina il programma.

E se uno qualsiasi degli input fosse 1?

io

Quindi lo ?legge 1ad un certo punto e lo )incrementa a 2. Ciò significa #che ora cambierà di nuovo gli IP e continueremo nell'angolo destro sul percorso rosso. ?legge un altro input (se ce n'è uno), che non ha molta importanza e si {sposta ulteriormente di un vantaggio. Questo deve essere un vantaggio inutilizzato, quindi funziona fino a 5 ingressi. L'IP si sposta in alto a destra dove viene immediatamente riflesso e si sposta nell'angolo sinistro. !stampa il 0bordo inutilizzato e #ritorna su IP 0. Quell'IP stava ancora aspettando sul #, andando a sud-ovest (percorso grigio), quindi colpisce immediatamente @e termina il programma.

In totale ci sono sette soluzioni a 7 byte per questo gate. 5 di questi funzionano allo stesso modo e usano semplicemente altri comandi per spostarsi su un bordo inutilizzato (e possono camminare attorno a un esagono diverso o in una direzione diversa):

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

E c'è un'altra classe di soluzioni che funziona solo con due input, ma i cui percorsi di esecuzione sono in realtà ancora più complicati:

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

1001: Uguaglianza

 ( ~
? / @
 # !

Questo fa anche un uso molto intelligente della selezione IP condizionale. Dobbiamo distinguere di nuovo tra A = 0e A = 1. Nel primo caso vogliamo stampare not B, nel secondo vogliamo stampare B. Per A = 0noi anche distinguere i due casi per B. Cominciamo con A = B = 0:

io

Iniziamo sul sentiero grigio. (~può essere ignorato, l'IP si sposta nell'angolo sinistro (sempre sul percorso grigio) e legge Acon ?. (lo decrementa, così otteniamo -1e IP avvolgiamo nell'angolo in basso a sinistra. Ora, come ho detto prima, #prende il valore modulo 6prima di scegliere l'IP, quindi un valore di -1effettivamente esce IP 5, che inizia nell'angolo sinistro sul percorso rosso. ?legge B, (decrementa anche quello in modo da rimanere su IP 5quando colpiamo di #nuovo. ~annulla il -1modo in cui l'IP si sposta nell'angolo in basso a destra, stampa 1e termina.

io

Ora, se Bè 1invece, il valore corrente sarà 0quando premiamo #la seconda volta, quindi torniamo a IP 0(ora sul percorso verde). Ciò colpisce ?una terza volta, cedendo 0, !stampandolo e @termina.

io

Infine, il caso in cui A = 1. Questa volta il valore corrente è già zero quando colpiamo #per la prima volta, quindi questo non passa mai all'IP 5in primo luogo. Continuiamo semplicemente immediatamente sul sentiero verde. ?ora non solo dà uno zero ma ritorna Binvece. !lo stampa e @termina di nuovo.

In totale ci sono tre soluzioni a 7 byte per questo gate. Gli altri due funzionano in modo molto diverso (anche gli uni dagli altri) e ne fanno un uso ancora più strano #. In particolare leggono uno o più valori con ,(leggendo un codice carattere anziché un numero intero) e quindi usano quel valore modulo 6 per scegliere un IP. È pazzesco.

),)#?@!

?~#,~!@

1010: Non B

 ? ?
| @ !
 ) .

Questo è abbastanza semplice. Il percorso di esecuzione è il ramo orizzontale che già conosciamo da andprima. ??legge Ae poi immediatamente B. Dopo aver riflettuto su |e ramificato, B = 0eseguiremo il ramo inferiore, dove )incrementa il valore su 1cui viene quindi stampato !. Sul ramo superiore (se B = 1) ?semplicemente reimpostare il bordo su 0cui viene anche stampato da !.

Esistono otto programmi a 6 byte per questo gate. Quattro di loro sono praticamente uguali, usando o >invece di |o 1invece di )(o entrambi):

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

Due usano un singolo ?che viene utilizzato due volte a causa di uno specchio. La negazione si verifica quindi come abbiamo fatto xorcon uno (~o ~).

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

E infine, due soluzioni utilizzano uno switch IP condizionale, perché perché usare il modo semplice se anche quello contorto funziona:

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

1011: B implica A

 \ #
? ? !
 1 @

Questo utilizza una commutazione IP piuttosto elaborata. Inizierò con il A = 1caso questa volta, perché è più semplice:

inserisci qui la descrizione dell'immagine

Iniziamo sul percorso grigio, che legge Acon ?e poi colpisce il #. Poiché Aè 1presente commuta IP 1(percorso verde). Lo !stampa immediatamente, l'IP si sposta in alto a sinistra, legge B(inutilmente) e termina.

Quando le A = 0cose diventano un po 'più interessanti. Per prima cosa consideriamo A = B = 0:

inserisci qui la descrizione dell'immagine

Questa volta, il #non fa nulla e restiamo su IP 0(percorso rosso da quel punto in poi). ?legge Be lo 1trasforma in a 1. Dopo esserci spostati nell'angolo in alto a sinistra, premiamo di #nuovo, quindi alla fine finiamo sul percorso verde e stampiamo 1come prima, prima di terminare.

Infine, ecco (A, B) = (0, 1)il caso falso:

inserisci qui la descrizione dell'immagine

Nota che ho rimosso il percorso grigio iniziale per chiarezza, ma il programma inizia allo stesso modo e finiamo sul percorso rosso di prima. Quindi questa volta il secondo ?ritorna 1. Ora incontriamo il 1. A questo punto è importante capire cosa fanno effettivamente le cifre in Esagonia (finora le abbiamo usate solo sugli zeri): quando si incontra una cifra, il valore corrente viene moltiplicato per 10 e quindi la cifra viene aggiunta. Questo è normalmente usato per scrivere numeri decimali alla lettera nel codice sorgente, ma significa che B = 1è effettivamente associato al valore 11. Quindi, quando colpiamo #, questo è preso modulo 6per dare 5e quindi passiamo a IP 5(invece di 1come prima) e continuiamo sul percorso blu. colpire?una terza volta restituisce uno zero, quindi !stampa che, e dopo altre due ?, l'IP si sposta in basso a destra dove termina il programma.

Esistono quattro soluzioni a 7 byte e funzionano tutte in modo diverso:

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

1100: Non A

 ? (
~ ! @
 . .

Semplicemente lineare: leggi Acon ?, nega con (~, stampa con !, termina con @.

C'è una soluzione alternativa, e questo invece sta negando ~):

?~)!@

1101: A implica B

 ? .
| @ !
 ) .

Questo è molto più semplice dell'implicazione opposta di cui abbiamo appena parlato. È di nuovo uno di quei programmi di diramazione orizzontale, come quello per and. Se lo Aè 0, viene semplicemente incrementato 1sul ramo inferiore e stampato. Altrimenti, il ramo superiore viene eseguito di nuovo dove ?legge Be poi lo !stampa invece.

Ci sono un sacco di alternative qui (66 soluzioni in totale), principalmente a causa della libera scelta di no-op efficaci. Per cominciare, possiamo variare la soluzione sopra in tutti gli stessi modi in cui potremmo ande possiamo anche scegliere tra )e 1:

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

E poi c'è una versione diversa che utilizza la selezione IP condizionale, in cui il primo comando può essere scelto quasi arbitrariamente, e c'è anche una scelta tra )e 1per alcune di quelle opzioni:

"?#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

 ? $
@ # )
 ! <

L'ultima complicata. Se stai ancora leggendo, ce l'hai quasi fatta. :) Diamo un'occhiata A = 0prima:

inserisci qui la descrizione dell'immagine

?legge Ae poi colpiamo $. Questo è un comando di salto (come quello di Befunge #) che salta le istruzioni successive in modo da non terminare su @. Invece l'IP continua a #. Tuttavia, dato che Aè 0, questo non fa nulla. )lo incrementa in 1modo che l'IP continui sul percorso inferiore in cui 1è stampato. Il <devia l'IP a destra dove si avvolge nell'angolo sinistro e il programma termina.

Successivamente, quando l'input è (A, B) = (1, 0), otteniamo questa situazione:

inserisci qui la descrizione dell'immagine

E 'essenzialmente la stessa di prima, tranne che al #si passa a IP 1(percorso verde), ma dal momento che Bè 0si passa di nuovo a IP 0quando colpiamo #una seconda volta (ora blu percorso), dove viene stampato 1come prima.

Infine, il A = B = 1caso:

inserisci qui la descrizione dell'immagine

Questa volta, quando siamo #la seconda volta, il valore corrente è ancora in 1modo da non modificare nuovamente l'IP. Il <riflesso e la terza volta che colpiamo ?otteniamo uno zero. Quindi l'IP si sposta in basso a sinistra dove !stampa lo zero e il programma termina.

Ci sono nove soluzioni a 7 byte in totale per questo. La prima alternativa utilizza semplicemente 1invece di ):

?$@#1!<

Quindi ci sono due soluzioni che faranno la tua testa con la quantità di commutazione IP che sta succedendo:

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

Questi in realtà mi hanno fatto impazzire: la parte interessante è che la commutazione IP può essere utilizzata come condizione differita. Le regole di commutazione IP della lingua sono tali che l'IP corrente fa un altro passo prima che avvenga lo switch. Se succede che quel passaggio attraversi un angolo, allora il valore corrente decide su quale ramo continuerà l'IP se dovessimo tornare ad esso. Questo succede esattamente quando l'ingresso è A = B = 1. Sebbene tutto ciò sia coerente con il modo in cui ho progettato la lingua, non sono mai stato consapevole di questa implicazione delle specifiche, quindi è bello quando la mia lingua mi insegna alcuni nuovi trucchi: D.

Poi c'è una terza soluzione la cui quantità di commutazione IP è ancora peggiore (anche se non utilizza quell'effetto condizionato differito):

>?1]#!@

E poi ce n'è un altro:

?$@#)!<

E poi ci sono queste quattro soluzioni equivalenti, che usano una commutazione IP non condizionale e implementano invece tutta la logica tramite rami e angoli:

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

1111: Vero

 1 !
@ . .
 . .

Ti sei guadagnato qualcosa di semplice per la fine: imposta il bordo su 1, stampa con !, termina con @. :)

Certo, c'è un'alternativa:

)!@

Come al solito, tutti i diagrammi di flusso di controllo creati con HexagonyColorer di Timwi e il diagramma di memoria con il suo EsotericIDE .


9
Aaaaaand the tl; dr award va a ... (scherzando ovviamente, ottima risposta e scritta molto bene, +1)
Bassdrop Cumberwubwubwub il

4
Questo è il motivo per cui non sei più attivo in chat ??
Ottimizzatore

Un po 'tardi, ma potresti aggiungere un link al tuo codice di forza bruta?
nedla2004,

@ nedla2004 Di solito non li tengo in giro, ma è sempre una versione modificata di questo script .
Martin Ender,

40

APL, 22 20 18 byte

Le voci true e false sono programmi completi e le altre 14 sono funzioni. (Grazie ad 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)

Provalo qui.


1
+1 Un buon uso dei top! È possibile salvare due byte trasformando 0000 e 1111 in trad-fns 0e 1.
Adám,

Esiste un consenso per consentire a tfns, ma non di contare la prima riga. Ciò corrisponde al non conteggio del nome file nelle lingue che utilizzano i file come contenitori del programma con nome programma = nome file.
Adám,


10
Gelatina: 19 byte. Questo: 18 byte. Questo non significa che hai superato Dolf ? +1 per quello.
NoOneIsHere il

29

Chess / mediocre giocatore di scacchi in endgame, 70 pezzi

Ispirato da quella risposta domino, ho deciso che un altro gioco avrebbe dovuto avere questo onore.

Nota che ho preso alcune regole su come si muovono i pezzi. Poiché non ho voglia di studiare le mosse ottimali per ogni situazione, le regole per le mosse dei bianchi sono semplici: stai fuori controllo, cattura il pezzo più alto che può fare in quel turno, perdendo il minor materiale possibile e ferma una pedina dalla promozione, in quell'ordine di priorità. Se ci sono due spazi in cui può spostarsi, con uguale preferenza, può spostarsi su entrambi (quindi in questi, se può spostarsi su più di un quadrato, hanno lo stesso colore). Nota che il bianco catturerà con qualcosa anche se viene catturato, se il pezzo che sta attaccando ha un valore più alto di quello perso. I valori sono qui:pawn<knight=bishop<rook<queen

L'input è se è presente una torre. Nota che le torri sono etichettate con i nomi A e B solo quando importa: se il gate si comporta allo stesso modo quando le torri sono commutate, non sono etichettate.

L'output è il colore del re quadrato bianco termina con: Bianco = 1, nero = 0

Prima delle immagini, voglio scusarmi per le immagini scadenti. Non sono molto bravo a tenere ferma una fotocamera.

Falso, 4:

falso

E, 4:

inserisci qui la descrizione dell'immagine

A e non B, 5 (penso di poter arrivare a tre, ma non ho il board in questo momento):

inserisci qui la descrizione dell'immagine

A, 4:

inserisci qui la descrizione dell'immagine

Non A e B, 5 (penso di poter arrivare a tre, ma non ho il board in questo momento):

inserisci qui la descrizione dell'immagine

B, 4:

inserisci qui la descrizione dell'immagine

Xor, 5 (conosco un modo per farlo 4, ma non ho il board in questo momento):

inserisci qui la descrizione dell'immagine

Oppure, 4:

inserisci qui la descrizione dell'immagine

Né 4:

inserisci qui la descrizione dell'immagine

Xnor, 5 (conosco un modo per farlo 4, ma non ho il board in questo momento):

inserisci qui la descrizione dell'immagine

Non B, 4:

inserisci qui la descrizione dell'immagine

B implica A, 5 (penso di poter arrivare a tre, ma non ho il board in questo momento):

inserisci qui la descrizione dell'immagine

Non A, 4:

inserisci qui la descrizione dell'immagine

A implica B, 5 (penso di poter arrivare a tre, ma non ho il board in questo momento):

inserisci qui la descrizione dell'immagine

Nand, 4:

inserisci qui la descrizione dell'immagine

Vero, 4:

inserisci qui la descrizione dell'immagine


1
Wow, non avevo idea che fosse possibile programmare negli scacchi ... Potresti pubblicare un video / simulazione di alcuni di questi in azione?
Decadimento beta

2
hmmm, al momento non ho accesso alla scacchiera. Probabilmente direi che A implica che B / B implica che a / etc sono più difficili da capire a causa dell'effetto dei pedoni sul movimento dei re. Probabilmente dovrei aggiungere una spiegazione migliore per quei due
Destructible Lemon

Sono contento di ispirare: D Se ho capito bene, la posizione del tabellone e dei pezzi è equivalente a un programma. I corvi sono l'input, quindi posso posizionarli su qualsiasi quadrato purché sia ​​del colore giusto?
NonlinearFruit

No, l'input delle torri è se sono presenti o assenti dal tabellone. Sono etichettati aeb quando non sono porte simmetriche (quando contano le diverse aeb). Inoltre mi sono reso conto di come avrei potuto giocare a golf con 2 pezzi, ma al momento non ho la tavola. Il pennello deve essere utilizzato :)
Limone distruttibile

Nel tuo caso "E", se rimuovi la torre giusta, cosa impedisce al re di spostarsi verso il basso (verso il bianco)?
Nathan Merrill,

27

Gelatina , 19 byte

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.

Provalo online!


13
Adoro l'uso di Factorial per convertire 0 o 1 in 1.
Neil,

Jelly UTF-8 è? Se sì allora ¤e ¬sono 2 byte, non 1.
Vi.

1
@Vi. Jelly supporta UTF-8, ma supporta anche una tabella codici personalizzata che codifica ciascuno dei 256 caratteri che comprende come un singolo byte ciascuno. Il collegamento byte nell'intestazione punta ad esso.
Dennis,

0 0 1 0 > 1 byte Greater than.questo non fallirebbe se il secondo input fosse negativo?
MD XF,

@MFXF Possiamo scegliere quale valore di verità e quale valore di falsità supportiamo.
Dennis,

24

Porte logiche NAND - 31 porte

Come creatore della serie originale di domande sulla porta NAND , non potevo lasciarmi sfuggire l'opportunità di usare queste porte per risolvere un altro problema di porta logica.

inserisci qui la descrizione dell'immagine

In ciascuno di questi diagrammi, l'ingresso superiore è A mentre l'ingresso inferiore è B.


5
@xnor potrebbe essere lusingato di sapere che la sua porta logica è quella che richiede il maggior numero di porte NAND per realizzare D:
Joe Z.

Potresti almeno usare Logisim per formattare il tuo codice?
mbomb007,

1
@ mbomb007 Lo modificherò più avanti. Non ho molta esperienza con Logisim, quindi potrebbe volerci un po '.
Joe Z.

3
Ma mi piace di più la calligrafia.
Leaky Nun,

1
In alternativa, non è possibile passare a né gate e formattarlo utilizzando la
pietra rossa

22

Tag ciclico bit a bit, 118 bit = 14,75 byte

Bitwise Cyclic Tag è forse il linguaggio Turing-complete più semplice mai concepito. C'è un nastro di programma e un nastro di dati, entrambi costituiti da un elenco di bit. Il nastro del programma viene interpretato ciclicamente fino a quando il nastro dati non è vuoto, come segue:

  • 0: elimina il primo bit dal nastro dati.
  • 1x: se il primo bit del nastro dati è 1, aggiungere il bit xal nastro dati.

Inizializziamo il nastro dati con un 1 seguito dai due bit di input (l'1 è necessario perché non è possibile creare un 1 se il nastro dati è costituito interamente da 0) e utilizziamo il bit di dati eliminato finale come output del gate .

  • 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

Congratulazioni!
Leaky Nun,

È il finale 1su falserichiesta?
Calcolatrice

@CalculatorFeline Sì, è necessario aggiungere un 0nastro al nastro in modo che possa essere eliminato per ultimo.
Anders Kaseorg,

Ah. Dimenticato + che si avvolge. Intelligente!
Calcolatrice

20

Python 2, 137 byte

[].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

Accetta input come min(True,False)(o come min(1,0)). Sfrutta al massimo le uscite che necessitano solo del giusto valore Truthy-Falsey. Quando possibile, utilizza un built-in per evitare un costoso lambda. Ho usato il codice per cercare i built-in che funzionano.

Il mio preferito è {0:1}.get, a cui ho pensato a mano. Il dizionario {0:1}associa la chiave 0al valore 1. Il suo getmetodo accetta una chiave e un valore predefinito, producendo il valore corrispondente alla chiave o il valore predefinito se non esiste tale chiave. Quindi, l'unico modo per produrre a 0è as {0:1}.get(1,0), con chiave mancante 1e impostazione predefinita 0. Si possono ottenere altre varianti con dizionari diversi, ma solo questa è la più breve.

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]

Non puoi usare metodi di built-in come int __lt__o __eq__? Ciò ridurrà ulteriormente il conteggio dei byte: int.__gt__anziché lambda a,b:b<1, int.__eq__anziché lambda a,b:a==be così via
Gábor Fekete,

@ GáborFekete Quelli non esistono in Python 2 perché inti confronti di offload sono cmp. Non ho provato questo per Python 3.
xnor

Oh adesso vedo!
Gábor Fekete,

Salvare 4 byte utilizzando la funzione notper 0001, False- ideone
Jonathan Allan,

1
@JonathanAllan È intelligente, ma penso che notnon soddisfi i requisiti di una funzione perché non puoi farlo f=not;f(3,4). La stringa notsembra funzionare perché i presunti argomenti della funzione sembrano una tupla, proprio come 3+funzionerebbe 3+(4)anche se 3+non come una funzione che può assumere 4come input.
xnor

20

Go (gioco), 33 pietre, 73 incroci

Se il domino e gli scacchi sono accettabili, allora questo. Non può essere troppo golfoso su una tavola da 19x19 Go completa. Quindi ho usato piccole tavole rettangolari. L'input è se sono presenti le pietre segnate 1 e 2. L'output è se il nero vince. Utilizza il punteggio dell'area, 0,5 komi, superko situazionale, nessun suicidio. Tutto nero per giocare. Ad alcune vengono fornite più soluzioni.

Il bianco vince (2, 1x5):

➊━━━➋

1 e 2 (3, 2x3):

➊◯➋
┗┷┛

1 e non 2 (2, 1x5):

╺➊━➁╸

1 (2, 1x5):

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

Non 1 e 2 (2, 1x5):

╺➋━➀╸

2 (2, 1x5):

╺➋➀━╸

1 xo 2 (2, 2x3):

➀┯➁
┗┷┛

1 o 2 (2, 1x5):

╺➊━➋╸
➀━━━➁

1 né 2 (2, 1x4):

➊━━➋
╺➀➁╸

1 = 2 (2, 1x7):

╺━➀━➁━╸

Non 2 (2, 1x3):

➀➁╸

1 o meno 2 (2, 1x4):

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

Non 1 (2, 1x3)

➁➀╸

Non 1 o 2 (2, 1x4):

➁➀━╸

1 nand 2 (2, 1x3):

➊━➋

Il nero vince (2, 1x3):

➊➋╸
➀━➁
➊━➁

Questa pagina mi ha aiutato un po ': http://www.mathpuzzle.com/go.html

Forse qualcuno potrebbe trovare una soluzione 2 di pietra per 1 e 2 su una scheda 1x9 ...


1
Quali sono le tue regole per il suicidio? Non consentito? E cosa succede quando una parte riempie l'intera scheda? È considerato un suicidio?
Martin Ender,

@MartinEnder non consentito. E sì, è considerato un suicidio.
jimmy23013,

La soluzione 1x7 sembrava sbagliata. Sto cercando di risolverlo ...
jimmy23013,

15

Javascript ES6, 124 byte

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

Odio seriamente le lambda in questo momento.


1
Se mi è permesso di scrivere alcuni programmi e alcune funzioni ... Penso che si potrebbe cambiare a=>b=>0per a=>0e dire la grammatica definendolo è (a=>0)(a,b), solo per quei 4 voci.
jimmy23013,

Oh sì, grazie!
Mama Fun Roll,

2
Math.mininvece di a=>b=>a&b. Math.maxinvece di a=>b=>a|b. Math.powinvece di a=>b=>a>=b.
Conor O'Brien,

1
Inoltre, poiché NaN è falso, puoi fare parseIntinvece di a=>b=>a>b.
Conor O'Brien,

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

14

Retina , 62 39 byte

23 byte grazie a @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: 

Accetta input come PQ.

Emette un numero intero tra 0a 3. 0è falso, altri sono sinceri.

Spiegazione

Sono solo regex .

Ad esempio, 01|10solo corrisponde 01o 10.

In 0000, 2non sarà mai nell'input, quindi non corrisponde mai.

In 1111, corrisponde alla stringa vuota, che ci sono 4.


^1|0$dovrebbe corrispondere solo a 1 stringhe di caratteri. Cosa sta succedendo qui?
Calcolatrice

@CalculatorFeline Corrisponde a [ 1all'inizio dell'input] OPPURE [ 0alla fine dell'input]. Mi ci è
voluto

Precedenza, ragazzi ....
Leaky Nun,

Immagino ^1|0$sia più difficile da leggere di 1.|.0. Sembra rendere la lettura più difficile in tutto
l4m2

10

Stack Cats , 67 + 64 = 131 byte

Si noti che il +64 deriva dall'applicazione dei -nmflag a ciascun programma. -nindica I / O numerico e -mriflette il codice sorgente sull'ultimo carattere - non tutti gli invii hanno bisogno di questi flag tecnicamente, ma per coerenza e semplicità li sto segnando allo stesso modo.

-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+

()in Stack Cats verifica se un elemento è positivo o non positivo (cioè 0 o negativo), quindi lo stiamo usando rispettivamente per verità / falsità. La seconda colonna è solo per interesse ed elenca le migliori porte con 0/ 1s come output (con punteggio totale 90).

L'ingresso è costituito da bit separati da delimitatori tramite STDIN. Provalo online!


Stack Cats è un linguaggio esoterico reversibile, in cui i programmi hanno una simmetria riflettente. Dato uno snippet f(ad es. >[[(!-)/), L'immagine speculare (ad es. \(-!)]]<) Calcola l'inverso f^-1. Come tale, anche i programmi di lunghezza non fanno nulla (o rimangono bloccati in un ciclo infinito) e gli unici programmi non banali hanno una lunghezza dispari, calcolando f g f^-1dov'è gl'operatore centrale.

Poiché metà del codice sorgente è sempre ridondante, può essere escluso e l'esecuzione del codice con il -mflag indica che il codice sorgente deve essere rispecchiato sull'ultimo carattere per recuperare il codice sorgente effettivo. Ad esempio, il programma *<Xè in realtà *<X>*, che è simmetrico.

Giocare a golf con Stack Cats non è molto intuitivo, quindi i programmi di cui sopra dovevano essere trovati con la forza bruta. Molti di loro sono sorprendentemente complessi, ma ne spiegherò alcuni e aggiungerò a questa risposta quando avrò tempo. Per ora, alcune spiegazioni e soluzioni alternative per le versioni 0/ 1sono disponibili sul repository Github qui .


1
Note that the +64 is from applying the -nm flags to each program.3 * 16 = 48 o 2 * 16 = 32, in entrambi i casi 64 è il modo in cui hai
cat

@cat I flag costano 4 per programma, poiché devi contare anche lo spazio.
FryAmTheEggman,


È passato più di un anno. Hai ancora tempo?
Calcolatrice

8

Haskell, 78 76 75 byte

  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

Modifica: -1 byte grazie a @cole.


Stavo per commentare "amico, _#_non è un operatore standard!" E poi ho capito ... Ben fatto.
MathematicalOrchid,

4 potrebbe esserepure
cole

@cole: grazie. Wow, è purestato introdotto Preludenel 2015, quindi era disponibile al momento di questa sfida.
nimi

6

Brachylog , 36 34 byte

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)

Questo si aspetta 0come valore di falsità e 1come valore di verità. Restituisce trueo false. p è Inpute q è Output.


Come si immette l'output?
Leaky Nun,

1
@LeakyNun Proprio come l'input. Il predicato principale su cui si esegue la query ha due argomenti, chiamati Inpute Outputper convenzione, ma è possibile impostare valori su entrambi o restituire valori da entrambi.
Fatalizza il

1
Questo è lo strumento giusto per il lavoro: P
Conor O'Brien,

6

Prolog, 147 145 byte

Guadagnato 2 byte grazie a @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

Eseguire una query x(P,Q).con xla lettera appropriata Pe Qimpostare su 0 o 1.
Restituisce trueo false.

Esempio SWISH inclusi test - invio runTest.per l'esecuzione.


Supporta a(2,2).falso?
jimmy23013,

@ jimmy23013 Immagino che potrebbe accadere se suppongo che 2 sia falso. Non sono sicuro che sia accettabile.
Fatalizza il

@ jimmy23013 In realtà, a(a,a).(o qualsiasi altra lettera) funziona anche e anon è un input accettabile per la verità, quindi va bene. Grazie per il suggerimento
Fatalizza il

6

NTFJ, 86 byte

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               #

Provalo qui! Ma leggi prima sotto.

L'input è implicito nello stack. Il risultato viene lasciato in pila. Aggiungere 16 byte (uno *alla fine di ciascuno) se si desidera 0x00o 0x01all'output che rappresenta 0 e 1. Aggiungere altri 160 byte se si desidera uno 0o uno 1stampato. (Metti ~~##~~~#{@prima di ciascuno *.)

L'unico operatore binario di NTFJ è NAND, quindi ognuno di questi è scritto in forma NAND.

Analizziamo ciascuno di essi.

0: falso

~

~rappresenta un bit falso. Abbastanza semplice. Poiché l'input è implicito nella parte inferiore dello stack, questo viene lasciato nella parte superiore.

1: p e q

|:|

NTFJ opera su uno stack. :è il comando per duplicato. Osserva che p and qnot (p nand q)e quello 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

(Nota, quindi, si :|può dire che è negazione e si |:|può dire che sia congiunzione )

2: p e non q

:||:|

Osserva che questa è solo una negazione :|e una congiunzione |:|.

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

3: p

$

$estrae un oggetto dalla pila. Quindi ... si.

4: non p e q

#{:||:|

Questa è la stessa cosa di 2, tranne #{all'inizio. #spinge 1 (il bit vero) e {ruota lo stack a sinistra una volta. Abbastanza semplice.

5: q

#{$

Ruota a sinistra una volta, rilascia.

6: xor

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

Osservare:

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

Tuttavia, non è possibile duplicare completamente lo stack. Quindi, stiamo andando ad avere per portare ciascuno dei p, qverso l'alto e duplicarlo.

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))

E quindi, abbiamo il nostro xor.

7: p o q

:|#{:||

Annulla la parte superiore, porta la parte inferiore in cima, annulla quella e mettile insieme. Fondamentalmente, p or q = (not p) nand (not q).

8: non p e non q

:|#{:||:|

Questa è semplicemente la negazione di 7. Facile.

9: eq

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

Questo è solo xnor o no xor. Di nuovo semplice.

10: non q

#{$:|

Negazione di 5.

11: p oppure no q

#{:||

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

12: non p

$:|

Rilascia, ferma e annulla.

13: non p o q

:||

Le leggi di De Morgan per salvare di nuovo la situazione! Stesso processo di 11, semplicemente negando qinvece di p.

14: non p o non q

|

Questa è solo una mimica nand.

15: vero

#

# è il vero bit.


solo perché ...> _>
Rɪᴋᴇʀ

idk esattamente come funziona ma sembra piuttosto interessante +1
Downgoat

Perché 5 non è solo un programma vuoto e 10 solo :|?
Joffan,

6

Minecraft, 89 blocchi

In tutte le seguenti foto, i blocchi blu sono per l'ingresso A e i blocchi arancioni sono per l'ingresso B

16. VERO gate - 1 blocco

inserisci qui la descrizione dell'immagine

15. Cancello NAND - 1x2x3 = 6 blocchi

inserisci qui la descrizione dell'immagine

14. A => B - 1x2x3 = 6 blocchiinserisci qui la descrizione dell'immagine

13. NON A - 2 blocchi inserisci qui la descrizione dell'immagine

12. B => A - 1x2x3 = 6 blocchiinserisci qui la descrizione dell'immagine

11. NON B - 2 blocchi inserisci qui la descrizione dell'immagine

10. XNOR - 1x3x4 = 12 blocchi inserisci qui la descrizione dell'immagine

9. NOR - 1x2x3 = 6 blocchiinserisci qui la descrizione dell'immagine

8. OPPURE - 1 blocco inserisci qui la descrizione dell'immagine

7. XOR - 1x3x4 = 12 blocchi inserisci qui la descrizione dell'immagine

6. B - 1 blocchi inserisci qui la descrizione dell'immagine

5.! A&B - 1x2x5 = 10 blocchi inserisci qui la descrizione dell'immagine

4. A - 1 blocchi inserisci qui la descrizione dell'immagine

3. A &! B - 1x2x5 = 10 blocchi inserisci qui la descrizione dell'immagine

2. AND - 2x2x3 = 12 blocchi inserisci qui la descrizione dell'immagine

1. FALSO - 1 blocco inserisci qui la descrizione dell'immagine


2
Nella penultima immagine (AND) è possibile salvare 6 blocchi posizionando le torce in cima al retro dei blocchi, cioè di fronte alle leve. Scambia la torcia nel mezzo per un pezzo di polvere e rimuovi la polvere in alto, portandola a 1x2x3 = 6 blocchi.
Luca H,

5

Mathematica, 67 byte

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

Ognuno di questi valuta una funzione, quindi puoi usarli come

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

Ah, se solo i numeri interi fossero veritieri / falsi in Mathematica, quei quattro più lunghi avrebbero potuto essere abbreviati considerevolmente.


Se i numeri interi non sono verità / falsità, cosa succede quando li inserisci in un'istruzione if?
Conor O'Brien,

3
@ CᴏɴᴏʀO'Bʀɪᴇɴ rimane non valutato.
Martin Ender,

5

MATL, 34 23 byte

Spero di aver capito bene! Zero è falso, non zero è verità. Ogni funzione accetta due input impliciti (sebbene possa ignorare alcuni input). Il primo input è A e il secondo è B. È possibile inserire 0/ 1per true / false o T/ F.

Ecco un esempio TryItOnline per il caso di test 3.

Salvati 4 byte usando *per and, e altri 4 usando >/ <invece di ~wY&/w~Y&Ho dopo che ho visto la risposta di Dennis!

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
Il numero sei pensa che sia divertente.
Conor O'Brien,

@ CᴏɴᴏʀO'Bʀɪᴇɴ Il numero 6 è il migliore, mi piace anche il numero 12! xD!
David,

Non hai la funzione "disuguale"?
Leaky Nun,

No (almeno non la penso così)
David,

2
@ David Penso che il numero 7 possa essere sostituito da-
Luis Mendo,

5

dc, 37 byte

dc("calcolatrice da tavolo") è un comando unix standard, una calcolatrice postfix basata su stack. Manca di operazioni a bit e gli operatori di confronto possono essere utilizzati solo per eseguire macro (che non vale i byte). La divisione intera ne compensa una parte.

Questi script prevedono valori 0e 1valori nello stack e lasciano il risultato nello stack.

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

Labyrinth , 85 byte

Grazie a Sp3000 per aver salvato 2 byte.

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

Tutti questi sono programmi completi, che leggono due numeri interi 0o 1da STDIN (usando qualsiasi separatore senza cifre) e stampano il risultato come 0o 1su STDOUT.

Provalo online! (Non una suite di test, quindi dovrai provare manualmente diversi programmi e input.)

Per quanto riguarda le spiegazioni, queste sono tutte piuttosto semplici. Tutti i programmi sono lineari e i comandi in uso eseguono le seguenti operazioni:

?   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.

Nota che sto usando #è sempre usato per combinarlo con $, cioè per calcolare XOR 1, o in altre parole per negazione logica. Solo in pochi casi sono stato in grado di utilizzare ~invece, perché il successivo &scarta tutti i bit indesiderati dal risultante -1o -2.


5

Codice macchina IA-32, 63 byte

Hexdump del codice, con lo smontaggio:

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;

Il codice è più lungo di quanto potrebbe essere, poiché utilizza una convenzione di codifica standard: input in ecxe edx, e output in al. Questo può essere espresso in C come

unsigned char __fastcall func(int, int);

Sembra che MS Visual Studio non capisca il SALCcodice operativo non documentato , quindi ho dovuto usare il suo codice, anziché il nome.

Grazie l4m2 per migliorare alcuni degli esempi di codice!


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

5

C 34 byte

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

Dove n è il numero della funzione da usare, ma penso che sarebbe rifiutato, quindi propongo questo altro:

C 244 byte (usando la memoria)

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};

utilizza una matrice indicizzata doppia. n[0][1]è(A implies B)(0,1)

Avanti 138 byte

Ho appena imparato Forth. Suppongo che sia compatibile con Ansi Forth in quanto funziona anche su 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

La funzione z crea una nuova funzione con il nome fornito, quindi porta il numero della porta logica dalla parte superiore dello stack al nuovo indirizzo della funzione. Lascia la successiva funzione (n + 1) della porta logica nello stack per la dichiarazione successiva.

puoi provarlo:
E AB

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

("." stampa la parte superiore della pila "cr" è il ritorno a capo)


Devi solo fornire frammenti di codice per ogni funzione.
Calcolatrice

4

C, 268 byte

#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 

Le macro sembrano più brevi delle funzioni.


4

Brian e Chuck , 183 byte

Grazie a Sp3000 per aver salvato 4 byte.

Alcuni programmi contengono un carattere non stampabile. In particolare, ogni \x01dovrebbe essere sostituito con il <SOH>carattere di controllo (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
?
#>+.

L'input e l'output utilizzano valori di byte , quindi l'input dovrebbe essere di due byte 0x00 o 0x01 (senza separatore) e l'output sarà uno di questi byte. Questa è in realtà anche la definizione più sensata di verità / falsità per B&C perché l'unico comando del flusso di controllo? considera gli zeri come falsità e tutto il resto verità.

spiegazioni

Prima un rapido primer B&C:

  • Ogni programma è composto da due istanze simili a Brainfuck, ciascuna scritta su una propria riga. Chiamiamo il primo Brian e il secondo Chuck . L'esecuzione inizia su Brian.
  • Il nastro di ciascun programma è il codice sorgente dell'altro programma e il puntatore alle istruzioni di ciascun programma è la testina del nastro dell'altro programma.
  • Solo Brian può usare il ,comando (input byte) e solo Chuck può usare il .comando (output byte).
  • Il []ciclo di Brainfuck non esiste. Invece, l'unico flusso di controllo che hai è ?che commuta il controllo sull'altra istanza se il valore corrente sotto la testina del nastro è diverso da zero.
  • Oltre a >e <, c'è {e }che sono essenzialmente equivalenti ai frammenti di Brainfuck [<]e [>], cioè, spostano la testina del nastro nella posizione zero successiva in quella direzione. La differenza principale è che {può anche essere arrestato all'estremità sinistra del nastro, indipendentemente dal valore che ha.
  • Per comodità, qualsiasi _s nel codice sorgente viene sostituito con byte nulli (poiché questi sono molto utili nei programmi non banali per catturare {e }).

Nota che in tutti i programmi, il nastro di Chuck inizia con a #. Questo potrebbe davvero essere qualsiasi cosa. ?funziona in modo tale che la testina del nastro si sposti di una cella prima di iniziare l'esecuzione (in modo che la condizione stessa non venga eseguita se si tratta di un comando valido). Quindi non possiamo mai usare la prima cella di Chuck per il codice.

Esistono cinque classi di programmi, che spiegherò in dettaglio più avanti. Per ora li sto elencando qui in ordine di crescente complessità.

0000, 1111: Funzioni costanti

?
#>.
?
#>+.

Questi sono molto semplici. Passiamo a Chuck incondizionatamente. Chuck sposta la testina del nastro nella cella inutilizzata a destra e la stampa direttamente oppure la incrementa prima per stampare 1.

0011, 0101, 1010, 1100: Funzioni seconda solo ingresso

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

A seconda che iniziamo con ,o ,,stiamo lavorando con Ao B. Diamo un'occhiata al primo esempio 0011(cioè A). Dopo aver letto il valore, utilizziamo ?come condizionale quel valore. Se A = 1, allora questo passa a Chuck, che sposta la testina a destra e stampa letteralmente il 1byte incorporato . Altrimenti, il controllo rimane su Brian. Qui, il 1 byte è un no-op. Quindi incrementiamo bene l'input con +per assicurarci che sia diverso da zero e poi passiamo a Chuck con ?. Questa volta, si >sposta in una cella non utilizzata a destra che viene quindi stampata come 0.

Per negare uno dei valori con cui semplicemente lo diminuiamo -. Questo si trasforma 1in 0e 0in -1, che è diverso da zero e quindi vero per quanto ?riguarda.

0001, 0010, 0100, 1000: Funzioni binarie con un risultato truthy

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

Questa è un'estensione dell'idea precedente per lavorare con due input. Diamo un'occhiata all'esempio di 1000(NOR). Leggiamo (potenzialmente) entrambi gli input con ,?. Se uno di questi è 1, ?passa a Chuck. Sposta la testina fino alla fine con }(sulla cella vuota dopo il codice di Brian), sposta un'altra cella con >(ancora zero) e la stampa con ..

Tuttavia, se entrambi gli ingressi sono zero, il controllo è ancora con Brian. >quindi sposta la testina del nastro in modo }tale che questo comando non venga eseguito quando passiamo a Chuck con ?. Ora tutto ciò che fa Chuck è >.che si sposta solo sulla 1cella e lo stampa.

Possiamo facilmente ottenere le altre tre funzioni negando uno o entrambi gli ingressi come richiesto.

0111, 1011, 1101, 1110: Funzioni binari con tre risultati truthy

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

Una piccola modifica dell'idea precedente al fine di negare il risultato (ovvero stampare 0quando abbiamo attraversato tutto Brian e 1non). Diamo un'occhiata a 0111(OR) come esempio. Si noti che il 1-byte incorporato è un no-op, quindi inizia ancora con ,?,?. Se uno dei due input è, 1passiamo a Chuck, che sposta la testina all'inizio con {. >.sposta la testina su quel 1byte e la stampa.

Se entrambi gli ingressi sono pari a zero, restiamo con Brian, spostiamo la testina su {per saltarlo e poi passiamo a Chuck. Quando esegue >.questa volta si sposta sulla cella vuota dopo il codice di Brian e stampa il 0.

Ancora una volta, otteniamo facilmente le altre funzioni negando uno o entrambi gli ingressi.

0110, 1001: Funzioni binarie con due risultati veritieri

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

Questo è un po 'più complicato. Le funzioni precedenti erano ragionevolmente semplici perché possono essere cortocircuitate : il valore del primo input può decidere l'output e, in caso contrario, guardiamo l'altro input. Per queste due funzioni, dobbiamo sempre esaminare entrambi gli ingressi.

L'idea di base è utilizzare il primo input per decidere se il secondo input sceglie tra 0e 1o tra 1e 0. Prendiamo 0110(XOR) come esempio:

Considerare A = 0. In questo caso vogliamo produrre così Bcom'è. ,legge A, ?non fa niente. >passa alla cella successiva (diversa da zero) in modo da }portarci _su Chuck. Qui, abbiamo letto Bcon ,e usare ?di nuovo. Se Bera 0così, siamo ancora su Brian. >salta }Chuck su e ?cambia in modo che le >.stampe siano 0incorporate nel codice sorgente di Brian. Se Bè stato 1d'altra parte, Chuck non esegue il }che si muove nel _nel codice di Brian già, in modo che il >.poi stampa il 1-byte invece.

Se A = 1, allora passiamo subito a Chuck, che eseguirà }+{>?. Ciò che fa è spostarsi _nel codice sorgente di Brian, trasformarlo in 1anche con +, quindi tornare all'inizio {e saltare Brian ?spostando una cella a destra con >prima di restituirgli il controllo. Questa volta, dopo Brian read's B, if B = 0, e Chuck usa >.la cella accanto a Brian ?sarà 1invece 0. Inoltre, quando B = 1, Chuck }salta su quello che era un divario e si sposta fino alla fine del nastro, in modo da >.stampare uno zero. In questo modo stiamo stampando not B.

Al fine di implementare l'equivalenza, abbiamo semplicemente negato Aprima di usarlo come condizione. Nota che per questo motivo dobbiamo anche aggiungerne un altro >a Chuck per saltare -anche questo quando torni all'inizio.


4

ClojureScript, 88 84 76 74 byte

nile falsesono falsi, tutti gli altri valori sono veritieri. I booleani vengono forzati a 0/1 per aritmetica e disuguaglianze. Le funzioni possono accettare il numero errato di argomenti.

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

Non è 0falsa?
Leaky Nun,

2
Non in ClojureScript.
MattPutnam,

@LeakyNun Non nella maggior parte dei LISP o nei linguaggi di programmazione funzionale, cosa che Clojure è sicuramente
cat

@cat nella maggior parte dei linguaggi di programmazione funzionali! Pitone, per esempio, restituisce not not(0)a False, che è il valore falsey.
Erik the Outgolfer,

3
@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Er ... Python non è né puramente funzionale né il tipo di linguaggio funzionale di cui sto parlando. Python è imperativo, principalmente e con alcuni aspetti funzionali più piccoli (mal eseguiti). Erlang, Haskell (credo), LISP comune, Clojure, Racchetta, Scheme, Fattore, Standard ML, Objective CAML, ecc 0 è solo un altro valore ed è il risultato truthy, e il simbolo per falso ( #f, f, false, ecc) è falsa. Tutti gli altri valori sono veritieri nella maggior parte dei linguaggi funzionali.
cat

4

Brainfuck , 184 178 174 byte

Input / output utilizza U + 0000 e U + 0001.

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

La lettura di un secondo input condizionale sembra costosa. Ad esempio, 0001non potresti semplicemente farlo ,[,>]<.(dato un interprete che ti permette di andare a sinistra della cella iniziale)?
Martin Ender,

@MartinEnder Ho pensato che non avrei semplicemente copiato la risposta di Dennis qui.
Leaky Nun,

4

Brain-Flak , 418 , 316 byte

Provalo online!

Lascia che gli input siano i primi due numeri nello stack all'inizio del programma (zero per uno falso per true) e l'output sia in cima allo stack alla fine del programma (zero per false, altrimenti per true).

falso, 4 byte (per gentile concessione di Leaky Nun )

(<>)

e, 36 byte

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

A e non B, 40 byte

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

A, 6 byte

({}<>)

non A e B, 38 byte

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

B, 2 byte

{}

xor, 34 byte

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

oppure, 6 byte

({}{})

né, 34 byte

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

xnor, 10 byte

({}{}[()])

non B, 34 byte

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

B implica A, 14 byte

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

non A, 34 byte

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

A implica B, 16 byte

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

nand, 12 byte

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

vero, 6 byte

<>(())

Spiegazione

Dal momento che la maggior parte di questi sono molto simili, non ho intenzione di spiegare esattamente come ciascuno di essi funziona. Faccio del mio meglio per chiarire come funzionano tutti e sedici.

Innanzitutto sono le porte che restituiscono tre dello stesso valore (ovvero 2, 3, 5, 8, 9, 12, 14 e 15). Tutti seguono lo stesso schema. Innanzitutto converti l'input in un numero a due bit con a come il posto a due e B come quelli. Questo viene fatto con questo frammento (({}){}{}). Quindi sottrarre il valore dell'ingresso a due bit che si desidera isolare ({}[value]). (Nel codice effettivo la sottrazione e la conversione vengono eseguite in un solo passaggio per salvare i byte). Questo può essere combinato con un non se necessario: (({}<(())>)){{}{}(((<{}>)))}{}{}.

Successivo: e, né, o, xor e xnor. Questi funzionano in modo simile a quelli sopra. In effetti alcuni di questi sono inclusi sopra, tuttavia questo metodo è più breve. Il trucco che ho usato qui è che ognuno corrisponde a una somma di A B. ad esempio xor valuta vero se A + B = 1 e falso altrimenti. Per prima cosa aggiungi AB e sottrai l'importo rilevante. Espresso come ({}{}[0,1,2 or 3]). Quindi, se necessario, condurre un non

A seguire: A, B, non A e non B. Questi sono praticamente autoesplicativi. Iniziamo rimuovendo il valore non necessario e quindi neghiamo o finiamo.

Infine sono i due simpleton: vero e falso. Per questi spingiamo il valore corretto nello stack. Il <>nilad restituisce zero in modo da poter salvare due byte utilizzando l'opzione come valore zero.

Non è la soluzione più efficiente là fuori (forse la più efficiente in Brain-Flak), ma mi sono divertito molto a scriverli e ti imploro di tentare di accorciarli.


(<>)è abbastanza per false; inoltre, (<{}{}>)è di 8 byte
Leaky Nun,

Wow, ho avuto una definizione molto più rigorosa della sfida. Grazie. Lo ridurrò notevolmente
Wheat Wizard

Cosa intendi?
Leaky Nun,

Ho pensato che dovevo rimuovere gli input esistenti e posizionare il risultato al suo posto. (<>)lascerà gli input e metterà lo zero sull'altro stack.
Wheat Wizard

1
Non è <>abbastanza per a falsecausa di zeri impliciti? Inoltre, penso che apossa essere il programma vuoto. truepuò essere <>[][](non salva byte, ma sembra bello: P).
Calcolatrice

4

ProgFk , 18,5 17,5 byte

Poiché le istruzioni di ProgFk sono specificate in nibble, il codice seguente è dato in esadecimale, una porta logica per riga e con spazi tra i byte.

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

Spiegazione

ProgFk è un esolang basato su nastro (simile a Brainfuck) in cui ogni cella è un po 'e le istruzioni sono fornite come stuzzichini (4 byte). Le istruzioni operano sulla cella a cui punta il puntatore dell'istruzione. L'input viene dato nella prima e nella seconda cella (con Ae Bessendo rispettivamente la prima e la seconda cella) e il puntatore dell'istruzione inizia alla prima cella. L'output è memorizzato nella prima cella.

Ogni istruzione utilizzata è spiegata di seguito.

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.

Salvato un byte grazie a @LeakyNun!


4

In realtà, 24 byte

Questi programmi prendono input come A\nB(con la \nrappresentazione di una nuova riga), che lascia B in cima allo stack, con A in basso. Falseè rappresentato da 0ed Trueè rappresentato da qualsiasi numero intero positivo.

é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)

Grazie a Leaky Nun per 3 byte

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.