このFooマシンは停止しますか?


43

チューリングマシンが停止するかどうかを判断することは、決定できないことがよく知られていますが、それは単純なマシンでは必ずしも当てはまりません。

Fooのマシンは、テープ上の各セルは整数または停止シンボルがある有限のテープ、と機械でh、例えば

2 h 1 -1

命令ポインターは、最初のセルを指すことから始まります。

2 h 1 -1
^

すべてのステップで、命令ポインターはそれが指す数値だけ前方に移動し、その数値を無効にします。したがって、1つのステップの後、2セルを前方に移動2し、aに変換し-2ます。

-2 h 1 -1
     ^

Fooマシンは、命令ポインターが停止記号(h)を指すまでこれを続けます。したがって、このプログラムの完全な実行は次のとおりです。

2 h 1 -1
^

-2 h 1 -1
     ^

-2 h -1 -1
         ^

-2 h -1 1
      ^

-2 h 1 1
   ^

テープも円形であるため、命令ポインターがテープの片側から外れると、反対側に移動します。例:

3 h 1 3
^
-3 h 1 3
       ^
-3 h 1 -3
     ^
-3 h -1 -3
         ^
-3 h -1 3
 ^
3 h -1 3
  ^

これらのFooマシンの興味深い点の1つは、停止しないものがあることです。たとえば:

1 2 h 2
^
-1 2 h 2
   ^
-1 -2 h 2
        ^
-1 -2 h -2
    ^
-1 2 h -2
        ^
-1 2 h 2
   ^

このプログラムは、最後の4つの状態で永遠にループを続けます。

したがって、Fooマシンが停止するかどうかを判断するプログラムを作成してください。Fooマシンには任意の(合理的な)入力形式を使用でき0、停止記号として使用することもできます。停止する場合と停止しない場合の2つの異なる出力を使用できます。もちろん、プログラムは、すべての有効な入力に対して有限時間で回答を出力する必要があります。

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

テストケース

2 h 1 -1
Halts
3 h 1 3
Halts
h
Halts
1 1 1 1 h
Halts
2 1 3 2 1 2 h
Halts
3 2 1 1 4 h
Halts
1 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 h -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36
Halts

2 h
Does not halt
1 2 h 2
Does not halt
8 1 2 3 3 4 8 4 3 2 h
Does not halt
1 2 4 3 h 2 4 5 3
Does not halt
3 1 h 3 1 1
Does not halt
1 2 h 42
Does not halt

5
これを解決するアルゴリズムについては確信しています。私はアルゴリズムのマスターではないので、間違った方向に進む前に尋ねることを好みます。停止しないFooマシンは常に正確な元の状態に戻りますか?または、「無秩序に動作する」非停止マシンがありますか?
V.クルトワ

5
@ V.Courtoisすべての停止しないFooマシンは状態のループになります。これは、Fooマシンが取り得る状態の数は限られているためです(命令ポインターが可能な場所はn個あり、2 ^ nは可能です)テープ構成)。各状態には、「次の状態」が1つだけあります。そのため、Fooマシンが既に存在していた状態に戻った場合、ループし続けるだけです。唯一の有限個の状態があるので、それが最終的にそれが既にされています1に行く羽目になるための状態の間の周りにジャンプカオス的に維持することはできません。
レオ・テネンバウム

3
推奨されるテストケース:(1 2 h 42停止しない)
Arnauld

6
推奨されるテストケース:3 2 1 1 4 h。これは停止しますが、要素数の2倍以上の反復が必要です。
アーナルド

10
提案された非常に長いテストケース:1 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 h -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36、786430ステップ後に停止します。
マグマ

回答:


11

C#(Visual C#Interactive Compiler)、71バイト

x=>{for(int i=0,k=0,f=x.Count;i++<1<<f;k%=f)k-=(x[k]*=-1)%f-f;i/=x[k];}

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

次の署名が有効なカスタムデリゲートが必要であり、使用unsafe delegate System.Action<int> D(int* a); するunsafeブロックにラップする必要があるため、以下が有効かどうかはわかりませんが、ここではとにかくです:

C#(.NET Core)、64バイト

x=>f=>{for(int i=0,k=0;i++<1<<f;k%=f)k-=(x[k]*=-1)%f-f;k/=x[k];}

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

この関数はint *を受け取り、Actionを返します。つまり、カリー化された関数です。ポインターを使用する唯一の理由は、codegolf.meta.stackexchange.com / a / 13262/84206のためです。これにより、配列の長さで既に定義された変数を既に持つことでバイトを節約できます。

@someoneのおかげで9バイト節約


:2つのバイトコードをGolfed tio.run/...
IQuick 143

@ IQuick143すてきなキャッチ、ありがとう
無知の

それは動作しませんのための任意のエッジケースがある場合、私はわからないんだけど、現在のテストケースのいずれかを壊すことなく、あなたは置き換えることができ1<<f2*fバイトを保存します。
ケビンクルーッセン

1
恐ろしいLINQマジックとArnauldの修正を加えた77バイト。このソリューションがどのように機能するかはわかりませんので、壊れた可能性があります。
誰か

1
通常の正常な1バイトのゴルフを介して63バイトで、IOをエラー/エラーなしに変更します。リンクへのリンク
誰か

7

Pythonの363の 89バイト

def f(x):
 for i in range(2**len(x)):a=x[0];x[0]=-a;b=a%len(x);x=x[b:]+x[:b]
 return a==0

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

Python 2でも機能します。Python 2でバイトを保存するには、returnをprintに置き換え、関数をreturnの代わりにstdoutに出力します。RはTrue、停止とFalse非停止を切り替えます。

@Neilと@Arnauldに、停止のためにもっと長い時間をチェックする必要があることに注意してくれてありがとう。の問題を指摘してくれた@Jitseに感謝し[2,0]ます。テープ値の絶対値がテープの長さを超える可能性があることに注意してくれた@mypetlionに感謝します。


5
噛むよ。どうやってx+x十分だとわかる?
ニール

4
@Neilそれは実際には十分ではありません。反例はで[ 3, 2, 1, 1, 4, 0 ]、これは12回以上の繰り返しで停止します。
アーナルド

1
@Jitse len(x)*xは機能しません。たとえば[8,7,6,5,7,4,0,3,6]、回以上の繰り返しで停止します。92
アーナウド

2
2**len(x)まだ最大値に少し足りませんか?状態の数をn*(2**n)(でn=len(x)-1)として計算します。
OOBalance

1
@OOBalance各状態は各セルにポインターを持つことができるので、あなたが言っていることがわかります...しかし、各セルは2つの他のセルにしか遷移できないという事実によって、他の制限が適用されているように感じます。注意点として:挑戦では何も述べていないが持っている入力で休止状態に
ジョー・キング

6

ゼリー15 11バイト

N1¦ṙ⁸ḢƊÐLḢẸ

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

0を使用して停止を意味する整数のリストとして入力を受け取るモナドリンク。入力を停止する場合は0を返し、停止しない入力の場合は1を返します。

ÐL新しい結果が見られなくなるまでループを使用するため、反復回数を計算する必要があるという問題を回避します。

バイトを保存してくれた@JonathanAllanに感謝します!

説明

      ƊÐL   | Loop the following as a monad until the result has been seen before:
N1¦         | - Negate the first element
   ṙ⁸       | - Rotate left by each of the elements
     Ḣ      | - Take just the result of rotating by the first element
         Ḣ  | Finally take the first element
          Ẹ | And check if non-zero

:すべてのエントリで回転して、ちょうど最初の結果を保つことによってバイトを保存N1¦ṙ⁸ḢƊÐLḢẸ
ジョナサン・アラン

5

Python 3、91バイト

def f(a):
	s={0,};i=0
	while{(*a,)}-s:s|={(*a,)};a[i]*=-1;i-=a[i];i%=len(a)
	return a[i]==0

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

JoKingとJitseのおかげで-40バイト


@JoKing 最初の行で変数の割り当てを行うことで109バイト
Jitse

タプル変換をスター付き展開に変更することにより、92バイトwhile。空のセットで開始せず、条件を言い換えます。
Jitse

@JoKingくそー、私は決して学ばない:p。93バイト
Jitse


@JoKingありがとう!
ハイパーニュートリノ

5

Perl 6の46の43 36バイト

{$_.=rotate(.[0]*=-1)xx 2**$_;!.[0]}

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

0停止を表し、マシンが停止するとtrueを返します。これは、論理2**(length n)時間を繰り返します。ポインターが停止セルに到達した場合は、そこに留まります。そうでない場合は、非停止セルに留まります。これ2**nは、Fooマシンが可能な状態(停止セルを無視する)のみが存在するためです。これは、非停止セルにはそれぞれ2つの状態しかないためです。はい、そうです、それよりも状態がありますが、ポインタ(および状態)間の遷移が限られているため、状態が2 ** $ _未満になります...

説明

{                                  }  # Anonymous codeblock
                     xx 2**$_         # Repeat 2**len(n) times
            .[0]*=-1                  # Negate the first element
 $_.=rotate(        )                 # Rotate the list by that value
                             ;!.[0]   # Return if the first element is 0

2
Fooマシンの状態には、各セルの兆候だけでなく、ポインターの位置も含まれます。
マグマ

1
テープa_1 ... a_n 0を使用したFooマシンの証明のスケッチ。頂点(=状態)間の有向エッジ(= Fooの反復)を持つ各セルの符号のnキューブを考えて、エッジのループを介して同じ頂点にアクセスすると、IPは開始位置と同じ位置になります。証明:ループでは、IPは各次元で偶数回移動します。つまり、IPは各次元でk×(a_j +(-a_j))%n≡0だけ変化するため、常に同じ位置に戻ります。各頂点のn個の状態のうち1個の状態、つまり合計最大2 ^ n個の状態(=立方体の頂点の数)のみが表示されます。
Kritixi Lithos

経験的な結果にが、長さテープでマシンを停止する間の最長サイクルを強引に強制することは、より厳密な上限がことを示唆します。2 のnL O G N / N n2n.log(n)/n
アーナウド

3

05AB1E14 13バイト

goFć©(š®._}®_

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

入力を、停止命令として0を持つ整数のリストとして受け取ります。停止する場合は1、停止しない場合は0を返します。

2バイトを節約してくれた@KevinCruijssenに感謝します!


いいですね、それがあなたのゼリーの答えです!rotateとć!私は私の答えをゴルフすることを望んで説明を待っていましたが、あなたは私にそれを打ちました、ハハ。; p -1バイトですが、私の答えと同じゴルフをして:g·Fto «vオンラインで試してみてください。
Kevin Cruijssen

そして©®DŠs次の代わりに-1を追加して使用します«vć©(š®._}®_オンラインで試してください。
Kevin Cruijssen

以下のようアルノーは 2回ループし、あなたのPythonの答えに述べた長さが十分ではありません。あなたが変更できるよう«vにしますgoF
ケビンクルーッセン

@KevinCruijssenありがとう
ニックケネディ

3

Java 8、78 79 73バイト

a->{int k=0,l=a.length,i=0;for(;i++<1<<l;k%=l)k-=(a[k]*=-1)%l-l;k/=a[k];}

@EmbodimentOfIgnoranceのC#.NETの答えの単純な移植版なので、必ず彼に賛成してください!2つのバグを発見して
くれた@Arnauldに感謝します(これは他の回答にも当てはまります)。

で結果java.lang.ArithmeticException: / by zeroそれが停止することができますエラー、またはエラーなしの場合ではありません。

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

説明:

a->{                   // Method with integer-array as parameter and no return-type
  int k=0,             //  Index integer, starting at 0
      l=a.length,      //  The length `l` of the input-array
  i=0;for(;i++<1<<l;   //  Loop 2^length amount of times:
          k%=l)        //    After every iteration: take mod `l` of `k`
    k-=                //   Decrease `k` by:
       (a[k]*=-1)      //    Negate the value at index `k` first
                 %l    //    Then take modulo `l` of this
                   -l; //    And then subtract `l` from it
                       //  (NOTE: the modulo `l` and minus `l` are used for wrapping
                       //  and/or converting negative indices to positive ones
  k/=a[k];}            //  After the loop: divide `k` by the `k`'th value,
                       //  which will result in an division by 0 error if are halting

2
ただ疑問に思う、あなたは追加の引数として長さを取ることができますか?メタのIOポストのデフォルトはそうではなく、私の2番目の答えに時間がかかる唯一の理由は、それがint*codegolf.meta.stackexchange.com/a/13262/84206から)を取り込むためです
無知の実施

@EmbodimentofIgnoranceああ、あなたの答えを見たとき、長さを追加入力として許可する何らかの種類のメタルールがあると思いましたが、それはポインターにのみ適用されます。知らせてくれてありがとうございます。長さパラメーターを削除しました(ただし、エラー/エラーなしを使用して結果を決定します)。
ケビンクルーッセン

3

Haskell、79バイト

s x|m<-length x,let g(n:p)=(drop<>take)(mod n m)(-n:p)=iterate g x!!(2^m)!!0==0

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

Trueマシンを停止したFalse場合などに戻ります。0停止状態を表すリスト形式の入力。

GHCのバージョンが8.4より大きいと想定しています(2018年2月にリリース)。


2

JavaScript(Node.js)71 67バイト

x=>{for(p=l=x.length,i=2**l;i--;)p+=l-(x[p%l]*=-1)%l;return!x[p%l]}

基本的に@EmbodimentOfIgnoranceのC#.NETの回答と同じ

@Arnaudによる 4バイトの節約

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

JavaScript(Node.js)、61バイト

x=>{for(p=l=x.length,i=2**l;i--;p+=l-(x[p%l]*=-1)%l)x[p%l].f}

このバージョンはundefined、停止シンボルとして使用しTypeError: Cannot read property 'f' of undefined、マシンが停止するとaをスローし、マシンが停止しないと静かに終了します。

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


1

Scala、156バイト

まだゴルフ可能なIMOですが、今のところは大丈夫です。戻り値0非停止のためのFooSや1停止のためFooの。入力を取るaようにArray[Int]、そうhとしています0

var u=Seq[Array[Int]]()//Keep track of all states
var i=0//Index
while(u.forall(_.deep!=a.deep)){if(a(i)==0)return 1//Check if we are in a previously encountered step ; Halt
u:+=a.clone//Add current state in the tracker
var k=i//Stock temp index
i=(a(i)+i)%a.length//Move index to next step
if(i<0)i+=a.length//Modulus operator in Scala can return a negative value...
a(k)*=(-1)}//Change sign of last seen index
0//Returns 0 if we met a previous step

実行したのはかなり長い(すべてのテストケースで約4秒)のは、私が行った複数のフルアレイルックアップに加えて.deep、コピーを作成するためです...しかし、まだオンラインで試すことができます。



1

アタッシュ、40バイト

Not@&N@Periodic[{On[0,`-,_]&Rotate!_@0}]

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

説明

{On[0,`-,_]&Rotate!_@0}

これにより、Fooマシンの単一の反復が実行されます。最初のメンバーを否定し、配列の(元の、否定ではない)最初の要素だけ配列を回転させます。

Periodic重複する結果が蓄積されるまでこの関数を適用します。マシンは停止するか、些細な無限ループに入ります。停止した場合、最初の要素は0になります。それ以外の場合、非ゼロになります。

&N数値配列の最初の要素を取得するゴルフの方法です。次に、0(マシンの停止)およびその他(マシンの停止なし)をNot返します。truefalse


1

、28バイト

≔⁰ηFX²L諧≔θ籧θη≧⁻§θη绬§θη

オンラインでお試しください!リンクは、コードの詳細バージョンです。Charcoalのデフォルトのブール出力を使用して出力します。これは-trueであり、false ではありません。説明:

≔⁰η

命令ポインタを初期化します。

FX²Lθ«

理論的に可能な状態の数だけループします。

§≔θ籧θη

命令ポインターで値を否定します。

≧⁻§θηη

命令ポインタから新しい値を引きます。チャコールの配列アクセスは周期的であるため、これはFooの円形テープを自動的にエミュレートします。

»¬§θη

ループの終わりに、プログラムが停止したかどうかを出力します。



0

Pyth、12バイト

!hu.<+_hGtGh

テストスイート!

簡単なアプローチを使用します。リストが同じ状態で2回表示されるまで繰り返します。停止するプログラム0の場合、再帰が停止するため、リストは最終的に先頭になります。停止しないプログラムの場合、リストはで始まるのでは0なく、プロセスが定期的に行われる状態になるため、Fooマシンは停止しません。

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