Hiển thị chế độ xem từ trên xuống của mái hông trong ASCII


23

Đầu tiên, một số thuật ngữ ( nguồn ):

  • Một mái hông được (trích dẫn Wikipedia) "một loại mái nhà, nơi tất cả các bên dốc xuống các bức tường, thường là với một độ dốc khá nhẹ nhàng"
  • Độ dốc là một mặt phẳng là một phần của mái nhà
  • Một sườn núi là một cạnh nơi hai sườn mái đối diện gặp nhau
  • Hông là một cạnh lồi, nơi hai sườn thuộc các bức tường vuông góc gặp nhau
  • Một thung lũng là một cạnh lõm, nơi hai sườn dốc của các bức tường vuông góc gặp nhau
  • Hông và thung lũng sẽ được gọi chung là các cạnh chéo.

Đầu vào có thể:

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

Đầu ra tương ứng:

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

Một vài trường hợp thử nghiệm nữa:

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

Đầu ra tương ứng:

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

Đầu vào của bạn sẽ là một bitmap - một mảng 2D pixel vuông - của khu vực cần được che bởi mái nhà. Bạn có thể cho rằng ranh giới của khu vực này sẽ là một đường cong Jordan - nghĩa là liên tục và không tự giao nhau - nghĩa là khu vực mái sẽ liên tục, không có lỗ hổng và sẽ không bao giờ có bốn bức tường gặp nhau tại một điểm. Các định dạng đầu vào hợp lệ bao gồm một chuỗi đơn với các dấu phân cách dòng mới, danh sách các chuỗi và một mảng 2D của ký tự hoặc booleans.

Các quy tắc xây dựng mái nhà là:

  • Mỗi đoạn thẳng của khu vực mái (từ đó được gọi là tường) sẽ có chính xác một độ dốc liền kề. Độ dốc sẽ tăng lên từ tường. Mỗi độ dốc phải có ít nhất một bức tường liền kề và tất cả các bức tường liền kề với một độ dốc phải được đặt thẳng hàng.
  • Tất cả các độ dốc phải có cùng một góc (khác không) so với bề mặt ngang. Đó là, họ phải có cùng một sân.
  • Các sườn sẽ tạo thành một bề mặt có ranh giới là ranh giới của khu vực mái. Đó là, không có bề mặt nào khác ngoài các sườn dốc có thể được sử dụng.
  • Bất kỳ kịch bản nào có nhiều hơn một giải pháp (tối đa tỷ lệ dọc) được cho phép bởi đặc tả này đều được coi là một lỗi trong đặc tả. Bất kỳ sửa chữa áp dụng hồi tố.

Tương tự, mái nhà có thể được xác định theo quy tắc rằng mỗi điểm của mái nhà được đặt càng cao càng tốt mà không vượt quá độ dốc tối đa cho mái đó như được đo bằng khoảng cách Ch Quashev trong chế độ xem từ trên xuống.

Đầu ra của bạn sẽ là một biểu diễn nghệ thuật ASCII của mái nhà - hoặc là một chuỗi chứa các ký tự dòng mới hoặc một chuỗi các chuỗi, mỗi chuỗi biểu thị một dòng đầu ra. Mái nhà sẽ được hiển thị ở chế độ xem từ trên xuống theo tỷ lệ 4x - nghĩa là, mỗi ô vuông của sơ đồ tầng sẽ ảnh hưởng đến một khu vực 5x5 của đầu ra sao cho các góc của khu vực 5x5 này được chia sẻ với các ô vuông lân cận (sao cho mỗi ô vuông ký tự góc bị ảnh hưởng bởi bốn ô vuông đầu vào khác nhau), như được chỉ ra bởi đầu ra ví dụ. Khoảng trắng thêm được cho phép miễn là hình dạng đầu ra được giữ nguyên. Các ký tự trong đầu ra sẽ là:

  • một dấu hiệu dòng mới do môi trường xác định sẽ được sử dụng (thường là U + 000A, U + 000D hoặc một cặp cả hai) nếu đầu ra ở dạng một chuỗi đơn
  • (Không gian U + 0020) biểu thị một điểm bên ngoài khu vực có mái hoặc nội thất điểm đến độ dốc
  • + (Dấu cộng U + 002B) biểu thị một điểm có hai bức tường vuông góc liền kề với nó
  • - (Dấu gạch nối U + 002D) đại diện cho một bức tường hoặc một sườn núi được định hướng theo chiều ngang (đông-tây)
  • / (U + 002F solidus) đại diện cho hông hoặc thung lũng được định hướng từ đông bắc sang đông nam hoặc một điểm tiếp giáp với hai trong số đó
  • < (Dấu nhỏ hơn U + 003C) biểu thị một điểm có hai cạnh chéo tiếp giáp với nó ở phía đông
  • > (Dấu lớn hơn U + 003E) biểu thị một điểm có hai cạnh chéo tiếp giáp với nó ở phía tây
  • \ (U + 005C solidus ngược) đại diện cho một hông hoặc một thung lũng được định hướng từ tây bắc sang đông nam, hoặc một điểm tiếp giáp với hai trong số đó
  • ^ (Dấu thập phân U + 005E) biểu thị một điểm có hai cạnh chéo tiếp giáp với nó ở phía nam
  • V (U + 0056 chữ hoa Latin v) đại diện cho một điểm có hai cạnh chéo tiếp giáp với nó ở phía bắc
  • X (U + 0058 chữ hoa Latin x) đại diện cho một điểm có các đường chéo chéo liền kề với nó ở cả bốn phía
  • | (Thanh dọc U + 007C) đại diện cho một bức tường hoặc một sườn núi được định hướng theo chiều dọc (bắc-nam)

Lưu ý rằng không thể có một số lẻ các cạnh đường chéo kết thúc tại cùng một điểm (ngoại trừ trên các bức tường). Chúng ta có thể hình dung rằng bằng cách phân vùng lân cận của mỗi điểm thành dốc phía bắc + dốc phía nam và vào sườn phía đông + dốc phía tây. Ranh giới giữa cả hai phân vùng phải bao gồm các cạnh chéo.

Nếu môi trường của bạn sử dụng mã hóa ký tự không tương thích với ASCII, bạn có thể sử dụng các ký tự tương đương (cùng glyph hoặc gần nhất có sẵn) trong mã hóa ký tự mà môi trường của bạn sử dụng.

Việc triển khai tham chiếu (xấu xí) sau đây trong Ruby là quy phạm đối với đầu ra không phải khoảng trắng. Đặc biệt lưu ý renderphương pháp:

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
Bạn nên thêm nhiều trường hợp thử nghiệm.
mbomb007

@ mbomb007 Đã thêm. Cho không gian họ chiếm - tôi có nên thêm nữa không?
John Dvorak

@JanDvorak Có thể thêm trường hợp thử nghiệm *. Nếu không thì có lẽ là đủ.
mbomb007

[[0,1,1],[1,0,1],[1,1,1]]đầu vào hợp lệ? (Đầu vào không có lỗ của người Viking, nhưng có một góc khó gần ngã tư.)
Lynn

@Lynn Bạn không cần phải lo lắng về trường hợp đó, đó không phải là đầu vào hợp lệ. Góc bạn đề cập không được tính là một ranh giới tự giao nhau (hay đúng hơn là một ranh giới không phải là một đường cong).
John Dvorak

Câu trả lời:


11

Python 2, 500 byte

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

Mệt mỏi vì chơi golf xuống, và tôi đã đạt được một số điểm tốt đẹp, vì vậy đây là.

Các vết lõm tám không gian là một tab.

Truyền ma trận nhị phân qua STDIN, như vậy:

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]]"

Chơi golf hoàn toàn hay không, điều này thật tuyệt vời. Làm tốt. +1
R. Kap
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.