แสดงมุมมองจากบนลงล่างของหลังคาสะโพกใน ASCII


23

ก่อนคำศัพท์บางคำ ( แหล่งที่มา ):

  • ปั้นหยาเป็น (quoting วิกิพีเดีย) "ประเภทของหลังคาที่ทุกทิศทุกทางลาดชันลงไปผนังมักจะมีความลาดชันค่อนข้างอ่อนโยน"
  • ความลาดชันเป็นพื้นผิวระนาบที่เป็นส่วนหนึ่งของหลังคา
  • สันเขาเป็นขอบที่ทั้งสองตรงข้ามกับหลังคาลาด
  • สะโพกเป็นขอบนูนที่มีความลาดเอียงสองด้านของผนังตั้งฉาก
  • หุบเขาเป็นขอบเว้าที่มีเนินเขาสองลูกอยู่ในแนวกำแพงตั้งฉาก
  • สะโพกและหุบเขาจะถูกเรียกรวมกันเป็นขอบแนวทแยงมุม

อินพุตที่เป็นไปได้:

 ** * ***
******** 
 ** *  **

ผลลัพธ์ที่สอดคล้องกัน:

    +-------+   +---+   +-----------+
    |\     /|   |\ /|   |\         /|
    | \   / |   | V |   | \   ^---< |
    |  \ /  |   | | |   |  \ / \   \|
+---+   V   +---+ | +---+   X   +---+
|\   \  |  /     \|/     \ / \  |
| >---> | <-------X-------V   > |
|/   /  |  \     /|\         /| |
+---+   ^   +---+ | +-------+ | +---+
    |  / \  |   | | |       | |/   /|
    | /   \ |   | ^ |       | /---< |
    |/     \|   |/ \|       |/     \|
    +-------+   +---+       +-------+

อีกสองกรณีทดสอบ:

** ***   *    *   * *
*       ***   *****  
    ** *****  *****  
* *  *  ***  *** *** 
* ****   *     * *   

ผลลัพธ์ที่สอดคล้องกัน:

+-------+   +-----------+           +---+               +---+           +---+   +---+
|\     /|   |\         /|           |\ /|               |\ /|           |\ /|   |\ /|
| \---< |   | >-------< |           | V |               | V |           | V |   | X |
| |\   \|   |/         \|           | | |               | | |           | | |   |/ \|
| | +---+   +-----------+       +---+ | +---+           | | +-----------+ | |   +---+
| | |                           |\   \|/   /|           | |/             \| |
| ^ |                           | \   V   / |           | <               > |
|/ \|                           |  \     /  |           |  \             /  |
+---+           +-------+   +---+   \   /   +---+       |   \-----------/   |
                |\     /|   |\   \   \ /   /   /|       |   |\         /|   |
                | >---/ |   | >--->   X   <---< |       |   | \       / |   |
                |/   /| |   |/   /   / \   \   \|       |   |  \     /  |   |
+---+   +---+   +---+ | |   +---+   /   \   +---+   +---+   ^   +---+   ^   +---+
|\ /|   |\ /|       | | |       |  /     \  |       |\   \ / \  |   |  / \ /   /|
| V |   | V |       | | |       | /   ^   \ |       | >---V   > |   | <   V---< |
| | |   | | |       | | |       |/   /|\   \|       |/       /| |   | |\       \|
| | |   | | +-------+ | |       +---+ | +---+       +-------+ | |   | | +-------+
| | |   | |/         \| |           | | |                   | | |   | | |
| ^ |   | /-----------\ |           | ^ |                   | ^ |   | ^ |
|/ \|   |/             \|           |/ \|                   |/ \|   |/ \|
+---+   +---------------+           +---+                   +---+   +---+

การป้อนข้อมูลของคุณจะเป็นบิตแมป - อาร์เรย์ 2D ของพิกเซลสี่เหลี่ยม - ของพื้นที่ที่ควรครอบคลุมด้วยหลังคา คุณอาจสันนิษฐานว่าขอบเขตของพื้นที่นี้จะเป็นเส้นโค้งของจอร์แดน - นั่นคือต่อเนื่องและไม่ตัดกัน - นั่นคือพื้นที่หลังคาจะต่อเนื่องโดยไม่มีรูและจะไม่มีกำแพงสี่จุดมารวมกันที่จุดเดียว รูปแบบอินพุตที่ถูกต้องประกอบด้วยสตริงเดี่ยวที่มีตัวคั่นบรรทัดใหม่รายการของสตริงและอาร์เรย์ 2 มิติของ chars หรือ booleans

กฎของการสร้างหลังคาคือ:

  • แต่ละส่วนตรงของพื้นที่หลังคา (ต่อจากนี้ไปเรียกว่ากำแพง) จะต้องมีความลาดชันที่อยู่ติดกัน ความชันจะเพิ่มขึ้นจากผนัง แต่ละความชันจะต้องมีกำแพงที่อยู่ติดกันอย่างน้อยหนึ่งแห่งและผนังทุกหลังที่อยู่ติดกับทางลาดจะต้องมี collinear
  • ความลาดชันทั้งหมดจะต้องมีมุม (ไม่ใช่ศูนย์) เดียวกันกับพื้นผิวแนวนอน นั่นคือพวกเขาจะต้องมีระดับเสียงเท่ากัน
  • เนินเขาจะกลายเป็นพื้นผิวที่มีขอบเขตเป็นขอบเขตของพื้นที่หลังคา กล่าวคือไม่ควรใช้พื้นผิวอื่นนอกจากเนินลาด
  • สถานการณ์ใด ๆ ก็ตามที่อนุญาตให้ใช้โซลูชันมากกว่าหนึ่งรายการ (การขยายสเกลแนวตั้ง) ได้รับอนุญาตโดยข้อกำหนดนี้ถือเป็นข้อบกพร่องในข้อกำหนด การแก้ไขใด ๆ จะมีผลย้อนหลัง

เท่ากันหลังคาอาจถูกกำหนดโดยกฎที่แต่ละจุดของหลังคาถูกวางไว้ให้สูงที่สุดเท่าที่จะทำได้โดยไม่เกินความชันสูงสุดของหลังคานั้นตามที่วัดได้โดยใช้ระยะทาง Chebyshevในมุมมองจากบนลงล่าง

ผลลัพธ์ของคุณจะต้องเป็นตัวแทนศิลปะ ASCII ของหลังคา - ทั้งสตริงเดี่ยวที่มีอักขระขึ้นบรรทัดใหม่หรืออาร์เรย์ของสตริงแต่ละอันแสดงถึงบรรทัดเดียวของเอาต์พุต หลังคาจะต้องแสดงในมุมมองจากบนลงล่างในระดับ 4x - นั่นคือแต่ละตารางของแผนผังชั้นควรมีผลต่อพื้นที่ 5x5 ของเอาต์พุตเช่นมุมของพื้นที่ 5x5 นี้จะถูกแชร์กับสี่เหลี่ยมที่อยู่ใกล้เคียง อักขระมุมได้รับผลกระทบจากช่องสี่เหลี่ยมสี่ช่องที่แตกต่างกัน) ตามที่ระบุโดยเอาต์พุตตัวอย่าง อนุญาตให้ใช้ช่องว่างพิเศษได้ตราบใดที่รูปร่างของเอาต์พุตยังคงอยู่ ตัวอักษรในการส่งออกจะต้อง:

  • เครื่องหมายขึ้นบรรทัดใหม่ที่กำหนดโดยสภาพแวดล้อมจะต้องใช้ (โดยปกติคือ U + 000A, U + 000D หรือทั้งคู่) หากเอาต์พุตอยู่ในรูปแบบของสตริงเดี่ยว
  • (ช่องว่าง U + 0020) หมายถึงจุดที่อยู่นอกพื้นที่หลังคาหรือจุดภายในที่ลาดเอียง
  • + (U + 002B เครื่องหมายบวก) หมายถึงจุดที่มีกำแพงสองฉากตั้งฉากอยู่ติดกัน
  • - (U + 002D ยัติภังค์ - ลบ) หมายถึงผนังหรือสันเขาแนวนอน (ตะวันออก - ตะวันตก)
  • / (U + 002F solidus) หมายถึงสะโพกหรือหุบเขาที่มุ่งไปทางตะวันออกเฉียงเหนือถึงตะวันออกเฉียงใต้หรือจุดที่อยู่ติดกับสองแห่งนั้น
  • < (เครื่องหมายน้อยกว่า U + 003C) หมายถึงจุดที่มีขอบทแยงมุมสองเส้นติดอยู่ทางทิศตะวันออก
  • > (เครื่องหมายมากกว่า U + 003E) หมายถึงจุดที่มีขอบทแยงมุมสองเส้นติดกันทางตะวันตก
  • \ (U + 005C reverse solidus) หมายถึงสะโพกหรือหุบเขาที่มุ่งเน้นทิศตะวันตกเฉียงเหนือไปทางตะวันออกเฉียงใต้หรือจุดที่อยู่ติดกับสองแห่งนั้น
  • ^ (U + 005E เน้นเสียงหมวก) หมายถึงจุดที่มีเส้นทแยงมุมสองเส้นติดอยู่ทางทิศใต้
  • V (U + 0056 ตัวอักษรละตินตัวพิมพ์ใหญ่ v) หมายถึงจุดที่มีขอบทแยงมุมสองเส้นติดอยู่ทางเหนือ
  • X (U + 0058 ตัวอักษรละตินตัวพิมพ์ใหญ่ x) หมายถึงจุดที่มีเส้นทแยงมุมติดกับทั้งสี่ด้าน
  • | (U + 007C แถบแนวตั้ง) หมายถึงผนังหรือแนวสันเขาแนวตั้ง (เหนือ - ใต้)

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

หากสภาพแวดล้อมของคุณใช้การเข้ารหัสอักขระที่เข้ากันไม่ได้กับ ASCII คุณสามารถใช้อักขระเทียบเท่า (glyph เดียวกันหรือใกล้เคียงที่สุด) ในการเข้ารหัสอักขระที่สภาพแวดล้อมของคุณใช้

การดำเนินการอ้างอิง (ugly) ต่อไปนี้ใน Ruby เป็นบรรทัดฐานที่เกี่ยวกับเอาต์พุตที่ไม่ใช่ whitespace หมายเหตุโดยเฉพาะอย่างยิ่งrenderวิธีการ:

def pad ary
  row = ary.first.map{-1}
  ([row] + ary + [row]).map{|r| [-1] + r + [-1]}
end

def parse str
  str.split("\n").map{|r| r.chars.map(&{" " => -1, "*" => Float::INFINITY})}
end

def squares ary, size
  ary.each_cons(size).map do |rows|
    rows.map{|row| row.each_cons(size).to_a}.transpose
  end
end

def consmap2d ary, size
  squares(ary, size).map{|sqrow| sqrow.map{|sq| yield sq}}
end

def relax ary
  loop do
    new = consmap2d(pad(ary), 3){|sq| sq[1][1] == -1 ? -1 : sq.flatten.min + 1}
    return new if new == ary
    ary = new
  end
end

def semidouble ary, op
  ary.zip(ary.each_cons(2).map{|r1,r2|r1.zip(r2).map(&op)}).flatten(1).compact.transpose
end

def heightmap str
  relax(semidouble(semidouble(semidouble(semidouble(pad(parse str),:max),:max),:min),:min))
end

def render heightmap
  puts consmap2d(heightmap, 3){|sq|
    next " " if sq[1][1] == -1
    hwall = sq[0][1] == -1 || sq[2][1] == -1
    vwall = sq[1][0] == -1 || sq[1][2] == -1
    next "+" if hwall && vwall
    next "-" if hwall
    next "|" if vwall
    next "+" if sq.flatten.min == -1

    nws = sq[0][1] == sq[1][0]
    nes = sq[0][1] == sq[1][2]
    sws = sq[2][1] == sq[1][0]
    ses = sq[2][1] == sq[1][2]

    next "X"  if nws && nes && sws && ses
    next "V"  if nws && nes
    next "^"  if sws && ses
    next ">"  if nws && sws
    next "<"  if nes && ses
    next "/"  if nes && sws
    next "\\" if nws && ses
    next " "  if sq[0][1] != sq[2][1] || sq[1][0] != sq[1][2]
    next "|"  if sq[0][1] == sq[1][1]
    next "-"  if sq[1][0] == sq[1][1]
    ??
  }.map(&:join)
end

render heightmap $<.read if __FILE__ == $0 

1
คุณควรเพิ่มกรณีทดสอบเพิ่มเติม
mbomb007

@ mbomb007 เพิ่มแล้ว เมื่อพิจารณาถึงพื้นที่ที่พวกเขาใช้ - ฉันควรเพิ่มอีกหรือไม่
John Dvorak

@JanDvorak *อาจจะเพิ่มกรณีทดสอบ ไม่อย่างนั้นอาจจะเพียงพอ
mbomb007

คือ[[0,1,1],[1,0,1],[1,1,1]]การป้อนข้อมูลที่ถูกต้อง? (อินพุตไม่มี“ รู” แต่มีมุมที่น่ารำคาญใกล้กับทางแยก)
ลินน์

@ ลินน์คุณไม่จำเป็นต้องกังวลเกี่ยวกับกรณีนี้มันเป็นอินพุตที่ไม่ถูกต้อง มุมที่คุณพูดถึงจะนับเป็นเขตแดนที่ตัดกันตัวเอง (หรือค่อนข้างเป็นเขตแดนที่ไม่ใช่เส้นโค้ง)
John Dvorak

คำตอบ:


11

Python 2, 500 ไบต์

z=input()
W=4*len(z[0])+1
H=4*len(z)+1
R=range
s=[-~W*[0]for _ in R(-~H)]
for y in R(H/4):
 for x in R(W/4):
        for h in R(25):s[y*4+h%5][x*4+h/5]|=z[y][x]
F=[(x/3-1,x%3-1)for x in[1,7,3,5,0,6,8,2]]
exec'for y in R(H):\n for x in R(W):s[y][x]+=0<s[y][x]<=min(s[y+d][x+e]for(e,d)in F)\n'*H
for y in R(H):
 l=''
 for x in R(W):h=s[y][x];a=[s[y+d][x+e]for(e,d)in F[:4]];l+=r' XabcVde^f ||g>h\\+//+<<jk<l//+\\+>>m --^^oVVqrX'[h and int(''.join(`int(n==h)`for n in a),2)*3+((h==1)*2or max(a)==h)+1]
 print l

เหนื่อยกับการเล่นกอล์ฟลงและฉันได้คะแนนรอบที่ดีดังนั้นนี่คือ

การเยื้องแปดช่องว่างคือแท็บ

ผ่านเมทริกซ์ไบนารีเหนือ STDIN เช่น:

python2.7 roof.py <<<"[[1,1,0,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0], [1,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0], [0,0,0,0,1,1,0,1,1,1,1,1,0,0,1,1,1,1,1,0], [1,0,1,0,0,1,0,0,1,1,1,0,0,1,1,1,0,1,1,1], [1,0,1,1,1,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0]]"

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