Відображайте вид зверху вниз кульшового даху в ASCII


23

По-перше, деяка термінологія ( джерело ):

  • Шатровий дах є (цитую Вікіпедію) «тип даху , де всі краї схилу вниз до стін, як правило , з досить пологим нахилом»
  • Схил - це плоска поверхня, яка є частиною даху
  • Хребет - це край, де зустрічаються два протилежні схили даху
  • Стегно - це опуклий край, де зустрічаються два схили, що належать до перпендикулярних стінок
  • Долина - це увігнутий край, де зустрічаються два схили, що належать до перпендикулярних стін
  • Стегна і долини разом називаються діагональними ребрами.

Можливий вхід:

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

Відповідний вихід:

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

Ще кілька тестових випадків:

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

Відповідні результати:

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

Вашим вкладом буде растрова карта - двовимірний масив квадратних пікселів - площі, яку слід покрити дахом. Ви можете припустити, що межею цієї області буде крива Йордану - тобто безперервна та непересічна, що перетинається - тобто дахова ділянка буде суцільною, без дірок, і ніколи не буде зустрічатися чотири стіни в одній точці. Дійсні формати введення включають один рядок з роздільниками нового рядка, списком рядків та 2D масивом символів або булів.

Правила будівництва даху :

  • Кожен прямий відрізок покрівельної ділянки (відтепер називається стіною) повинен мати рівно один сусідній ухил. Ухил повинен підніматися від стіни. Кожен схил повинен мати принаймні одну сусідню стіну, а всі стіни, що прилягають до схилу, повинні бути колінеарними.
  • Усі схили повинні мати однаковий (ненульовий) кут щодо горизонтальної поверхні. Тобто вони повинні мати однаковий крок.
  • Схили утворюють поверхню, межа якої є межею даху. Тобто ніякі поверхні, крім схилів, не можуть використовуватися.
  • Будь-який сценарій, де дана специфікація дозволено більше ніж одне рішення (до вертикального масштабування), вважається помилкою у специфікації. Будь-які виправлення застосовуються заднім числом.

Еквівалентно дах може бути визначений правилом, що кожну точку даху розміщують якомога вище, не перевищуючи максимальний нахил даної покрівлі, виміряний, використовуючи відстань Чебишева у вигляді зверху вниз.

Ваш вихід повинен бути ASCII мистецтво подання даху - або одна рядки , що містить символи нового рядка або масив рядків, кожна з позначають одну рядки виведення. Дах повинен бути виведений вгорі вгору в масштабі 4х - тобто кожен квадрат планування поверху повинен впливати на 5х5 площу виходу, щоб кути цієї площі 5х5 були спільними з сусідніми квадратами (таким, що кожен на кутовий символ впливають чотири різні вхідні квадрати), як зазначено у прикладі виводу. Додатковий пробіл дозволений до тих пір, поки збережена форма виводу. Символи на виході повинні бути:

  • слід використовувати визначений середовищем маркер нового рядка (зазвичай U + 000A, U + 000D або пара обох), якщо вихід є у вигляді однієї рядка
  • (Простір U + 0020) являє собою точку поза покрівельною ділянкою або точкову внутрішню частину до схилу
  • + (Знак U + 002B плюс) являє собою точку з двома перпендикулярними стінками, прилеглими до неї
  • - (U + 002D дефіс-мінус) являє собою стіну або кряж, орієнтовані горизонтально (схід-захід)
  • / (U + 002F solidus) являє собою стегно або долину, орієнтовану на північний схід на південний схід, або точку, прилеглу до двох із них
  • < (U + 003C менше знака) являє собою точку з двома діагональними ребрами, прилеглими до неї на сході
  • > (U + 003E більший за знак) являє собою точку з двома діагональними ребрами, прилеглими до неї на захід
  • \ (U + 005C зворотний солідус) являє собою стегно або долину, орієнтовану з північного заходу на південний схід, або точку, прилеглу до двох із них
  • ^ (U + 005E круговий наголос) являє собою точку з двома діагональними краями, прилеглими до неї на півдні
  • V (U + 0056 латинська велика літера v) являє собою точку з двома діагональними ребрами, прилеглими до неї на північ
  • X (U + 0058 латинська велика літера x) являє собою точку з прилеглими до неї діагональними краями з усіх чотирьох сторін
  • | (Вертикальна смуга U + 007C) являє собою стіну або кряж, орієнтовані вертикально (північ-південь)

Зауважте, що неможливо, щоб непарне число діагональних ребер закінчилося в одній точці (за винятком стін). Ми можемо це уявити, розділивши сусідство кожної точки на північний схил + південний схил і на східний схил + західний схил. Межа між обома перегородками повинна складатися з діагональних ребер.

Якщо ваше середовище використовує кодування символів, несумісне з ASCII, ви можете використовувати еквівалентні символи (той самий гліф або найближчий доступ) у кодуванні символів, яке використовує ваше середовище.

Наступна (некрасива) реалізація посилань у Ruby є нормативною щодо виходу непробільного простору. Зокрема, зверніть увагу на 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 Додано Враховуючи простір, який вони займають - я повинен додати більше?
Джон Дворак

@JanDvorak Можливо, додамо тестовий випадок *. Інакше цього, мабуть, достатньо.
mbomb007

Чи [[0,1,1],[1,0,1],[1,1,1]]дійсний вхід? (На вході немає «дірок», але є кумедний кут біля самопересічення.)
Лінн

@Lynn Вам не потрібно турбуватися про цей випадок, це неправдивий ввід. Кут, про який ви згадуєте, вважається кордоном, що перетинається (а точніше - кордоном, який не є кривою).
Джон Дворак

Відповіді:


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
Р. Кап
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.