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

asked Jun 27, 2017 at 21:39
\$\endgroup\$
12
  • \$\begingroup\$ related \$\endgroup\$ Commented Jun 27, 2017 at 21:44
  • 3
    \$\begingroup\$ Am I right to understand there may not be two +'s touching? \$\endgroup\$ Commented Jun 27, 2017 at 22:53
  • \$\begingroup\$ @xnor Yes, that is correct. \$\endgroup\$ Commented Jun 27, 2017 at 23:04
  • 3
    \$\begingroup\$ Great first challenge, by the way. \$\endgroup\$ Commented Jun 27, 2017 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\$ Commented Jun 28, 2017 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;}
answered Jun 27, 2017 at 21:58
\$\endgroup\$
1
  • \$\begingroup\$ Suggest for(;h;printf("%c%*c\n",c,i,c=++j%3?--h,124:43)); instead of for(j=1;h;printf("%c%*c\n",c,i,c))c=j++%3?--h,124:43; \$\endgroup\$ Commented Jul 15, 2020 at 19:07
5
\$\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
answered Jun 28, 2017 at 3:49
\$\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!

answered Jun 27, 2017 at 22:27
\$\endgroup\$
9
  • 2
    \$\begingroup\$ It's longer now but the issue has been fixed. \$\endgroup\$ Commented Jun 27, 2017 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\$ Commented Jun 27, 2017 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\$ Commented Jun 28, 2017 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\$ Commented Jun 28, 2017 at 1:21
  • 1
    \$\begingroup\$ a=~-w//3-~w; to save 1 byte \$\endgroup\$ Commented Jun 28, 2017 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}])&
answered Jun 28, 2017 at 2:28
\$\endgroup\$
4
\$\begingroup\$

Charcoal, (削除) 47 (削除ここまで) (削除) 45 (削除ここまで) 40 bytes

×ばつ+¬%κ3-P+¿=ι1J0¦0

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:

×ばつ+¬%κ−3%ι2-⟲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.

answered Jun 28, 2017 at 0:16
\$\endgroup\$
1
  • 1
    \$\begingroup\$ @LeakyNun Last time I beat Pyth was for Double up some diamonds, and even then it was only just shorter. \$\endgroup\$ Commented Jun 28, 2017 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>

answered Jun 28, 2017 at 2:38
\$\endgroup\$
2
\$\begingroup\$

Pyth, 40 bytes

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

Test suite.

answered Jun 28, 2017 at 0:18
\$\endgroup\$
0
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

answered Jun 28, 2017 at 11:17
\$\endgroup\$
2
  • \$\begingroup\$ You can save a byte by currying the parameters: w->h-> Try it here. \$\endgroup\$ Commented Jun 28, 2017 at 12:38
  • \$\begingroup\$ Yep, I constantly forget about currying... It's not something I find natural :s \$\endgroup\$ Commented Jun 28, 2017 at 13:49
1
\$\begingroup\$

Charcoal, (削除) 47 45 (削除ここまで) 37 bytes

×ばつ3N2β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.

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

05AB1E, 58 bytes

×ばつD'+2ǝ.:ø»

Try it online!

Harder in 05AB1E than I thought.

answered Jun 28, 2017 at 16:16
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.