给定一个真值表,输出一个满足它的Stackylogic程序


17

Stackylogic是我在上一个挑战中提出的一种编程语言:运行Stackylogic。请阅读该帖子以获取完整的详细信息和示例,但是下面解释了它的工作方式:

Stackylogic采用01来输入和输出单个01完成时。

程序由仅包含字符01?以及其中一行<的末尾恰好包含一个字符的行组成。行不能为空,并与该行<必须至少有一个01?之前。

这是一个示例程序,用于计算两位的NAND

1
?<
11
?
0

程序中的每一行都被视为一个堆栈,其底部在左侧,顶部在右侧。隐式地,在程序的第一行之前和最后一行之后有一个空栈(即空行)。

<运行程序时,称为光标,标记堆栈开始。执行过程如下:

  1. 将顶部字符从光标当前指向的堆栈中弹出。

    • 如果该字符为?,则提示用户输入a 0或a,1并像该字符一样进行操作。
    • 如果字符是0,则将光标向上移动一个堆栈(到当前行上方的行)。
    • 如果字符是1,则将光标向下移动一个堆栈(到当前行下方的行)。
  2. 如果光标移动到的堆栈为空,则输出从堆栈弹出的最后一个值(始终为a 01),然后结束程序。

  3. 否则,如果光标移动到的堆栈不为空,请返回步骤1并重复该过程。

应对这一挑战的关键是,所有Stackylogic程序都等同于一个真值表。输入一些预定数量的布尔值,并确定性地输出一个布尔值。

因此,您的任务是生成一个满足或模拟的Stackylogic程序,即与任何给定的真值表具有相同的输出。但是Stackylogic 可以模拟任何真值表并不明显,因此这是归纳法证明

基本情况

两个0输入真值表是始终输出0或 的表1。这些表的Stackylogic等效项 分别为0<1<

归纳步

假设Stackylogic可以模拟任何N输入的真值表。令M = N + 1。

M输入表T可以表示为两个N输入表T 0和T 1以及附加输入位B。当B为0时,使用T 0的结果。当B为1时,将使用T 1的结果。

例如,对应于伪代码的3输入真值表

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

这实际上是两个和输入的NAND和OR的两个2输入真值表,并用混合位B堆叠在一起。

令S 0和S 1是分别满足T 0和T 1的Stackylogic程序(我们根据第一个假设知道它们的存在)。然后,可以将满足T的程序S构造为:

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

这种安排基于第一个输入位(来自线)有效地在S 0和S 1之间复用?<。如果是 0,则光标将沿附加0的光标移动到S 0的原始光标位置,然后该位置将由顶部和底部由空堆栈边界,从而与原始S 0完全相同。同样,如果1输入,则光标将 1沿着'向下移动到S 1的光标位置,并像单独执行一样继续执行它。

例如,用于OR和NAND的Stackylogic程序是

?
?<

1
?<
11
?
0

它们可以结合起来模拟

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

像这样:

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

因此,可以通过Stackylogic程序模拟任何真值表。

挑战

编写一个程序或函数,该程序或函数以2个N个布尔值的列表的形式接收N个输入真值表(N> 0),这些值以二进制升序表示表的输出。

任何合理的输入格式都可以。例如对于OR真值表

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

这些输入方式中的任何一种都可以:

0111

0, 1, 1, 1

0
1
1
1

[False, True, True, True]

打印或返回满足真值表的Stackylogic程序,即在给定相同输入的情况下具有完全相同的输出。满足该表的任何有限程序都是有效输出。您不需要遵循归纳证明的构造方法。Stackylogic程序不需要最短。

例如,如果输入为11100111,则一个有效的输出为

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

但是还有很多其他的。

以字节为单位的最短代码获胜。

如果需要翻译,请参阅原始的Stackylogic挑战


我们可以将N作为第二输入吗?
Leaky Nun

@LeakyNun是(或2 ^ N),如有必要。
加尔文的爱好

Answers:


8

Pyth,53个字节

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

在线尝试

这是挑战中描述的系统的精确实现,该系统说明如何在Stackylogic中实现任意真值表。我们只将真值表切成两半,递归地实现它,然后适当地附加0和1。

这定义了一个递归函数,其返回值是[1, ['0', '?', '1']],其中第一个数字是指针的位置,其余的是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.

好吧...我刚回到家来纠正我的解决方法...
Leaky Nun

3

Python 3, 352个 208 205字节

这仍然是不可行的,稍后我将尝试添加一个解释。 经过一些修改后,我设法删除了 144147个字节。

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

功能 f将真值表值的输入作为形式为的布尔值列表(['1','1','1','0','0','1'...]其中'1'true '0'是false),并返回Stackylogic程序。

在Ideone上尝试

如果要测试生产的程序,可以使用GamrCorps在此处的Convex解释器。

怎么运行的

这是一个递归函数,并使用问题中描述的归纳方法。

在零索引递归级别a,该函数n/2 a+1n a列表中的-input程序创建-input Stackylogic程序。这是通过将列表中两个程序的所有相邻对与结合在一起来完成的?。由于光标始终位于每个组成程序的中间元素,因此可以通过迭代要联接的程序的每一行来执行所需的01附加操作,如果当前行的索引小于或等于/大于该值,则可以附加大于或等于中间索引。如果列表仅包含两个程序,则下一个递归调用将给出最终程序;否则,将返回最后一个程序。由于这需要使用游标,因此会在上进行联接?<

当列表具有length时1,列表必须仅包含一个包含完整程序的元素。因此,程序中的所有行都在换行符上连接,然后返回。

一个示例有助于说明这一点:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.