Code golf ABC's: The ASCII Box Challenge

14

1

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!

James

Posted 2016-08-18T06:31:24.073

Reputation: 54 537

Related – James – 2016-08-18T06:31:51.593

Must I start the pattern from the top left hand corner clockwise? – Leaky Nun – 2016-08-18T06:33:17.257

@LeakyNun Yes, that is necessary. – James – 2016-08-18T06:33:59.573

If a is 1 is it the left wall or the right wall? – Leaky Nun – 2016-08-18T06:42:48.507

@LeakyNun I'm not sure if it makes any difference. Either way, I added a test case with a = 1 – James – 2016-08-18T06:46:25.623

do i have to print the box? – downrep_nation – 2016-08-18T08:32:53.677

7Isn't the first example wrong? (3,5) should be 3 wide and 5 tall – Brian – 2016-08-18T10:27:19.423

@Brian Yes, you're right. Sorry about that, fixed now. – James – 2016-08-18T14:56:24.563

Is a leading newline ok? – jrich – 2016-08-18T15:10:11.830

Answers

4

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!

Leaky Nun

Posted 2016-08-18T06:31:24.073

Reputation: 45 011

4

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

TheLethalCoder

Posted 2016-08-18T06:31:24.073

Reputation: 6 930

2

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

Loovjo

Posted 2016-08-18T06:31:24.073

Reputation: 7 357

2

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

user2428118

Posted 2016-08-18T06:31:24.073

Reputation: 2 000

I think \${c}${a}`.repeat(l+1)` might save you a byte. – Neil – 2016-08-18T19:17:48.103

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?) – Neil – 2016-08-18T20:11:02.373

2

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

Leibrug

Posted 2016-08-18T06:31:24.073

Reputation: 121

1You 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. – Jordan – 2016-08-22T06:27:56.723

2

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.

ncke

Posted 2016-08-18T06:31:24.073

Reputation: 151

2

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.

Neil

Posted 2016-08-18T06:31:24.073

Reputation: 95 035

You can use currying by changing (w,h)=> to w=>h=> to save a byte – TheLethalCoder – 2016-08-19T08:03:13.783

0

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

t-clausen.dk

Posted 2016-08-18T06:31:24.073

Reputation: 2 874

0

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])

RootTwo

Posted 2016-08-18T06:31:24.073

Reputation: 1 749