14
\$\begingroup\$

Given two positive integers, 'a' and 'b', output an ascii-art "box" that is a characters wide and b characters tall. For example, with '4' and '6':

****
*  *
*  *
*  *
*  *
****

Simple right? Here's the twist: The border of the box must be the characters of "a" and "b" alternating. This starts at the top left corner, and continues in a clockwise spiral. For example, the previous example with 4 and 6 should be

4646
6  4
4  6
6  4
4  6
6464

A and B may be two-digit numbers. For example, the inputs "10" and "3" should output this:

1031031031
1        0
3013013013

In order to keep the output relatively small, you do not have to support three or more digit numbers. Also, since inputs are restricted to positive integers, '0' is an invalid input, which you do not have to handle.

Here are some more test cases:

Input: (3, 5)
Output:

353
5 5
3 3
5 5
353

Input: (1, 1)
Output:

1

Input: (4, 4)
Output:

4444
4  4
4  4
4444

Input: (27, 1)
Output:

271271271271271271271271271

Input: (1, 17)
Output:

1
1
7
1
1
7
1
1
7
1
1
7
1
1
7
1
1

Input: (12, 34):
Output:

123412341234
4          1
3          2
2          3
1          4
4          1
3          2
2          3
1          4
4          1
3          2
2          3
1          4
4          1
3          2
2          3
1          4
4          1
3          2
2          3
1          4
4          1
3          2
2          3
1          4
4          1
3          2
2          3
1          4
4          1
3          2
2          3
1          4
432143214321

You may take input and output in any reasonable format, and standard loopholes are banned. Since this is code-golf, the shortest answer in bytes wins!

\$\endgroup\$
  • \$\begingroup\$ Related \$\endgroup\$ – DJMcMayhem Aug 18 '16 at 6:31
  • \$\begingroup\$ Must I start the pattern from the top left hand corner clockwise? \$\endgroup\$ – Leaky Nun Aug 18 '16 at 6:33
  • \$\begingroup\$ @LeakyNun Yes, that is necessary. \$\endgroup\$ – DJMcMayhem Aug 18 '16 at 6:33
  • \$\begingroup\$ If a is 1 is it the left wall or the right wall? \$\endgroup\$ – Leaky Nun Aug 18 '16 at 6:42
  • 7
    \$\begingroup\$ Isn't the first example wrong? (3,5) should be 3 wide and 5 tall \$\endgroup\$ – Brian Aug 18 '16 at 10:27
4
\$\begingroup\$

Pyth, 65 51 bytes

juXGhHX@GhHeH@jkQ~hZ{s[+L]0UhQ+R]thQUeQ+L]teQ_UhQ+R]0_UeQ)m*;hQeQ
AQjuXGhHX@GhHeH@jkQ~hZ{s[,L0G,RtGH_,LtHG_,R0H)m*;GH

Try it online!

\$\endgroup\$
4
\$\begingroup\$

C#, 301 bytes

I'm sure there is a lot more golfing that can be done here but I'm just happy I got a solution that worked.

I found a bug where the bottom line was in the wrong order, damnit!

a=>b=>{var s=new string[b];int i=4,c=b-2,k=a;var t="";for(;i++<2*(a+b);)t+=t.EndsWith(a+"")?b:a;s[0]=t.Substring(0,a);if(b>2){for(i=0;++i<b-1;)s[i]=(a<2?t.Substring(1,c):t.Substring(2*a+c))[c-i]+(a>1?new string(' ',a-2)+t.Substring(a,c)[i-1]:"");for(;--k>=0;)s[b-1]+=t.Substring(a+c,a)[k];}return s;};

Old version: 280 bytes

a=>b=>{var s=new string[b];int i=4,c=b-2;var t="";for(;i++<2*(a+b);)t+=t.EndsWith(a+"")?b:a;s[0]=t.Substring(0,a);if(b>2){for(i=0;++i<b-1;)s[i]=(a<2?t.Substring(1,c):t.Substring(2*a+c))[c-i]+(a>1?new string(' ',a-2)+t.Substring(a,c)[i-1]:"");s[b-1]=t.Substring(a+c,a);}return s;};
\$\endgroup\$
2
\$\begingroup\$

Python 2, 199 bytes

w,h=input()
s=(`w`+`h`)*w*h
r=[s[:w]]+[[" "for i in[0]*w]for j in[0]*(h-2)]+[s[w+h-2:2*w+h-2][::-1]]*(h>1)
for y in range(1,h-1):r[y][w-1],r[y][0]=s[w+y-1],s[w+h+w-2-y]
print"\n".join(map("".join,r))
\$\endgroup\$
2
\$\begingroup\$

Ruby, 128 bytes

->w,h{s="%d%d"%[w,h]*q=w+h;a=[s[0,w]];(h-2).times{|i|a<<(s[2*q-5-i].ljust(w-1)+s[w+i,1])[-w,w]};puts a,h>1?(s[q-2,w].reverse):p}

Outputs trailing newline if height is 1.

Ideone link: https://ideone.com/96WYHt

\$\endgroup\$
  • 1
    \$\begingroup\$ You can do [w,h]*"" instead of "%d%d"%[w,h] for 4 bytes, and you don't need the parentheses around s[q-2,w].reverse, but then you'll need a space after the :, so -1 byte. \$\endgroup\$ – Jordan Aug 22 '16 at 6:27
2
\$\begingroup\$

JavaScript, 213 212 202

c=>a=>{for(a=$=a,c=_=c,l=c*a*2,b=0,s=Array(l+1).join(c+""+a),O=W=s.substr(0,a),W=W.substr(0,a-2).replace(/./g," ");--_;)O+="\n"+s[l-c+_]+W+s[$++];return O+"\n"+[...s.substr(l-a-c+1,a)].reverse().join``}

Surely has room for improvement.

Edit: Saved a byte thanks to TheLethalCoder

\$\endgroup\$
  • \$\begingroup\$ I think `${c}${a}`.repeat(l+1) might save you a byte. \$\endgroup\$ – Neil Aug 18 '16 at 19:17
  • \$\begingroup\$ Oh, and isn't' W=W.substr(0,a-2).replace(/./g," ") the same as W=" ".repeat(a-2)? (Does your code actually work for a=1?) \$\endgroup\$ – Neil Aug 18 '16 at 20:11
2
\$\begingroup\$

C, 311 bytes

char s[5];sprintf(s,"%d%d",a, b);int z=strlen(s);int i=0;while(i<a){printf("%c",s[i++%z]);}if(b>2){i=1;while(i<b-1){char r=s[(a+i-1)%z];char l=s[(2*a+2*b-i-4)%z];if(a>1){printf("\n%c%*c",l,a-1,r);}else{printf("\n%c",l);}i++;}}printf("\n");if(b>1){i=0;while(i<a){printf("%c",s[(2*a+b-i-3)%z]);i++;}printf("\n");}

Uses automatically included libraries stdio.h and string.h.

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

JavaScript (ES6), 171 bytes

(w,h)=>[...Array(h)].map((_,i)=>i?++i<h?(w>1?s[p+p+1-i]+` `.repeat(w-2):``)+s[w+i-2]:[...s.substr(p,w)].reverse().join``:s.slice(0,w),s=`${w}${h}`.repeat(p=w+h-2)).join`\n`

Where \n represents the literal newline character. Creates a repeated digit string, then decides what to concatenate based on which row we're on; top row is just the initial slice of the repeated digit string, bottom row (if any) is a reversed slice from the middle of the string, while intervening rows are built up using characters taken from other parts of the string.

\$\endgroup\$
  • \$\begingroup\$ You can use currying by changing (w,h)=> to w=>h=> to save a byte \$\endgroup\$ – TheLethalCoder Aug 19 '16 at 8:03
0
\$\begingroup\$

TSQL, 291 bytes

Golfed:

DECLARE @ INT=5,@2 INT=4

,@t INT,@z varchar(max)SELECT @t=iif(@*@2=1,1,(@+@2)*2-4),@z=left(replicate(concat(@,@2),99),@t)v:PRINT iif(len(@z)=@t,left(@z,@),iif(len(@z)>@,right(@z,1)+isnull(space(@-2)+left(@z,1),''),reverse(@z)))SET @z=iif(len(@z)=@t,stuff(@z,1,@,''),substring(@z,2,abs(len(@z)-2)))IF @<=len(@z)goto v

Ungolfed:

DECLARE @ INT=5,@2 INT=4

,@t INT,@z varchar(max)
SELECT @t=iif(@*@2=1,1,(@+@2)*2-4),@z=left(replicate(concat(@,@2),99),@t)

v:
  PRINT
    iif(len(@z)=@t,left(@z,@),iif(len(@z)>@,right(@z,1)
      +isnull(space(@-2)+left(@z,1),''),reverse(@z)))
  SET @z=iif(len(@z)=@t,stuff(@z,1,@,''),substring(@z,2,abs(len(@z)-2)))
IF @<=len(@z)goto v

Fiddle

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

Python 3, 155 148 bytes

Golfed off 7 more bytes:

p=print
def f(w,h):
 s=((str(w)+str(h))*w*h)[:2*w+2*h-4or 1];p(s[:w])
 for i in range(h-2):p(['',s[-i-1]][w>1]+' '*(w-2)+s[w+i])
 p(s[1-h:1-h-w:-1])

Substituted 2*w+2*h-4or 1 for max(1,2*w+2*h-4) and ['',s[-i-1]][w>1] for (s[-i-1]if w>1else'').

Prior version:

p=print
def f(w,h):
 s=((str(w)+str(h))*w*h)[:max(1,2*w+2*h-4)];p(s[:w])
 for i in range(h-2):p((s[-i-1]if w>1else'')+' '*(w-2)+s[w+i])
 p(s[1-h:1-h-w:-1])
\$\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.