이 Foo 기계가 정지합니까?


43

튜링 머신의 정지 여부를 결정하는 것은 결정 불가능한 것으로 알려져 있지만, 더 단순한 머신에서는 반드시 그런 것은 아닙니다.

푸 기계 테이프의 각 셀은 정수 또는 중지 심볼 갖는 유한 테이프있는 컴퓨터 인 h, 예를

2 h 1 -1

명령 포인터는 첫 번째 셀을 가리켜 서 시작합니다.

2 h 1 -1
^

모든 단계에서 명령 포인터는 가리키는 숫자만큼 앞으로 이동 한 다음 해당 숫자를 무시합니다. 따라서 한 단계 후에는 2셀을 앞으로 이동 하고를 다음 2으로 바꿉니다 -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 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 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. Courtois

5
@ V.Courtois 정지하지 않는 모든 Foo 머신은 Foo 머신이있을 수있는 상태가 유한하게 많기 때문에 (상태 포인터가있을 수있는 가능한 장소가 있고, 2 ^ n 가능합니다.) 테이프 구성). 각 상태에는 하나의 "다음 상태"만 있습니다. 따라서 Foo 머신이 이미있는 상태로 돌아 가면 계속 반복됩니다. 유한하게 많은 주만이 있기 때문에, 결국 주정부가 이미 있었던 주로 갈 수 있기 때문에 주들 사이를 혼란스럽게 뛰어 넘을 수 없습니다.
Leo Tenenbaum

3
권장 테스트 사례 : 1 2 h 42(중지되지 않음)
Arnauld

6
권장 테스트 사례 : 3 2 1 1 4 h. 이것은 정지하지만 요소 수의 두 배보다 더 많은 반복이 필요합니다.
Arnauld

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 # 대화식 컴파일러) , 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 코어) , 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바이트를 저장합니다.
케빈 크루이 ssen

1
끔찍한 LINQ 마술과 Arnauld의 수정으로 77 바이트 . 이 솔루션이 어떻게 작동하는지 잘 모르므로 문제가 발생했을 수 있습니다.
누군가

1
정상적인 정상 1 바이트 골프를 통해 63 바이트이며 IO를 오류 / 오류 없음으로 변경합니다. 링크 링크
누군가

7

파이썬 3 , 63 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에서도 작동합니다. return을 print로 바꾸고 return 대신 함수를 stdout으로 출력하여 파이썬 2에 바이트를 저장할 수 있습니다. R은 True정지 및 False비 정지 상태로 바뀝니다 .

@Neil 및 @Arnauld 덕분에 중지를 더 이상 확인해야한다는 점에 주목했습니다. 문제를 지적 해 주신 @Jitse에게 감사드립니다 [2,0]. 테이프 값의 절대 값이 테이프 길이를 초과 할 수 있다는 점을 지적한 @mypetlion에게 감사드립니다.


5
알았어, 물어볼 게 어떻게 x+x충분하니?

4
@Neil 실제로 충분하지 않습니다. 반례는 [ 3, 2, 1, 1, 4, 0 ]입니다.이 반복은 12 회 이상 중단됩니다.
Arnauld

1
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 각 상태가 각 셀에 포인터를 가질 수 있기 때문에 의미하는 바를 알지만 각 셀이 두 개의 다른 셀로만 전이 될 수 있다는 사실에 의해 다른 제한이 적용되는 것처럼 느낍니다. 참고로, 도전의 어떤 것도 입력에 정지 상태 있어야 한다고 말하지 않습니다
Jo King

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ḢẸ
Jonathan Allan

5

파이썬 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

빈 세트로 시작하지 않고 while조건을 다시 표현하지 않고 튜플 변환을 별표로 확장하여 92 바이트 .
Jitse

@ JoKing 젠장, 나는 결코 배우지 않는다 : p. 그런 다음 93 바이트 .
Jitse


@JoKing 감사합니다!
HyperNeutrino

5

펄 6 , 46 43 36 바이트

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

온라인으로 사용해보십시오!

정지를 0나타내고 기계가 정지하면 true를 리턴합니다. 이것은 논리 2**(length n)시간을 반복하는데 , 포인터가 정지 셀에서 끝나면 거기에 머무르고 그렇지 않으면 정지되지 않은 셀에있게됩니다. Foo 머신에있을 수있는 상태 (정지 셀 무시) 만 있기 때문에 작동합니다. 2**n각 중지되지 않은 셀에는 상태가 두 개뿐입니다. 네, 그보다 상태가 있지만 포인터 (및 상태) 사이의 가능한 전이가 제한되어 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 개의 상태 중 하나의 상태, 즉 총 최대 2 ^ n 상태 (= 큐브의 정점 수) 만 표시됩니다.
Kritixi Lithos

n2n.log(n)/n

3

05AB1E , 14 13 바이트

goFć©(š®._}®_

온라인으로 사용해보십시오!

중지 명령으로 0을 입력하여 정수 목록으로 입력을받습니다. 정지하면 1을, 정지하지 않으면 0을 반환합니다.

2 바이트를 절약 한 @KevinCruijssen에게 감사합니다!


오, 그래서 그것은 당신의 젤리 답변이하는 일입니다! 회전을 많이 사용 ć! 나는 내 대답을 골프화하기 위해 설명을 기다리고 있었지만, 당신은 나를 이겼다. 내 대답과 같은 골프를함으로써; p -1 바이트 : g·Fto «v( 온라인으로 시도하십시오. )
Kevin Cruijssen

그리고 ©®대신에 다음 을 사용하여 -1을 하나 더 추가 하십시오 DŠs. «vć©(š®._}®_( 온라인으로 시도하십시오. )
Kevin Cruijssen

으로 Arnauld가 두 번 반복, 파이썬 대답에 언급 된 길이가 충분하지 않습니다. 그래서 당신은을 변경할 수 있습니다 «vgoF.
케빈 크루이

@KevinCruijssen 감사합니다
Nick Kennedy

3

자바 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 answer간단한 포트이므로 그를 찬성 해야합니다! 두 가지 버그를 찾는 @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 포스트의 기본은 그렇게 말씀하지 않으며, 그것은에 걸리기 때문에 내 두 번째 대답은 길이를 소요하는 유일한 이유는 int*(에서 codegolf.meta.stackexchange.com/a/13262/84206 )
무지의 실시 예

무지 @ 구현의 아 아, 당신의 대답을 보았을 때 길이를 추가 입력으로 취할 수 있지만 포인터에만 적용되는 일종의 메타 규칙이 있다고 가정했습니다. 알려 줘서 고마워. 길이 매개 변수를 제거했지만 여전히 오류 / 오류 없음을 사용하여 결과를 결정합니다.
Kevin Cruijssen

3

하스켈 , 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정지 상태 를 나타내는 목록 형식으로 입력하십시오 .

8.4보다 큰 GHC 버전을 가정합니다 (2018 년 2 월 출시).


2

자바 스크립트 (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 바이트 저장

온라인으로 사용해보십시오!

자바 스크립트 (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기계가 정지하면 기계가 정지하지 않으면 조용히 종료됩니다.

온라인으로 사용해보십시오!


1

스칼라 , 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

내가 한 여러 번의 전체 배열 조회와 .deep복사본을 만드는 것 때문에 실행하는 데 꽤 오래 걸립니다 (모든 테스트 사례에서 약 4 초) ...하지만 온라인으로 시도해 볼 수 있습니다.



1

첨부 , 40 바이트

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

온라인으로 사용해보십시오!

설명

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

Foo 머신의 단일 반복을 수행합니다. 첫 번째 멤버를 부정한 다음 배열의 (음이 아닌 원래의) 첫 번째 요소에 의해 배열을 회전시킵니다.

Periodic중복 결과가 누적 될 때까지이 기능을 적용합니다. 기계가 멈추거나 사소한 무한 루프로 들어갑니다. 정지하면 첫 번째 요소는 0이되고, 그렇지 않으면 0이 아닙니다.

&N숫자 배열의 첫 번째 요소를 얻는 골치 아픈 방법입니다. 그런 다음 0 (정지 기) 및 기타 (정지 기 이외 )를 Not반환 true합니다 false.


1

, 28 바이트

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

온라인으로 사용해보십시오! 링크는 자세한 버전의 코드입니다. Charcoal의 기본 부울 출력을 사용하여 출력합니다. 이는 -true이고 false는 아닙니다. 설명:

≔⁰η

명령 포인터를 초기화하십시오.

FX²Lθ«

이론적으로 가능한 상태가있는 횟수만큼 반복합니다.

§≔θ籧θη

명령 포인터에서 값을 무효화하십시오.

≧⁻§θηη

명령어 포인터에서 새 값을 뺍니다. 차콜의 어레이 액세스는 주기적이므로 Foo의 원형 테이프를 자동으로 에뮬레이트합니다.

»¬§θη

루프가 끝나면 프로그램 정지 여부를 출력합니다.



0

Pyth , 12 바이트

!hu.<+_hGtGh

테스트 스위트!

간단한 접근 방식을 사용합니다. 동일한 상태에서 목록을 두 번 볼 때까지 반복하십시오. 중단되는 프로그램 0의 경우 재귀가 중지되는 위치이기 때문에 목록이 결국 선행을 갖습니다 . 중단되지 않는 프로그램의 경우 목록이로 시작되지 0않고 프로세스가 주기적으로 진행되는 Foo 머신이 중지되지 않은 상태에있게됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.