การสร้าง Brainf *** NOPs


26

บางครั้งเมื่อเขียนโค้ด brainfuck คุณรู้สึกว่าจำเป็นที่จะต้องทำให้มันนานเกินความจำเป็นเพื่อกระตุ้นการดีบั๊ก คุณสามารถทำได้โดยการ plopping ที่><นั่น แต่ความสนุกคืออะไร คุณจะต้องมีสิ่งที่ยาวและน้อยกว่า NOPey เพื่อสร้างความสับสนให้ใครก็ตามที่อ่านรหัสของคุณ

บทนำสู่ Brainfuck อย่างรวดเร็ว

Brainfuckเป็นภาษาโปรแกรมลับที่สร้างขึ้นในปี 1993 โดย Urban Müllerและมีชื่อเสียงในเรื่องความเรียบง่ายแบบสุดขั้ว (วิกิพีเดีย)

Brainfuck เป็นภาษาที่ใช้คำสั่งแปดคำ: +-><,.[]. รหัสนี้ทำงานบนเครื่องทัวริง: เทปที่ไม่มีที่สิ้นสุดซึ่งสามารถเปลี่ยนค่าได้ ในการท้าทายนี้เราจะเน้นไปที่สี่ข้อแรก:

+    increment the value at the pointer
-    decrement the value at the pointer
>    move the pointer right
<    move the pointer left

Brainfuck NOPs

brainfuck NOP เป็นลำดับของตัวละครในสมองที่เมื่อดำเนินการจากรัฐใด ๆ จะไม่มีการเปลี่ยนแปลงในรัฐ ประกอบด้วยอักขระสี่ตัวที่กล่าวถึงข้างต้น

ความท้าทาย

ความท้าทายคือการเขียนโปรแกรมหรือฟังก์ชั่นซึ่งเมื่อประมวลผลแล้วจะสร้าง brainfuck แบบสุ่ม NOP ตามความยาวที่กำหนด

อินพุต

คุณจะได้รับการป้อนข้อมูลเป็นจำนวนเต็มคู่ที่nไม่จำเป็น (NOPs เป็นไปไม่ได้สำหรับคี่n)

เอาท์พุต

คุณจะเอาท์พุท NOP brainfuck nสุ่มของความยาว

กฎระเบียบ

  • คำจำกัดความของ NOP: เมื่อแทรกเอาท์พุทของโปรแกรม ณ จุดใด ๆ ในโปรแกรม brainfuck พฤติกรรมของโปรแกรมดังกล่าวจะต้องไม่เปลี่ยนแปลง แต่อย่างใด กล่าวอีกนัยหนึ่งมันจะต้องไม่เปลี่ยนสถานะของล่าม
    • โปรดทราบว่าตัวอย่าง+>-<ไม่ถูกต้องเนื่องจากจะเปลี่ยนค่าของเซลล์ทั้งสองโดยไม่เปลี่ยนกลับ โปรดทดสอบวิธีแก้ปัญหาของคุณก่อนทำการโพสต์
    • นอกจากนี้ทราบว่า+>-<->+<เป็น NOP >< <> +- -+ที่ไม่สามารถลดลงไปไม่มีอะไรเพียงแค่ลบ ดังนั้นคุณไม่สามารถใช้อัลกอริทึมที่เพิ่งแทรกสิ่งเหล่านี้เข้าด้วยกัน
  • NOP ที่ถูกต้องทุกตัวของความยาวnจะต้องมีโอกาสที่ไม่เป็นศูนย์ในการแสดงผล การกระจายไม่จำเป็นต้องเหมือนกัน
  • ล่าม brainfuck ที่เป็นปัญหามีเทปที่ไม่ จำกัด สองเท่าของเซลล์ความแม่นยำตามอำเภอใจ นั่นคือคุณสามารถไปยังทั้งสองทิศทางได้อย่างไม่ จำกัด และเพิ่ม / ลดเซลล์แต่ละเซลล์ไปเรื่อย ๆ
  • โปรแกรมจะต้องเสร็จสิ้นภายใน 1 นาทีสำหรับn= 100ในเครื่องของฉันดังนั้นจึงไม่มีการสร้าง NOP ที่เป็นไปได้ทั้งหมดและเลือกหนึ่งรายการ
  • หากได้รับการป้อนข้อมูลที่ไม่ถูกต้อง (ไม่ใช่จำนวนเต็มลบคี่และอื่น ๆ ) คุณสามารถทำสิ่งที่คุณต้องการรวมถึงความผิดพลาด

เกณฑ์การให้คะแนน

นี่คือดังนั้นคำตอบที่สั้นที่สุดในหน่วยไบต์ชนะ

ตัวอย่าง

นี่คือผลลัพธ์ที่ถูกต้องทั้งหมดสำหรับn= 4:

++--    +-+-    +--+    --++    -+-+    -++-
>><<    ><><    ><<>    <<>>    <><>    <>><
><+-    ><-+    <>+-    <>-+
>+-<    >-+<    <+->    <-+>
+><-    -><+    +<>-    -<>+
+-><    -+><    +-<>    -+<>

นี่เป็นผลลัพธ์ที่เป็นไปได้บางอย่างสำหรับn= 20:

+>>->+<->-<<<->>++<<
>+>-<+<->+-<>->+<-<+
+--+-++--++-+--+-++-
>>>>>>>>>+-<<<<<<<<<

18
นี่คือ brainfuck NOP ที่ไม่ได้ใช้+-<>อย่างที่คุณขอ:a
undergroundmonorail

1
ฉันไม่คิดว่ามี NOP ที่ไม่ธรรมดาอยู่ดังนั้นคุณอาจลบคุณสมบัตินั้นออกได้ .มีผลข้างเคียง, เขียนทับค่าที่ไม่สามารถกู้คืนได้โดยไม่ต้องใช้ที่, []แต่[]จะสิ้นสุดการตั้งค่าเป็นศูนย์ สิ่งนี้จะเขียนทับค่าด้วย (ดังนั้นเราจึงต้องการค่าอื่น[]ในการกู้คืน) เว้นแต่เราจะมั่นใจได้ว่าเซลล์ที่ได้รับผลกระทบนั้นจะเริ่มต้นที่ศูนย์ อย่างไรก็ตามเราต้องค้นหาเซลล์ดังกล่าวด้วยสิ่งที่ต้องการ[>]และมันเป็นไปไม่ได้ที่จะกลับไปยังตำแหน่งที่เราเชื่อถือได้อย่างน่าเชื่อถือ
Martin Ender

4
@Eumel "ล่ามในสมองที่สงสัยมีเทปที่ไม่ จำกัด สองเท่าของเซลล์ความแม่นยำตามอำเภอใจ"
Martin Ender

2
โปรดทราบว่า"Brainfuck" ไม่ได้รับอนุญาตในชื่อคำถามในระดับระบบอีกต่อไป ดูเหมือนว่าคุณสามารถหลีกเลี่ยงข้อ จำกัด โดยใช้อักขระที่ไม่ใช่ ASCII ในอนาคตโปรดปฏิบัติตามข้อ จำกัด นี้
Alex A.

2
@undergroundmonorail เอาล่ะทัวริงสมบูรณ์ ... ดังนั้นในทางเทคนิคเราสามารถเขียน PRNG ลงไปได้เหมือนภาษาอื่น ๆ (แม้ว่าการเพาะมันอาจเป็นเรื่องยาก)
PurkkaKoodari

คำตอบ:


13

CJam, 62 59 ไบต์

ขอบคุณ nhahtdh สำหรับการบันทึก 3 ไบต์

เนื่องจากไม่มีความต้องการสำหรับการแจกแจงใด ๆ โดยเฉพาะตราบใดที่แต่ละ op ไม่ปรากฏขึ้นพร้อมกับความน่าจะเป็นที่ จำกัด เราสามารถทำให้สิ่งนี้ง่ายขึ้นโดยการสร้างสตริงที่มีจำนวนที่สมดุล-+และ<>ทดสอบตามลำดับว่ามันเป็น NOP หรือไม่ ไม่ใช่

แน่นอนว่าสำหรับอินพุตที่ยาวกว่านี้จะส่งผลให้เรียงลำดับผลลัพธ์ออกมาเกือบตลอดเวลา แต่คุณสามารถทดสอบโค้ดด้วยอินพุตบางอัน8เพื่อดูว่าในหลักการสามารถสร้าง NOP ใด ๆ ตามความยาวที่กำหนด

ri_0a*\2/{;"-+<>":L2/mR}%smr:SL["Xa.Xm"3/2e*L]z:sers~0-S$S?

ลองออนไลน์


1
ใช่ ... ข้อ จำกัด โดยพลการควรจะเป็น n = 1,000 ต่ำกว่า 10 วินาที คอมพิวเตอร์เป็นวิธีที่รวดเร็วในวันนี้ ^^ เพราะคำตอบของอัลกอริธึมแก้ไขได้ภายในไม่กี่วินาทีแม้กระทั่งสำหรับ n = 1,000
Falco

สำหรับ n ที่ใหญ่กว่าฉันคิดว่ามันเป็นไปได้ที่จะเรียงลำดับผลลัพธ์หากสตริงที่สมดุลไม่ใช่ NOP การแจกแจงเบ้ชะมัด แต่มันได้รับอนุญาตจากคำถาม
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ นั่นเป็นความคิดที่เรียบร้อย
Martin Ender

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ขอบคุณที่ช่วยประหยัดสามไบต์ได้เช่นกัน
Martin Ender

16

CJam, 118 116 ไบต์

สิ่งนี้ออกไปจากมือเล็กน้อย ... โดยเฉพาะในช่วงครึ่งหลังดูเหมือนว่าควรจะเล่นกอล์ฟได้ดีมาก

ri2/_)mr:R-"<>"R*mr_'=fm0\{1$+}%+__&e`]:\{mr1aa..+}*\@](\z:~\{~\("+-"*mr1$3$e=[{_,)mr_2$<@@>}*+]@@f{`1$`={(}@?\}W<}/

ทดสอบที่นี่

สิ่งนี้จัดการN = 100ได้ทันที ตอนนี้ฉันไม่มีเวลาเขียนการวิเคราะห์เต็มรูปแบบของรหัสดังนั้นนี่คืออัลกอริทึม:

  • สร้างสตริงที่สมดุลแบบสุ่มของ<และ>มีความยาวแบบสุ่ม (คู่) ระหว่าง0และNรวม
  • Riffle ตำแหน่งหัวเทปในอาร์เรย์นี้ เช่นจะกลายเป็น"<>><"[0 '< -1 '> 0 '> 1 '< 0]
  • รับรายการตำแหน่งทั้งหมดที่อยู่ในกระบวนการ
  • สำหรับแต่ละตำแหน่งดังกล่าวเริ่มต้นสตริงว่าง Nนอกจากนี้ยังกำหนดวิธีการหลายคู่ของตัวละครที่เหลือไปถึงสตริงของความยาว
  • สำหรับแต่ละคู่ที่เหลือ+-จะต่อท้ายสตริงของตำแหน่งสุ่ม
  • สุ่มสตริงทั้งหมด
  • สำหรับแต่ละตำแหน่งกำหนดความถี่ที่ตำแหน่งนั้นเกิดขึ้นในอาร์เรย์ riffled และแยกสตริงที่สอดคล้องกันเป็นชิ้น ๆ (ความยาวแบบสุ่ม) จำนวนมาก
  • ในอาร์เรย์ riffled ให้แทนที่การเกิดขึ้นของตำแหน่งด้วยชิ้นแบบสุ่ม

เสร็จสิ้น สิ่งนี้มีพื้นฐานจากการสังเกตที่:

  • NOP ใด ๆ จะต้องมีจำนวนเท่ากัน<และ>จะคืนค่าหัวเทปกลับสู่ตำแหน่งเดิม
  • รหัสจะเป็น NOP ตราบใดที่แต่ละเทปเซลล์เพิ่มขึ้นบ่อยเท่าที่ลดลง

โดยการกระจายจำนวน+s และ-s แบบสุ่ม แต่มีความสมดุลระหว่างสถานที่ทั้งหมดที่หัวเทปอยู่ในเซลล์ที่กำหนดเรามั่นใจว่าเราพบ NOP ที่เป็นไปได้ทั้งหมด


4

Mathematica, 350 ไบต์

Quiet@(For[a="+",If[{##4}=={},#3!=0||Union@#!={0},Switch[#4,"+",#0[ReplacePart[#,#2->#[[#2]]+1],#2,#3,##5],"-",#0[ReplacePart[#,#2->#[[#2]]-1],#2,#3,##5],">",#0[#~Append~0,#2+1,#3+1,##5],"<",If[#2<2,#0[#~Prepend~0,1,#3-1,##5],#0[#,#2-1,#3-1,##5]]]]&@@{{0},1,0}~Join~Characters@a,a=""<>RandomSample@Flatten@RandomChoice[{{"+","-"},{">","<"}},#/2]];a)&

นานเกินไปไหม ใช่. ฉันยังสนใจไหม ไม่จนกว่าจะมีคนอื่นโพสต์คำตอบที่ถูกต้อง


4
คุณจะช่วยเพิ่มคำอธิบายเพื่อให้ผู้คนสามารถโน้มน้าวตัวเองว่าสิ่งนี้ถูกต้องหรือไม่ :)
Martin Ender

วิธีการว่าจะทำงานนี้ +ถ้าผมเรียกฟังก์ชั่นที่มีจำนวนเพียงผลตอบแทน
Martin Ender

@ MartinBüttnerคงที่ ... ปัจจุบันก็แค่สร้างโปรแกรมสุ่มที่มีจำนวนเท่ากัน+- -และ<- >คู่จนกว่าจะมีใครที่จะเกิดขึ้น NOP ครึ่งหนึ่งเป็นล่ามแปลภาษาง่ายๆ
LegionMammal978

ไม่สร้างความยาวไม่ถูกต้องของความยาว 100 ในไม่ถึงหนึ่งนาที?
Martin Ender

@ MartinBüttnerใช่ โดยเฉลี่ยแล้วฉันจะบอกว่าใช้เวลาประมาณ 5 วินาที ตอนแรกฉันลองใช้โปรแกรมแบบสุ่มอย่างสมบูรณ์ แต่มันไม่สิ้นสุดสำหรับความยาว 100
LegionMammal978

2

Python 3 , 177 ไบต์

from random import*
n=int(input())
r=[0]*n*3
p=0
a=[43,45]
s=choices(a+[60,62],k=n)
for c in s:p+=~c%2*(c-61);r[p]+=c%2*(44-c)
if any(r+[p]):s=a*(n//2)
print(*map(chr,s),sep='')

ลองออนไลน์!

ฉันใช้รหัสจากคำตอบของ Bubbler สำหรับการจำลอง BF


2

Python 3 , 163 ไบต์

from random import*
n=int(input())
p=0;d=[0]*n;a=choices(b'+-<>',k=n)
for c in a:d[p]+=c%2*(44-c);p+=~c%2*(c-61)
if p|any(d):a=n//2*b'+-'
print(*map(chr,a),sep='')

ลองออนไลน์!

โปรแกรมเต็มรูปแบบที่พิมพ์ผลลัพธ์ไปยัง STDOUT บรรทัดที่ใช้รหัส BF อาจเล่นได้

ใช้แนวทางของ Tyilo หากรหัส BF ที่สร้างขึ้นไม่ใช่ NOP ให้ละทิ้งทิ้งไปและกลับไป'+-'ทำซ้ำ


หมดเวลาสำหรับ n = 100
l4m2

@ l4m2 ไม่ได้สังเกตข้อกำหนดนั้น คงที่
Bubbler


1

ภาษา Wolfram (Mathematica) , 224 ไบต์

(s=RandomSample[##&@@@Table["<"">",(r=RandomInteger)[#/2]]];While[(g=Length@s)<#,s=Insert[s=Insert[s,"+",i=r@g+1],"-",RandomChoice@@Select[GatherBy[0~Range~++g,Count[#,"<"]-Count[#,">"]&@Take[s,#]&],!FreeQ[#,i]&]+1]];""<>s)&

ลองออนไลน์!

นี่คือเวอร์ชั่นที่ยังไม่ตีกอล์ฟ (หรือค่อนข้างก่อนตีกอล์ฟ):

Function[{n},
 k = RandomInteger[n/2];
 s = RandomSample[## & @@@ Table["<" ">", k]];
 While[Length[s] < n,
   s = Insert[s, "+", i = RandomInteger[Length[s]] + 1];
   p = GatherBy[Range[0, Length[s]], 
     Count[#, "<"] - Count[#, ">"]& @ Take[s, #]&];
   j = RandomChoice @@ Select[p, ! FreeQ[#, i] &]];
   s = Insert[s, "-", j + 1];
   ];
 ""<>s]

อันดับแรกเราเลือกจำนวนสุ่ม<และ>เพื่อใช้และสร้างรายการสุ่มที่มีจำนวนเท่ากัน

ในการเติมอักขระที่เหลือเราเลือกตำแหน่งที่จะเพิ่ม a +จากนั้นหาตำแหน่งที่ตัวชี้ชี้ไปยังตำแหน่งเดียวกันและเพิ่มที่-นั่น

ทำซ้ำจนกระทั่งรายการมีความยาวnและทำให้ผลเป็นผลลัพธ์

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