พายุเฮอริเคนแมทธิวและสายฟ้า


27

ท้าทาย

แรงบันดาลใจจากความท้าทายนี้และHurricane Matthew ที่น่ารังเกียจเราจะสร้างสายฟ้าแบบไดนามิก

n = 15:

   \
   /\
  /  \
 /   /
/\  /\
 /  \ \
/   / /\
   /\ \
  / /  \
 /\ \  /\
  /  \ \
 /\  /  
   \
    \
    /\

อินพุต

Positive Integer nกำหนดความลึกของรอบฟ้าผ่า

กฎและข้อ จำกัด

  • /และ\ควรใช้
  • ความน่าจะเป็นที่ชี้นำทิศทางของสายฟ้ามีดังนี้:
    • 25% แบ่งออกเป็น 2 เส้นทาง
    • เส้นทาง 25% ถึงจุดจบ
    • 25% ไปทางซ้าย
    • 25% ถูกต้องแล้ว
    • มีข้อยกเว้นบางประการเกี่ยวกับการซ้อนทับและสิ้นสุดด้านล่าง:
  • รหัสไม่ควรถูกกำหนดไว้สายฟ้าชนิดใหม่ควรถูกสร้างขึ้นแบบสุ่มทุกครั้ง
  • สลักเกลียวไม่ควรทับซ้อนกัน: เช่นถ้ามีสลักเกลียวอยู่ทางด้านซ้ายของสลักเกลียวปัจจุบันแล้วสลักเกลียวปัจจุบันควรจะสิ้นสุดหรือไปทางขวา แต่ไม่ไปทางซ้ายหรือแยก (ความน่าจะเป็นยังคงมีอยู่ในกรณีนี้ / 50% จากขวา)
  • หากไม่มีเส้นทางแยกอื่นที่มีอยู่เส้นทางนั้นไม่ควรสิ้นสุด: เช่นในตอนเริ่มต้นเมื่อมีเพียง 1 เส้นทางเส้นทางนั้นไม่ควรสิ้นสุดจนกว่าจะแยกออกและยังใช้เมื่อมีหลายเส้นทาง แต่ทุกเส้นทางยกเว้นเส้นทางเดียวจะตาย , (ความน่าจะเป็นแบ่ง 33% / 33% ซ้าย / ขวา 33%) เป้าหมายของคุณคือไปถึงด้านล่าง
  • ช่องว่างสามารถเพิ่มทางด้านซ้าย (ทั้งหมดที่คุณต้องการเพียงความสูง -1)
  • อย่างไรก็ตามคุณต้องการสร้างโบลต์ขึ้นอยู่กับคุณคุณสามารถไปจากล่างขึ้นบนซ้ายไปขวา ฯลฯ ตราบใดที่กฎทั้งหมดข้างต้นพอใจ

ตัวอย่างอื่น

n = 10

 \
 /
 \
 /\
  /\
 / /
/\ \
 / /\
 \   \
 /

เห็นได้ชัดว่าเฮอร์ริเคนแมทธิวยิงสลักเกลียวสีแดงขึ้นไปบนท้องฟ้าซึ่งเรียกว่าสไปรต์

อยู่อย่างปลอดภัยและสนุกกับการเล่นกอล์ฟ! กรุณาตีกอล์ฟอย่างรับผิดชอบเฉพาะเมื่อคุณอยู่ในพื้นที่ปลอดภัย !!


7
Stay safe and have fun golfing!อาจระบุด้วยว่าถ้าการประท้วงของ EAS ให้ละทิ้งทุกอย่างและทำตามคำสั่ง! รหัสการเล่นกอล์ฟไม่ใช่สิ่งที่คุณให้ความสำคัญในสถานการณ์เช่นนี้
Erik the Outgolfer

17
@EriktheGolfer คุณไม่ใช่นักกอล์ฟตัวจริง
บลู

4
ฉันไม่เชื่อว่า "เส้นทางที่ตรงกลางที่สุดควรเป็นเส้นทางถึง" สอดคล้องกับส่วนที่เหลือของคำอธิบายแบบสุ่ม ยกตัวอย่างเช่นมันเป็นไปได้ที่จะมีการสุ่มให้กลอนต้นฉบับแยกสองครั้ง ความเป็นไปได้นี้จะถูกแทนที่อย่างไรในขณะที่ยังคงรักษาความน่าจะเป็นที่ระบุไว้?
Greg Martin

นอกจากนี้จะเกิดอะไรขึ้นหาก (ตัวอย่าง) สองขั้นตอนแรกแยกทั้งสองอย่าง จากนั้นสลักเกลียวกลางสองอันแตะกันซึ่งดูเหมือนว่ามีปัญหา แต่ยังไม่ได้ถูกตัดออกโดยกรณีพิเศษ
Greg Martin

@ GregMartin จุดที่ดีในจุดศูนย์กลางส่วนใหญ่ แต่เดิมฉันหวังว่ามันจะสร้างโบลต์ที่สมดุล แต่ตอนนี้ฉันคิดว่ามันถึงแม้ว่าจะไม่มีข้อ จำกัด ก็ตามประมาณ 50% ของเวลาที่มันควรจะอยู่ที่ไหนสักแห่งที่อยู่ตรงกลาง จาก 15 จะมีโอกาส 1-2% เท่านั้นที่ทางขวาหรือทางซ้ายสุดของเส้นทาง ฉันจะลบกฎนั้น และสำหรับการแยกส่วน 2 ขั้นตอนสิ่งเดียวที่ต้องป้องกันคือไม่มีเส้นทาง 2 ทางที่ควรรวม 2 เส้นทาง: \/ณ จุดใด ๆ
Zukaberg

คำตอบ:


6

Perl, 92 90 89 84 ไบต์

รวม +1 สำหรับ -n

ให้ความสูงกับ STDIN:

perl -M5.010 bolt.pl <<< 15

bolt.pl:

#!/usr/bin/perl -n
map{$_=$;until$;=$_,s/.6|3.?/53|16*rand/eg,/3|6/>/36/;say y|3615|\\/ |r}(1x$_.6)x$_

คำอธิบาย

หากคุณเรียกออฟเซ็ตของจุดเริ่มต้น 0 (จุดหนึ่งอยู่ที่มุมของกล่องอักขระ) จากนั้นในแถวถัดไปคุณสามารถไปทางซ้ายหรือขวา (หรือไม่) และสามารถจบลงด้วยคะแนนที่ออฟเซ็-1,1ต แถวถัดไปจะให้-2,0,2ออฟเซ็ตที่เป็นไปได้ ฯลฯ พวกมันต่างกัน 2 ถ้าคุณเรียกอักขระไปทางซ้ายล่างของจุดคู่และอักขระไปทางขวาล่างคี่คุณสามารถขยายการกำหนดให้เป็นคู่หรือคี่กับตำแหน่งอักขระแต่ละตำแหน่ง ในแถวที่เป็นทางเลือกคู่และคู่ (ในความเป็นจริงแล้วระนาบทั้งหมดจะถูกเรียงในรูปแบบกระดานหมากรุก) ตำแหน่งยังสามารถมี/หรือเป็นตำแหน่งที่แปลกสามารถมีหรือ\

ตัวละครก่อนที่จะ/อยู่ในตำแหน่งที่แปลกดังนั้นมันอาจเป็น\หรือแต่\/เป็นสิ่งต้องห้ามเท่านั้นที่เป็นไปได้ ในทำนองเดียวกันตัวละครหลังจาก\ ต้องเป็น(สมมติว่าแถวจะเต็มไปด้วยช่องว่างเพียงพอไปทางซ้ายและขวาเพื่อให้ขอบเขตของแถวจะไม่มีปัญหา) ดังนั้นสายฟ้าจะยังคงอยู่ในแถวถัดไปที่ด้านล่าง\หรือด้านล่าง/เสมอ ในทั้งสองกรณีจุดลดลงอยู่ในระดับกลางและแถวถัดไปสามารถมีหนึ่งใน, /, \หรือ/\ด้านล่างด้านบน 2 ตัวอักษร ดังนั้นเพื่อสร้างแถวถัดไปฉันสามารถแทนที่ใด ๆ\หรือ/โดยการขยายใด ๆ ของ 4 เหล่านี้ด้วยความน่าจะเป็นที่เท่ากัน (คุณสามารถแทนที่อักขระแรกโดยหรือ/และอักขระที่สองตามหรือ\) ใน Perl คุณสามารถทำสิ่งนี้กับสิ่งที่ชอบ:

s#\\ | /#("  "," \\","/ ","/\\")[rand 4]#eg

หากแถวผลลัพธ์มี\/(ต้องเข้าร่วมที่ต้องห้าม) หรือไม่/หรือ\เลย (สายฟ้าตายและไม่ถึงด้านล่าง) ผลลัพธ์จะไม่ถูกต้อง ในกรณีนี้ฉันทิ้งแถวทั้งหมดและลองอีกครั้ง มีความต่อเนื่องที่ถูกต้องอยู่เสมอและหากคุณลองพบบ่อยพอที่จะพบสิ่งใดสิ่งหนึ่ง (เช่นทุกอย่างตายไปยกเว้นการไหล 1 ครั้ง) นี่คือการกระจายความน่าจะเป็นที่แตกต่างกันเล็กน้อยจากอัลกอริทึมป้องกันการทับซ้อนที่แนะนำ แต่ฉันคิดว่านี่เป็นความจริงที่ดีกว่าเนื่องจากไม่มีอคติทิศทาง ความถูกต้องสามารถทดสอบในวิธีที่ Golfish ใช้

m#\\|/#>m#\\/#

ปัญหาที่นี่คือการทดแทนแบบสุ่มนั้นเป็น looooong และการ\หลบหนีทั้งหมดเหล่านี้ก็กินเป็นจำนวนไบต์ด้วย ดังนั้นผมจึงตัดสินใจที่จะสร้างแถวของฉันโดยใช้สายหลักและแทนที่ตัวเลขที่เหมาะสมโดย, /และ\เพียงแค่ก่อนที่จะพิมพ์ การเปลี่ยนแบบสุ่มขั้นพื้นฐานคือ

53|16*rand

ซึ่งจะช่วยให้หนึ่ง53, 55, 61หรือ63มีโอกาสที่เท่าเทียมกัน จากนั้นผมก็ตีความ5และ1เป็น, 3เป็น\และเป็น6 /ที่อธิบายการพิมพ์แถว:

say y|3615|\\/ |r

ในการแข่งขันกอล์ฟที่รุนแรงตอนนี้ฉันจะเริ่มสำรวจสูตรเวทย์มนตร์ทางเลือกอย่างเป็นระบบ แต่สิ่งนี้ควรจะค่อนข้างดี (ภายใน 3 ไบต์ที่เหมาะสมที่สุด)

ส่วนประกอบที่เหลือของโปรแกรม:

1x$_.6

initializes นี้$_(ดูแผนที่ถัดไป) /ไปที่ช่องว่างความสูงตามด้วย นี่คือแถวที่มองไม่เห็นด้านบนแถวแรกที่ถูกพิมพ์และตรวจสอบให้แน่ใจว่าฟิลด์นั้นกว้างพอที่จะทำให้โบลต์ไม่สามารถวิ่งออกจากพื้นที่ด้านซ้ายได้

map{ ... ; say ...}(1x$_.6)x$_

ฉันจะประมวลผลความสูงของสตริงเริ่มต้นเดียวกันนี้เท่าเมื่อพิมพ์แถวใหม่ในแต่ละครั้ง

$_=$;until$;=$_,...

$;บันทึกแถวปัจจุบันใน หากการเปลี่ยนกลายเป็นการเรียกคืนที่ไม่ถูกต้อง$_จาก$;

s/.6|3.?/53|16*rand/eg

ทำการทดแทนที่แท้จริง ฉันไม่ต้องตรวจสอบสิ่งที่เกิดขึ้นก่อน/หรือหลัง\เนื่องจากต้องมีพื้นที่ นี้จะสะดวกเนื่องจากพื้นที่สามารถแสดงโดยทั้งสองหรือ1 5เนื่องจากฉันเพิ่มเฉพาะสตริงไปทางซ้ายเว้นวรรคหลังจากที่\ยังสามารถหายไปได้

/3|6/>/36/

ตรวจสอบว่าแถวใหม่ใช้ได้หรือไม่


+1 เรียบร้อย! คุณควรรวมเครื่องมือทดสอบออนไลน์ นี้perl -M5.010 main.pl <<< 25ฉันได้รับผลลัพธ์ที่ดีแล้ว!
Zukaberg

ใจอธิบายเล็กน้อยว่ามันทำงานอย่างไร ฉันสนุกมากเกินไปที่จะสร้างพวกเขาฮ่าฮ่าฉันไม่ได้คาดหวังถึงผลลัพธ์ที่ดีเช่นนั้น
Zukaberg

น่าเสียดายที่คุณต้องเพิ่ม 3 ไบต์-nเพราะพื้นที่และเส้นประนับด้วย กฎเดียวกันสำหรับอาร์กิวเมนต์บรรทัดคำสั่ง ดู "การเรียกใช้พิเศษ" สัญลักษณ์แสดงหัวข้อย่อยที่สอง: ฉันนับว่าเป็นความแตกต่างในการนับตัวละครเป็นการขอร้องที่สั้นที่สุดเทียบเท่าโดยไม่ต้องพวกเขา
Erik the Outgolfer

1
@EriktheGolfer ไม่, +1 ไม่เป็นไรเพราะโปรแกรมนี้ทำงานได้ดีจาก commandline โดยใช้-nEมากกว่า 1 ตัวอักษร-Eเท่านั้น (ดูบทความที่คุณอ้างถึงนี่ยังกำจัดความต้องการ-M5.010) ฉันมักจะแสดงรหัสของฉันเป็นไฟล์เพราะมัน สะดวกกว่า แต่ฉันจะนับจำนวนตัวเลือกเช่นนี้เสมอ: หากสามารถเรียกใช้จาก commandline ฉันจะไม่นับพื้นที่และเส้นประ ถ้ามันจะต้องอยู่ในไฟล์ (เช่นเพราะมันใช้do$0) ฉันจะนับพื้นที่และเส้นประ
Ton Hospel

@TonHospel -Eโอ้ฉันไม่ทราบว่าคุณใช้ ถ้าเป็นเช่นนั้นคุณเป็นคนดี
Erik the Outgolfer

0

JavaScript (ES6), 154 ไบต์

f=(n,r=[],s=" ".repeat(n)+"/",t=s.replace(/ \/|\\ |\\$/g,_=>"  /  \\/\\".substr(Math.random()*8&6,2)))=>n?/^ +$|\\\//.test(t)?f(n,r,s):f(n-1,[...r,t],t):r
<input type="number" min=1 oninput=o.textContent=f(this.value).join`\n`><pre id=o>

ฉันดิ้นรนกับการนำไปใช้จนกว่าฉันจะเห็นคำตอบของ @ TonHospel ที่จุดนี้มันเสื่อมโทรมลงในพอร์ต ตัวอย่างผลลัพธ์:

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