Mots -> Horizon de la ville

40

Le défi

Votre programme ou votre fonction acceptera une seule chaîne d'entrée de STDIN ou un paramètre de fonction. Vous pouvez supposer que l'entrée ne contiendra que des caractères alphabétiques (a-zA-Z), des espaces et des points. La saisie est insensible à la casse, vous devez donc traiter "a" exactement de la même façon que vous traiteriez "A".

Pour chaque caractère de la chaîne, vous allez générer une représentation d'un bâtiment conformément à la spécification suivante.

Chaque bâtiment doit avoir un toit, désigné par un trait de soulignement sur la ligne supérieure, puis par une barre oblique, une espace, une barre oblique inverse sur la deuxième ligne.

 _
/ \

Vous aurez alors un nombre d'étages, correspondant au numéro de lettre (a = 1, b = 2, c = 3, etc.) qui sont représentés par un mur (|) de chaque côté et un espace au milieu. Le plancher inférieur (et seulement le plancher inférieur) devrait avoir une fondation, qui est un soulignement entre les murs. Comme ça...

|_|

Ainsi, par exemple, 'b' ressemblerait à ceci

 _
/ \
| |
|_|

Nous savons maintenant que les bâtiments très hauts et étroits ne peuvent pas subsister et doivent s'élargir à la base, de sorte qu'aucun bâtiment ne peut supporter plus de trois étages sans un soutien supplémentaire. Donc, tous les trois niveaux (pas moins), vous devriez ajouter un "calque élargissant". La couche d’élargissement consiste en une barre oblique et une barre oblique inverse directement au-dessus des murs de la section située en dessous, la section ci-dessous devant être plus large de deux espaces que la section ci-dessus. La couche supplémentaire ne compte pas pour la hauteur du bâtiment.

Les bâtiments ne doivent pas se chevaucher mais ne doivent pas comporter d'espaces inutiles, et le sol étant toujours plat, tous les bâtiments doivent avoir leur base au même niveau.

Par exemple, "abcdefga" ressemblera à ceci.

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

Les espaces dans l'entrée de chaîne doivent être représentés par un double espace.

Les arrêts complets dans l'entrée de chaîne doivent être représentés par des gravats comme celui-ci.

/\/\

Autres exemples

Entrée = Hello world.

Sortie =

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

Entrée = lorem ipsum

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

Entrée = a.a.a.x.x.x.a.a.a

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

Règles

  • Bien sûr, c'est du golf de code, le score le plus bas en octets gagne
  • Les règles standard relatives aux échappatoires s'appliquent
  • N'importe quel nombre de lignes vides supplémentaires avant ou après la sortie est autorisé
  • Vous pouvez choisir d'afficher le résultat entier dans une chaîne ou d'offrir la sortie sous forme de tableau dans lequel chaque élément représente une ligne de sortie, ou de l'envoyer à STDOUT.

Remarque

Ceci est mon premier message sur PPCG, alors je vous en prie, allez-y doucement. Il a traversé le bac à sable. Des points négatifs ou des améliorations possibles s'il vous plaît poster comme un commentaire et je ferai ce que je peux

Darren H
la source
7
La conversion [a,z]et [A,Z]en [1,26]semble être une exigence inutile. Il serait bien mieux d’utiliser simplement une liste de nombres entiers comme entrée (ayant 0été l’entrée pour les décombres). De plus, publier votre défi après seulement 21 heures de jeu dans le bac à sable , sans attendre d'obtenir des votes ou des commentaires de plus d'un utilisateur, n'est pas pris en compte, car il a été "passé par le bac à sable". Il est recommandé de laisser les défis dans le bac à sable pendant 48 à 72 heures au minimum, afin de donner aux gens suffisamment de temps pour les examiner.
Mego
2
Cela me rappelle ce . Belle premier défi, mais je vous suggère de songer à modifier [a,z], les [1.26]parties ont mentionné le Mego. Le faire en option est souvent le meilleur (à moins que ce soit un élément clé du défi (ce n'est pas ici).
Stewie Griffin
2
Je dirai que c’est un très beau premier défi. Bienvenue sur le site!
DJMcMayhem
1
Je peux comprendre le point concernant le mappage az en entiers. Cela avait du sens lors de la première itération du défi, mais depuis l'édition pour la clarté et la brièveté (il y a une histoire que j'ai supprimée), les lettres ne sont plus pertinentes. Je vais éditer comme il convient dès que possible
Darren H
1
Je préfère z, espace, période, personnellement.
isaacg

Réponses:

10

JavaScript (ES6), 330 326 ... 315 309 octets

Construit l'art ASCII de manière récursive, en commençant par l'étage inférieur et en appliquant plusieurs expressions régulières entre chaque étape:

(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)

Comment ça marche

1) rez-de-chaussée

Nous commençons par traduire la chaîne d'entrée en un étage inférieur tel que:

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

où:

  • y est un alias plus court pour la barre oblique inverse (qui nécessite une évasion)
  • Le chiffre ( 0, 1ou 2) juste avant une séquence de _est le mur de gauche du bâtiment. Il représente le nombre de murs qui doivent être placés au-dessus avant la prochaine "couche d'élargissement".
  • Le chiffre après une séquence de _correspond au mur de droite du bâtiment et est toujours défini sur 0.

2) Expressions régulières appliquées entre chaque étape

Le processus récursif consiste à appliquer 9 remplacements à l'étage précédent, en utilisant les expressions régulières suivantes:

  1. /\/y/g=> " "(enlever les décombres)
  2. /_/g=> "x"(remplacez la fondation ou le sommet du bâtiment par un bloc solide)
  3. /\/xy/g=> " _ "(remplace la dernière couche d'élargissement par le haut du bâtiment)
  4. /1/g=> "3"(remplacer temporairement 1par 3- voir dernière étape)
  5. /2/g=> "1"(remplacer 2par 1)
  6. /\/xx(x+)y/g=> " 2$10 "(remplace une couche d'élargissement par un nouveau mur plus étroit)
  7. /0(x+)0/g=> "/$1y"(remplacez le haut du mur par une couche d'élargissement)
  8. /3/g=> "0"(remplacer 3par 0)

Par exemple, voici les transformations successives de 2___0(étage inférieur généré par 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 

NB : Le sommet du bâtiment est alors remplacé par un x. Ceci n'est pas montré dans le diagramme ci-dessus.

3) Expressions régulières appliquées au résultat final

La récursivité s'arrête lorsqu'il n'y a plus rien à remplacer, ce qui signifie que nous sommes au-delà du sommet du bâtiment le plus élevé.

Nous devons maintenant tout nettoyer avec encore quelques expressions régulières:

  1. /\d/g=> "|"(remplace les chiffres par des tuyaux)
  2. /x/g=> " "(remplace les blocs pleins par des espaces)
  3. /y/g=> "\"(remplacer ypar des barres obliques inverses)

Par exemple:

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

Démo

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'));

Contributeurs:
4 octets sauvés grâce à Hedi
8 octets sauvés grâce à Not that Charles

Arnauld
la source
Toute personne souhaitant prendre une entrée sous forme d'entier est la bienvenue, mais je suggérerais qu'une telle entrée ne soit pas en concurrence
mbomb007 le
@ mbomb007 - Ceci est corrigé. Mes optimisations actuelles ne compensent cependant pas le coût de l'infâme .charCodeAt().
Arnauld
Vous n'avez pas besoin new denew RegExp(e,'g')
Hedi
J'aime beaucoup cette approche. Quelques idées qui peuvent aider: 1. utiliser un caractère comme ycelui-ci ne nécessite pas d'échapper à votre barre oblique. 2. Si vous utilisez _pour le rez - de - chaussée, vous pouvez toujours différencier le haut avec l'expression rationnelle: /_ /.
Pas que Charles
1
@NotthatCharles - En fait, je n'ai jamais remarqué la règle du "double espace". ;) Ceci est corrigé.
Arnauld
7

PHP, 386 376 367 364 362 358 356 octets

première approche; peut encore être golfable.

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 octets

approche similaire avec une sous-fonction:

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

ventilation pour la seconde approche

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 octets si les nouvelles lignes principales ne sont pas autorisées:
remplacez echo"$o[$y]\n;par if($s=rtrim($o[$y]))echo"$s\n";.

-3 octets pour les ;<=>?[\]^_{|}~gravats: Remplacer 1) ($n=31&ord($c))par $n, 2) $n=28,$w='.'!=$cpar ($n=31&ord($c))<27et 3) 4par ($n=28)/7.

Un autre -8 pour >, ^ou en ~tant que décombres: Annuler 3)

Titus
la source
1
if(!$n){$o[$y++].=str_pad(_,$w," ",2);}-2 octets pour les crochets
Jörg Hülsermann le
et la sortie peut être fait 3 octets plus courte: for($y=36;$y--;)echo"$o[$y]\n";; mais j'ai une nouvelle approche qui sauve un autre 2 octets.
Titus
1
php.net/manual/fr/functions.anonymous.php pour la deuxième approche `fonction a ($ p, $ r) utiliser ($ o, $ w, $ y) 'au lieu de global
Jörg Hülsermann le
@ JörgHülsermann: usene fonctionne que pour les fonctions anonymes. cela économiserait 2 octets; mais je devrais stocker cette fonction dans une variable $a=au lieu de lui donner un nom (+3 octets) et d’ajouter un $à chacun des quatre appels.
Titus
4

Pyth, 93 79 octets

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

Essayez-le en ligne. Suite de tests.

Explication

Je l'ai caché par défaut car c'est beaucoup trop long.

PurkkaKoodari
la source
4

Perl, 147 146 octets

Inclut +1 pour -p

Exécuter avec une entrée sur STDIN, par exemple

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%__/|||\\ %

Fonctionne comme indiqué, mais remplacez les \xhhéchappés par leur valeur littérale pour obtenir le score revendiqué. Vous pouvez le faire en utilisant cette ligne de commande:

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

Je n'ai pas vraiment exploré d'autres approches, donc ça peut être très battable ...

Ton Hospel
la source
2

Haskell, 289 octets

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]]
Damien
la source
2

Ruby, 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}

Vous autorisez autant de nouvelles lignes que vous le souhaitez, je prends donc cette liberté. En dehors de cela, le processus est le suivant:

  1. Initialiser un tableau de sortie a.
  2. Pour chaque personnage:
    1. si c'est '', ajoutez  àa[0]
    2. si c'est '.', ajoutez /\/\àa[0]
    3. autrement:
      1. calculer la hauteur ( c.upcase.ord + (c.upcase.ord-1)/3)
      2. pour chaque rangée dans a:
        1. remplissez la rangée avec des espaces. a[t]+=w*(a[0].size-a[t].size)
        2. si nous sommes au h- dessus , centrez un_
        3. sinon si nous sommes au-dessus de la hauteur, centrez un 
        4. sinon si nous sommes en dessous de la hauteur, du centre | |ou / \de la largeur appropriée ( 1+2*((h-t)/4), selon sih-t%4==0
        5. ajouter "|___|"de la bonne largeur àa[0]
  3. revenir a.reverse

Je parie que je peux le réduire si je fais le calcul pour éviter reverse

Pas que Charles
la source
2

PHP, 297 octets

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,'
');

Une version plus lisible:

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, '
');
chocochaos
la source