Build ASCII ladders

28

4

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.

Doorknob

Posted 2016-01-09T04:04:43.193

Reputation: 68 138

Do we have to take length first, then size? – RK. – 2016-01-10T00:50:02.717

@RK. You can take them in whichever order is more convenient. – Doorknob – 2016-01-10T16:55:13.567

1Can there be a leading newline? – Conor O'Brien – 2016-01-10T22:35:38.473

1@CᴏɴᴏʀO'Bʀɪᴇɴ Uhh... I'm going to go with no on that one. – Doorknob – 2016-01-10T23:01:03.377

1Okay :P It was worth a shot. – Conor O'Brien – 2016-01-10T23:01:46.457

Hey, issacg's Pyth answer is shorter! Not mine! – Akangka – 2016-01-16T22:14:08.880

@ChristianIrwan ... oh, whoops, I can't count. Fixed. – Doorknob – 2016-01-16T22:34:37.370

Answers

4

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.

isaacg

Posted 2016-01-09T04:04:43.193

Reputation: 39 268

11

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]

Level River St

Posted 2016-01-09T04:04:43.193

Reputation: 22 049

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 – 2016-01-11T10:25:00.417

@manatwork oops, thanks, fixed. I don't know how that happened, I must have golfed and not run it afterwards. – Level River St – 2016-01-11T10:41:17.853

9

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

Akangka

Posted 2016-01-09T04:04:43.193

Reputation: 1 859

1I like that you worded it as a question. "I'm not Dennis... right?" – undergroundmonorail – 2016-01-10T23:16:09.650

7

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>

edc65

Posted 2016-01-09T04:04:43.193

Reputation: 31 086

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 – 2016-01-10T15:16:06.520

2

@F.Hauri it works in almost every browser, but should be avoided (except when coding for fun). Info and links http://stackoverflow.com/questions/3434278/do-dom-tree-elements-with-ids-become-global-variables

– edc65 – 2016-01-10T15:27:23.810

6

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

Reed Jones

Posted 2016-01-09T04:04:43.193

Reputation: 69

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 – 2016-01-09T05:37:06.857

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#.)

– user48538 – 2016-01-09T09:20:04.580

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 – 2016-01-09T12:01:14.707

3Missed 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);}} – RedLaser – 2016-01-09T12:07:54.167

2Down 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 – 2016-01-09T20:44:40.850

6

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

Alex A.

Posted 2016-01-09T04:04:43.193

Reputation: 23 761

5

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

F. Hauri

Posted 2016-01-09T04:04:43.193

Reputation: 2 654

5

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

undergroundmonorail

Posted 2016-01-09T04:04:43.193

Reputation: 5 897

4

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!

nimi

Posted 2016-01-09T04:04:43.193

Reputation: 34 639

Patternmatching for -1 score m=init$[1..l]>>("|"!" "<$u)++["+"!"-"] => (_:m)=[1..l]>>["+"!"-"]++("|"!" "<$u) – Akangka – 2016-01-10T13:00:13.120

Surprisingly_:m=[1..l]>>["+"!"-"]++("|"!" "<$u) works – Akangka – 2016-01-10T13:21:23.960

@ChristianIrwan: well spotted! Thanks! – nimi – 2016-01-10T17:21:39.967

3

PowerShell, 77 80

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

Joey

Posted 2016-01-09T04:04:43.193

Reputation: 12 260

77 bytes – Veskah – 2019-03-18T12:27:36.140

3

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

undergroundmonorail

Posted 2016-01-09T04:04:43.193

Reputation: 5 897

2

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

ZILjr

Posted 2016-01-09T04:04:43.193

Reputation: 121

1An 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 – 2016-01-10T02:00:38.023

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 – 2016-01-11T05:03:16.093

Unless otherwise specified in the question, the rule is here http://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 – 2016-01-11T11:06:24.520

2

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 -...-

Conor O'Brien

Posted 2016-01-09T04:04:43.193

Reputation: 36 228

1

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.

grc

Posted 2016-01-09T04:04:43.193

Reputation: 18 565

1

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.

Cjolly

Posted 2016-01-09T04:04:43.193

Reputation: 111

1

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.

Ismael Miguel

Posted 2016-01-09T04:04:43.193

Reputation: 6 797

0

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!

Xcali

Posted 2016-01-09T04:04:43.193

Reputation: 7 671

0

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.

DLosc

Posted 2016-01-09T04:04:43.193

Reputation: 21 213

0

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)

TFeld

Posted 2016-01-09T04:04:43.193

Reputation: 19 246