ASCII’de bir kalça çatısının yukarıdan aşağıya görünüşünü oluşturma


23

İlk olarak, bazı terminoloji ( kaynak ):

  • Bir kalça çatı (Wikipedia alıntı) olan "çatı türüdür nerede duvarlara bütün taraflar yamaç aşağıya doğru, genellikle oldukça hafif eğimli olan"
  • Eğim, çatının bir parçası olan düzlemsel bir yüzeydir.
  • Bir sırt, iki zıt çatı eğiminin birleştiği bir kenardır
  • Bir kalça, dik duvarlara ait iki eğimin buluştuğu dışbükey bir kenardır.
  • Bir vadi, dik duvarlara ait iki yamacın birleştiği içbükey bir kenardır
  • Kalçalar ve vadiler toplu olarak köşegen kenarlar olarak adlandırılır.

Olası giriş:

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

Karşılık gelen çıktı:

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

Birkaç daha fazla test durumu:

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

Karşılık gelen çıktılar:

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

Kişisel giriş kare piksel 2D dizi - - çatıyla kaplanmış olmalıdır alanın bir bit eşlem olacaktır. Bu alanın sınırının Ürdün eğrisi - yani, sürekli ve kendiliğinden kesişmeyen - olacağı varsayılabilir, yani çatılı alanın deliksiz, kesintisiz olacağı ve hiçbir zaman tek bir noktada toplanan dört duvar olmayacağı varsayılabilir. Geçerli girdi biçimleri arasında yeni satır ayırıcıları olan tek bir dize, bir dizi listesi ve bir 2B karakter veya boolean dizisi bulunur.

Çatının inşa kuralları :

  • Çatılı alanın her düz kesimi (bundan böyle duvar olarak anılacaktır) tam olarak bir bitişik eğime sahip olacaktır. Eğim duvardan uzağa doğru yükselecektir. Her eğim en az bir bitişik duvara sahip olmalı ve bir eğime bitişik tüm duvarlar aynı olmalıdır.
  • Tüm eğimler yatay yüzeye karşı aynı (sıfır olmayan) açıya sahip olacaktır. Yani, aynı perdeye sahip olmalılar.
  • Eğimler, sınırı çatılı alanın sınırı olan bir yüzey oluşturacaktır. Yani, eğimden başka yüzey kullanılamaz.
  • Bu tarifnamede birden fazla çözüme (dikey ölçeklendirmeye kadar) izin verilen herhangi bir senaryo şartnamede bir hata olarak kabul edilir. Herhangi bir düzeltme geriye dönük olarak uygulanır.

Eşdeğer olarak, çatı, tavanın her bir noktasının, Chebyshev mesafesi yukarıdan aşağıya bakıldığında kullanılarak ölçüldüğü haliyle, çatı için maksimum eğimi aşmadan mümkün olduğu kadar yükseğe yerleştirilmesi kuralı ile tanımlanabilir .

Sizin çıkış satır karakterlerini veya dize dizisi içeren tek bir dize olsun, her çıkışın tek bir satır gösteren - çatı bir ASCII sanatı gösterimi olacaktır. Çatı, 4x ölçeğinde yukarıdan aşağı bakacak şekilde yapılmalıdır - yani kat planının her bir karesi, çıkışın 5x5 alanını etkilemeli, böylece bu 5x5 alanın köşeleri, komşu kareler ile paylaşılmalıdır (her biri köşe karakteri, örnek çıktı tarafından belirtildiği gibi dört farklı giriş karesinden) etkilenir. Çıkış şekli korunduğu sürece ekstra boşluk bırakılır. Çıktıdaki karakterler şöyle olacaktır:

  • çıktı tek bir dize biçimindeyse, çevre tanımlı bir yeni satır işareti (genellikle U + 000A, U + 000D veya her ikisi de bir çift) kullanılacaktır
  • (U + 0020 alanı) çatılı bir alanın dışındaki bir noktayı veya bir yokuşun içindeki bir noktayı temsil eder.
  • + (U + 002B plus işareti), kendisine bitişik iki dik duvarı olan bir noktayı temsil eder.
  • - (U + 002D kısa çizgi-eksi) yatay olarak yönlendirilmiş bir duvarı veya çıkıntıyı temsil eder (doğu-batı)
  • / (U + 002F solidus) kuzey-doğuya güney-doğu yönündeki bir kalçayı veya vadiyi veya bunlardan ikisine bitişik bir noktayı temsil eder.
  • < (U + 003C işaretinden az), doğuda bitişik iki çapraz kenarı olan bir noktayı temsil eder.
  • > (U + 003E işaretinden büyük), batıya bitişik iki çapraz kenarı olan bir noktayı temsil eder.
  • \ (U + 005C ters solidus) kuzey-batıdan güney-doğuya yönlendirilmiş bir kalça veya vadiyi veya bunlardan ikisine bitişik bir noktayı temsil eder.
  • ^ (U + 005E sirkumfleks aksanı), güneyde birbirine bitişik iki çapraz kenarı olan bir noktayı temsil eder.
  • V (U + 0056 latin büyük harf v) kuzeyde kendisine bitişik iki çapraz kenar bulunan bir noktayı temsil eder.
  • X (U + 0058 latin büyük harf x) dört kenarın hepsine bitişik köşegen kenarları olan bir noktayı temsil eder
  • | (U + 007C dikey çubuk) dikey olarak yönlendirilmiş bir duvarı veya sırtı (kuzey-güney) temsil eder

Tek sayıda çapraz kenarın aynı noktada sona ermesinin mümkün olmadığını unutmayın (duvarlar hariç). Her noktanın mahallesini kuzey yamacında + güney yamacında ve doğu yamacında + batı yamacında bölümlere ayırarak görselleştirebiliriz. Her iki bölüm arasındaki sınır, diyagonal kenarlardan oluşmalıdır.

Ortamınız ASCII ile uyumlu olmayan bir karakter kodlaması kullanıyorsa, ortamınızı kodlayan karakterde eşdeğer karakterleri (aynı glif veya en yakın kullanılabilir) kullanabilirsiniz.

Ruby'deki aşağıdaki (çirkin) referans uygulaması , boşluk olmayan çıktıya göre normaldir. Özellikle renderyöntemi not alın:

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
Daha fazla test senaryosu eklemelisin.
mbomb007

@ mbomb007 Eklendi. Aldıkları alan göz önüne alındığında - daha fazla eklemeli miyim?
John Dvorak

@JanDvorak Belki de test senaryosunu ekleyin *. Aksi takdirde bu muhtemelen yeterli.
mbomb007

Mi [[0,1,1],[1,0,1],[1,1,1]]geçerli giriş? (Girdide “delik” yoktur, ancak kendi kendine kesişme noktasında sinir bozucu bir köşe vardır.)
Lynn

@Lynn Bu durumda endişelenmenize gerek yok, geçerli bir giriş değil. Bahsettiğiniz köşe, kendiliğinden kesişen bir sınır (veya eğri olmayan bir sınır) olarak sayılır.
John Dvorak

Yanıtlar:


11

Python 2,500 bayt

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

Aşağı golf bıktınız ve güzel bir yuvarlak puan aldım, işte burada.

Sekiz boşluk girintisi bir sekmedir.

İkili bir matrisi STDIN üzerinden geçir, şöyle:

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

Tamamen golf oynamış ya da oynamam, bu şaşırtıcı. Aferin. +1
R. Kap
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.