Dairesel bantlar heyecan verici mi?


32

Bir Brainfuck türevi

Brainfuck benzeri bir programlama dili tanımlayalım . İki yönlü bir hücre bandına sahiptir ve her hücre bir bit tutar. Tüm bitler başlangıçta 0'dır. Kasette, başlangıçta 0 konumunda, hareketli bir kafa vardır. Program, karakterlerin üzerinde, <>01!soldan sağa doğru, aşağıdaki anlambilimiyle yürütülen bir dizgedir :

  • < kafa bir adım sola hareket eder.
  • > kafa bir adım sağa doğru hareket eder.
  • 0 geçerli hücreye 0 koyar.
  • 1 geçerli hücreye 1 koyar.
  • ! mevcut hücreyi çevirir

Döngü yoktur, bu nedenle n karakter programı tam olarak n adımdan sonra sona erer . Bir program, tüm hücrelerin yürütme sonunda 0 içermesi durumunda sıkıcı ve en az bir tane olması durumunda heyecan vericidir . Teybin boyutunun belirtilmediğine dikkat edin; dairesel.

Örnek bir program

Programı düşünün 1>>>!<<<<0>!>>>!. Sonsuz bir kasette, yürütme aşağıdaki şekilde ilerler:

     v
00000000000000  Put 1
     v
00000100000000  Move by >>>
        v
00000100000000  Flip
        v
00000100100000  Move by <<<<
    v
00000100100000  Put 0
    v
00000100100000  Move by >
     v
00000100100000  Flip
     v
00000000100000  Move by >>>
        v
00000000100000  Flip
        v
00000000000000

Sonunda, tüm hücreler 0, bu nedenle bu program sıkıcı. Şimdi, aynı programı 4 uzunluğundaki dairesel bir bant üzerinde çalıştıralım.

v
0000  Put 1
v
1000  Move by >>>
   v
1000  Flip
   v
1001  Move by <<<< (wrapping around at the edge)
   v
1001  Put 0
   v
1000  Move by > (wrapping back)
v
1000  Flip
v
0000  Move by >>>
   v
0000  Flip
   v
0001

Bu sefer 1 değerinde bir hücre var, bu yüzden program heyecan verici! Bir programın sıkıcı veya heyecan verici olup olmadığını kasetin boyutuna bağlı olduğunu görüyoruz.

Görev

Girişiniz <>01!, yukarıdaki programlama dilinde bir programı temsil eden boş olmayan bir dizedir . Bir karakter dizisi de kabul edilebilir bir giriş biçimidir. Sonsuz bir kasette çalıştırıldığında programın sıkıcı olacağı garantilidir. Çıktınız, programın heyecan verici olduğu bant uzunluklarının listesi olacaktır. Programı yalnızca program uzunluğundan daha kısa olan bantlar üzerinde test etmeniz gerektiğini unutmayın.

Her dilde en düşük bayt sayısına sahip çözüm kazanır. Standart kuralları geçerlidir.

Test durumları

> : []
110 : []
1>0<! : [1]
0>>1>0<<>! : [1]
1>>>!<<<<0>!>>>! : [2, 4]
!<!<><<0>!>!<><1!>>0 : [2]
>>!>><>001>0<1!<<!>< : [1, 2, 3]
1!><<!<<<!!100><>>>! : [1, 3]
!!1>!>11!1>>0<1!0<!<1><!0<!<0> : [3, 4]
<><<>>!<!!<<<!0!!!><<>0>>>>!>> : [1, 2, 4]
0>>><!<1><<<0>!>>!<<!!00>!<>!0 : [3]
0000!!!!><1<><>>0<1><<><<>>!<< : []
!>!>!>!>!>1>!>0<!<!<!<0<!<0<!<!<!<1>!>0<<! : [1, 2, 5, 7]
<!!>!!><<1<>>>!0>>>0!<!>1!<1!!><<>><0<<!>><<!<<!>< : [1, 2, 4, 5]
!>1<<11<1>!>!1!>>>0!!>!><!!00<><<<0<<>0<<!<<<>>!!> : [1, 2, 3, 5, 6]

1
Bunun yerine farklı ve tutarlı karakterler seçebilir miyiz <>01!?
Bay Xcoder

1
Bir dizi talimat kabul edilebilir bir girdi midir?
Arnauld

@ Mr.Xcoder Hayır, bu karakterleri kullanmalısınız.
Zgarb

@Arnauld Bir karakter dizisi bir dizgiye yeterince yakın, buna izin vereceğim.
Zgarb

Yanıtlar:


6

Haskell, 119 bayt

t#'<'=last t:init t
(h:t)#c|c<'#'=1-h:t|c>'='=t++[h]|1<2=read[c]:t
f p=[n|n<-[1..length p],sum(foldl(#)(0<$[1..n])p)>0]

Çevrimiçi deneyin!

İşlev #, tek bir komutun yorumlayıcısıdır c. Bütün program ptarafından çalıştırılan folding #içine başlayan bantla p. Her bir bant için fçalıştırılır pve hücrelerin toplamının en az 1 olduğu yerlerde tutulur.


n<-[1..length p] ... 0<$[1..n]oldukça uzun görünüyor, daha kısa bir yol olmalı.
nimi

Daha kısa bir yol göremiyorum. Gördüğüm sorun, aslında nsonucun değerine ihtiyaç duymanızdır , bu nedenle 0<$[1..n]farklı bir yol yaptıysanız (söyleyelim scanr(:)), bunu kullanmanız gerekir length. (Ayrıca 1(yerine koymak lengthiçin sum) veya False( ortest için kullanmak için ) kullanmayı da denedim 0, ancak daha kısa gelmedi.)
Ørjan Johansen

@ ØrjanJohansen: evet, n<-init$scanr(:)[]$0<$p ... nhangisinin 2 bayt daha kısa olduğunu denedim , ancak uzunluğu yerine başlangıç ​​kasetlerinin bir listesini döndürür, örn [[0],[0,0,0]]. Biraz kural bükme ile bantlar unary sayılar olarak görebiliyordu, belki de sorun değil.
nimi

init$[0]İlk liste olarak koyarak değiştirilebilir , ancak yine de yeterince kısa kalmadı. Bence, unary'ye sadece daha doğal bir sayı temsili olmayan diller için izin veriliyor .
Ørjan Johansen

4

Stax , 56 54 43 38 35 bayt CP437

è¥%►BΣ░ÜY⌂y(â&.═ªê►V½▲y▌)▀♫♂╣ª?√»!#

Ambalajı açıldığında 42 byte,

%fz(y{{|(}{|)}{B!s+}{0_]e&}4ls"><! "I@!F|a

Çevrimiçi çalıştırın ve hata ayıklayın!

@Recursive tarafından yorum başına -2 bayt

açıklama

Sürümü açıklamak için bir önekle i(yani i%fz(y{{|(}{|)}{B!s+}{0_]e&}4ls"><! "I@!F|a) kullanacağım ve neden ikaldırılabileceğini açıklayacağım

i               Suppress implicit eval
                    This prevents the test case "110" from being interpreted as a number
                    However, this can be removed because a program containing only numbers cannot be exciting and the output will be empty anyway.
                    This is based on the fact that the program is boring on non-circular tapes
 %f             Filter range [1..n] with the rest of this program
                    Where n is the length of the input
                    Implicit output the array after filtering, one element per line
   z(           Initialize the tape
     y{  F      Run the program
          |a    Any cell is non-zero

Programı çalıştırma kodu:

{|(}                                 Block to rotate left by one element
    {|)}                             Block to rotate right by one element
        {B!s+}                       Block to perform logical not on the element at index 0
              {0_]e&}                Block to obtain current instruction,
                                         Convert it to a number
                                         And assign to element at index 0

                     4l              Pack the 4 blocks in an array
                       s"<>! "I      Find the index of current instruction in string, if not found, the index will be -1
                                         And when indexed with -1, it wraps around to the 4th element.

                               @!    And execute the corresponding block.

1
iÇekinizi doğrulamak için tüm basamaklardan bir test durumu ekledim .
Zgarb

0]*ile değiştirilebilir z(. Ayrıca, daha sonra, "! <>" Dize değiştirirseniz 0ve 1bu şekilde sizin blok liste sadece 4 blok ihtiyacı böylece beri çalışacak 5. Bu yerine, endeks -1 verecek 0ve 1işleyicileri özdeş zaten vardır.
özyinelemeli

@recursive İyi nokta alındı.
Weijun Zhou,




2

Kırmızı , 243 bayt

func[p][repeat n length? p[b: copy[]insert/dup b 0 n i: 1
parse p[any["<"(i: i - 1 if i < 1[i: n])|">"(i: i + 1 if i > n[i: 1])|"0"(b/(i): 0)|"1"(b/(i): 1)|"!"(b/(i): either b/(i) = 0[1][0])|
skip]]s: 0 foreach c b[s: s + c]if s > 0[print n]]]

Çevrimiçi deneyin!

Prety ayrıntılı ve basit bir uygulama. Red'in 1 indekslemesi, dairesel bantlar boyunca döngü oluşturmak için modüler aritmetik kullanarak bayt sayısını azaltmama izin vermiyor.

Ungolfed

f: func[p][ 
    repeat n length? p[
        b: [] 
        insert/dup b 0 n
        i: 1
        parse p[
            some [
                 "<" (i: i - 1 if i < 1[i: n])
               | ">" (i: i + 1 if i > n[i: 1])
               | "0" (b/(i): 0)
               | "1" (b/(i): 1)
               | "!" (b/(i): either b/(i) = 0 [1][0])
               | skip 
            ]
        ]
        s: 0
        foreach c b[s: s + c]
        if s > 0 [print n]
    ]
]


2

Retina , 121 bayt

.+
$.&*0¶$&
\G0
0$`¶
{ms`^.(?=.*¶¶(0|1))
$1
"¶¶!"&mT`d`10`^.
"¶¶>"&`(.)(.*)¶
$2$1¶
"¶¶<"&`(.*)(.)¶
$2$1¶
)`¶¶.
¶¶
G`1
%`.

Çevrimiçi deneyin! Açıklama:

.+
$.&*0¶$&
\G0
0$`¶

Giriş programının uzunluğuna kadar her uzunlukta bir bant dizisi oluşturun.

{

Program tüketilene kadar döngü.

ms`^.(?=.*¶¶(0|1))
$1

Programdaki bir sonraki karakter 0 veya 1 ise, her satırdaki ilk karakteri o karakterle değiştirin.

"¶¶!"&mT`d`10`^.

Eğer öyleyse, !her satırdaki ilk karakteri değiştir.

"¶¶>"&`(.)(.*)¶
$2$1¶
"¶¶<"&`(.*)(.)¶
$2$1¶

A ise >veya <sonra çizgiyi döndürün. (Kafayı hareket ettirmekten daha kolay.)

)`¶¶.
¶¶

Talimatı silin ve döngüyü sonlandırın.

G`1

Sadece heyecan verici çizgileri koru.

%`.

Her çizginin uzunluğunu sayın.


2

JavaScript (ES6), 126 118 bayt

@ User71546 sayesinde 3 bayt kaydedildi

Girdiyi 1 karakterli dizeler dizisi olarak alır.

f=(s,l=0,p=0,t=[])=>s[l++]?s.map(c=>1/c?t[p%l]=+c:c>'='?p++:c>';'?p+=l-1:t[p%l]^=1)&&+t.join``?[l,...f(s,l)]:f(s,l):[]

Çevrimiçi deneyin!


Değiştirilmesi t.some(x=>x)?ile +t.join``?yerine basamak olarak bir dizi kontrol (0 hepsi sıfir bir bant gösterir), ancak 3 bayt daha azdır.
Shieru Asakoto

2

APL (Dyalog Unicode) , 79 64 54 bayt ( Adám's SBCS )

⍸⊂{∨/⍎⍕(↓',',⍨5 3'0@11@1~@1 1⌽¯1⌽')['01!<'⍳⌽⍺]⍵}¨0=,\

Çevrimiçi deneyin!

-15 Adám sayesinde (monadik hakkında unuttum ).
-10 ngn sayesinde .



@ Adám Hm, optimal değil gibi görünüyor (örneğin, ihtiyacınız yok ). Bunu inceleyip güncelleyeceğim. :)
Outgolfer Erik

Ama kaldırırsan, ihtiyacın olacak ;, değil mi?
18'de

@ Adám hayır , neden olmasın ?
Outgolfer Erik


1

MATL , 46 39 bayt

f"@:~G"@59>?@61-YS}@33=?t1)~}@U]1(]]a?@

Çevrimiçi deneyin! Veya tüm test durumlarını doğrulayın .

Nasıl çalışır

f             % Push indices of nonzero chars of (implicit) input string: gives
              % [1 2 ... n] where n is input length
"             % For each k in [1 2 ... n]. These are the possible tape lengths
  @:~         %   Push array of k zeros. This is the tape, in its initial state
  G           %   Push input string
  "           %   For each char in the input string
    @59>?     %     If code point of current char exceeds 59 (so it is '<' or '>')
      @61-    %       Push code point minus 61: gives -1 for '<', or 1 for '>'
      YS      %       Circularly shift the tape by that amount. Instead of moving
              %       the head, we shift the tape and keep the head at entry 1
    }         %     Else
      @33=?   %       If code point of current char is 33 (so it is '!')
        t1)   %         Duplicate the array representing the tape, and get its
              %         first entry
        ~     %         Logical negate
      }       %       Else
        @U    %         Push current char (it is '0' or '1') converted to number
      ]       %       End
      1(      %       Write (either 0, 1 or old value negated) at entry 1
    ]         %     End
  ]           %   End
  a?          %   If the tape contains at least a nonzero value
    @         %     Push tape length, k
              %   End (implicit)
              % End (implicit)
              % Display (implicit)

1

APL (Dyalog Unicode) , 192 78 bayt

⊂{t/⍵⊣⍵{t[m]←('01!'⍳⍵)⊃0 1,e,⍨~et[m←⍺|ii+←¯1 1 0⊃⍨'<>'⍳⍵]}¨⍺⊣i←⊃t←⍬⍳⍺}¨1+⍳∘≢

Çevrimiçi deneyin! (düzleştirilmiş sonuç)

Çevrimiçi deneyin! (Düzleştirilmiş)

Bir süre kafamı duvara çarparak geçirdikten sonra Dfn yerine Tradfn yapmaya karar verdim. Sonuç budur. Benden daha zeki insanlar bu halttan golf oynayabilirler.

Akıllı Sürpriz köpek biri bana daha yaptılar golf bunun dışında halt. 114 bayt için teşekkürler Adám.

Dedi ki:

İçiniz yerine indeksleme kullanmak dışında, tam programınız olduğuna dikkat edin: Ifs ve daraltma: Global'in yerine sol bir argüman verirken {_} ¨ döngülerine karşılık gelir.

İşlev varsayılır ⎕IO←0.


Nasıl?

(Bu açıklama, okumayı kolaylaştırmak için bir "ungolfed" versiyonunu kullanır)

⊂{                                   Enclose
      i←⊃t←⍬⍳⍺                       Assign a vector of 0s to t (the tape), then assign the first 0 to i.
      t/⍵⊣⍵{                         Use  as left argument for the nested function, then compress the result into t. If there is a 1 anywhere in t, the result will be a vector of the result. If not, the result is an empty vector.
          i+←¯1 1 0⊃⍨'<>'⍳⍵          Map the string '<>' to the argument (which is the BF program). That yields 0 for <, 1 for >, and 2 for anything else.
                                     The resulting vector will then be used as the argument for  to add -1 (index 0), 1 (index 1) or 0 (index 2) to the variable i.
          et[m←⍺|i]                 Assign i mod  (left arg) to m, and use it to index t. Then, assign the value to e.
          t[m]←('01!'⍳⍵)⊃0 1,e,⍨~e   Map the string '01!' to ⍵. As before, this yields 0 for 0, 1 for 1, 2 for ! and 3 for anything else.
                                     Then, concatenate (not e) with e, then concatenate that with the vector 0 1. This is used as argument to be picked from, and it is assigned to t[m].
      }¨⍺                            Do that for each argument
  1+⍳∘≢                            And do that for each possible tape length from 1 to the length of the input.

1
Yaparak Kaydet bir byte t←l⍴0olmak t←l⍴i←0ve üstündeki çizgiyi kaldırarak. Ayrıca değiştirerek başka kaydedebilirsiniz t[i|⍨≢t]←1-t[i|⍨≢t]için t[i|⍨≢t]←~t[i|⍨≢t].
Zacharý

2
@ Zacharý sağ ve ayrıca 112 bayt daha kaydedin . Kesinlikle aynı kod, birazcık golf oynadım.
Ad

Evet, sadece "biraz" yüceltildi. S ihtiyacın yok mu
Zacharý

@ Zacharý Nedir ? Bu tam bir işlevdir.
Adám

@ Zacharý Ben bu güzel Adám'd düşünürdüm, değil mi?
J. Sallé


0

C (clang) , 171 bayt

l,i;f(S){for(char*p,t[l=strlen(S)];l;memchr(t,1,l)&&printf("%d ",l),l--)for(memset(t,i=0,l),p=S;*p;p++)*p==60?i=i?i-1:l-1:*p==62?i=i^l-1?i+1:0:*p^33?t[i]=*p-48:(t[i]^=1);}

Çevrimiçi deneyin!

char*p,t[l=strlen(S)]Başlatma ifadesi olarak kullanmak , bazı nedenlerden dolayı GCC'yi beyan etmek istediğimi düşündürdüğü için clang kullanmak zorunda kaldım.strlen yerine .

Oldukça dümdüz: Programı, azalan uzunlukta dairesel bantlar üzerinde çalıştırır ve kasette bir yerde 1 ile sonuçlanan herhangi bir uzunluğu verir.

Üçlü operatörlerin arapsaçılarını kısaltmaya çalıştı, ancak sağlıklıdan daha fazla parantez kullanmaya başladı.


Öner i=0,bzero(t,l)yerine memset(t,i=0,l)ve *p-62?t[i]=*p^33?*p-48:t[i]^1:(i=~i+l?i+1:0)yerine*p==62?i=i^l-1?i+1:0:*p^33?t[i]=*p-48:(t[i]^=1)
ceilingcat
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.