28
\$\begingroup\$

Given an input of two integers n and m, output an ASCII ladder of length n and size m.

This is an ASCII ladder of length 3 and size 3:

o---o
|   |
|   |
|   |
+---+
|   |
|   |
|   |
+---+
|   |
|   |
|   |
o---o

This is an ASCII ladder of length 5 and size 1:

o-o
| |
+-+
| |
+-+
| |
+-+
| |
+-+
| |
o-o

This is an ASCII ladder of length 2 and size 5:

o-----o
|     |
|     |
|     |
|     |
|     |
+-----+
|     |
|     |
|     |
|     |
|     |
o-----o

To be specific:

  • The length (n) represents how many squares the ladder is made up of.

  • The size (m) represents the width and height of the interior of—that is, not counting the "borders"—each square.

  • Each square is made up of the interior area filled with spaces, surrounded by -s on the top and bottom, |s on the left and right, and +s at all four corners.

  • Borders between squares merge together, so two lines in a row with +--...--+ merge into one.

  • The corners of the entire ladder are replaced with the character o.

  • You may optionally output a trailing newline.

The length of the ladder (n) will always be ≥ 2, and the size (m) will always be ≥ 1.

Input can be taken as a whitespace-/comma-separated string, an array/list/etc., or two function/command line/etc. arguments. The arguments can be taken in whichever order is most convenient / golfiest.

Since this is , the shortest code in bytes wins.

Tip: The examples above can also be used as test cases.

\$\endgroup\$
  • \$\begingroup\$ Do we have to take length first, then size? \$\endgroup\$ – RK. Jan 10 '16 at 0:50
  • \$\begingroup\$ @RK. You can take them in whichever order is more convenient. \$\endgroup\$ – Doorknob Jan 10 '16 at 16:55
  • 1
    \$\begingroup\$ Can there be a leading newline? \$\endgroup\$ – Conor O'Brien Jan 10 '16 at 22:35
  • 1
    \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ Uhh... I'm going to go with no on that one. \$\endgroup\$ – Doorknob Jan 10 '16 at 23:01
  • 1
    \$\begingroup\$ Okay :P It was worth a shot. \$\endgroup\$ – Conor O'Brien Jan 10 '16 at 23:01

19 Answers 19

4
\$\begingroup\$

Pyth, 34 bytes

.NjjNm*QTvz*2YjC:M++J"+|o"m"- -"QJ

Test suite

Takes arguments newline separated on STDIN.

Uses a helper function, :, which builds each type of vertical string from three characters, then replicates as necessary, transposes and joins on newlines.

\$\endgroup\$
11
\$\begingroup\$

Ruby, 71

->m,n{h=0;(?o+?+*(n-1)+?o).chars{|c|puts [?|+' '*m+?|]*h,c+?-*m+c;h=m}}

ungolfed in test program

f=->m,n{
  h=0                             #The number of | above the 1st rung is 0
  (?o+?+*(n-1)+?o).chars{|c|      #Make a string of all the rung ends o++...++o and iterate through it
    puts [?|+' '*m+?|]*h,         #draw h vertical segments |  ...  |
      c+?-*m+c                    #and a rung with the correct ends
    h=m                           #The number of | above all rungs except the 1st is m
  }
}


f[gets.to_i,gets.to_i]
\$\endgroup\$
  • \$\begingroup\$ There seems to be minor issues with the golfed version: need ; after h=0, need space after puts. But you score grows only with 1 character as there is an extra space before puts. \$\endgroup\$ – manatwork Jan 11 '16 at 10:25
  • \$\begingroup\$ @manatwork oops, thanks, fixed. I don't know how that happened, I must have golfed and not run it afterwards. \$\endgroup\$ – Level River St Jan 11 '16 at 10:41
9
\$\begingroup\$

CJam, 43 42 bytes

I'm not sastified by the score. But I'm not Dennis, right?

q~:Z;'-'o{[\Z*1$N]}:X~['-_'+X\'|XZ*]@*1>1$

Input is 2 space separated items. Length first

2 3
o---o
|   |
|   |
|   |
+---+
|   |
|   |
|   |
o---o

Explanation

q~:Z;'-'o{[\Z*1$N]}:X~['-_'+X\'|XZ*]@*1>1$
q~                                         e# read input
  :Z;                                      e# Record the size in Z and discard
     '-'o{[\Z*1$N]}:X~                     e# Create the initial line (and final). also creates a shorcut to do this later
           \                               e# Capture two arguments
            Z*                             e# The separator is repeated size times
              1$                           e# Repeat the first argument
                N                          e# Add newline
                                           e# X is a function to create line in a ladder
                      ['-_'+X\'|XZ*]       e# Design the repeating part
                                    @*     e# Repeat the pattern n times
                                      1>   e# Discard the initial
                                        1$ e# Since the final line is same than the initial, we just write it.
                                           e# Implicit printing
\$\endgroup\$
  • 1
    \$\begingroup\$ I like that you worded it as a question. "I'm not Dennis... right?" \$\endgroup\$ – undergroundmonorail Jan 10 '16 at 23:16
7
\$\begingroup\$

JavaScript (ES6), 89

... repeat, repeat, repeat ...

(n,m,R=x=>x.repeat(m),b=R(`|${R(' ')}|
`),d=`o${c=R('-')}o
`)=>d+R(b+`+${c}+
`,m=n-1)+b+d

Test

F=(n,m,R=x=>x.repeat(m),b=R(`|${R(' ')}|
`),d=`o${c=R('-')}o
`)=>d+R(b+`+${c}+
`,m=n-1)+b+d

// Less golfed
U=(n,m)=>
{
  var R=x=>x.repeat(m),
      a=R(' '),
      b=R(`|${a}|\n`);
      c=R('-'),
      d=`o${c}o\n`;
  m=n-1;
  return d+R(b+`+${c}+\n`)+b+d
}

function test() {
  var i=I.value.match(/\d+/g)
  if (i) O.textContent=F(+i[0],+i[1])
  console.log(i,I.value)
}  
 
test()
N,M: <input id=I value="3,5" oninput=test()>
<pre id=O></pre>

\$\endgroup\$
  • \$\begingroup\$ I did'nt know that document.getElementById('elem'). could be replaced by elem. ! +1 for this, but please, could you point out some docs about this? \$\endgroup\$ – F. Hauri Jan 10 '16 at 15:16
  • 2
    \$\begingroup\$ @F.Hauri it works in almost every browser, but should be avoided (except when coding for fun). Info and links stackoverflow.com/questions/3434278/… \$\endgroup\$ – edc65 Jan 10 '16 at 15:27
6
\$\begingroup\$

C#, 1412 bytes

... My first CodeGolf attempt, Not likely to win but it works so here we go:

using System;

namespace Ascii_Ladders
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = 0;
            int m = 0;

            Console.Write("Please enter Height: ");
            n = int.Parse(Console.ReadLine());
            Console.Write("Please Enter Width: ");
            m = int.Parse(Console.ReadLine());

            Console.Write("o");
            for (int i = 0; i < m; i++)
            {
                Console.Write("-");
            }
            Console.WriteLine("o");

            for (int k = 0; k < n; k++)
            {
                for (int i = 0; i < m; i++)
                {
                    Console.Write("|");
                    for (int j = 0; j < m; j++)
                    {
                        Console.Write(" ");
                    }
                    Console.WriteLine("|");
                }
                if (k != n - 1)
                {
                    Console.Write("+");
                    for (int i = 0; i < m; i++)
                    {
                        Console.Write("-");
                    }
                    Console.WriteLine("+");
                }
            }

            Console.Write("o");
            for (int i = 0; i < m; i++)
            {
                 Console.Write("-");
            }
            Console.WriteLine("o");

            Console.ReadKey();
        }
    }
}
\$\endgroup\$
  • 9
    \$\begingroup\$ Welcome to Programming Puzzles & Code Golf! You have a lot of whitespace in your code that you can remove to shorten your code, if you would like more help golfing your code, you can check out Tips for golfing in C#. \$\endgroup\$ – Downgoat Jan 9 '16 at 5:37
  • \$\begingroup\$ I agree with @Doᴡɴɢᴏᴀᴛ here. I've been able to potentially golf it to just 533 bytes. But it could be better. (Warning: I don't program in C#.) \$\endgroup\$ – user48538 Jan 9 '16 at 9:20
  • \$\begingroup\$ I got it down to 314 with using System;class P{static int m;static void Main(){int n = int.Parse(Console.ReadLine());m = int.Parse(Console.ReadLine());M('o','-');for(int k=0;k<n;k++){for(int i=0;i<m;i++){M('|',' ');}if(k!=n-1){M('+','-');}}M('o','-');Console.ReadKey();}static void M(char x,char y){Console.WriteLine(x+new string(y,m)+x);}} \$\endgroup\$ – RedLaser Jan 9 '16 at 12:01
  • 3
    \$\begingroup\$ Missed a few spaces so 310 with using System;class P{static int m;static void Main(){int n=int.Parse(Console.ReadLine());m=int.Parse(Console.ReadLine());M('o','-');for(int k=0;k<n;k++){for(int i=0;i<m;i++){M('|',' ');}if(k!=n-1){M('+','-');}}M('o','-');Console.ReadKey();}static void M(char x,char y){Console.WriteLine(x+new string(y,m)+x);}} \$\endgroup\$ – RedLaser Jan 9 '16 at 12:07
  • 2
    \$\begingroup\$ Down to 270 without changes in the approach used: using C=System.Console;class P{static void Main(){int i,k,n=int.Parse(C.ReadLine()),m=int.Parse(C.ReadLine());System.Action<char,char> M=(x,y)=>C.WriteLine(x+new string(y,m)+x);M('o','-');for(k=0;k<n;k++){for(i=0;i<m;i++){M('|',' ');}if(k<n-1){M('+','-');}}M('o','-');}}. There is most likely more potential here, though, simply by changing how to do things a bit. \$\endgroup\$ – Joey Jan 9 '16 at 20:44
6
\$\begingroup\$

Julia, 87 bytes

f(n,m)=(g(x)=(b=x[1:1])x[2:2]^m*b*"\n";(t=g("o-"))join([g("| ")^m for i=1:n],g("+-"))t)

This is a function that accepts two integers and returns a string.

Ungolfed:

function f(n::Int, m::Int)
    # Create a function g that takes a string of two characters and
    # constructs a line consisting of the first character, m of the
    # second, and the first again, followed by a newline.
    g(x) = (b = x[1:1]) * x[2:2]^m * b * "\n"

    # Assign t to be the top and bottom lines. Construct an array
    # of length n where each element is a string containing the
    # length-m segment of the interior. Join the array with the
    # ladder rung line. Concatenate all of this and return.
    return (t = g("o-")) * join([g("| ")^m for i = 1:n], g("+-")) * t
end
\$\endgroup\$
5
\$\begingroup\$

pb - 147 bytes

^t[B]>>[B]vw[T!0]{b[43]<[X]b[43]>w[B=0]{b[45]>}v[X-1]w[B=0]{b[124]^}v[X]t[T-1]}t[111]b[T]<w[X!0]{b[45]<}b[T]w[Y!0]{w[B!0]{^}b[124]^}b[T]^>>[B]vb[T]

This is the kind of challenge that, by rights, pb should be really good at. Drawing simple pictures with characters is exactly what pb was designed for. Alas, it's just a wordy language I guess.

Takes input length first, followed by size. Takes input in the form of byte values, for example: python -c 'print(chr(5) + chr(7))' | ./pbi.py ladder.pb

Look, a fun animation!

With comments:

^t[B]            # Save length to T
>>[B]v           # Go to X=size+1, Y=0

w[T!0]{          # While T is not 0:
    b[43]            # Write a '+'
    <[X]b[43]        # Write a '+' on the left side as well
    >w[B=0]{b[45]>}  # Travel back to the right '+', writing '-' on the way
    v[X-1]           # Go down by X-1 (== size)
    w[B=0]{b[124]^}  # Travel back up to the '+', writing '|' on the way
    v[X]             # Go down by X (== size + 1, location of next '+')
    t[T-1]           # Decerement T
}

t[111]           # Save 'o' to T (it's used 4 times so putting it
                 # in a variable saves bytes)

b[T]             # Write an 'o' (bottom right)

<w[X!0]{         # While not on X=0:
    b[45]<           # Travel left, writing '-' on the way
}

b[T]             # Write an 'o' (bottom left)

w[Y!0]{          # While not on Y=0:
    w[B!0]{^}        # Skip nonempty spaces
    b[124]           # Write a '|'
    ^                # Travel up
}

b[T]             # Write an 'o' (top left, replaces existing '+')

^>>[B]v          # Go back to where the size is saved and go to X=size+1, Y=0

b[T]             # Write an 'o' (top right, replaces existing '+')
\$\endgroup\$
5
\$\begingroup\$

Pure bash, 132 130 128 127 bytes

Yes I could drop 1 more byte replacing last ${p% *}, but I prefer this:

p=printf\ -v;$p a %$1s;$p b %$2s;o="|$a|\n";h=+${a// /-}+\\n v=${a// /$o}
a=${b// /$h$v}${h//+/o};a=${a/+/o};${p% *} "${a/+/o}"

Sample:

ladders() {
    p=printf\ -v;$p a %$1s;$p b %$2s;o="|$a|\n";h=+${a// /-}+\\n v=${a// /$o}
    a=${b// /$h$v}${h//+/o};a=${a/+/o};${p% *} "${a/+/o}"
}

ladders 3 4
o---o
|   |
|   |
|   |
+---+
|   |
|   |
|   |
+---+
|   |
|   |
|   |
+---+
|   |
|   |
|   |
o---o

ladders 2 1
o--o
|  |
|  |
o--o
\$\endgroup\$
4
\$\begingroup\$

Haskell, 100 97 bytes

l#s=unlines$t:m++[t]where _:m=[1..l]>>["+"!"-"]++("|"!" "<$u);t="o"!"-";o!i=o++(u>>i)++o;u=[1..s]

Usage example:

*Main> putStr $ 4 # 3
o---o
|   |
|   |
|   |
+---+
|   |
|   |
|   |
+---+
|   |
|   |
|   |
+---+
|   |
|   |
|   |
o---o

How it works:

l#s=unlines$t:m++[t]         -- concat top line, middle part and end line
                             -- with newlines between every line
  where                      -- where
  _:m=                       -- the middle part is all but the first line of
     [1..l]>>                -- l times
         ["+"!"-"]           --    a plus-dashes-plus line
         ++("|"!" "<$u)      --    followed by s times a bar-spaces-bar line

  t="o"!"-"                  -- very first and last line
  o!i=o++(u>>i)++o           -- helper to build a line
  u=[1..s]

Edit: @Christian Irwan found 3 bytes. Thanks!

\$\endgroup\$
  • \$\begingroup\$ Patternmatching for -1 score m=init$[1..l]>>("|"!" "<$u)++["+"!"-"] => (_:m)=[1..l]>>["+"!"-"]++("|"!" "<$u) \$\endgroup\$ – Akangka Jan 10 '16 at 13:00
  • \$\begingroup\$ Surprisingly_:m=[1..l]>>["+"!"-"]++("|"!" "<$u) works \$\endgroup\$ – Akangka Jan 10 '16 at 13:21
  • \$\begingroup\$ @ChristianIrwan: well spotted! Thanks! \$\endgroup\$ – nimi Jan 10 '16 at 17:21
3
\$\begingroup\$

brainfuck - 334 bytes

,[<+<<<<+>>>>>-]<[[>>]+[<<]>>-]<----[>---<----]--[>[+>>]<<[<<]>++++++]>[+.>>]-[<+>---]<+++++++>>--[<+>++++++]->---[<------->+]++++++++++[<++<]+++++[>[++++++>>]<<[<<]>-]>[-]>.-<<----[>>+++<<----]--[>+<--]>---<<<<++++++++++.,[>[>+>+<<-]>[<+>-]>[<<<<[>>>>>>[.>>]<<[<<]>>-]>>>>>[.>>]<<[<<]>-]<<<<+>-]>>>>[-]----[>---<----]>+.[>]<<<<<[.<<]

I expected this to be a lot shorter.

This sets up a "string" that looks like | (...) | and one that looks like +----(...)----+, printing each one as necessary, with some special casing for the os on the top and bottom.

Requires an interpreter that uses 8-bit cells and allows you to go left from cell 0 (be it into negative cells or looping). In my experience, these are the most common default settings.

With comments:

,[<+<<<<+>>>>>-]<[[>>]+[<<]>>-] Get m from input; make a copy
                      Turn it into m cells containing 1 with empty cells between

<----[>---<----]      Put 67 at the beginning (again with an empty cell between)

--[>[+>>]<<[<<]>++++++]  Add 43 to every nonempty cell

>[+.>>]               Add 1 to each cell and print it

-[<+>---]<+++++++    Put 92 after the last 45 (no empty cell!)

>>--[<+>++++++]      Put 43 immediately after the 92

->---[<------->+]    Put 234 after 43

++++++++++           And 10 after that

[<++<]             Add two to the 234; 92; the empty spaces; and left of the 111

+++++[>[++++++>>]<<[<<]>-] Add 30 to each 2; the 94; and the 236

>[-]>.-<<----[>>+++<<----] Erase leftmost 32; Print 111; subtract 68 from it

--[>+<--]>---        Put 124 where the 32 was

<<<<++++++++++.,     Print a newline; override the cell with n from input

[                    n times:

  >[>+>+<<-]>[<+>-]    Make a copy of m

  >[                   m times:

    <<<<                 Look for a flag at a specific cell

    [                    If it's there:

      >>>>>>[.>>]          Go to the 43; print it and every second cell after

      <<[<<]>>-            Clear the flag

    ]

    >>>>>[.>>]           Go to the 124; print it and every second cell after

    <<[<<]>              Go back to the copy of m

  -]

  <<<<+>               Plant the flag

-]

>>>>

[-]----[>---<----]>+ Erase the 124; add 68 to 43

.[>]                 Print it; then head to the end

<<<<<[.<<] Go to the last 45; print it; then print every second cell to the left
\$\endgroup\$
3
\$\begingroup\$

PowerShell, 77 80

param($l,$s)$a='-'*$s
($c="o$a`o")
(($b=,"|$(' '*$s)|"*$s)+"+$a+")*--$l
$b
$c
\$\endgroup\$
2
\$\begingroup\$

Jolf, 36 bytes

Try it here!

ρpi,a+2J+2J"o-| "j"o(.+)o
o.+o'+$1+

Explanation

ρpi,a+2J+2J"o-| "j"o(.+)o\no.+o'+$1+
 pi              j                   repeat vertically j times
   ,a+2J+2J"o-| "                    a box with dimensions 2+J
ρ                 "o(.+)p\np.+o'     replace with regex
                                +$1+ with the -...-
\$\endgroup\$
2
\$\begingroup\$

Perl, 98 bytes

($n,$m)=@ARGV;print$h="o"."-"x$m."o\n",((("|".(" "x$m)."|\n")x$m.$h)x$n)=~s{o(-+)o(?=\n.)}{+$1+}gr
\$\endgroup\$
  • 1
    \$\begingroup\$ An excellent first answer. But I don't see any + signs in your code, have you considered that the intermediate rungs have + signs at each end? \$\endgroup\$ – Level River St Jan 10 '16 at 2:00
  • \$\begingroup\$ Thank you for the very nicely worded comment--I totally spaced the plus signs! Cost me quite a bit of space, too; still thinking of how I can shorten it... besides omitting the ($n,$m)=@ARGV; and assuming those are set already--not sure if that's in the spirit or not. I'll have to look it up. \$\endgroup\$ – ZILjr Jan 11 '16 at 5:03
  • \$\begingroup\$ Unless otherwise specified in the question, the rule is here meta.codegolf.stackexchange.com/a/2422/15599 . You can't just assume the variables are set, but you can write a function instead of a program, if that helps. I don't do Perl but I assume that might save you the @ARGV. Also, when replying to someone remember to include @username so they get an alert. I don't need to do it as this is your post. \$\endgroup\$ – Level River St Jan 11 '16 at 11:06
1
\$\begingroup\$

C, 122 bytes

f(int m,int n,char*s){int i=0,w=3+m++;for(;i<w*m*n+w;++i)*s++=i%w>m?10:" |-+-o"[!(i/w%m)*2+!(i%w%m)+!(i/w%(m*n))*2];*s=0;}

Try it online.

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

Tcl, 187 bytes

lassign $argv n w
set c 0
while { $c < [expr {($w * $n) + ($n + 2)}]} {if {[expr {$c % ($n + 1)}] == 0} {puts "o[string repeat "-" $w ]o"} else {puts "|[string repeat " " $w ]|"}
incr c}

This code is made to put into a file with arguments input on the command line. provide number of boxes and width in that order.

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

PHP, 81bytes

Expects 2 arguments, passed when calling the PHP command directly. The first one is the size and the 2nd one is the number of steps.

$R=str_repeat;echo$P="o{$R('-',$W=$argv[1])}o
",$R("|{$R(' ',$W)}|
$P",$argv[2]);

May require some improvements.

\$\endgroup\$
0
\$\begingroup\$

Python 2, 94 bytes

def F(n,m):a,b,c,d='o|+-';r=[a+d*m+a]+([b+' '*m+b]*m+[c+d*m+c])*n;r[-1]=r[0];print'\n'.join(r)

'Ungolfed':

def F(n,m):
 # 'o---o'
 r = ['o'+'-'*m+'o']
 # ('|   |'*m+'+---+') n times
 r += (['|'+' '*m+'|']*m+['+'+'-'*m+'+'])*n
 # replace last +---+ with o---o
 r[-1] = r[0]
 print '\n'.join(r)
\$\endgroup\$
0
\$\begingroup\$

Perl 5, 91 + 1 (-a) = 92 bytes

$_='|'.$"x$F[1].'|';push@a,y/| /+-/r,($_)x$F[1]while$F[0]--;$a[0]=y/| /o-/r;say for@a,$a[0]

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Pip -l, 35 bytes

(^YsXbRLaJW'-)XbWR^('|XbRLaJ'+)WR'o

Try it online!

Explanation

(^YsXbRLaJW'-)XbWR^('|XbRLaJ'+)WR'o
                                     a is length, b is size, s is space (implicit)
   sXb                               String containing b spaces
      RLa                            List containing a copies of that string
         JW'-                        Join on "-" and wrap the result in "-" as well
  Y                                  Necessary for operator precedence reasons
 ^                                   Split into a list of characters
(            )Xb                     String-repeat each character in the list b times
                                     This list represents the central columns of the ladder

                    '|Xb             String containing b pipe characters
                        RLa          List containing a copies of that string
                           J'+       Join on "+"
                   (          )WR'o  Wrap in "o"
                  ^                  Split into a list of characters
                                     This list represents the outer columns of the ladder

                WR                   Wrap the left list in the right list, vectorizing

Some other versions

I tried a lot of different approaches trying to catch Pyth...

[Y'-XbWR'o;@>(sXbWR'|RLbPE'-XbWR'+RL:a)y]  41
Y^(t**b.1*:t**bX--a.1)" --"@yXbWR"|o+"@y   40
Y'|XbRLaJ'+YyWR'o;Z:sXbRLaJW'-RLbPEyAEy    39
t**:b(" |-o-+"<>2)@_@^t.1M$*Y[ttXa-1].1    39
J*Z:sXbRLaJW'-RLbWR:^('|XbRLaJ'+)WR'o      37
Y^$*Y[t**:btXa-1].1" --"@yXbWR"|o+"@y      37

I'm particularly fond of the t**b ones, which use math to generate the ladder's vertical pattern:

        b           Size; e.g. 3
    t               Preset variable for 10
     **:            Set t to t**b (e.g. 1000)
           a        Length; e.g. 3
            -1      2
         tX         String-repeat (the new value of) t 2 times: 10001000
   [          ]     Put t and the above into a list: [1000; 10001000]
               .1   Append 1 to both of them: [10001; 100010001]
$*(              )  Fold on multiplication: 1000200020001

The 1000200020001 can then be used to generate the patterns o|||+|||+|||o and - - - -, which make up the ladder. Unfortunately, I couldn't get this approach to be shorter than the join/wrap approach.

\$\endgroup\$

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.