34
\$\begingroup\$

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!

(and don't forget to include your favourite building in your solution)

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.

\$\endgroup\$
3
  • \$\begingroup\$ Seems tall 9 to me...:-? \$\endgroup\$
    – friol
    Jan 21 '14 at 6:52
  • \$\begingroup\$ 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. \$\endgroup\$
    – friol
    Jan 21 '14 at 7:04
  • \$\begingroup\$ ok, i misread your specification of the offset. \$\endgroup\$
    – Howard
    Jan 21 '14 at 8:21

16 Answers 16

6
\$\begingroup\$

GolfScript, 69

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

Not far off the APL solution.

Test online

\$\endgroup\$
6
\$\begingroup\$

Ruby, 88 85

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
\$\endgroup\$
6
\$\begingroup\$

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!

\$\endgroup\$
1
  • \$\begingroup\$ Great monuments! :) \$\endgroup\$
    – friol
    Jan 22 '14 at 17:59
6
\$\begingroup\$

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

enter image description here

\$\endgroup\$
6
\$\begingroup\$

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
\$\endgroup\$
3
  • \$\begingroup\$ 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. \$\endgroup\$
    – C0deH4cker
    Jan 23 '14 at 21:10
  • \$\begingroup\$ @C0deH4cker nice, thanks! That saves me four chars. \$\endgroup\$
    – FireFly
    Jan 23 '14 at 21:52
  • \$\begingroup\$ @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 \$\endgroup\$
    – FireFly
    Jan 24 '14 at 19:01
5
\$\begingroup\$

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!

\$\endgroup\$
4
  • \$\begingroup\$ I have the feeling this can be further golfed. Any ideas? \$\endgroup\$
    – AviFS
    Jun 26 at 5:16
  • 1
    \$\begingroup\$ can change 1+⍎¨⎕D⍳ \$\endgroup\$
    – Razetime
    Jun 26 at 5:36
  • \$\begingroup\$ @Razetime Wow, that's really clever. Thanks!! \$\endgroup\$
    – AviFS
    Jun 26 at 5:41
  • \$\begingroup\$ ↓¨↑∘'XXXOOoo...'¨N←⎕D⍳⍵~A←'abc'} \$\endgroup\$
    – Adám
    Jun 27 at 5:10
3
\$\begingroup\$

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
\$\endgroup\$
3
  • \$\begingroup\$ I don't know APL very well, but are you sure you need the space at the beginning of the ' XXXOOoo...' string? \$\endgroup\$
    – friol
    Jan 21 '14 at 7:05
  • \$\begingroup\$ @friol: yes, it's used to fill up the "empty" space \$\endgroup\$
    – marinus
    Jan 21 '14 at 10:12
  • \$\begingroup\$ Outgolfed! \$\endgroup\$
    – AviFS
    Jun 26 at 5:10
2
\$\begingroup\$

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!

\$\endgroup\$
2
\$\begingroup\$

Canvas, 35 33 bytes

±{⌐╷≡?┤╵“`Fc|C!‟m]c96- ×11╋╋}})⤢⇵

Try it here!

\$\endgroup\$
2
\$\begingroup\$

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
\$\endgroup\$
2
\$\begingroup\$

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
              Ʋ                   -   Last 4 links as a monad f([L]) or f([]):
        Ø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... "
\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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      
 
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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.
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Further outgolfed! \$\endgroup\$
    – AviFS
    Jun 26 at 5:10
  • \$\begingroup\$ @AviFS Nice approach! \$\endgroup\$
    – rues
    Jun 26 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.