真理値表が与えられたら、それを満たすStackylogicプログラムを出力します


17

Stackylogicは、前の課題で作成したプログラミング言語です:Stackylogicを実行します。詳細と例については、その投稿を読んでください。しかし、次のように機能します。

Stackylogicは、入力用に0とを取り1、単一0 または1完了時に出力します。

プログラムは、文字のみを含む行で構成さ01?だけでなく、正確に一つとして<ラインの1の終わりに。行は空ではないかもしれないとして行が<少なくとも一つ持っている必要があります01または ?それ以前に。

2ビットのNANDを計算するサンプルプログラムを次に示します。

1
?<
11
?
0

プログラム内のすべての行はスタックと見なされ、左が下、右が上になります。暗黙的に、プログラムの最初の行の前と最後の行の後に空のスタック(つまり空の行)があります。

<プログラムが実行されたときに、カーソルと呼ばれ、マークスタックは上を開始します。実行は次のように進行します。

  1. カーソルが現在指しているスタックから先頭の文字をポップします。

    • 文字がの場合、?ユーザーにa 0またはa を要求し、それが文字であるかのよう1に動作します。
    • 文字がの場合、0カーソルを1スタック上に(現在の行の上の行に)移動します。
    • 文字がの場合、1カーソルを1スタック下に(現在の行の下の行に)移動します。
  2. カーソルの移動先のスタックが空の場合、スタックからポップされた最後の値(常にa 0または1)を出力し、プログラムを終了します。

  3. それ以外の場合、カーソルの移動先のスタックが空でない場合は、手順1に戻ってプロセスを繰り返します。

この課題を実現するために重要なことは、すべてのStackylogicプログラムが真理値表と同等であることです。所定の数のブール値が入力され、正確に1つのブール値が確定的に出力されます。

したがって、あなたのタスクは、満たすかシミュレートするStackylogicプログラムを作成することです。つまり、与えられた真理値表と同じ出力を持ちます。しかし、Stackylogic 任意の真理値表をシミュレートできることは明らかではないため、ここに帰納法による証明があります。

規範事例

2つの0入力の真理値表は、常に0またはを 出力する表です1。これらのテーブルに相当するStackylogicは0<1< それぞれです。

誘導ステップ

Stackylogicが任意のN入力真理値表をシミュレートできると仮定します。M = N + 1とします。

M入力テーブルTは、2つの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つの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]

この配置は、(lineからの)最初の入力ビットに基づいて、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プログラムで真理値表をシミュレートできます。

チャレンジ

Nの入力真理値表(N> 0)を2 Nブール値のリストの形式で取得するプログラムまたは関数を作成します。これは、テーブルの出力をバイナリの昇順で表します。

妥当な入力形式であれば問題ありません。例: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つの有効な出力は

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

しかし、他にもたくさんあります。

バイト単位の最短コードが優先されます。

通訳が必要な場合は、元のStackylogicチャレンジをご覧ください。


Nを2番目の入力として使用できますか?
リーキー修道女

@LeakyNunはい(または2 ^ N)、必要な場合。
カルビンの趣味

回答:


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.

うーん...私はちょうど...私の解決策を修正するために帰って行きました
漏れ修道女

3

Pythonの3、352の 208 205バイト

これはまだ非常に手付かずで、後で説明を追加しようとします。 いくつかの変更の後、144 147バイトを削除できました。

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'truthyと'0'falseyであり、そしてStackylogicプログラムを返します。

Ideoneでお試しください

作成したプログラムをテストする場合は、GamrCorpsのConvexインタープリターをここで使用できます。

使い方

これは再帰関数であり、質問で説明されている帰納法を使用します。

インデックスがゼロの再帰レベルaで、関数は以下を作成しますn/2 a+1n aリスト内の-inputプログラムから-input Stackylogicプログラムをします。これは、リスト内の2つのプログラムのすべての隣接するペアを?; で結合することにより行われます。カーソルは常に各構成プログラムの中央の要素にあるため、必要な追加0または追加は、1結合されるプログラムの各行を反復処理し、現在の行のインデックスが以下またはそれ以上の場合に追加することで実行できます。必要に応じて、中央のインデックス以下。リストに2つのプログラムしか含まれていない場合、次の再帰呼び出しは最終プログラムを提供します。これにはカーソルが必要なので、代わりにで結合が行われ?<ます。

リストにlengthがある場合、リストには1プログラム全体を含む要素が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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.