円形テープは刺激的ですか?


32

Brainfuck派生物

簡単なBrainfuckのようなプログラミング言語を定義しましょう。セルの双方向テープがあり、各セルは1ビットを保持します。すべてのビットは最初は0です。最初は位置0にテープの移動ヘッドがあります。プログラムは<>01!、次のセマンティクスを使用して、左から右に実行される文字上の文字列です。

  • < ヘッドを1ステップ左に移動します。
  • > 頭を1ステップ右に移動します。
  • 0 現在のセルに0を入れます。
  • 1 現在のセルに1を入れます。
  • ! 現在のセルを反転します。

ループがないため、n文字のプログラムは正確にnステップで終了します。実行の最後にすべてのセルに0が含まれる場合、プログラムは退屈です。少なくとも1 つがあれば、エキサイティングです。テープのサイズは指定されていないため、実装によっては双方向無限または円形。

サンプルプログラム

プログラムを検討してください1>>>!<<<<0>!>>>!。無限テープでは、実行は次のように進行します。

     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

最後に、すべてのセルは0なので、このプログラムは退屈です。次に、長さ4の円形テープで同じプログラムを実行しましょう。

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

今回は、値1のセルがあるため、プログラムは刺激的です!プログラムが退屈であるか刺激的であるかは、テープのサイズに依存することがわかります。

タスク

入力は<>01!、上記のプログラミング言語のプログラムを表す空ではない文字列です。文字の配列も受け入れ可能な入力形式です。このプログラムは、無限のテープで実行すると退屈することが保証されています。出力は、プログラムがエキサイティングなテープ長のリストです。プログラムの長さより短いテープでのみプログラムをテストする必要があることに注意してください。

各言語で最も少ないバイト数のソリューションが勝者です。標準の規則が適用されます。

テストケース

> : []
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
ではなく、明確で一貫した文字を選択できますか<>01!
Mr Xcoder

1
命令の配列は受け入れ可能な入力ですか?
アーナルド

@ Mr.Xcoderいいえ、これらの正確な文字を使用する必要があります。
ズガルブ

@Arnauld文字の配列は文字列に十分近いため、許可します。
ズガルブ

回答:


6

Haskell、119バイト

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]

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

関数#は、単一のコマンドのインタープリターですc。全体のプログラムはpによって運営されているfoldINGの#に始まるテープでp。すべてのテープに対してf実行さpれ、セルの合計が少なくとも1であるテープを保持します。


n<-[1..length p] ... 0<$[1..n]かなり長いようです。もっと短い方法が必要です。
nimi

もっと短い方法は見当たりません。私が見る問題はn、結果としての値が実際に必要であるということです。そのため0<$[1..n]、別の方法(たとえばscanr(:))を構築した場合、それを利用する必要がありますlength。(私も使ってみました1置き換えるために(lengthsum)またはFalse(使用するorテスト用)の代わりに0、それは短く出てきませんでした。)
Ørjanヨハンセン

@ØrjanJohansen:はい、n<-init$scanr(:)[]$0<$p ... n2バイト短くしましたが、長さの代わりに開始テープのリストを返します[[0],[0,0,0]]。少し規則を曲げれば、テープは単項の数値と見なされる可能性があるので、おそらく大丈夫でしょう。
nimi

init$[0]最初のリストとしてを置くことで置き換えることができますが、それでも十分に短くなりませんでした。単項は、より自然数表現のない言語でのみ許可されると思います。
Ørjanヨハンセン

4

スタックス56 54 43 38 35 バイトCP437

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

解凍すると42バイト、

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

オンラインで実行してデバッグします!

@recursiveによるコメントごとに-2バイト

説明

接頭辞付きのバージョンi(つまりi%fz(y{{|(}{|)}{B!s+}{0_]e&}4ls"><! "I@!F|a)を使用して説明し、i削除できる理由を説明します

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

プログラムを実行するためのコード:

{|(}                                 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チェックを検証するために、すべての数字のテストケースを追加しました。
ズガルブ

0]*に置き換えることができますz(。また、あなたはその後、「!<>」に文字列を変更した場合01その方法は、あなたのブロックリストはわずか4つのブロックを必要とするので、以来、動作します。5.これの代わりに、インデックスを-1与える01ハンドラが同じとにかくされています。
再帰的な

@recursive良い点が取られました。
周We順




2

、243バイト

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]]]

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

かなり冗長でわかりやすい実装。Redの1-indexingでは、循環テープをループ処理するためにモジュラー演算を使用してバイトカウントを減らすことはできません。

非ゴルフ

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

網膜、121バイト

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

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

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

入力プログラムの長さまでの各長さのテープの配列を作成します。

{

プログラムが消費されるまでループします。

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

プログラムの次の文字が0または1の場合、各行の最初の文字をその文字に変更します。

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

の場合!、各行の最初の文字を切り替えます。

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

それがある場合><、行を回転させます。(頭を動かすよりも簡単です。)

)`¶¶.
¶¶

命令を削除して、ループを終了します。

G`1

エキサイティングなラインのみを保持します。

%`.

各行の長さを数えます。


2

JavaScriptの(ES6)、126の 118バイト

@ user71546のおかげで3バイト節約

入力を1文字の文字列の配列として受け取ります。

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):[]

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


置換t.some(x=>x)?によって+t.join``?代わりする数字として、配列を確認し(0は全てゼロテープを示す)が、3バイト以下です。
浅琴しえる

2

APL(Dyalog Unicode)79 64 54バイト(AdámのSBCS

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

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

-15Adámに感謝(モナドを忘れた)。
-10 ngnに感謝します



@AdámHm、それは最適ではないようです(たとえば、必要ありません)。調べて更新します。:)
エリック・ザ・アウトゴルファー

しかし、削除する場合;、必要になります、いいえ?
アダム

@アダムがない、なぜだろうか?
エリックアウトゴルファー


1

MATL46 39バイト

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

オンラインでお試しください!またはすべてのテストケースを確認します

使い方

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バイト

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

オンラインでお試しください!(平坦化されていない結果)

オンラインでお試しください!(平坦化)

頭を壁にぶつけてしばらくしてから、DfnではなくTradfnを作成することにしました。これが結果です。私よりも賢い人は、これからゴルフをすることができるかもしれません。

賢くサプライズ、驚き、誰かが私よりもやったゴルフは、このうちの一体。アダム、114バイトありがとうございます。

彼は言った:

それはあなたの正確なプログラムであることに注意してください。ただし、内側の:Ifsの代わりにインデックスを使用し、{_}¨に:For-loopsを折りたたみながら、グローバルを置換する左引数を指定します。

関数はを想定してい⎕IO←0ます。


どうやって?

(この説明では、読みやすくするために「ungolfed」バージョンを使用しています)

⊂{                                   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
t←l⍴0be を作成しt←l⍴i←0、その上の行を削除して1バイトを保存します。に変更t[i|⍨≢t]←1-t[i|⍨≢t]して別のファイルを保存することもできt[i|⍨≢t]←~t[i|⍨≢t]ます。
ザカリー

2
@Zacharý右、さらに112バイトを保存します。まったく同じコードで、ちょっとゴルフをしました。
アダム

ええ、それは「ちょっと」だけです。s は必要ありませんか?
ザカリー

@Zacharýなに?これは暗黙の機能です。
アダム

@ザカリーこれはかなりアダムだと思いますよね?
J.サレ


0

C(clang)、171バイト

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);}

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

char*p,t[l=strlen(S)]何らかの理由で初期化式として使用することで、GCC strlenを呼び出す代わりに宣言したいと思うようになるため、clangを使用する必要がありました。

かなり簡単です:テープ上のどこかで1になった任意の長さを出力して、長さが減少する円形テープでプログラムを実行します。

三項演算子のもつれを短くしようとしましたが、最終的には健康よりも多くの括弧が必要になりました。


提案i=0,bzero(t,l)の代わりmemset(t,i=0,l)*p-62?t[i]=*p^33?*p-48:t[i]^1:(i=~i+l?i+1:0)代わりに*p==62?i=i^l-1?i+1:0:*p^33?t[i]=*p-48:(t[i]^=1)
ceilingcat
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.