nを法とする数論のインタープリター


12

(私たちの目的のための)数論の文は、次の記号のシーケンスです。

  • 0および'(後継者)-後継者は+1、0'''' = 0 + 1 + 1 + 1 + 1 = 4
  • +(加算)と*(乗算)
  • = (に等しい)
  • (と)(括弧)
  • 論理演算子nand(a nand bis not (a and b))
  • forall (ユニバーサル数量詞)
  • v0、v1、v2、など(変数)

    ここに文の例があります:

forall v1 (forall v2 (forall v3 (not (v1*v1*v1 + v2*v2*v2 = v3*v3*v3))))

ここでnot xは省略形ですx nand x-実際の文が使用する(v1*v1*v1 + v2*v2*v2 = v3*v3*v3) nand (v1*v1*v1 + v2*v2*v2 = v3*v3*v3)からx nand x = not (x and x) = not xです。

3つの自然数の組み合わせ毎に、この状態v1、v2およびv3、それがV1とは限らない3 + v2の3 = v3の3は(それはなるだろうという事実を除き、理由フェルマーの最終定理の真のだろうどの0 ^ 3 + 0 ^ 3 = 0 ^ 3)。

残念ながら、ゲーデルによって証明されたように、数論の文章が真実であるかどうかを判断することは不可能です。

ただし、自然数のセットを有限セットに制限することは可能です。

したがって、この課題は、いくつかの正の整数に対して、モジュロ nで解釈したときに、数論の文が真であるかどうかを判断することnです。たとえば、文

forall v0 (v0 * v0 * v0 = v0)

(すべての数値x、x 3 = x についてのステートメント)

通常の算術(たとえば、2 3 = 8≠2)には当てはまりませんが、3を法とする場合は当てはまります。

0 * 0 * 0 ≡ 0 (mod 3)
1 * 1 * 1 ≡ 1 (mod 3)
2 * 2 * 2 ≡ 8 ≡ 2 (mod 3)

入出力フォーマット

入力は、n「合理的な」形式の文と正の整数です。以下は、forall v0 (v0 * v0 * v0 = v0)3を法とする数論の文の適切な形式の例です。

("forall v0 (v0 * v0 * v0 = v0)", 3)
"3:forall v0 (((v0 * v0) * v0) = v0)"
"(forall v0)(((v0 * v0) * v0) = v0) mod 3" 
[3, "forall", "v0", "(", "(", "(", "v0", "*", "v0", ")", "*", "v0", ")", "=", "v0", ")"]
(3, [8, 9, 5, 5, 5, 9, 3, 9, 6, 3, 9, 6, 4, 9, 6]) (the sentence above, but with each symbol replaced with a unique number)
"f v0 = * * v0 v0 v0 v0"
[3, ["forall", "v0", ["=", ["*", "v0", ["*", "v0", "v0"]], "v0"]]]
"3.v0((v0 * (v0 * v0)) = v0)"

入力は、stdin、コマンドライン引数、ファイルなどから取得できます。

プログラムは、文が真であるかどうかについて2つの異なる出力を持つことができます。たとえば、yes真であるno場合とそうでない場合で出力することができます。

forallたとえば、のように、1つの変数が2回の対象になることをサポートする必要はありません(forall v0 (v0 = 0)) nand (forall v0 (v0 = 0))。入力には有効な構文があると想定できます。

テストケース

forall v0 (v0 * v0 * v0 = v0) mod 3
true

forall v0 (v0 * v0 * v0 = v0) mod 4
false (2 * 2 * 2 = 8 ≡ 0 mod 4)

forall v0 (v0 = 0) mod 1
true (all numbers are 0 modulo 1)

0 = 0 mod 8
true

0''' = 0 mod 3
true

0''' = 0 mod 4
false

forall v0 (v0' = v0') mod 1428374
true

forall v0 (v0 = 0) nand forall v1 (v1 = 0) mod 2
true (this is False nand False, which is true)

forall v0 ((v0 = 0 nand v0 = 0) nand ((forall v1 (v0 * v1 = 0' nand v0 * v1 = 0') nand forall v2 (v0 * v2 = 0' nand v0 * v2 = 0')) nand (forall v3 (v0 * v3 = 0' nand v0 * v3 = 0') nand forall v4 (v0 * v4 = 0' nand v0 * v4 = 0')))) mod 7
true
(equivalent to "forall v0 (v0 =/= 0 implies exists v1 (v0 * v1 = 0)), which states that every number has a multiplicative inverse modulo n, which is only true if n is 1 or prime)

forall v0 ((v0 = 0 nand v0 = 0) nand ((forall v1 (v0 * v1 = 0' nand v0 * v1 = 0') nand forall v2 (v0 * v2 = 0' nand v0 * v2 = 0')) nand (forall v3 (v0 * v3 = 0' nand v0 * v3 = 0') nand forall v4 (v0 * v4 = 0' nand v0 * v4 = 0')))) mod 4
false

これはなので、プログラムをできるだけ短くしてください!


1
変数名は常に形式v numberですか?
— ジョーキング

1
@JoKing彼らはあなたが彼らになりたいのであればあなたはそれをすることができますvar number- あなたは使うことができます、あるいはそれだけでも1 + number(そう1なるでしょうv0、2そうなるでしょうv1)
— Leo Tenenbaum

1
@JoKing(理論的には)無限の数の変数を許可する必要があります。変数の最大数が整数の最大サイズによって制限されていても問題ありませんが、そのような低い制限はありません。これが問題である場合は、他の入力形式のいずれかを選択できます。
— レオTenenbaum

1
@UnrelatedStringもちろん、任意の長さにできる限り。
— Leo Tenenbaum

1
prefix-syntaxオプションを選択した場合の'v number代わりに使用できv number'ますか?
— Xcoder氏

回答:


3

パイソン2、252の 236バイト

def g(n,s):
 if str(s)==s:return s.replace("'","+1")
 o,l,r=map(g,[n]*3,s);return['all((%s)for %s in range(%d))'%(r,l,n),'not((%s)*(%s))'%(l,r),'(%s)%%%d==(%s)%%%d'%(l,n,r,n),'(%s)%s(%s)'%(l,o,r)]['fn=+'.find(o)]
print eval(g(*input()))

オンラインでお試しください!

のf代わりにforallとのn代わりに、ネストされた接頭辞構文として入力を受け取りますnand。

[3, ["f", "v0", ["=", ["*", "v0", ["*", "v0", "v0"]], "v0"]]]

現在、Pythonコードを出力していますが、文がtrueかfalseかについて、2つの異なる出力があるはずです。使用できますprint(eval(g(*input())))。
— Leo Tenenbaum

@LeoTenenbaumええ、最初のバージョンではそれがありましたが、ゴルフ後に追加するのを忘れていました
— TFeld

1

APL(Dyalog Unicode)、129バイトSBCS

{x y z←3↑⍵⋄7≤x:y×7<x⋄5≡x:∧/∇¨y{⍵≡⍺⍺:⍵⍺⋄x y z←3↑⍵⋄7≤x:⍵⋄6≡x:x(⍺∇y)⋄x(⍺∇⍣(5≢x)⊢y)(⍺∇z)}∘z¨⍳⍺⍺⋄y←∇y⋄6≡x:1+y⋄y(⍎x⊃'+×⍲',⊂'0=⍺⍺|-')∇z}

オンラインでお試しください!

TFeldのpython answerと同様に、プレフィックス構文ツリーを使用しますが、整数エンコーディングを使用します。エンコーディングは

plus times nand eq forall succ zero ← 1 2 3 4 5 6 7

各変数には、8から始まる番号が割り当てられます。このエンコードは、コードをゴルフしているときに微調整したため、以下の非ゴルフバージョンで使用されているものとは少し異なります。

タスクには2つの入力(ASTとモジュロ)のみが含まれますが、関数ではなく演算子としてそれを記述すると、モジュロについて何度も言及することを避けます(常に再帰呼び出しで実行されるため)。

コメントなしのゴルフ

⍝ node types; anything ≥8 will be considered a var
plus times eq nand forall succ zero var←⍳8
⍝ AST nodes have 1~3 length, 1st being the node type
⍝ zero → zero, succ → succ arg, var → var | var value (respectively)

⍝ to (from replace) AST → transform AST so that 'from' var has the value 'to' attached
replace←{
  ⍵≡⍺⍺:⍵⍺             ⍝ variable found, attach the value
  x y z←3↑⍵
  zero≤x: ⍵           ⍝ zero or different variable: keep as is
  succ≡x: x(⍺∇y)      ⍝ succ: propagate to y
  forall≡x: x y(⍺∇z)  ⍝ forall: propagate to z
  x(⍺∇y)(⍺∇z)         ⍝ plus, times, eq, nand: propagate to both args
}
⍝ (mod eval) AST → evaluate AST with the given modulo
eval←{
  x y z←3↑⍵
  zero≡x:   0
  var≤x:    y                    ⍝ return attached value
  forall≡x: ∧/∇¨y replace∘z¨⍳⍺⍺  ⍝ check all replacements for given var
  succ≡x:   1+∇y
  plus≡x:   (∇y)+∇z
  times≡x:  (∇y)×∇z
  eq≡x:     0=⍺⍺|(∇y)-∇z         ⍝ modulo equality
  nand≡x:   (∇y)⍲∇z              ⍝ nand symbol does nand operation
}

オンラインでお試しください!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.