İ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 render
yö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
*
. Aksi takdirde bu muhtemelen yeterli.
[[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.)