Data una tabella di verità, genera un programma Stackylogic che lo soddisfa


17

Stackylogic è un linguaggio di programmazione che ho inventato in una precedente sfida: eseguire Stackylogic . Leggi quel post per tutti i dettagli e gli esempi, ma ecco come funziona parafrasato:

Stackylogic prende 0's e 1' s per l'input ed emette un singolo 0 o 1al completamento.

Un programma è composto da righe che contengono solo i caratteri 01?, nonché esattamente uno <alla fine di una delle righe. Linee possono non essere vuoto e la riga con il <devono avere almeno una 0, 1o ?prima.

Ecco un programma di esempio che calcola la NAND di due bit:

1
?<
11
?
0

Ogni riga di un programma è considerata una pila , con il fondo a sinistra e quello in alto a destra. Implicitamente, c'è uno stack vuoto (cioè una riga vuota) prima della prima riga di un programma e dopo l'ultima riga.

Il <, chiamato il cursore, segna lo stack per iniziare quando viene eseguito un programma. L'esecuzione procede come segue:

  1. Rimuovi il carattere superiore dallo stack a cui punta attualmente il cursore.

    • Se il personaggio è ?, chiedi all'utente a 0o a 1e agisci come se quello fosse il personaggio.
    • Se il personaggio è 0, sposta il cursore di una pila verso l'alto (sulla riga sopra la riga corrente).
    • Se il personaggio è 1, sposta il cursore di una pila verso il basso (sulla riga sotto la riga corrente).
  2. Se lo stack su cui si sposta il cursore è vuoto, emette l'ultimo valore estratto da uno stack (sempre a 0o 1) e termina il programma.

  3. Altrimenti, se lo stack su cui si sposta il cursore non è vuoto, tornare al passaggio 1 e ripetere il processo.

La cosa chiave da realizzare per questa sfida è che tutti i programmi Stackylogic equivalgono a una tabella di verità . Viene immesso un numero predeterminato di valori booleani e viene determinato in modo deterministico esattamente un valore booleano.

Quindi il tuo compito è quello di produrre un programma Stackylogic che soddisfi o simuli, cioè abbia lo stesso output di qualsiasi data tabella di verità. Ma non è ovvio che Stackylogic può simulare qualsiasi tabella di verità, quindi ecco una prova per induzione :

Caso base

Le due tabelle di verità 0 input sono le tabelle che producono sempre 0o 1. Gli equivalenti Stackylogic di queste tabelle sono 0<e 1< rispettivamente.

Passo induttivo

Supponiamo che Stackylogic possa simulare qualsiasi tabella di verità N-input. Sia M = N + 1.

Una tabella di input M, T, può essere espressa come due tabelle di input N, T 0 e T 1 , più il bit di input aggiuntivo B. Quando B è 0, viene utilizzato il risultato di T 0 . Quando B è 1, viene utilizzato il risultato di T 1 .

Ad esempio, la tabella di verità a 3 input corrispondente allo pseudocodice

if B:
    result = x OR y
else:
    result = x NAND y

è

B x y | result
0 0 0 | 1
0 0 1 | 1
0 1 0 | 1
0 1 1 | 0
1 0 0 | 0
1 0 1 | 1
1 1 0 | 1
1 1 1 | 1

che sono in realtà le due tabelle di verità a 2 input per NAND e OR sovrapposte l'una all'altra con il bit di muxing B.

Siano S 0 e S 1 i programmi Stackylogic che soddisfano rispettivamente T 0 e T 1 (sappiamo che esistono sulla base del primo presupposto). Il programma S che soddisfa T può quindi essere costruito come:

[lines of S0 excluding the cursor, with 0 appended to all lines below the cursor]
?<
[lines of S1 excluding the cursor, with 1 appended to all lines above the cursor]

Questa disposizione si combina efficacemente tra S 0 e S 1 in base al primo bit di ingresso (dalla linea ?<). In tal caso 0, il cursore si sposta su quello aggiunto 0fino alla posizione originale del cursore di S 0 , che sarà quindi delimitato in alto e in basso da pile vuote, e quindi verrà eseguito esattamente identico allo S 0 originale . Allo stesso modo, se 1viene inserito, il cursore si sposterà 1verso il basso fino alla posizione del cursore di S 1 e procederà ad eseguirlo come se fosse solo.

Ad esempio, i programmi Stackylogic per OR e NAND sono

?
?<

e

1
?<
11
?
0

Possono essere combinati per simulare

if B:
    result = x OR y
else:
    result = x NAND y

così:

1
?
110
?0
00
0
?<
?1
?

Pertanto, qualsiasi tabella di verità può essere simulata da un programma Stackylogic.

Sfida

Scrivi un programma o una funzione che accetta una tabella di verità di input N (N> 0) sotto forma di un elenco di 2 valori booleani N che rappresentano gli output della tabella in ordine binario crescente.

Qualsiasi formato di input ragionevole va bene. ad es. per una tabella di verità OR

x y | OR
0 0 | 0
0 1 | 1
1 0 | 1
1 1 | 1

uno di questi stili di input andrebbe bene:

0111

0, 1, 1, 1

0
1
1
1

[False, True, True, True]

Stampa o restituisce un programma Stackylogic che soddisfa la tabella di verità, ovvero ha lo stesso output esatto dato lo stesso input. Qualsiasi programma finito che soddisfa quella tabella è un output valido. Non è necessario seguire il metodo di costruzione della prova induttiva. Non è necessario che i programmi Stackylogic siano brevi in ​​modo ottimale.

Ad esempio, se l'input fosse 11100111, un output valido sarebbe

1
?
110
?0
00
0
?<
?1
?

ma ce ne sono molti altri.

Vince il codice più breve in byte.

Vedi la sfida Stackylogic originale se hai bisogno di un interprete.


Possiamo prendere N come secondo input?
Leaky Nun,

@LeakyNun Sì (o 2 ^ N), se necessario.
Calvin's Hobbies,

Risposte:


8

Pyth, 53 byte

L?tb,lehJyMc2bsX0.e.e+W>_Wk-Yhb0ZkebJ\?,0]`hbjXF+yQ\<

Prova online

Questa è un'implementazione esatta del sistema descritto nella sfida per come implementare tabelle di verità arbitrarie in Stackylogic. Semplicemente dimezziamo la tabella della verità, la implementiamo in modo ricorsivo e quindi appendiamo 0 e 1 come appropriato.

Questo definisce una funzione ricorsiva, il cui valore di ritorno è [1, ['0', '?', '1']], in cui il primo numero è la posizione del puntatore e il resto è un programma stackylogic.

L?tb,lehJyMc2bsX0.e.e+W>_Wk-Yhb0ZkebJ\?,0]`hbjXF+yQ\<
                                                         Q = eval(input())
L?tb,lehJyMc2bsX0.e.e+W>_Wk-Yhb0ZkebJ\?,0]`hb
L                                                 def y(b): return
 ?tb                                              if b[1:] (base case on false)
                                      ,0]`hb      else: [0, str([0])]
                                                  then:
           c2b                                    Cut the input in half
         yM                                       Map y over the halves
        J                                         Store that in J
    ,leh                                          The cursor position is the length 
                                                  of the body of the first function
                 .e                 J             enum-map, where k is the index
                                                  and b is the value, over J
                   .e             eb              enum-map, Y is the index and
                                                  Z is the value, over body of b
                     +W         Zk                Add to Z (line) k (the overall 
                                                  index, 0 or 1) conditional on
                          -Yhb                    Y (line index) - cursor
                       _Wk                        Negated if k
                      >       0                   > 0
               X0                    \?           Add '?' to the first element
              s                                   Concatenate, giving the body

jXF+yQ\<
    yQ      Call the above on the input
   +  \<    Append a '<'
 XF         Splat the 3 element list into the 'append-at' function,
            adding the curson in the right place
j           Join on newlines and print.

Bene ... Sono appena tornato a casa per correggere la mia soluzione ...
Leaky Nun,

3

Python 3, 352 208 205 byte

Questo è ancora molto non golfato, e proverò ad aggiungere una spiegazione in seguito. Dopo alcune modifiche, sono riuscito a rimuovere 144 147 byte.

f=lambda x,l=len,r=range:'\n'.join(*x)if l(x)<2 else f([[x[i][j]+['0',''][j<=l(x[i])//2]for j in r(l(x[i]))]+[['?','?<'][l(x)<3]]+[x[i+1][j]+['1',''][j>=l(x[i])//2]for j in r(l(x[i]))]for i in r(0,l(x),2)])

Una funzione fche accetta i valori della tabella di verità come un elenco di valori booleani della forma ['1','1','1','0','0','1'...], dove '1'è verità e '0'falsità, e restituisce un programma Stackylogic.

Provalo su Ideone

Se vuoi testare un programma prodotto, puoi usare qui l' interprete Convex di GamrCorps .

Come funziona

Questa è una funzione ricorsiva e utilizza il metodo induttivo descritto nella domanda.

A livello di ricorsione a indice zero a, la funzione crea i n/2 a+1programmi Stackylogic in ingresso dai programmi in ingresso n anell'elenco. Questo viene fatto unendo tutte le coppie adiacenti di due programmi nell'elenco con ?; poiché il cursore si trova sempre nell'elemento centrale di ciascun programma costituente, l'aggiunta richiesta di 0o1 può essere eseguita ripetendo iterando su ciascuna riga dei programmi che vengono uniti e aggiungendo se l'indice della riga corrente è minore o uguale a / maggiore uguale o uguale all'indice medio, a seconda dei casi. Se l'elenco contiene solo due programmi, la successiva chiamata ricorsiva fornirà il programma finale; poiché ciò richiede un cursore, l'unione si verifica invece su ?<.

Quando l'elenco ha lunghezza 1 , l'elenco deve contenere solo un elemento contenente l'intero programma. Quindi, tutte le righe del programma vengono unite su una nuova riga e quindi restituite.

Un esempio aiuta a illustrare questo:

Take the input ['1', '1', '1', '0', '0', '1', '1', '1'].

Level  Return value

0  [['1', '?', '1'], ['1', '?', '0'], ['0', '?', '1'], ['1', '?', '1']]
1  [['1', '?', '10', '?', '11', '?', '0'], ['0', '?', '10', '?', '11', '?', '1']]
2  [['1', '?', '10', '?', '110', '?0', '00', '?<', '01', '?1', '101', '?', '11', '?', '1']]
3  '1\n?\n10\n?\n110\n?0\n00\n?<\n01\n?1\n101\n?\n11\n?\n1'

which when printed gives:

1
?
10
?
110
?0
00
?<
01
?1
101
?
11
?
1
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.