Stackylogic是我在上一个挑战中提出的一种编程语言:运行Stackylogic。请阅读该帖子以获取完整的详细信息和示例,但是下面解释了它的工作方式:
Stackylogic采用
0
和1
来输入和输出单个0
或1
完成时。程序由仅包含字符
01?
以及其中一行<
的末尾恰好包含一个字符的行组成。行不能为空,并与该行<
必须至少有一个0
,1
或?
之前。这是一个示例程序,用于计算两位的NAND:
1 ?< 11 ? 0
程序中的每一行都被视为一个堆栈,其底部在左侧,顶部在右侧。隐式地,在程序的第一行之前和最后一行之后有一个空栈(即空行)。
在
<
运行程序时,称为光标,标记堆栈开始。执行过程如下:
将顶部字符从光标当前指向的堆栈中弹出。
- 如果该字符为
?
,则提示用户输入a0
或a,1
并像该字符一样进行操作。- 如果字符是
0
,则将光标向上移动一个堆栈(到当前行上方的行)。- 如果字符是
1
,则将光标向下移动一个堆栈(到当前行下方的行)。如果光标移动到的堆栈为空,则输出从堆栈弹出的最后一个值(始终为a
0
或1
),然后结束程序。否则,如果光标移动到的堆栈不为空,请返回步骤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挑战。