# ASCII Landscapes

Objective: Write a program that generates beautiful (?) ASCII-art landscapes and skylines!

Your program has just one input: a string composed of any combination/repetition of the chars 0123456789abc.

For each input character, output a vertical line composed as follows:

         .
..
...
oooo
ooooo
OOOOOO
OOOOOOO
XXXXXXXX
XXXXXXXXX
XXXXXXXXXX

0123456789


Letters abc instead are followed by one number n, and draw the vertical line n with respectively 1,2 or 3 holes (spaces) at the bottom.

Examples

The Chrysler Building

Input: 2479742

   .
.
...
ooo
ooo
OOOOO
OOOOO
XXXXXXX
XXXXXXX
XXXXXXX


The Taj Mahal

Input: 0804023324554233204080

 .                  .
.                  .
o                  o
o        oo        o
O O     OOOO     O O
O O  OO OOOO OO  O O
X X XXXXXXXXXXXX X X
X X XXXXXXXXXXXX X X
XXXXXXXXXXXXXXXXXXXXXX


The Eiffel Tower

Input: 011a2b3b5c9c9b5b3a2110

      ..
..
..
oo
oooo
OOOO
OOOOOO
XXX  XXX
XXX      XXX
XXX        XXX


You can assume input is not empty and that it's well-formed.
Any language is accepted, from A+ to Z++.

This is code-golf: the shortest source code wins.
If anything in the rules is not clear, feel free to ask below in the comments.

Have fun, and capture hundred meters high structures in a few bytes!

P.S.: no, you can't download/access data from the Internet, use your file name as data and all that stuff. Be fair, and use only your code-golf skills.

• Seems tall 9 to me...:-? Jan 21, 2014 at 6:52
• Oh, I see it: the top is defined as "c9", that means: draw a vertical line with height 9 and shave off the 3 bottom chars. That's why it seems tall 7 to you. Read the rules again and tell me if it's ok. Jan 21, 2014 at 7:04
• ok, i misread your specification of the offset. Jan 21, 2014 at 8:21

## GolfScript, 69

'XXXOOoo...':s\{.96>{96-.' '*\@>+}{47-<' '10*+10<s\}if}%10/zip-1%n*\;


Not far off the APL solution.

Test online

Fun challenge!

9.downto(0){|h|puts$*[0].gsub(/(\D?)(.)/){'XXXOOoo... '[h<$1.hex-9||$2.hex<h ?-1:h]}}  Takes input on the commandline, eg: ruby landscapes.rb 011a2b3b5c9c9b5b3a2110  Will print out:  .. .. .. oo oooo OOOO OOOOOO XXX XXX XXX XXX XXX XXX  ## Python 2.7 - 186 Probably can be shorter... x=[] l=iter(raw_input()) a="XXX00oo..." for i in l: try:i=int(i);o=0 except:o=" abc".index(i);i=int(next(l)) x.append(" "*o+a[o:i+1]+" "*(9-i)) for i in zip(*x)[::-1]:print''.join(i)  Sample run: 08040233245542332040800000247974200000011a2b3b5c9c9b5b3a2110 . .. . . . .. . . ... .. o o ooo oo o oo o ooo oooo 0 0 0000 0 0 00000 0000 0 0 00 0000 00 0 0 00000 000000 X X XXXXXXXXXXXX X X XXXXXXX XXX XXX X X XXXXXXXXXXXX X X XXXXXXX XXX XXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX  ## Sydney Harbour Bridge a1a13443a1a2a3a4a5a6a6a7a7a8a8a8a8a9a9a9a9a9a9a8a8a8a8a7a7a6a6a5a4a4a3a2a13443a1a1 ...... .............. .................. oooooooooooooooooooooo oooooooooooooooooooooooo 00 000000000000000000000000000 00 0000 00000000000000000000000000000 0000 XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXX  ## Golden gate bridge / Cisco logo a2a0a0a4a0a06a0a0a4a0a0a2a0a0a4a0a06a0a0a4a0a0a2 o o o o 0 0 0 0 0 0 0 0 0 0 0 0 X X X X X X X X X X X X X X X X X X X X  Great question by the way! • Great monuments! :) Jan 22, 2014 at 17:59 # C64 BASIC, 276 PETSCII chars My own solution, golfed down to 276 chars and 10 lines of BASIC V2.0! 0inputa$:dIc$(10):fOi=0to9:rE c$(i):nE:fOr=0to9
1z=1
2c=aS(mI(a$,z,z+1)) 3ifc>57tHgO8 4ifc>=57-r tH?c$(9-r);:gO6
5?" ";
6z=z+1:ifz<=len(a$)gO2 7?:nE:eN 8z=z+1:w=aS(mI(a$,z,z+1)):ifw>=57-r aNc<=73-r tH?c$(9-r);:gO6 9?" ";:gO6:dA"x","x","x","o","o","W","W",".",".","."  (copy and paste in an emulator to see the result). And finally, my favourite monument, the Brooklyn Bridge :) ## C, 130 126 chars Kinda long compared to the competition, but I blame the language... char*p,b[99];r=10,q;main(o){for(gets(&b);r--;puts("")) for(p=b;q=*p++;)o=q<60?putchar("XXXOOoo... "[o<r&r<q-47?r:10]),-1:q-97;}  I don't know about favourite building, but one of the more recognizable ones around here is Globen, so here is a poor rendition of it. % ./a.out <<<24556667777776665542 ...... oooooooooooo oooooooooooooooo OOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOO XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX  • You can chop off a character by switching the declaration order of char b[99],*p; so it reads char*p,b[99];. Also it may be shorter to use puts for printing the newline. Jan 23, 2014 at 21:10 • @C0deH4cker nice, thanks! That saves me four chars. Jan 23, 2014 at 21:52 • @friol oh, I didn't mean it like that at all, it's just that I dunno what I'd consider my favourite building. :P Jan 24, 2014 at 19:01 # APL, 59 bytes SBCS {⊖⍉↑(-N)↑¨(L/⍨1,2≤/L←A⍸⍵)↓¨(N←⎕D⍳⍵~A←'abc')↑¨⊂'XXXOOoo...'}  Try it on online! Shorter than the other APL answers so far! I think it can probably be further golfed. Will add explanation soon! Thanks to dzaima & hyper-neutrino for their advice in the The APL Orchard! • I have the feeling this can be further golfed. Any ideas? Jun 26, 2021 at 5:16 • can change 1+⍎¨⎕D⍳ Jun 26, 2021 at 5:36 • @Razetime Wow, that's really clever. Thanks!! Jun 26, 2021 at 5:41 • ↓¨↑∘'XXXOOoo...'¨N←⎕D⍳⍵~A←'abc'} – Adám Jun 27, 2021 at 5:10 ## APL (69 66) ' XXXOOoo...'[1+⌽⍉⌽↑{z×(z<' abc'⍳⍵)<(1+⍎⍺)≥z←⍳10}/↑2↑¨I⊂⍨⎕D∊⍨I←⌽⍞]  Examples:  ' XXXOOoo...'[1+⌽⍉⌽↑{z×(z<' abc'⍳⍵)<(1+⍎⍺)≥z←⍳10}/↑2↑¨I⊂⍨⎕D∊⍨I←⌽⍞] 0804023324554233204080 . . . . o o o oo o O O OOOO O O O O OO OOOO OO O O X X XXXXXXXXXXXX X X X X XXXXXXXXXXXX X X XXXXXXXXXXXXXXXXXXXXXX ' XXXOOoo...'[1+⌽⍉⌽↑{z×(z<' abc'⍳⍵)<(1+⍎⍺)≥z←⍳10}/↑2↑¨I⊂⍨⎕D∊⍨I←⌽⍞] 011a2b3b5c9c9b5b3a2110 .. .. .. oo oooo OOOO OOOOOO XXX XXX XXX XXX XXX XXX  • I don't know APL very well, but are you sure you need the space at the beginning of the ' XXXOOoo...' string? Jan 21, 2014 at 7:05 • @friol: yes, it's used to fill up the "empty" space Jan 21, 2014 at 10:12 • Outgolfed! Jun 26, 2021 at 5:10 # PowerShell, 127 bytes $r=,''*10
$args|% t*y|%{if($_-in97..99){$b=$_-96}else{,' '*$b+'XXXOOoo...'[$b.."$_"]+,' '*(9-"$_")|%{$r[--$i]+=$_}$b=$i=0}}$r


Try it online!

# Canvas, 35 33 bytes

±｛⌐╷≡？┤╵“Fc|C！‟ｍ］ｃ96－ ×１１╋╋｝｝）⤢⇵


Try it here!

# PHP, 131 114 bytes

for($b=10;$b--;print"
")foreach(str_split($argn)as$a)$c=strpos(' abc',$a)?:!print$a<$b|$b<$c?' ':'XXXOOoo...'[$b];  Try it online! $ echo 2479742|php -nF land.php
.
.
...
ooo
ooo
OOOOO
OOOOO
XXXXXXX
XXXXXXX
XXXXXXX

$echo 011a2b3b5c9c9b5b3a2110|php -nF land.php .. .. .. oo oooo OOOO OOOOOO XXX XXX XXX XXX XXX XXX$ echo a2a0a0a4a0a06a0a0a4a0a0a2a0a0a4a0a06a0a0a4a0a0a2|php -nF land.php

o           o
o           o
O  O  O     O  O  O
O  O  O     O  O  O
X  X  X  X  X  X  X  X  X
X  X  X  X  X  X  X  X  X
X           X


# Jelly, 33 bytes

~kµṪV‘R×ØaiⱮ0xƲ)Ṗz0Ṛị“XXXOOoo...


Try it online!

Full program returning a list of lines. If that isn't acceptable, +2 bytes.

Note the trailing space. Included my favourite:

.                 .
..               ..
...             ...
oooo           oooo
ooooo         ooooo
OOOOOO       OOOOOO
OOOOOOO     OOOOOOO
XXXXXXXX   XXXXXXXX
XXXXXXXXX XXXXXXXXX
XXXXXXXXXXXXXXXXXXX


## How it works

~kµṪV‘R×ØaiⱮ0xƲ)Ṗz0Ṛị“XXXOOoo...  - Main link. Takes a string on the left
~                                 - Bitwise NOT. This maps digits d to ~d and non-digits to 0
k                                - Partition the string after falsey values
This groups the string as we want, with a trailing []
µ            )                  - Over each element, either [L, x] or [x]:
Ṫ                              -   Extract x, modifying the element
V                             -   Evaluate as a digit
‘                            -   Increment
R                           -   Create a range
ØaiⱮ                      -     Index in the alphabet
0x                    -     Get that many zeros
If the element was [x], this yields []
If the element was [L, x], this returns 1, 2 or 3 zeros, depending on L
×                          -   Multiple elementwise, zeroing the first 1,2 or 3 elements in the range if L is in the element
Ṗ                 - Remove the trailing [] element
z0               - Transpose, padding with zeros
Ṛ              - Reverse
ị“XXXOOoo...  - Index into "XXXOOoo... "


# Perl 6, 93 bytes

{for 9...0 ->\n {say .subst(/(\D)?(.)/,{'XXXOOoo... '.comb[$1>=n>=ord($0//0)-96??n!!10]}):g}}


A block that takes in the string and prints to stdout.

Try it online!

# 05AB1E (legacy), 34 bytes

Rvy.ïi"XXXOOoo..."y>£ëðAykÝǝ])ζRí»


Uses the legacy version of 05AB1E to save 2 bytes, since ζ also works on strings instead of just lists of characters.

Try it online.

Explanation:

R                  # Reverse the (implicit) input-string
v                 # Loop y over each character:
y.ïi             #  If y is a digit:
"XXXOOoo..." #   Push string "XXXOOoo..."
y>£        #   And only leave the first y+1 characters as substring
ë             #  Else (y is a letter):
Ayk         #   Get the index of y in the lowercase alphabet
Ý        #   Create a list in the range [0, alphabet-index]
ð    ǝ       #   Replace in the string at the top of the stack the characters at
#   those indices with a space
]                 # Close the if-else statement and loop
)                # Wrap all strings on the stack into a list
ζ               # Zip/transpose; swapping rows/columns
Rí             # Reverse this list, as well as each individual line
»            # And join the strings by newlines
# (after which the result is output implicitly)


As for my favorite 'building', let's go with this tree. ;)

b2b3b4b5b6b7898b7b6b5b4b3b2

.
...
.....
ooooooo
ooooooooo
OOOOOOOOOOO
OOOOOOOOOOOOO
XXXXXXXXXXXXXXX
XXX
XXX



# Japt-R, 36 bytes

óÈ¦nÃ£ÒXÌ î"XXXOOoo..."hSpXÎnD)s9Ãz3


Try it

óÈ¦nÃ£ÒXÌ î"..."hSpXÎnD)s9Ãz3     :Implicit input of string
ó                                 :Partition at
È                                :Characters that return true when passed through the following function
¦                               :  Test for inequality with
n                              :  Convert to number
Ã                             :End function
£                            :Map each X
Ò                           :  Bitwise increment
XÌ                         :  Last character of X
î                       :  Slice the following to that length
"..."                  :    Literal string
h                 :    Replace as many characters as necessary at the start of that string with
S                :      Space
p               :      Repeat
XÎ             :        First character of X
n            :        Convert from base
D           :        14
)          :      End repeat
s9        :      Slice off the first 9 characters
Ã       :End map
z3     :Rotate clockwise by 90 degrees 3 times
:Implicit output, joined by newlines


# Pip-l, 45 bytes

Z:R{sXtRAb:Ab%4\,c"XXXOOoo..."@b}MRaC KXL.CXD


Takes input as a command-line argument. Try it here! Or, here's a 46-byte equivalent in Pip Classic: Try it online!

### Explanation

High-level:

  R{sXtRAb:Ab%4\,c"XXXOOoo..."@b}              Apply this function
MR            to each match
C KXL.CXD  of this regex
a           in the input string
Z:                                             Transpose the result
Autoprint as lines (-l flag)


The regex:

   XL       Lowercase letter            [a-z]
K         Apply Kleene star           [a-z]*
C           Wrap in a capturing group   ([a-z]*)
XD   Digit                       \d
C     Wrap in a capturing group   (\d)
.      Concatenate                 ([a-z]*)(\d)


The replacement function takes three arguments: a is the full match, b is the first capturing group (a letter or empty string), c is the second capturing group (a digit).

R{sXtRAb:Ab%4\,c"XXXOOoo..."@b}
s                              Space character
Xt                            repeated 10 times
Ab                      ASCII code of the letter (nil if empty string)
%4                    Mod 4 ("a"->1, "b"->2, "c"->3, ""->nil)
\,c                 Inclusive range from that number to the digit
(treats a left argument of nil as 0)
b:                        Assign that value to b
RA                          and replace those indices in the space string
"XXXOOoo..."@b   with the equivalent indices in this string
R                                Reverse to put the "top" of the building at the left


# APL (Dyalog Extended), 67 bytes

{⊖⍉↑(((' '⍴⍨2⊃⊢),'XXXOOoo...'↑⍨1+⊃)∘⌽0,48|⎕UCS)¨'[abc]?\d'⎕S'\0'⊢⍵}


Try it online!

Longer than the other answer, but I'll try golfing it later. Proper explanation coming soon.

• '[abc]?\d'⎕S'\0'⊢⍵ - Extract single digits or characters followed by digits
• (((' '⍴⍨2⊃⊢),'XXXOOoo...'↑⍨1+⊃)∘⌽0,48|⎕UCS)¨ - Train to turn each digit or pair into a horizontal string
• ⊖⍉↑` - Turn it into a matrix, transpose to make it vertical, and flip it upside-down.
• Further outgolfed! Jun 26, 2021 at 5:10
• @AviFS Nice approach!
– user
Jun 26, 2021 at 14:44