Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

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

17 Answers 17

up vote 4 down vote accepted

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.

share|improve this answer

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]
share|improve this answer
    
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. – manatwork Jan 11 at 10:25
    
@manatwork oops, thanks, fixed. I don't know how that happened, I must have golfed and not run it afterwards. – Level River St Jan 11 at 10:41

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
share|improve this answer
5  
+1 for recognizing you are a mortal :-D – Level River St Jan 10 at 19:16
    
I like that you worded it as a question. "I'm not Dennis... right?" – undergroundmonorail Jan 10 at 23:16

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>

share|improve this answer
    
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? – F. Hauri Jan 10 at 15:16
2  
@F.Hauri it works in almost every browser, but should be avoided (except when coding for fun). Info and links stackoverflow.com/questions/3434278/… – edc65 Jan 10 at 15:27

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();
        }
    }
}
share|improve this answer
9  
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#. – Downgoat Jan 9 at 5:37
    
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#.) – zyabin101 Jan 9 at 9:20
    
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);}} – RedLaser Jan 9 at 12:01
3  
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(i‌​nt 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);}} – RedLaser Jan 9 at 12:07
2  
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. – Joey Jan 9 at 20:44

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
share|improve this answer

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 '+')
share|improve this answer

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
share|improve this answer

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!

share|improve this answer
    
Patternmatching for -1 score m=init$[1..l]>>("|"!" "<$u)++["+"!"-"] => (_:m)=[1..l]>>["+"!"-"]++("|"!" "<$u) – Christian Irwan Jan 10 at 13:00
    
Surprisingly_:m=[1..l]>>["+"!"-"]++("|"!" "<$u) works – Christian Irwan Jan 10 at 13:21
    
@ChristianIrwan: well spotted! Thanks! – nimi Jan 10 at 17:21

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
share|improve this answer

PowerShell, 80

param($l,$s)
$a='-'*$s
($c="o$a`o")
(($b=,"|$(' '*$s)|"*$s)+"+$a+")*($l-1)
$b
$c
share|improve this answer

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 -...-
share|improve this answer

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
share|improve this answer
1  
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? – Level River St Jan 10 at 2:00
    
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. – ZILjr Jan 11 at 5:03
    
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. – Level River St Jan 11 at 11:06

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.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer

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)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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