ทำหิมะบ้าง!


18

งานของคุณ: สร้างเกล็ดหิมะ Koch ให้ลึกที่ n คุณไม่จำเป็นต้องสร้างเกล็ดหิมะ Koch ที่สมบูรณ์เพียงด้านใดด้านหนึ่งของสามเหลี่ยมเริ่มต้น วิกิพีเดียสะเก็ด Koch: https://en.wikipedia.org/wiki/Koch_snowflake

กฎ:

  • โปรแกรมจะต้องสร้างเกล็ดหิมะ Koch ด้านใดด้านหนึ่งให้ลึกที่ n
  • เอาต์พุตต้องเป็น ASCII
  • คุณสามารถสร้างเกล็ดหิมะทั้งหมด; ไม่จำเป็น
  • กฎมาตรฐานสำหรับอินพุต / เอาต์พุตและช่องโหว่และสิ่งที่ใช้
  • ช่องว่างไม่สำคัญตราบใดที่อักขระทั้งหมดอยู่ในตำแหน่งที่ถูกต้องซึ่งสัมพันธ์กัน
  • รหัสที่สั้นที่สุดชนะ!

กรณีทดสอบ:

n = 0:

__

n = 1:

__/\__

n = 2:

      __/\__
      \    /
__/\__/    \__/\__

n = 3:

                        __/\__
                        \    /
                  __/\__/    \__/\__
                  \                /
                  /_              _\
                    \            /
      __/\__      __/            \__      __/\__
      \    /      \                /      \    /
__/\__/    \__/\__/                \__/\__/    \__/\__

ฉันหวังว่านี่จะสมเหตุสมผล โปรดสังเกตว่าในแต่ละกรณีทดสอบเศษส่วนสามารถแบ่งออกเป็นสามส่วนเท่ากันในความยาว สังเกตว่าความกว้างของเกล็ดหิมะแต่ละครั้งนั้นมีความกว้างเป็นสามเท่าของรุ่นก่อนหน้าของเกล็ดหิมะ


FYI มันก็ตกลงกันว่านี้ไม่ได้ล่อของนี้
สหาย SparklePony

ฉันไม่คิดว่าคุณได้กำหนดไว้อย่างเหมาะสมว่าการแสดง ASCII ที่เหมาะสมของเส้นโค้ง Koch ที่ n คืออะไร
orlp

ฉันไม่แน่ใจว่าสัดส่วนที่เหมาะสม ไม่ใช่การล่อจับคู่ที่ใช้__/\__กับการขีดเส้นใต้สองเส้นซึ่งทำให้การวนซ้ำแต่ละครั้งอย่างต่อเนื่อง 3 เท่าเท่าครั้งก่อน การใช้ขีดเส้นใต้เพียงอันเดียวดูเหมือนว่าจะขัดแย้งกันและเริ่มรู้สึกอึดอัดใจใน n = 3 เช่นชิ้นส่วนด้านนอกมีความกว้าง 12 ในขณะที่ส่วนตรงกลางมีความกว้างเพียง 10 เป็นผลมาจาก/_และ_\ ที่แคบเกินไป และแม้กระทั่งก่อนที่คุณได้_ขยายไปยังสองเท่าความกว้างของและ/ \
Ørjan Johansen

ผมคิดว่า/_และ_\ เป็นเพียงส่วนหนึ่งที่ร้ายแรงจริงๆ - ขีดจำเป็นต้องไปเพราะพวกเขาต้องการที่จะอยู่ในตำแหน่งเดียวกับและ/ \ เมื่อเสร็จแล้วสิ่งต่างๆสามารถขยายได้ 3 เท่าจาก n = 1 เป็นต้นไป (แต่ n = 0 ไม่พอดี)
Ørjan Johansen

อนิจจาไม่ส่วนตรงกลางยังคงมีความกว้างไม่ตรงกับชิ้นส่วนด้านนอกตามหลักฐานโดย n = 3 ที่มีความกว้าง 52 มากกว่า 54 = 2 * 3 ^ 3 ลองของเหล่านี้ ฉันรวมรุ่นกลับหัวที่มีบางส่วนแสดงเฉพาะจาก n = 4 หรือ n = 5 - พวกเขาแตกต่างจากรุ่นขึ้นในที่ที่ขีดล่างถูกลดลง
Ørjan Johansen

คำตอบ:


10

Haskell , 308 300 299 ไบต์

การแก้ไข:

  • -4 ไบต์: การเปลี่ยนzipWith(+)ไปzipWith(-)และการปรับการเข้ารหัสและการชดเชยได้กำจัดสัญญาณปฏิเสธทุก
  • -1 ไบต์: การปรับแต่งการเข้ารหัสเพิ่มเติมอนุญาตให้ชื่อตัวแปรหลายตัว#ถูกดร็อปโดยใช้r=reverseแทนการจับคู่รูปแบบโดยตรง
  • -2 ไบต์: การใช้ผู้ประกอบการแทน alphanum zipWith(-)สำหรับ
  • -1 ไบต์: การกำหนดo=[0,0]เพื่อย่นค่ารายการให้สั้นลง
  • -1 ไบต์: ?การผสานสองสาขาของ
import Data.List
k n=0?sort(o#(f=<<scanl1(+)(iterate(>>=(:[1,4,1]))[6]!!n)))
x?l@(([_,w],c):r)|x>w='\n':0?l|0<1=([2..w-x]>>" ")++[c|w>x]++w?r
_?_=""
w#((c,l):m)=(l&w,c):r l&(l&w)#m
_#_=[]
f x=zip"_/\\_/\\"([id,r]<*>[0:1:o,[0,1,0,1],o++[1,1]])!!mod x 6<$[1,3..gcd 3x]
(&)=zipWith(-)
r=reverse
o=[0,0]

ลองออนไลน์! (น่าเศร้าสิ่งที่ใหญ่กว่า n = 3 จะถูกห่อหุ้มและอ่านไม่ออกอย่างน่ากลัว แต่คุณสามารถคัดลอกไปยังโปรแกรมอื่นเพื่อดู)

รูปแบบ

  • หากคุณเปลี่ยน[6]เป็น[6,4,4]คุณจะได้รับเกล็ดหิมะทั้งหมด ลองออนไลน์!
  • หากคุณลบ,3..gcd 3xคุณจะได้รับส่วนโค้งในสไตล์ที่คำถามนี้ให้ไว้ ลองออนไลน์!
  • หรือทั้งสองอย่างพร้อมกัน: ลองออนไลน์!

มันทำงานอย่างไร

  • kเป็นหน้าที่หลักก็จะใช้เวลาและผลตอบแทนInt nString
  • iterate(>>=(:[1,4,1]))[6]สร้างรายการที่ไม่มีที่สิ้นสุดที่มีสำหรับแต่ละ n ที่ผลัดกันระหว่างบรรทัดต่อเนื่องในการทำซ้ำที่โค้งสไตล์กราฟิกเต่าหมายเลขนามระหว่างและ0 5การวนซ้ำแต่ละครั้งเป็นเพียงครั้งก่อน ๆ โดยมีการเลี้ยว1,4,1สลับ เหตุผลเดียวที่รายการย่อยเริ่มออกมาพร้อมกับ6แทน0คือการทำให้gcdเคล็ดลับในการทำงานโดยการหลีกเลี่ยงff 0
  • scanl1(+)แปลงผลัดกันเป็นทิศทาง "สัมบูรณ์" สูงสุดถึงโมดูโล 6. A 0หมายถึงทางขวาจากนั้นจำนวนที่สูงกว่าคือ 60 องศาทวนเข็มนาฬิกาจากก่อนหน้า (ถ้าเป็นรูปวาดที่เหมาะสมแทนที่จะเป็น ASCII จะเป็น 60 องศา)
  • f แปลงทิศทางแบบสัมบูรณ์เป็นรายการของคู่ (อักขระ, การเข้ารหัสออฟเซต) ที่เข้ารหัสอักขระที่จะเพิ่มไปยังเส้นโค้ง
  • #iterates ผู้ประกอบการผ่านรายการก่อนหน้า (ตัวอักษร, การเข้ารหัส offset) คู่ที่สร้างจริง (พิกัดตัวอักษร) คู่
  • หลักการเข้ารหัส:
    • อักขระจาก_/\ในนามหมายถึงเส้นที่ลากจากมุมเริ่มต้นจนถึงเซลล์รูปสี่เหลี่ยมผืนผ้าไปยังมุมสิ้นสุดที่แตกต่างกัน
    • พิกัดของเซลล์มีรูปแบบจาก[y,x]บนลงล่างซ้ายไปขวาเพื่อให้เรียงลำดับตามที่เราต้องการพิมพ์ คอลัมน์เป็นแบบ 1 รายการจะถูกนำมาใช้แทน tuples (&)=zipWith(-)สำหรับคณิตศาสตร์เวกเตอร์ที่สั้นลงด้วย
    • มุมจะแสดงด้วยพิกัด[y,x]เดียวกับเซลล์ไปทางซ้ายบน สิ่งนี้ทำให้มั่นใจได้ว่าการชดเชยจากมุมหนึ่งไปยังเซลล์ข้างเคียงนั้นไม่ติดลบเพื่อหลีกเลี่ยงค่าคงที่เชิงลบ
    • อย่างไรก็ตามพิกัดมุมถูกส่งไปรอบ ๆ เมื่อตะกี้เพื่อให้การดำเนินการเวกเตอร์ทั้งหมดเป็นการลบแทนการเพิ่มเติมซึ่งจะหลีกเลี่ยงสัญญาณที่ชัดเจนอื่น ๆ ทั้งหมด
    • รายการเข้ารหัสออฟเซ็ตคือ[y1,x1,x2,y2]ตำแหน่งที่[y1,x1]พิกัดออฟเซ็ตจากมุมเริ่มต้นไปยังเซลล์อักขระและ[y2,x2]เป็นออฟเซ็ตจากมุมปลายไปยังเซลล์อักขระ หมายความว่า:
      • รายการเข้ารหัสสำหรับทิศทาง3.. 5เป็นเพียงการย้อนกลับของรายการสำหรับ0.. ช่วยให้พวกเขาได้รับการสร้างขึ้นด้วย2[id,r]<*>
      • การคำนวณเวกเตอร์ที่จำเป็นทั้งหมดสามารถทำได้โดยใช้(&)=zipWith(-)กับรายการเข้ารหัสหรือย้อนกลับ
  • หลังจากเรียงลำดับรายการของคู่ (พิกัด, ตัวอักษร) แล้วจะถูกส่งผ่านไปยัง?ซึ่งสร้างคู่สุดท้ายStringจากพวกเขา
    • ในx?l@(([_,w],c):r) xคือพิกัด x ของอักขระก่อนหน้านี้ที่แสดงในบรรทัดนี้หรือ0ถ้าตอนเริ่มต้นของบรรทัด lเป็นรายการปัจจุบันทั้งหมดwเป็นพิกัด x ของอักขระถัดไปที่จะเพิ่มcเป็นอักขระและrเป็นรายการที่เหลือ
    • ในขั้นตอนนี้ไม่จำเป็นต้องใช้พิกัด y อีกต่อไป เนื่องจากทุกบรรทัดมีอักขระและอักขระแรกของทุกบรรทัดนั้นอยู่ทางซ้ายของจุดสิ้นสุดของบรรทัดก่อนหน้าการตรวจพบจุดเริ่มต้นของบรรทัดใหม่โดยตรวจสอบว่าพิกัด x ลดลงหรือไม่
    • ขีดล่างมีค่า ASCII ที่ใหญ่กว่า\และ/ดังนั้นจึงถูกเรียงลำดับล่าสุดหากทับซ้อนกับอักขระอื่นในตำแหน่งเดียวกัน ดังนั้นขีดล่างที่ซ้ำซ้อนถูกตรวจพบโดยการตรวจสอบว่าพิกัด x ได้ถูกทำซ้ำ

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