ก่อนคำศัพท์บางคำ ( แหล่งที่มา ):
- ปั้นหยาเป็น (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
*
อาจจะเพิ่มกรณีทดสอบ ไม่อย่างนั้นอาจจะเพียงพอ
[[0,1,1],[1,0,1],[1,1,1]]
การป้อนข้อมูลที่ถูกต้อง? (อินพุตไม่มี“ รู” แต่มีมุมที่น่ารำคาญใกล้กับทางแยก)