Dada uma tabela verdade, produza um programa Stackylogic que a satisfaça


17

Stackylogic é uma linguagem de programação que criei em um desafio anterior: Execute Stackylogic . Leia esse post para obter detalhes e exemplos completos, mas aqui está como ele é parafraseado:

Stackylogic pega 0's' e 1's para entrada e saída uma única 0 ou 1após a conclusão.

Um programa consiste em linhas que contêm apenas os caracteres 01?e exatamente um <no final de uma das linhas. As linhas podem não estar vazio e a linha com o <deve ter pelo menos um 0, 1ou ?antes dela.

Aqui está um programa de exemplo que calcula a NAND de dois bits:

1
?<
11
?
0

Cada linha de um programa é considerada uma pilha , com a parte inferior à esquerda e a parte superior à direita. Implicitamente, há uma pilha vazia (ou seja, linha vazia) antes da primeira linha de um programa e depois da última linha.

O <, chamado cursor, marca a pilha para iniciar quando um programa é executado. A execução procede da seguinte maneira:

  1. Retire o caractere superior da pilha para a qual o cursor está apontando.

    • Se o personagem for ?, solicite a 0ou a um usuário 1e aja como se fosse o personagem.
    • Se o caractere for 0, mova o cursor uma pilha para cima (para a linha acima da linha atual).
    • Se o caractere for 1, mova o cursor uma pilha para baixo (para a linha abaixo da linha atual).
  2. Se a pilha para a qual o cursor se move estiver vazia, imprima o último valor que foi retirado de uma pilha (sempre a 0ou 1) e encerre o programa.

  3. Caso contrário, se a pilha para a qual o cursor se move não estiver vazia, volte para a etapa 1 e repita o processo.

O principal a realizar para esse desafio é que todos os programas Stackylogic equivalem a uma tabela de verdade . Algum número predeterminado de valores booleanos são inseridos e exatamente um booleano é produzido de forma determinística.

Portanto, sua tarefa é produzir um programa Stackylogic que satisfaça ou simule, ou seja, tenha a mesma saída que qualquer tabela de verdade. Mas não é óbvio que o Stackylogic possa simular qualquer tabela verdade, então aqui está uma prova por indução :

Caso base

As duas tabelas verdadeiras com 0 entradas são as tabelas que sempre produzem 0ou 1. Os equivalentes Stackylogic destas tabelas são 0<e 1< respectivamente.

Etapa indutiva

Suponha que o Stackylogic possa simular qualquer tabela verdade de entrada N. Seja M = N + 1.

Uma tabela de entrada M, T, pode ser expressa como duas tabelas de entrada N, T 0 e T 1 , mais o bit de entrada adicional B. Quando B é 0, o resultado de T 0 é usado. Quando B é um, o resultado do t 1 é utilizado.

Por exemplo, a tabela verdade de 3 entradas correspondente ao pseudocódigo

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

que são realmente as duas tabelas verdadeiras de 2 entradas para NAND e OR empilhadas umas sobre as outras com o bit de muxing B.

Sejam S 0 e S 1 os programas Stackylogic que satisfazem T 0 e T 1 respectivamente (sabemos que estes existem com base na primeira suposição). O programa S que satisfaz T pode então ser construído como:

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

Esse arranjo efetivamente alterna entre S 0 e S 1 com base no primeiro bit de entrada (da linha ?<). Se estiver 0, o cursor passará os anexos 0até a posição original do cursor de S 0 , que será delimitada superior e inferior por pilhas vazias e, portanto, executada exatamente idêntica à S 0 original . Da mesma forma, se 1for introduzido, o cursor vai rodar com a 1's até S um de posição do cursor e proceder para executá-lo como se fosse a única.

Por exemplo, os programas Stackylogic para OR e NAND são

?
?<

e

1
?<
11
?
0

Eles podem ser combinados para simular

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

igual a:

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

Assim, qualquer tabela verdade pode ser simulada por um programa Stackylogic.

Desafio

Escreva um programa ou função que obtenha uma tabela verdade N de entrada (N> 0) na forma de uma lista de 2 N valores booleanos que representam as saídas da tabela em ordem binária crescente.

Qualquer formato de entrada razoável está bom. por exemplo, para uma tabela de verdade OR

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

qualquer um desses estilos de entradas seria bom:

0111

0, 1, 1, 1

0
1
1
1

[False, True, True, True]

Imprima ou retorne um programa Stackylogic que satisfaça a tabela verdade, ou seja, tenha exatamente a mesma saída, com a mesma entrada. Qualquer programa finito que satisfaça essa tabela é uma saída válida. Você não precisa seguir o método de construção da prova indutiva. Os programas Stackylogic não precisam ser otimamente curtos.

Por exemplo, se a entrada fosse 11100111, uma saída válida seria

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

mas existem muitos outros.

O código mais curto em bytes vence.

Veja o desafio Stackylogic original se precisar de um intérprete.


Podemos tomar N como uma segunda entrada?
Leaky Nun

@LeakyNun Sim (ou 2 ^ N), se necessário.
22716 Calvin's Hobbies

Respostas:


8

Pitão, 53 bytes

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

Experimente on-line

Esta é uma implementação exata do sistema descrito no desafio de como implementar tabelas de verdade arbitrárias no Stackylogic. Simplesmente cortamos a tabela verdade pela metade, implementamos recursivamente e, em seguida, anexamos 0 e 1 conforme apropriado.

Isso define uma função recursiva, cujo valor de retorno é [1, ['0', '?', '1']]onde o primeiro número é a localização do ponteiro e o restante é um programa empilógico.

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.

Bem ... Acabei de voltar para casa para corrigir minha solução ... #
Leaky Nun

3

Python 3, 352 208 205 bytes

Isso ainda é muito não-destruído, e tentarei adicionar uma explicação mais tarde. Após algumas modificações, consegui remover 144 147 bytes.

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

Uma função fque recebe entrada dos valores da tabela verdade como uma lista de Booleanos do formulário ['1','1','1','0','0','1'...], onde '1'é verdade e '0'é falsey, e retorna um programa Stackylogic.

Experimente no Ideone

Se você quiser testar um programa produzido, pode usar o interpretador Convex do GamrCorps aqui .

Como funciona

Esta é uma função recursiva e usa o método indutivo descrito na pergunta.

No nível de recursão indexado a zero a, a função cria n/2 a+1programas Stackylogic -input a partir dos n aprogramas -input na lista. Isso é feito juntando todos os pares adjacentes de dois programas na lista com ?; como o cursor está sempre no elemento do meio de cada programa constituinte, o acréscimo necessário de 0ou 1pode ser executado iterando sobre cada linha dos programas que estão sendo unidos e acrescentando se o índice da linha atual for menor ou igual a / maior igual ou igual ao índice do meio, conforme apropriado. Se a lista contiver apenas dois programas, a próxima chamada recursiva fornecerá o programa final; como isso requer um cursor, a união ocorre em vez disso ?<.

Quando a lista tem tamanho 1, a lista deve conter apenas um elemento que contém o programa completo. Portanto, todas as linhas do programa são unidas em uma nova linha e, em seguida, retornadas.

Um exemplo ajuda a ilustrar isso:

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.