15
\$\begingroup\$

Challenge

This is a simple challenge. Given two positive integers w and h create an ASCII fence with a width of w and a height of h. The fence should be constructed using the following rules:

  • The + character will represent a post.
  • The - character will be used to represent the width of the fence.
  • The | will be used to represent the height of the fence.
  • After exactly three - characters have been outputted, a + character must be outputted afterward. Excluding the four corners, any other time you output a + would be invalid. You are allowed to follow this rule starting either from the left or the right (see examples), but you must be consistent.
  • After exactly two | characters have been outputted, a + character must be outputted afterward. Excluding the four corners, any other time you output a + would be invalid. You are allowed to follow this rule starting either from the top or bottom (see examples), but you must be consistent.
  • Each fence will have exactly four corners, and each corner will be represented with a +.

In other words: At every three - characters, you must output a +. And at every two | characters, you must output a +.

You can assume that the fence will always be a rectangle, and that both w and h will never be greater than 100 or less than 1. Trailing and/or preceding whitespace is allowed.

Examples/Test Cases

w = 1
h = 1

+-+ 
| |
+-+


w = 3
h = 2

+---+
|   |
|   |
+---+


w = 5
h = 7

+---+--+ or +--+---+
|      |    |      |
|      |    +      +
+      +    |      |
|      |    |      |
|      |    +      +
+      +    |      |
|      |    |      |
|      |    +      +
+      +    |      |
|      |    |      |
+---+--+    +--+---+

w = 10
h = 5

+---+---+---+-+  or +-+---+---+---+
|             |     |             |
|             |     +             +
+             +     |             |
|             |     |             |
|             |     +             +
+             +     |             |
|             |     |             |
+---+---+---+-+     +-+---+---+---+


w = 4
h = 4

+---+-+ or +-+---+
|     |    |     |
|     |    |     |
+     +    +     +
|     |    |     |
|     |    |     |
+---+-+    +-+---+

Rules

\$\endgroup\$
  • \$\begingroup\$ related \$\endgroup\$ – vroomfondel Jun 27 '17 at 21:44
  • 3
    \$\begingroup\$ Am I right to understand there may not be two +'s touching? \$\endgroup\$ – xnor Jun 27 '17 at 22:53
  • \$\begingroup\$ @xnor Yes, that is correct. \$\endgroup\$ – Christian Dean Jun 27 '17 at 23:04
  • 3
    \$\begingroup\$ Great first challenge, by the way. \$\endgroup\$ – xnor Jun 27 '17 at 23:13
  • 1
    \$\begingroup\$ @LeakyNun Your right. That's a case I didn't have in mind when making my rules. I added a rule to state why +-+-+-+-+-+ is invalid. Sorry for the confusion. \$\endgroup\$ – Christian Dean Jun 28 '17 at 5:17

10 Answers 10

9
\$\begingroup\$

C, 131 bytes

#define L for(i=0,j=w;j;)putchar(i++%4?--j,45:43);puts("+")
f(w,h,i,j,c){L;for(j=1;h;printf("%c%*c\n",c,i,c))c=j++%3?--h,124:43;L;}

Try it online!

Explanation:

// The first and the last line are always similar, so let's use a macro
// to avoid code duplication.
#define L

// Let's initialize 'i' and 'j'. 'i' will be used to keep track of which
// character ('+' or '-') we should print, whereas 'j' starts from the
// input width and the loop terminates when 'j' reaches zero.
for(i=0,j=w;j;)

// We post-increment 'i' and take a modulo 4 of its previous value.
// If i%4 == 0, we print '+' (ASCII 43), otherwise we decrement 'j'
// and print '-' (ASCII 45).
putchar(i++%4?--j,45:43);

// After the loop we print one more '+' and newline.
puts("+")

// The function declaration which takes the two input parameters, and
// also declares three integer variables. These three variables could
// also be declared as global variables with the same bytecount.
f(w,h,i,j,c)

// The start of the function body. We use the macro 'L' to print the 
// first line along with a newline.
{L;

// This loop prints all the lines between the first and the last. 'j'
// keeps track of when we should output a '+' instead of a '|'. 'h',
// which is the input parameter for height, serves as a terminator
// for the loop as it reaches zero.
for(j=1;h;<stuff missing from here>)

// We post-increment 'j' and check if its previous value is divisible
// by three, and if it isn't, we decrement 'h' and assign 124 (ASCII
// value for '|') to 'c'. Otherwise we assign '+' (ASCII 43) to 'c'.
c=j++%3?--h,124:43;

// The following is inside the 'increment' part of the 'for' loop.
// We print the character corresponding to the value of 'c', then
// the same character again, but padded with i-1  spaces before it 
// ('i' hasn't been touched since the first loop, so it still stores
// the length of the first line), then a newline.
printf("%c%*c\n",c,i,c)

// Lastly we print the first line again using the same macro 'L'.
L;}
\$\endgroup\$
5
\$\begingroup\$

Python 3, 140 137 128 119 106 105 bytes

def f(w,h):a=~-w//3-~w;b=("+---"*w)[:a]+'+';print(b,*[i+' '*~-a+i for i in"||+"*h][:h+~-h//2],b,sep='\n')

Try it online!

\$\endgroup\$
  • 2
    \$\begingroup\$ It's longer now but the issue has been fixed. \$\endgroup\$ – GarethPW Jun 27 '17 at 23:12
  • 1
    \$\begingroup\$ You could save a byte by removing the space between in and [w+1+(w-1)//3]] in the last part. \$\endgroup\$ – Christian Dean Jun 27 '17 at 23:45
  • 1
    \$\begingroup\$ Welcome to PPCG! You can remove the space in '\n') for as well. Also, you can change (w-1) to ~-wwhich allows you to remove the parentheses since unary operators have a higher precedence than binary ones. Same for (h-1) -> ~-h and (a-1) -> ~-a. Try it online - 128 bytes \$\endgroup\$ – musicman523 Jun 28 '17 at 1:17
  • 1
    \$\begingroup\$ Also since all of your output is printed, def f(w,h) is the same length as lambda w,h, but allows you to use multiple lines if that helps you golf your code further \$\endgroup\$ – musicman523 Jun 28 '17 at 1:21
  • 1
    \$\begingroup\$ a=~-w//3-~w; to save 1 byte \$\endgroup\$ – Felipe Nardi Batista Jun 28 '17 at 12:36
4
\$\begingroup\$

Mathematica, 165 bytes

v=Column;d[w_,y_,m_,n_]:=Table[If[Mod[i,y]==0&&i!=w,m,n],{i,w}];(a="+"<>d[#,3,"-+","-"]<>"+";b=v@d[#2,2,"|\n+","|"];v[{a,Row[{b,""<>Table[" ",#+Floor[#/3]],b}],a}])&
\$\endgroup\$
4
\$\begingroup\$

Pip, 38 bytes

37 bytes of code, +1 for -n flag.

Ph:'-Xa<>3JW'+PsX#h-2WR:'|Xb<>2J'+^xh

Takes width and height as command-line arguments. Try it online!

Explanation

                         a,b are cmdline args; s is space; x is empty string (implicit)
Ph:'-Xa<>3JW'+
   '-Xa                  String of hyphens of length a
       <>3               grouped into substrings of (maximum) length 3
          JW'+           Join on +, also wrapping the result in +
 h:                      Assign that string to h (mnemonic: "header")
P                        and print it (with newline)

PsX#h-2WR:'|Xb<>2J'+^xh
          '|Xb           String of pipes of length b
              <>2        grouped into substrings of (maximum) length 2
                 J'+     joined on +
                    ^x   and split on empty string (i.e. converted to list of chars)
 sX#h-2                  String of len(h)-2 spaces
       WR:               Wrap the spaces with the list of chars
                         Note 1: WR operates itemwise on lists, so the result is a list,
                          each item of which consists of the spaces wrapped in an item
                          from the list of chars
                         Note 2: the : compute-and-assign meta-operator is here abused
                          to give WR: lower precedence than J and ^ and avoid parentheses
P                        Print that list, newline-separated (-n flag)
                      h  Autoprint the header a second time as the footer
\$\endgroup\$
4
\$\begingroup\$

Charcoal, 47 45 40 bytes

F⁴«¿﹪ι³FIη↓⁺×+¬﹪κ²|FIθ⁺×+¬﹪κ³-P+¿⁼ι¹J⁰¦⁰

Explanation: Works by drawing each side's -s/|s in turn, inserting +s where necessary, then finishing with a +. After drawing the top and right sides, jumps back to the start to draw them in reverse order, effectively drawing the left and bottom sides. I don't know whether rotational symmetry is permitted, but if so, then for 27 25 bytes:

F⁴«FI⎇﹪ι²ηθ⁺×+¬﹪κ⁻³﹪ι²-⟲T

Takes the above idea to the extreme by drawing the top side, rotating left, drawing the right side, rotating again, and then repeating to draw the bottom and left sides in reverse.

\$\endgroup\$
  • 1
    \$\begingroup\$ @LeakyNun Last time I beat Pyth was for Double up some diamonds, and even then it was only just shorter. \$\endgroup\$ – Neil Jun 28 '17 at 0:27
4
\$\begingroup\$

JavaScript (ES6), 133 132 bytes

w=>h=>(a="-".repeat(w).replace(/--?-?/g,"+$&")+`+`)+(`
|`.padEnd(a.length)+`|`).repeat(h).replace(/(\|( +)\|\n)\1/g,`$&+$2+
`)+`
`+a

Takes input in currying syntax: f(width)(height).

Test Snippet

f=
w=>h=>(a="-".repeat(w).replace(/--?-?/g,"+$&")+`+`)+(`
|`.padEnd(a.length)+`|`).repeat(h).replace(/(\|( +)\|\n)\1/g,`$&+$2+
`)+`
`+a
O.innerHTML=f(W.value=5)(H.value=10)
<div oninput="O.innerHTML=f(+W.value)(+H.value)">
W <input id=W type=number min=1> H <input id=H type=number min=1>
</div>
<pre id=O>

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

Pyth, 40 bytes

AQj++KjJj\+c*\-G3"++"m++d*lJ;dj\+c*\|H2K

Test suite.

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

Java (OpenJDK 8), 178 177 bytes

w->h->{int i=0;String t="",m,r;for(;i<w;)t+=i++%3<1?"+-":"-";r=t+="+\n";m=t.format("|%"+(t.length()-3)+"s|\n","");for(i=0;i<h;)r+=i++%2<1&i>1?m.replace("|","+")+m:m;return r+t;}

Try it online!

-1 byte thanks to @KevinCruijssen

\$\endgroup\$
  • \$\begingroup\$ You can save a byte by currying the parameters: w->h-> Try it here. \$\endgroup\$ – Kevin Cruijssen Jun 28 '17 at 12:38
  • \$\begingroup\$ Yep, I constantly forget about currying... It's not something I find natural :s \$\endgroup\$ – Olivier Grégoire Jun 28 '17 at 13:49
1
\$\begingroup\$

Charcoal, 47 45 37 bytes

A…+---÷⁺²×⁴N³αA…+||÷⁺¹×³N²βPα↓βα+↖↑⮌β

Try it online!

  • 2 bytes saved after playing with the signs in the string creation.
  • 8 bytes saved thanks to Neil, who came up with a much simpler way to calculate the lengths of the fences.

A different approach from @Neil's: first I create the strings α and β containing the chars in the horizontal and vertical borders, using the Range operator that creates a repetition of a string until a given length is reached. Then I print them in the proper order:

  • Print α without moving the cursor.
  • Print β downwards.
  • Print α.
  • Print a "+".
  • Move the cursor up and to the left.
  • Print β upwards, reversed.

Link to a verbose version.

\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks for reminding me about Range, that saves 3 bytes on my second approach! \$\endgroup\$ – Neil Jun 28 '17 at 7:53
  • \$\begingroup\$ @Neil that's nice because I have just outgolfed you and I just can't believe it. :-) \$\endgroup\$ – Charlie Jun 28 '17 at 7:59
  • 1
    \$\begingroup\$ Better still, I managed to optimise your expressions, saving 8 bytes: A…+---÷⁺²×⁴N³αA…+||÷⁺¹×³N²βPα↓βα+↖↑⮌β. \$\endgroup\$ – Neil Jun 28 '17 at 20:13
  • \$\begingroup\$ @Neil Wow. Such optimization. Very Charcoal. \$\endgroup\$ – Charlie Jun 28 '17 at 20:34
0
\$\begingroup\$

05AB1E, 58 bytes

D3/ó+DU'-×'+.ø©'|DXú«²D2/ó+.D®»'-4×D'+3ǝ.:¶¡ø'|3×D'+2ǝ.:ø»

Try it online!

Harder in 05AB1E than I thought.

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