Слова -> Горизонт міста


40

Змагання

Ваша програма або функція прийме введення одного рядка від STDIN або параметра функції. Можна припустити, що вхід буде містити лише алфавітні символи (a-zA-Z), пробіли та повні зупинки. Введення даних є нечутливим до регістру, тому ви маєте ставитися до "a" точно так само, як і до "A".

Для кожного символу в рядку виведете подання будівлі відповідно до наступних специфікацій.

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

 _
/ \

Потім у вас буде кілька поверхів, що відповідають номеру літери (a = 1, b = 2, c = 3 тощо), які зображені стіною (|) з кожного боку та пробілом посередині. Нижній поверх (і лише нижній поверх) повинен мати фундамент, який є підкресленням між стінами. Подобається це...

|_|

Так, наприклад, "b" виглядатиме так

 _
/ \
| |
|_|

Тепер ми знаємо, що дуже високі, вузькі будівлі не можуть стояти і повинні бути ширшими біля основи, тому жодна будівля не може стояти більше трьох поверхів без додаткової підтримки. Тож кожні три рівні (не менше) слід додавати "розширюється шар". Шар, що розширюється, складається з косої та зворотної нахилів безпосередньо над стінками секції під ним, а ділянка внизу повинна бути на два проміжки ширше, ніж переріз вище. Додатковий шар не враховується до висоти будівлі.

Будинки не повинні перетинатися, але не повинні мати зайвих проміжків між ними, а земля завжди рівна, тому всі будівлі повинні мати свою базу на одному рівні.

Наприклад, "abcdefga" буде виглядати приблизно так.

                           _
                          / \
                     _    | |
                _   / \   | |
           _   / \  | |   | |
          / \  | |  | |  /   \
       _  | |  | |  | |  |   |
    _ / \ | |  | | /   \ |   |
 _ / \| | | | /   \|   | |   |  _
/ \| || |/   \|   ||   |/     \/ \
|_||_||_||___||___||___||_____||_|

Проміжки у рядковому вході повинні бути представлені подвійним пробілом.

Повні зупинки на вводі рядка повинні бути представлені таким чином щебеню.

/\/\

Подальші приклади

Вхід = Hello world.

Вихід =

                                                   _                                                  
                                                  / \                                                 
                                                  | |                                                 
                                                  | |                                                 
                                                  | |                                                 
                                                 /   \                                                
                                                 |   |                                                
                                                 |   |                       _                        
                                                 |   |                      / \                       
                                                /     \                     | |                       
                                                |     |                     | |                       
                                   _            |     |          _          | |                       
                                  / \           |     |         / \        /   \                      
                                  | |          /       \        | |        |   |                      
                                  | |          |       |        | |        |   |                      
                _        _        | |          |       |        | |        |   |        _             
               / \      / \      /   \         |       |       /   \      /     \      / \            
               | |      | |      |   |        /         \      |   |      |     |      | |            
               | |      | |      |   |        |         |      |   |      |     |      | |            
               | |      | |      |   |        |         |      |   |      |     |      | |            
   _          /   \    /   \    /     \       |         |     /     \    /       \    /   \           
  / \         |   |    |   |    |     |      /           \    |     |    |       |    |   |           
  | |         |   |    |   |    |     |      |           |    |     |    |       |    |   |           
  | |         |   |    |   |    |     |      |           |    |     |    |       |    |   |           
  | |    _   /     \  /     \  /       \     |           |   /       \  /         \  /     \          
 /   \  / \  |     |  |     |  |       |    /             \  |       |  |         |  |     |   _      
 |   |  | |  |     |  |     |  |       |    |             |  |       |  |         |  |     |  / \     
 |   |  | |  |     |  |     |  |       |    |             |  |       |  |         |  |     |  | |     
 |   |  | | /       \/       \/         \   |             | /         \/           \/       \ | |     
/     \/   \|       ||       ||         |  /               \|         ||           ||       | | |     
|     ||   ||       ||       ||         |  |               ||         ||           ||       |/   \    
|_____||___||_______||_______||_________|  |_______________||_________||___________||_______||___|/\/\

Вхід = lorem ipsum

                                                                                             _                  
                                                                                            / \                 
                                                                              _             | |                 
                                                                             / \            | |                 
                          _                                                  | |            | |                 
                         / \                                                 | |           /   \                
                         | |                                    _            | |           |   |                
                         | |                                   / \          /   \          |   |                
              _          | |                                   | |          |   |          |   |                
             / \        /   \                                  | |          |   |         /     \               
             | |        |   |              _                   | |          |   |         |     |         _     
             | |        |   |             / \                 /   \        /     \        |     |        / \    
    _        | |        |   |             | |                 |   |        |     |        |     |        | |    
   / \      /   \      /     \            | |                 |   |        |     |       /       \       | |    
   | |      |   |      |     |            | |                 |   |        |     |       |       |       | |    
   | |      |   |      |     |           /   \               /     \      /       \      |       |      /   \   
   | |      |   |      |     |           |   |        _      |     |      |       |      |       |      |   |   
  /   \    /     \    /       \          |   |       / \     |     |      |       |     /         \     |   |   
  |   |    |     |    |       |          |   |       | |     |     |      |       |     |         |     |   |   
  |   |    |     |    |       |         /     \      | |    /       \    /         \    |         |    /     \  
  |   |    |     |    |       |         |     |      | |    |       |    |         |    |         |    |     |  
 /     \  /       \  /         \   _    |     |     /   \   |       |    |         |   /           \   |     |  
 |     |  |       |  |         |  / \   |     |     |   |   |       |    |         |   |           |   |     |  
 |     |  |       |  |         |  | |  /       \    |   |  /         \  /           \  |           |  /       \ 
 |     |  |       |  |         |  | |  |       |    |   |  |         |  |           |  |           |  |       | 
/       \/         \/           \ | |  |       |   /     \ |         |  |           | /             \ |       | 
|       ||         ||           |/   \ |       |   |     | |         |  |           | |             | |       | 
|       ||         ||           ||   |/         \  |     |/           \/             \|             |/         \
|_______||_________||___________||___||_________|  |_____||___________||_____________||_____________||_________|

Вхід = a.a.a.x.x.x.a.a.a

                             _                    _                    _                             
                            / \                  / \                  / \                            
                            | |                  | |                  | |                            
                            | |                  | |                  | |                            
                            | |                  | |                  | |                            
                           /   \                /   \                /   \                           
                           |   |                |   |                |   |                           
                           |   |                |   |                |   |                           
                           |   |                |   |                |   |                           
                          /     \              /     \              /     \                          
                          |     |              |     |              |     |                          
                          |     |              |     |              |     |                          
                          |     |              |     |              |     |                          
                         /       \            /       \            /       \                         
                         |       |            |       |            |       |                         
                         |       |            |       |            |       |                         
                         |       |            |       |            |       |                         
                        /         \          /         \          /         \                        
                        |         |          |         |          |         |                        
                        |         |          |         |          |         |                        
                        |         |          |         |          |         |                        
                       /           \        /           \        /           \                       
                       |           |        |           |        |           |                       
                       |           |        |           |        |           |                       
                       |           |        |           |        |           |                       
                      /             \      /             \      /             \                      
                      |             |      |             |      |             |                      
                      |             |      |             |      |             |                      
                      |             |      |             |      |             |                      
                     /               \    /               \    /               \                     
 _      _      _     |               |    |               |    |               |     _      _      _ 
/ \    / \    / \    |               |    |               |    |               |    / \    / \    / \
|_|/\/\|_|/\/\|_|/\/\|_______________|/\/\|_______________|/\/\|_______________|/\/\|_|/\/\|_|/\/\|_|

Правила

  • Звичайно, це кодовий гольф, найнижчий бал у виграші байтів
  • Застосовуються стандартні правила лазівки
  • Дозволяється будь-яка кількість додаткових порожніх рядків до або після виводу
  • Ви можете вивести весь результат в одному рядку або запропонувати вихід у вигляді масиву, де кожен елемент являє собою один рядок виводу, або надіслати STDOUT

Примітка

Це моє перше повідомлення до PPCG, тому будь ласка, будь ласка, на мене. Це пройшло через пісочницю. Будь-які негативні моменти або можливі покращення, будь ласка, опублікуйте як коментар, і я зроблю все, що можу


7
Перетворення [a,z]і [A,Z]в [1,26]здається безглуздим вимога. Було б набагато краще просто використовувати цілі списки як вхідні дані (маючи 0вхід для щебеню). Крім того, опублікування виклику після того, як він пробув у «Пісочниці» лише 21 годину , не чекаючи отримання голосів чи відгуків більше ніж одного користувача, не вважається тим, що він «пройшов через пісочницю». Рекомендується залишати проблеми в «Пісочниці» мінімум на 48–72 години, щоб дати людям достатньо часу для їх перегляду.
Mego

2
Нагадує мені про це . Хороший перший виклик, але я пропоную вам розглянути можливість зміни [a,z], [1.26]частин , на Mego згадується. Необов'язково мати його необов'язково (якщо тільки це не є ключовою частиною виклику (його тут немає).
Стюі Гріффін

2
Скажу, це дуже приємний перший виклик. Ласкаво просимо на сайт!
DJMcMayhem

1
Я можу зрозуміти пункт про а.з. відображення на цілі числа. Це мало сенс у першій ітерації виклику, але оскільки редагування для ясності та стислості (була попередня історія, яку я видалив), листи більше не мають значення. Я відредагую якнайшвидше
Darren H

1
Я віддаю перевагу аз, простір, період, особисто.
isaacg

Відповіді:


10

JavaScript (ES6), 330 326 ... 315 309 байт

Макет ASCII будує рекурсивно, починаючи з нижнього поверху і застосовуючи кілька регулярних виразів між кожним етапом:

(a,l,R=(E,b)=>E.split`:`.map((e,i)=>l=(l||a).replace(RegExp(e,'g'),b?b.split`:`[i]:n=>(x=(n.charCodeAt()-65)%32)<0?x+1?'/y/y':n+n:x%3+'_'.repeat((x/3<<1)+1)+0)))=>(L=l)?(R('/y:_:/xy:1:2:/xx(x+)y:0(x+)0:3','  :x: _ :3:1: 2$10 :/$1y:0'),L==l?(l=a.join`
`,R('\\d:x:y','|: :\\'),l):f([l].concat(a),l)):f(R('.'),l)

Як це працює

1) Нижня підлога

Почнемо з перекладу вхідного рядка в нижній поверх, наприклад:

"ab cd.df.hcab"  -->  "0_01_0  2_00___0/y/y0___02___0/y/y1_____02_00_01_0"

де:

  • y - коротший псевдонім для зворотної косої риски (що вимагає втечі)
  • Цифра ( 0, 1або 2) безпосередньо перед послідовністю _є лівою стіною будівлі. Він представляє кількість стін, які повинні бути розміщені над ним перед наступним «розширювальним шаром».
  • Цифра після послідовності символів _є правою стіною будівлі і завжди встановлюється 0.

2) Регулярні вирази, застосовані між кожним етапом

Рекурсивний процес полягає у застосуванні 9 замін на попередньому поверсі, використовуючи такі регулярні вирази:

  1. /\/y/g=> " "(видалити завали)
  2. /_/g=> "x"(замініть фундамент або верх будівлі суцільним блоком)
  3. /\/xy/g=> " _ "(замініть останній розширювальний шар верхом будівлі)
  4. /1/g=> "3"(тимчасово замінити 1на 3- див. останній крок)
  5. /2/g=> "1"(замінити 2на 1)
  6. /\/xx(x+)y/g=> " 2$10 "(замініть розширювальний шар на нову, більш вузьку стінку)
  7. /0(x+)0/g=> "/$1y"(замініть верхню частину стіни розширювальним шаром)
  8. /3/g=> "0"(замінити 3на 0)

Наприклад, ось послідовні перетворення 2___0(нижній поверх, породжений a 'f'):

"2___0" > "1xxx0" > "0xxx0" > "/xxxy" > " 2x0 " > " 1x0 " > " 0x0 " > " /xy " > "  _  "

                                                                                   _   
                                                                        /xy       /xy  
                                                              0x0       0x0       0x0  
                                                    1x0       1x0       1x0       1x0  
                                          2x0       2x0       2x0       2x0       2x0  
                               /xxxy     /xxxy     /xxxy     /xxxy     /xxxy     /xxxy 
                     0xxx0     0xxx0     0xxx0     0xxx0     0xxx0     0xxx0     0xxx0 
           1xxx0     1xxx0     1xxx0     1xxx0     1xxx0     1xxx0     1xxx0     1xxx0 
 2___0     2___0     2___0     2___0     2___0     2___0     2___0     2___0     2___0 

Примітка : Верх будівлі замінюється на a x. Це не показано на наведеній діаграмі.

3) Регулярні вирази, застосовані до кінцевого результату

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

Тепер нам потрібно все очистити за допомогою ще кількох регулярних виразів:

  1. /\d/g=> "|"(замініть цифри на труби)
  2. /x/g=> " "(замініть суцільні блоки пробілами)
  3. /y/g=> "\"(замінити yкосою рисою)

Наприклад:

  _            _  
 /xy          / \ 
 0x0          | | 
 1x0          | | 
 2x0   -->    | | 
/xxxy        /   \
0xxx0        |   |
1xxx0        |   |
2___0        |___|

Демо

let f =

(a,l,R=(E,b)=>E.split`:`.map((e,i)=>l=(l||a).replace(RegExp(e,'g'),b?b.split`:`[i]:n=>(x=(n.charCodeAt()-65)%32)<0?x+1?'/y/y':n+n:x%3+'_'.repeat((x/3<<1)+1)+0)))=>(L=l)?(R('/y:_:/xy:1:2:/xx(x+)y:0(x+)0:3','  :x: _ :3:1: 2$10 :/$1y:0'),L==l?(l=a.join`
`,R('\\d:x:y','|: :\\'),l):f([l].concat(a),l)):f(R('.'),l)

console.log(f('ab cd.df.hcab'));

Автори:
4 байти збережено завдяки Хеді,
8 байт збережено завдяки не тому, що Чарльз


Кожен, хто хоче взяти введення як ціле число, вітаю, але я б припустив, що такий запис повинен бути неконкурентоспроможним
mbomb007,

@ mbomb007 - це виправлено. Мої поточні оптимізації не компенсують вартості сумнозвісних .charCodeAt().
Арнольд

Вам не потрібно new вnew RegExp(e,'g')
Хеді

Мені дуже подобається такий підхід. Деякі ідеї, які можуть допомогти: 1. використовуйте таку табличку, yяка не потребує втечі для нахилу вперед. 2. якщо ви використовуєте _для першого поверху, ви можете відрізнити вершину з регулярним виразом: /_ /.
Не те, що Чарльз

1
@NotthatCharles - я насправді ніколи не помічав правила "подвійного простору". ;) Це виправлено.
Арнольд

7

PHP, 386 376 367 364 362 358 356 байт

перший підхід; може все ще бути гольфуючим.

foreach(str_split($argv[1])as$c)for($n=28,$w='.'!=$c?1+2*ceil(1/3*$n=31&ord($c)):4,$p=$y=0;$y<36;){$s=str_pad("",$w,$y||!$n?" ":_);if($n>26&&!$y){$s="/\\/\\";$n=-1;}elseif($n-->0){$s[$p]=$s[$w-$p-1]="|";if($n%3<1){$o[$y++].=$s;$s=str_pad("",$w);$s[$p]="/";$s[$w-++$p]="\\";}}$o[$y++].=$s;if(!$n)$o[$y++].=str_pad(_,$w," ",2);}for($y=36;$y--;)echo"$o[$y]
";

PHP, 366 362 361 360 357 байт

аналогічний підхід з підфункцією:

function a($p,$r){global$o,$w,$y;$o[$y++].=str_pad(str_pad($r[0],2*$p,$r[1]).$r[2],$w," ",2);}foreach(str_split($argv[1])as$i=>$c)for($n=28,$w='.'!=$c?1+2*$p=ceil(1/3*$n=31&ord($c)):$p=4,$y=0;$y<36;)if($n>26&&!$y)$o[$n=$y++].="/\\/\\";elseif($n-->0){a($p,$y?"| |":"|_|");if($n%3<1)a($p--,"/ \\");if(!$n)a(1," _");}else a(0,"");for($y=36;$y--;)echo"$o[$y]
";

розбивка для другого підходу

function a($p,$r)
{
    global$o,$w,$y;
    $o[$y++].=                  // 3. add result to current line, increase line counter
        str_pad(                // 2. pad ...
        str_pad($r[0],2*$p,$r[1]).$r[2]     // 1. A + inner width(=2*$p-1) times B + C
        ,$w," ",2);             // ... to $w with blanks on both sides # 2==STR_PAD_BOTH
}

foreach(str_split($argv[1])as$i=>$c)
    for(
    $n=28,
    $w='.'!=$c                          // $w=total width
        ?1+2*$p=ceil(1/3*$n=31&ord($c)) // $n=storey count, $p=(inner width+1)/2
        :$p=4                           // $n=28, $p <= $w=4 for rubble
    ,
    $y=0;$y<36;)                        // $y=line counter
        if($n>26&&!$y)
            $o[$n=$y++].="/\\/\\";      // bottom line=rubble, $n=0
        elseif($n-->0)
        {
            a($p,$y?"| |":"|_|");       // add storey
            if($n%3<1)a($p--,"/ \\");   // add widening layer/roof
            if(!$n)a(1," _");           // add roof top
        }
        else
            a(0,"");                    // idk why str_pad doesn´t yield a warning here

for($y=36;$y--;)if($s=rtrim($o[$y]))echo"$s\n"; // output

+16 байт, якщо провідні нові рядки не дозволені:
Замініть echo"$o[$y]\n;на if($s=rtrim($o[$y]))echo"$s\n";.

-3 байти для будь-якого із ;<=>?[\]^_{|}~завалів: замініть 1) ($n=31&ord($c))на $n, 2) $n=28,$w='.'!=$cна ($n=31&ord($c))<27і 3) 4на ($n=28)/7.

Інший -8 для >, ^або , ~як щебінь: Скасувати 3)


1
if(!$n){$o[$y++].=str_pad(_,$w," ",2);}-2 байти для дужок
Йорг Гюльсерманн

і вихід може бути зроблена 3 байт коротше: for($y=36;$y--;)echo"$o[$y]\n";; але у мене є новий підхід, який зберігає інші 2 байти.
Тіт

1
php.net/manual/en/functions.anonymous.php для другого підходу `функція a ($ p, $ r) використовує ($ o, $ w, $ y) 'замість глобальної
Йорг Гюльсерманн,

@ JörgHülsermann: useпрацює лише для анонімних функцій. це дозволить заощадити 2 байти; але мені доведеться зберігати цю функцію в змінній, $a=а не давати їй ім’я (+3 байти) і додавати а $до кожного з чотирьох викликів.
Тит

4

Pyth, 93 79 байт

K"/\\"j_.tsm?hJxGdC_m.[hyNk\ +\_mj*hy/k4?nkJ\ \_?%k4"||"Kh=+J=Nh/J3[F*2|@d;Krz0

Спробуйте в Інтернеті. Тестовий набір.

Пояснення

Я приховав це за замовчуванням, оскільки це занадто довго.


4

Perl, 147 146 байт

Включає +1 для -p

Виконати з введенням на STDIN, наприклад

citysky.pl <<< " abcdefgxyz."

citysky.pl:

#!/usr/bin/perl -p
s%.%@{[map chr~-ord(lc$&)*4/3-4*(abs||-9),-9..9]}%g;y/M\xa248
A|-\xc6\0-\xff/MA||
A}-\xc6A/d,$a=(lc$a).$_ for($_)x36;*_=a;s/\x9f.*?\K\x9f/\xa3/g;y%A\xc6\x9f-\xa3\x0b-\xff%__/|||\\ %

Працює, як показано, але замініть \xhhвтечі їх буквальним значенням, щоб отримати заявлений бал. Це можна зробити за допомогою цього командного рядка:

perl -0pi -e 's/\\x(..)/chr hex $1/eg;s/\n$//' citysky.pl

Я ще не вивчав жодних інших підходів, тому це може бути дуже зрозумілим ...


2

Haskell, 289 байт

c?l=c++l++c
c%s=("|"?(drop 2(r s)>>c)):s
g 46=["/\\"?""]
g 32=["  "]
g x="_"%h(mod x 32)
h 1=["/ \\"," _ "]
h x=(" "%h(x-1))!x
v!x|mod x 3/=1=v|z<-'/':r v++"\\"=z:map(" "?)v
r v=v!!0>>" "
f t|l<-map(g.fromEnum)t,m<-maximum(map length l)-1=unlines[l>>= \x->(x++cycle[r x])!!i|i<-[m,m-1..0]]

2

Рубі, 245

->s{a=['']*36
w=' '
s.chars{|c|a[u=0]+=c<?!?w*2:c<?/?"/\\"*2:(h=c.upcase.ord-64
1.upto(1+h+=(h-1)/3){|t|u=[u,l=1+2*((f=h-t)/4)].max
a[t]+=w*(a[0].size-a[t].size)+(f<-1?w:f<0??_:(f%4<1?[?/,?\\]:[?|]*2)*(w*l)).center(u+2)}
"|#{?_*u}|")}
a.reverse}

Ви дозволяєте стільки зайвих нових рядків, скільки вам захочеться, тому я беру на себе сміливість з цим. Крім цього, процес такий:

  1. Ініціалізувати вихідний масив a.
  2. Для кожної картки:
    1. якщо це '', додати  доa[0]
    2. якщо це ".", додати /\/\доa[0]
    3. інакше:
      1. обчислити висоту ( c.upcase.ord + (c.upcase.ord-1)/3)
      2. для кожного рядка в a:
        1. прокладіть рядок пробілом. a[t]+=w*(a[0].size-a[t].size)
        2. якщо ми один вище h, по центру_
        3. інакше, якщо ми вище висоти, по центру 
        4. інакше, якщо ми нижче висоти, центру | |або / \належної ширини ( 1+2*((h-t)/4), залежно від тогоh-t%4==0
        5. додати "|___|"правильну ширину доa[0]
  3. повернення a.reverse

Б'юсь об заклад, що я можу отримати її менше, якщо буду працювати з математикою, щоб цього уникати reverse


2

PHP, 297 байт

foreach(str_split($argv[1])as$c)for($j=0,$h=ord($c)-64,$g=$h+$f=ceil($h/3),$w=$v=$h<0?$h<-18?2:4:2*$f+1;$j<36;$j++,$g--,$v-=$h>0&&$v>1?($g%4||!$j)?0*$n="|$s|":2+0*$n="/$s\\":$v+0*$n=['','_','',0,'/\/\\'][$v],$o[$j].=str_pad($n,$w,' ',2))$s=str_repeat($j?' ':'_',$v-2);krsort($o);echo join($o,'
');

Більш прочитана версія:

foreach (str_split($argv[1]) as $character) {
    for (
        $line = 0,
        $buildingHeight = ord($character) - 64,
        $floorsLeft = $buildingHeight + $supportFloors = ceil($buildingHeight / 3),
        $buildingWidth = $widthOnThisFloor = $buildingHeight < 0
            ? $buildingHeight < -18
                ? 2
                : 4
            : 2 * $supportFloors + 1;

        $line < 36;

        // The body of the for-loop is executed between these statements

        $line++,
        $floorsLeft--,
        $widthOnThisFloor -= $buildingHeight > 0 && $widthOnThisFloor > 1
            ? ($floorsLeft % 4 || !$line)
                ? 0 * $floorString = "|$middleSpacing|"
                : 2 + 0 * $floorString = "/$middleSpacing\\"
            : $widthOnThisFloor + 0 * $floorString = ['', '_', '', 0, '/\/\\'][$widthOnThisFloor],
        $outputArray[$line] .= str_pad($floorString, $buildingWidth, ' ', 2)
    ) {
        $middleSpacing = str_repeat($line ? ' ' : '_', $widthOnThisFloor - 2);
    }
}
krsort($outputArray);
echo join($outputArray, '
');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.