เทปวงกลมน่าตื่นเต้นไหม?


32

อนุพันธ์ Brainfuck

มานิยามภาษาโปรแกรมง่ายๆเหมือนBrainfuckกัน มันมีเทปสองทิศทางของเซลล์และแต่ละเซลล์เก็บหนึ่งบิต บิตทั้งหมดเป็น 0 เริ่มแรกมีหัวที่เคลื่อนที่อยู่บนเทปเริ่มต้นที่ตำแหน่ง 0 โปรแกรมคือสตริงที่อยู่เหนืออักขระ<>01!เรียกใช้จากซ้ายไปขวาด้วยซีแมนทิกส์ต่อไปนี้:

  • < ย้ายหัวหนึ่งก้าวไปทางซ้าย
  • > ย้ายหัวหนึ่งก้าวไปทางขวา
  • 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
อาร์เรย์ของคำแนะนำเป็นอินพุตที่ยอมรับได้หรือไม่?
Arnauld

@ Mr.Xcoder ไม่คุณควรใช้อักขระที่แน่นอนเหล่านี้
Zgarb

@Arnauld อาร์เรย์ของอักขระอยู่ใกล้พอกับสตริงฉันจะอนุญาต
Zgarb

คำตอบ:


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จะดำเนินการโดยfoldไอเอ็นจีกับเทปเริ่มต้นเข้าสู่# เอ็กซีคิวต์สำหรับทุก ๆ เทปและเก็บผลรวมของเซลล์อย่างน้อย 1pfp


n<-[1..length p] ... 0<$[1..n]ดูเหมือนจะค่อนข้างนานจะต้องมีวิธีที่สั้นกว่า
nimi

ฉันไม่เห็นวิธีที่สั้นกว่านี้ ปัญหาที่ฉันเห็นคือคุณต้องการคุณค่าnเป็นผลลัพธ์ดังนั้นหากคุณสร้าง0<$[1..n]วิธีที่แตกต่าง (พูดกับscanr(:)) คุณจะต้องใช้lengthมัน (ฉันลองใช้1(เพื่อแทนที่lengthด้วยsum) หรือFalse(เพื่อใช้orสำหรับการทดสอบ) แทน0แต่ก็ไม่ได้ออกมาสั้นกว่านี้)
Ørjan Johansen

@ ØrjanJohansen: ใช่ผมพยายามn<-init$scanr(:)[]$0<$p ... nซึ่งเป็น 2 ไบต์สั้น [[0],[0,0,0]]แต่มันกลับรายการของการเริ่มต้นเทปแทนของความยาวของพวกเขาเช่น ด้วยกฏเล็กน้อยการดัดงอจึงสามารถดูเทปว่าเป็นตัวเลขต่าง ๆ ดังนั้นอาจจะโอเค
nimi

init$สามารถถูกแทนที่โดยการใส่[0]เป็นรายการเริ่มต้น แต่ก็ยังไม่สั้นพอ ฉันคิดว่าสามารถใช้ได้เฉพาะภาษาที่ไม่มีการแสดงตัวเลขที่เป็นธรรมชาติมากขึ้นเท่านั้น
Ørjan Johansen

4

Stax , 56 54 43 38 35 bytes CP437

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

42 ไบต์เมื่อคลายการแพค

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

เรียกใช้และแก้ไขข้อบกพร่องออนไลน์!

-2 ไบต์ต่อความคิดเห็นโดย @recursive

คำอธิบาย

ฉันจะใช้เวอร์ชันพร้อมคำนำหน้า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ตรวจสอบ
Zgarb

0]*z(สามารถถูกแทนที่ด้วย นอกจากนี้หากคุณเปลี่ยนสตริงเป็น "<>!" จากนั้น0และ1จะให้ดัชนี -1 ดังนั้นวิธีที่รายการบล็อกของคุณต้องการเพียง 4 บล็อกแทนที่จะเป็น 5 ซึ่งจะใช้งานได้เนื่องจาก0และ1ตัวจัดการเหมือนกันอยู่แล้ว
เรียกซ้ำเมื่อ

@recursive จุดดีเอา
Weijun Zhou


3

Perl 5 , 83 82 79 77 ไบต์

รวม+3สำหรับ-F

ให้คำแนะนำเป็นบรรทัดเดียวใน STDIN

#!/usr/bin/perl -F
1~~@$m&&say$m until++$m>map{*r=\$$m[($n+=/>/-/</)%$m];$r=/\d/?$&:$r^/!/}@F

ลองออนไลน์!


ธงตอนนี้นับเป็นส่วนหนึ่งของภาษาแทนการให้คะแนน
Ørjan Johansen


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

ลองออนไลน์!

การใช้งาน verbose และตรงไปตรงมา การจัดทำดัชนี 1 ของ Red ไม่อนุญาตให้ฉันลดจำนวนไบต์โดยใช้การคำนวณแบบแยกส่วนสำหรับการวนลูปผ่านเทปวงกลม

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

จอตาติน่า 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 ไบต์

บันทึกแล้ว 3 ไบต์ด้วย @ user71546

รับอินพุตเป็นอาร์เรย์ของสตริง 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 ไบต์
Shieru Asakoto

2

APL (Dyalog Unicode) , 79 64 54 ไบต์ ( SBCS ของAdám )

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

ลองออนไลน์!

-15 ต้องขอบคุณAdám (ลืมเรื่อง monadic )
-10 ขอบคุณที่NGN



@ อืมดูเหมือนว่ามันไม่เหมาะ (ตัวอย่างเช่นคุณไม่ต้องการ) ฉันจะตรวจสอบและอัปเดต :)
Erik the Outgolfer

แต่ถ้าคุณลบคุณจะต้องมี;หรือไม่
อดัม

@ อดัมไม่มีเหตุผลที่คุณจะ?
Erik the Outgolfer

เพราะอันดับ 2 อาร์เรย์ต้องสองส่วนดัชนี
อดัม

1

MATL , 46 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+⍳∘≢

ลองออนไลน์! (ผลที่ไม่แบน)

ลองออนไลน์! (บี้)

หลังจากบางครั้งใช้เวลาต่อสู้หัวของฉันกับกำแพงฉันตัดสินใจทำ Tradfn แทนที่จะเป็น Dfn นี่คือผลลัพธ์ ผู้คนที่ฉลาดกว่าฉันอาจจะสามารถตีกอล์ฟออกไปได้

แปลกใจประหลาดใจมีคนฉลาดกว่าที่ฉันทำกอล์ฟ heck ออกจากนี้ ขอบคุณAdámสำหรับ 114 ไบต์

เขาพูดว่า:

ขอให้สังเกตว่ามันเป็นโปรแกรมที่แน่นอนของคุณยกเว้นการใช้การจัดทำดัชนีแทนด้านใน: Ifs และยุบ: สำหรับลูปไปที่ {_} ¨ในขณะที่ให้อาร์กิวเมนต์ที่เหลือเพื่อแทนที่ทั่วโลก

⎕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และถอดสายเหนือ นอกจากนี้คุณยังสามารถบันทึกอื่นโดยการเปลี่ยนไปt[i|⍨≢t]←1-t[i|⍨≢t] t[i|⍨≢t]←~t[i|⍨≢t]
Zacharý

2
@ Zachary ขวาและเพิ่มเติมบันทึกเพิ่มเติม 112 ไบต์ รหัสเดียวกันแน่นอน golfed เพียงเล็กน้อย
อดัม

ใช่มันก็แค่ "บิต" คุณไม่จำเป็นต้องหรือไม่?
Zacharý

@ Zacharýอะไรนะ? มันเป็นฟังก์ชั่นโดยปริยาย
อดัม

@ Zacharýฉันจะพิจารณาอันนี้สวยAdám'dคุณจะไม่?
J. Sallé


0

C (เสียงดังกราว) , 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แทนที่จะเรียกมัน

ตรงไปตรงมาสวย: รันโปรแกรมบนเทปวงกลมที่มีความยาวลดลงส่งออกความยาวใด ๆ ที่ส่งผลให้ 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)
แมวเพดาน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.