Bu Foo makinesi duruyor mu?


43

Bir Turing makinesinin durup durmadığının belirlenmesi iyi anlaşılamaz olarak bilinmektedir, ancak bu daha basit makineler için mutlaka doğru değildir.

Bir Foo makinesi banda her hücre bir tam sayıyı ya da durdurmak sembolü sonlu bant ile bir makine olup h, örneğin

2 h 1 -1

Komut işaretçisi ilk hücreye işaret ederek başlar:

2 h 1 -1
^

Her adımda, komut gösterici işaret ettiği sayı ile ileri hareket eder, sonra bu sayıyı olumsuzlar. Böylece, bir adımdan sonra, 2hücreleri ileri doğru hareket ettirir ve 2a -2:

-2 h 1 -1
     ^

Foo makinesi, talimat göstericisi durma sembolünü ( h) gösterene kadar bunu yapmaya devam eder . Yani, işte bu programın tam yürütülmesi:

2 h 1 -1
^

-2 h 1 -1
     ^

-2 h -1 -1
         ^

-2 h -1 1
      ^

-2 h 1 1
   ^

Bant aynı zamanda daireseldir, bu nedenle, talimat imleci bandın bir tarafından hareket ederse, diğer tarafa gider, örneğin:

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

Bu Foo makineleri hakkında ilginç bir şey, bazılarının durmamasıdır;

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

Bu program sonsuza dek son dört durumda döngü devam edecek.

Bu yüzden bir Foo makinesinin durup durmayacağını belirleyen bir program yazın! Foo makineleri için istediğiniz herhangi bir (makul) giriş biçimini kullanabilir 0ve durma sembolü olarak kullanmayı seçebilirsiniz . Durdurulan durum ve durmadığı durumlar için iki ayrı çıktı kullanabilirsiniz. Elbette, programınız tüm geçerli girişler için sınırlı bir süre içinde cevap yazmalıdır.

Bu , bu yüzden programınızı mümkün olduğunca kısa tutmaya çalışın!

Test durumları

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
Sadece eminim, bunu çözmek için algoritma hakkında. Ben bir algoritma ustası değilim, bu yüzden yanlış yöne gitmeden önce sormayı tercih ederim. Kesintisiz bir Foo makinesi her zaman orijinal durumuna geri döner mi? Yoksa “kaotik davranışlı” kesintisiz makineler var mı?
V. Courtois

5
@ V.Courtois Tüm durmayan Foo makineleri bir durum döngüsünde sona erer, çünkü bir Foo makinesinin içinde olabileceği çok az sayıda durum vardır (talimat göstergesinin olabileceği muhtemel yerler var ve 2 ^ n mümkün teyp yapılandırmaları). Her eyaletin bir ve sadece bir "sonraki eyalete" sahiptir. Yani, eğer bir Foo makinesi zaten içinde olduğu bir durumda sona ererse, sadece döngü devam edecektir. Çünkü sadece çok sayıda devlet var, devletler arasında düzensiz bir şekilde dolaşmaya devam edemez çünkü sonunda zaten içinde olan birine gidiyor.
Leo Tenenbaum

3
Önerilen test durumu: 1 2 h 42(durmuyor)
Arnauld,

6
Önerilen test durumu: 3 2 1 1 4 h. Bu durur ancak element sayısının iki katından daha fazla yineleme gerektirir.
Arnauld,

10
Önerilen ekstra uzun test durumu: 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 -36786430 adımdan sonra durdu.
Magma,

Yanıtlar:


11

C # (Visual C # Etkileşimli Derleyici) , 71 bayt

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

Çevrimiçi deneyin!

Aşağıdakilerin geçerli olup olmadığını bilmiyorum, çünkü imzası olan özel bir temsilci gerektirir unsafe delegate System.Action<int> D(int* a); ve unsafekullanılacak bir bloğa sarılması gerekir, ancak yine de burada:

C # (.NET Çekirdeği) , 64 bayt

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

Çevrimiçi deneyin!

Bu işlev bir int * alır ve bir Eylem döndürür; Başka bir deyişle, bu köreli bir işlevdir. İşaretçileri kullanmamın tek nedeni, zaten zaten dizinin uzunluğu ile tanımlanmış bir değişkene sahip olan baytları kaydetmeme izin veren codegolf.meta.stackexchange.com/a/13262/84206.

@Someone sayesinde 9 bayt kaydedildi


Kodunuzu 2 bayt ile golf
yaptınız

@ IQuick143 Güzel yakalamak, teşekkürler
Ignorance uygulaması

Emin işe yaramaz olduğu herhangi kenar durumlar vardır eğer değilim, ama şu anki test durumları herhangi bozmadan değiştirmek olabilir 1<<file 2*fbir byte kaydedin.
Kevin Cruijssen

1
Korkunç LINQ büyüsü ve Arnauld'un düzeltmesiyle 77 byte . Bu çözümün nasıl çalıştığını bilmiyorum, o yüzden kırmış olabilirim.
biri

1
Normal akıl sağlığı ile 63 bayt 1 bayt golf ve IO'yu hataya / hataya çevirmek. Bağlantıya bağlantı
Birisi

7

Python 3 , 63 89 bayt

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

Çevrimiçi deneyin!

Ayrıca Python 2 için de çalışır; Python 2'ye bir byte, return ile print değiştirilerek ve return işlevinin stdout işlevine yazdırılmasıyla kaydedilebilir. R, Truedurma ve durma Falseiçin döner .

@Neil ve @Arnauld'a, durmak için daha uzun süre kontrol etmem gerektiğine dikkat çekti. Bir sorunu işaret ettiği için @Jitse'e teşekkürler [2,0]. Bant değerlerinin mutlaklığının bant uzunluğunu aşabileceğini belirttiği için @ mypetlion sayesinde.


5
Tamam, ısırırım: x+xyeterli olduğunu nereden biliyorsun ?
Neil

4
@Neil Aslında yeterli değil. Bir karşı örnek, [ 3, 2, 1, 1, 4, 0 ]12'den fazla iterasyonda durma anlamına gelir.
Arnauld,

1
len(x)*x[8,7,6,5,7,4,0,3,6]92

2
2**len(x)Hala azami miktardan biraz daha kısa değil mi? Durum sayısını n*(2**n)(ile n=len(x)-1) olarak hesaplıyorum .
OOBalance

1
@OOBalance Ne demek istediğinizi anlıyorum, çünkü her bir durumun her hücrede bir imleci olabilir ... ancak, her hücrenin ancak diğer iki hücreye yalnızca muhtemel olarak geçebileceği gerçeği tarafından uygulanan başka bir limit olduğunu hissediyorum. Bir yan not olarak: mücadeleden hiçbir şey söylüyor orada vardır girişteki bir durdurulması devlet olmak
Jo Kral

6

Jöle , 15 11 bayt

N1¦ṙ⁸ḢƊÐLḢẸ

Çevrimiçi deneyin!

Girdiyi, durma demek için 0 kullanan bir tam sayıların listesi olarak alan bir monadik bağlantı. Girişleri durdurmak için 0, durmayanlar için 1 değerini döndürür.

ÐLYeni bir sonuç görünene kadar kullanımı döngüden kaynaklanacağı için tekrar sayısı üzerinde çalışmak gerekmemesini önler .

Bayt tasarrufu için @JonathanAllan teşekkürler!

açıklama

      ƊÐ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

Tüm girişleri döndürerek ve ardından ilk sonucu koruyarak bir bayttan tasarruf edin:N1¦ṙ⁸ḢƊÐLḢẸ
Jonathan Allan

5

Python 3 , 91 bayt

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

Çevrimiçi deneyin!

JoKing ve Jitse sayesinde -40 bayt


@JoKing İlk satırda değişken atamalarını yaparak 109 bayt .
Jitse,

92 bayt , boş bir kümeyle başlayıp whilekoşulu değiştirerek, yıldızlı genleşmeye tuple dönüşümünü değiştirerek .
Jitse,

@JoKing Lanet olsun, asla öğrenemiyorum: s. 93 bayt o zaman.
Jitse,


@JoKing teşekkürler!
HyperNeutrino

5

Perl 6 , 46 43 36 bayt

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

Çevrimiçi deneyin!

Durma temsil 0eder ve makine durursa doğru döner. Bu 2**(length n), imleç durma hücresinde sona ererse, orada kaldığı takdirde mantık zamanlarını tekrarlar , aksi takdirde durmayan bir hücrede olacaktır. Bu işe yarıyor çünkü 2**nFoo makinesinin içinde olması için sadece olası durumlar (durma hücreleri yok sayılıyor) var, çünkü durmayan her hücre sadece iki duruma sahip. Tamam evet, bundan daha başka devletler var, ancak işaretçiler (ve dolayısıyla devletler) arasındaki sınırlı geçişlerden dolayı 2'den az ** devlet olacak ... sanırım ...

açıklama

{                                  }  # 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 makinesinin durumu ayrıca, her bir hücrenin sadece işaretlerini değil, işaretçinin konumunu da içerir.
Magma

1
Bantlı bir Foo makinesi için bir kanıt taslağı a_1 ... a_n 0. Yönlendirilmiş kenarlara (= Foo'nun bir yinelemesine) sahip kenarları olan her hücrenin işaretlerinin bir n küpünü (= durumlar) düşünün, aynı köşeyi herhangi bir kenar döngüsüyle ziyaret etmek IP'nin başladığı konumda kalmasına neden olur. . İspat: Bir döngüde IP her boyutta eşit sayıda hareket eder, yani IP her boyut için k × (a_j + (-a_j))% n ≡ 0 olarak değişir, dolayısıyla her zaman aynı konuma döner, sadece her tepe noktası için n durumu dışında 1 durum, yani toplam maksimum 2 ^ n durumu (= küp tepe noktası sayısı) görüyoruz.
Kritixi Lithos

n2n.lÖg(n)/n

3

05AB1E , 14 13 bayt

goFć©(š®._}®_

Çevrimiçi deneyin!

Girdiyi, durma talimatı olarak 0 olan bir tamsayı listesi olarak alır. Durdurma için 1, durdurma için 0 döndürür.

2 byte tasarruf için @KevinCruijssen teşekkürler!


Güzel, bu yüzden Jelly'in cevabının yaptığı bu! Döndürme ve büyük kullanın ć! Cevabımı golf yapmak umuduyla ilgili bir açıklama bekliyordum, ama beni yendin, haha. ; gerçi benim cevap olarak aynı golf yaparak s -1 bayt: g·Fiçin «v( çevrimiçi deneyin. )
Kevin Cruijssen

Ve bir ek -1 kullanarak ©®yerine DŠs: «vć©(š®._}®_( Deneyin çevrimiçi. )
Kevin Cruijssen

Arnaut'un Python cevabında belirttiği gibi , uzunluğun iki katı döngü yeterli değildir. Yani değiştirebilir «viçin goF.
Kevin Cruijssen

@KevinCruijssen teşekkürler
Nick Kennedy

3

Java 8, 78 79 73 bayt

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'in C # .NET yanıtının doğrudan ileri doğru bağlantı noktası , bu yüzden onu oyladığınızdan emin olun! @Arnauld'a
teşekkürler iki hata bulmak için (bu, diğer bazı cevaplar için de geçerlidir).

Durduğunda bir java.lang.ArithmeticException: / by zerohatayla sonuçlanır, aksi takdirde hata olmaz.

Çevrimiçi deneyin.

Açıklama:

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
Merak ediyorum, uzunluğa ek bir argüman olarak izin veriyor musunuz? Meta üzerinde IO yazı için varsayılan yüzden demiyor ve bir alır çünkü benim ikinci cevap uzunluğu alır tek nedeni int*(den codegolf.meta.stackexchange.com/a/13262/84206 )
Cehalet şekillenme

Ahbap, cevabınızı gördüğümde, uzunluğun ek girdi olarak alınmasına izin veren bir tür meta kuralı olduğunu varsaydım, ancak bu yalnızca işaretçiler için geçerli. Bilmeme izin verdiğin için teşekkürler. Length parametresini kaldırdım (ancak sonucu belirlemek için hala hatayı / hatayı kullanın).
Kevin Cruijssen

3

Haskell , 79 bayt

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

Çevrimiçi deneyin!

İade Truedurdurulması makineleri ve için Falsebaşka türlü. 0Bir durma durumunu temsil eden bir liste şeklinde giriş yapın .

GHC'nin 8,4'ten daha büyük olduğunu varsayar (Şubat 2018'de yayınlandı).


2

JavaScript (Node.js) , 71 67 bayt

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

Temelde @EmbodimentOfIgnorance'ın C # .NET cevabı ile aynı

@Arnaud sayesinde 4 byte tasarruf

Çevrimiçi deneyin!

JavaScript (Node.js) , 61 bayt

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

Bu versiyon undefinedbir durdurma sembolü olarak kullanılır ve bir TypeError: Cannot read property 'f' of undefinedmakine durmadığında durur ve durursa bir atar .

Çevrimiçi deneyin!


1

Scala , 156 bayt

Hala golf oynayabilir IMO, ama şimdilik bununla iyiyim. İade 0olmayan durdurulması için Foos ve 1durdurulması için Foos. Girdiyi abir olarak alır Array[Int], holduğu gibi alınır 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

Yaptığım çok sayıda tam dizi arama nedeniyle (testlerin tümü için yaklaşık 4 saniye) çalışması çok uzun, artı .deepkopyalar oluşturuyor ... Ama yine de çevrimiçi deneyebilirsiniz.



1

ataşe , 40 bayt

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

Çevrimiçi deneyin!

açıklama

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

Bu, Foo makinesinin tek bir yineleme işlemini gerçekleştirir; ilk üyeyi olumsuzlar, daha sonra diziyi dizinin (orijinal, negatife edilmemiş) ilk öğesi tarafından döndürür.

Periodicyinelenen bir sonuç birikinceye kadar bu işlevi uygulayacaktır. Bir makine durur veya önemsiz bir sonsuz döngüye girer. Durursa, ilk eleman 0 olur. Aksi takdirde sıfır olmaz.

&Nsayısal bir dizinin ilk elemanını elde etmenin golf yolu. Ardından, 0 (durdurma makineleri) ve başka herhangi bir şey için (durma makineleri) Notdöndürür .truefalse


1

Kömür , 28 bayt

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

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı bir versiyonudur. Kömürün varsayılan Boolean çıktısını kullanarak çıktı alır; bu, -doğru ve yanlış için bir şey değildir. Açıklama:

≔⁰η

Talimat işaretçisini başlat.

FX²Lθ«

Teorik olarak mümkün olan hallerin olduğu kadar çok döngü yapın.

§≔θ籧θη

Komut göstergesindeki değeri olumsuzlayın.

≧⁻§θηη

Yeni değeri komut göstergesinden çıkarın. Kömürün dizi erişimi döngüseldir, bu nedenle otomatik olarak Foo'nun dairesel bandını öykünür.

»¬§θη

Döngünün sonunda, programın durup durmadığını çıktı.



0

Pyth , 12 bayt

!hu.<+_hGtGh

Test odası!

Düz ileri yaklaşımı kullanır. Listeyi aynı durumda iki kez görene kadar tekrar uygulayın. Durdurulan programlar için listenin sonunda bir önceliği olacaktır, 0çünkü özyinelemenin durduğu yer burasıdır. Durmayan programlar için, liste ile başlamayacak 0, ancak sürecin periyodik olacağı ve dolayısıyla Foo makinesinin durmayacağı bir durumda olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.