23
\$\begingroup\$

Problem

given input a,b,c

where a,b,c are positive even integers

and a > b > c

Make a box of any allowed character with dimensions a x a

Center a box of a different allowed character with dimensions b x b within the previous

Center a box of another different allowed character with dimensions c x c within the previous

Allowed Characters are ASCII characters are in [a-zA-z0-9!@#$%^&*()+,./<>?:";=_-+]

Input a=6, b=4, c=2

######
#****#
#*@@*#
#*@@*#
#****#
######

Input a=8, b=6, c=2

########
#******#
#******#
#**@@**#
#**@@**#
#******#
#******#
########

Input a=12, b=6, c=2

############
############
############
###******###
###******###
###**@@**###
###**@@**###
###******###
###******###
############
############
############

Rules

  • Shortest code wins
  • Remember that you can choose which char to print within the range given
  • Trailing newlines accepted
  • Trailing whitespace accepted
  • functions may return string with newlines, string array, or print it
\$\endgroup\$
  • 5
    \$\begingroup\$ Will the input always be valid (i.e. each number is at least 2 less than the previous)? And will the numbers always be (all even) or (all odd) to ensure symmetrical drawing? \$\endgroup\$ – scatter Jun 14 '17 at 11:16
  • \$\begingroup\$ Quite similar to Show tree rings age. \$\endgroup\$ – manatwork Jun 14 '17 at 11:20
  • 1
    \$\begingroup\$ @Christian the first 3 lines define those requirements, please let me know if they are sufficient. \$\endgroup\$ – LiefdeWen Jun 14 '17 at 11:23
  • \$\begingroup\$ @StefanDelport Right you are, I missed that. Thanks. \$\endgroup\$ – scatter Jun 14 '17 at 12:09

16 Answers 16

7
\$\begingroup\$

Charcoal, 14 bytes

F#*@UO÷N²ι‖C←↑

Try it online! Link is to verbose version of code.

\$\endgroup\$
  • 1
    \$\begingroup\$ Verbose mode should work now \$\endgroup\$ – ASCII-only Jun 17 '17 at 6:17
7
\$\begingroup\$

Jelly,  20  19 bytes

-1 byte using the quick ` to avoid a link, as suggested by Erik the Outgolfer.

H»þ`€Ḣ>ЀHSUṚm€0m0Y

A full program taking a list [a,b,c] printing the boxes using a:2 b:1 c:0
... in fact, as is, it will work for up to 10 boxes, where the innermost box is 0 (for example).

Try it online!

How?

H»þ`€Ḣ>ЀHSUṚm€0m0Y - Main link: list of boxes, B = [a, b, c]
H                   - halve B = [a/2, b/2, c/2]
    €               - for €ach:
   `                -   repeat left argument as the right argument of the dyadic operation:
  þ                 -     outer product with the dyadic operation:
 »                  -       maximum
                    - ... Note: implicit range building causes this to yield
                    -       [[max(1,1),max(1,2),...,max(1,n)],
                    -        [max(2,1),max(2,2),...,max(2,n)],
                    -        ...
                    -        [max(n,1),max(n,2),...,max(n,n)]]
                    -       for n in [a/2,b/2,c/2]
     Ḣ              - head (we only really want n=a/2 - an enumeration of a quadrant)
         H          - halve B = [a/2, b/2, c/2]
       Ѐ           - map across right with dyadic operation:
      >             -   is greater than?
                    - ...this yields three copies of the lower-right quadrant
                    -    with 0 if the location is within each box and 1 if not
          S         - sum ...yielding one with 0 for the innermost box, 1 for the next, ...
           U        - upend (reverse each) ...making it the lower-left
            Ṛ       - reverse ...making it the upper-right
             m€0    - reflect €ach row (mod-index, m, with right argument 0 reflects)
                m0  - reflect the rows ...now we have the whole thing with integers
                  Y - join with newlines ...making a mixed list of integers and characters
                    - implicit print - the representation of a mixed list is "smashed"
\$\endgroup\$
7
\$\begingroup\$

Python 2, 107 103 bytes

a,b,c=input()
r=range(1-a,a,2)
for y in r:
 s=''
 for x in r:m=max(x,y,-x,-y);s+=`(m>c)+(m>b)`
 print s

Full program, prints boxes with a=2,b=1,c=0

Slightly worse answer, with list comprehension (104 bytes):

a,b,c=input()
r=range(1-a,a,2)
for y in r:print''.join(`(m>c)+(m>b)`for x in r for m in[max(x,y,-x,-y)])
\$\endgroup\$
5
\$\begingroup\$

C#, 274 232 bytes

using System.Linq;(a,b,c)=>{var r=new string[a].Select(l=>new string('#',a)).ToArray();for(int i=0,j,m=(a-b)/2,n=(a-c)/2;i<b;++i)for(j=0;j<b;)r[i+m]=r[i+m].Remove(j+m,1).Insert(j+++m,i+m>=n&i+m<n+c&j+m>n&j+m<=n+c?"@":"*");return r;}

Terrible even for C# so can definitely be golfed but my mind has gone blank.

Full/Formatted version:

using System;
using System.Linq;

class P
{
    static void Main()
    {
        Func<int, int, int, string[]> f = (a,b,c) =>
        {
            var r = new string[a].Select(l => new string('#', a)).ToArray();

            for (int i = 0, j, m = (a - b) / 2, n = (a - c) / 2; i < b; ++i)
                for (j = 0; j < b;)
                    r[i + m] = r[i + m].Remove(j + m, 1).Insert(j++ + m,
                        i + m >= n & i + m < n + c &
                        j + m > n & j + m <= n + c ? "@" : "*");

            return r;
        };

        Console.WriteLine(string.Join("\n", f(6,4,2)) + "\n");
        Console.WriteLine(string.Join("\n", f(8,6,2)) + "\n");
        Console.WriteLine(string.Join("\n", f(12,6,2)) + "\n");

        Console.ReadLine();
    }
}
\$\endgroup\$
  • \$\begingroup\$ You seem to have regained your mind, j + m <= n + c can become n + c > j + m \$\endgroup\$ – LiefdeWen Jun 14 '17 at 14:20
  • \$\begingroup\$ As well then as i + m >= n to n < i + m \$\endgroup\$ – LiefdeWen Jun 14 '17 at 14:22
  • \$\begingroup\$ you use i+m 4 times, so you can add it to a variable in your for to save some \$\endgroup\$ – LiefdeWen Jun 14 '17 at 14:29
  • \$\begingroup\$ Not checked these properly, but: you never use i in isolation, just initialise i=m and compare i<b+m; or... just use i, init i=0 but loop on i<a, then add r[i]=new string('#',a), next to j=0, and add a condition to check i is within bounds for j's loop (this ought to pay off, because you lose all the Linq). \$\endgroup\$ – VisualMelon Jun 14 '17 at 16:47
3
\$\begingroup\$

Haskell, 126 bytes

f a b c=r[r["#*@"!!(v c+v b)|x<-[1..d a],let v k|x>a#k&&y>a#k=1|2>1=0]|y<-[1..d a]]where r x=x++reverse x;d=(`div`2);x#y=d$x-y

Try it online!

\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 174 170 147 bytes

a=>b=>c=>(d=("#"[r="repeat"](a)+`
`)[r](f=a/2-b/2))+(e=((g="#"[r](f))+"*"[r](b)+g+`
`)[r](h=b/2-c/2))+(g+(i="*"[r](h))+"@"[r](c)+i+g+`
`)[r](c)+e+d

Try it

fn=
a=>b=>c=>(d=("#"[r="repeat"](a)+`
`)[r](f=a/2-b/2))+(e=((g="#"[r](f))+"*"[r](b)+g+`
`)[r](h=b/2-c/2))+(g+(i="*"[r](h))+"@"[r](c)+i+g+`
`)[r](c)+e+d
oninput=_=>+x.value>+y.value&&+y.value>+z.value&&(o.innerText=fn(+x.value)(+y.value)(+z.value))
o.innerText=fn(x.value=12)(y.value=6)(z.value=2)
label,input{font-family:sans-serif;}
input{margin:0 5px 0 0;width:50px;}
<label for=x>a: </label><input id=x min=6 type=number step=2><label for=y>b: </label><input id=y min=4 type=number step=2><label for=z>c: </label><input id=z min=2 type=number step=2><pre id=o>


Explanation

a=>b=>c=>            :Anonymous function taking the 3 integers as input via parameters a, b & c
(d=...)              :Assign to variable d...
("#"[r="repeat"](a)  :  # repeated a times, with the repeat method aliased to variable r in the process.
+`\n`)               :  Append a literal newline.
[r](f=a/2-b/2)       :  Repeat the resulting string a/2-b/2 times, assigning the result of that calculation to variable f.
+                    :Append.
(e=...)              :Assign to variable e...
(g=...)              :  Assign to variable g...
"#"[r](f)            :    # repeated f times.
+"*"[r](b)           :  Append * repeated b times.
+g+`\n`)             :  Append g and a literal newline.
[r](h=b/2-c/2)       :  Repeat the resulting string b/2-c/2 times, assigning the result of that calculation to variable h.
+(...)               :Append ...
g+                   :  g
(i=...)              :  Assign to variable i...
"*"[r](h)            :    * repeated h times.
+"@"[r](c)           :  @ repeated c times
+i+g+`\n`)           :  Append i, g and a literal newline.
[r](c)               :...repeated c times.
+e+d                 :Append e and d.
\$\endgroup\$
2
\$\begingroup\$

C (gcc), 97 bytes

x,y;f(a,b,c){for(y=1-a;y<a;y+=2,puts(""))for(x=1-a;x<a;x+=2)printf(x/c|y/c?x/b|y/b?"#":"*":"@");}

Try it online!

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

V, 70, 44, 42 bytes

Àé#@aÄÀG@b|{r*ÀG@c|{r@òjdòÍ.“.
ç./æ$pYHP

Try it online!

This is hideous. Eww. Much better. Still not the shortest, but at least somewhat golfy.

Saved two bytes thanks to @nmjmcman101!

Hexdump:

00000000: c0e9 2340 61c4 c047 4062 7c16 7b72 2ac0  ..#@a..G@b|.{r*.
00000010: 4740 637c 167b 7240 f26a 64f2 cd2e 932e  G@c|.{r@.jd.....
00000020: 0ae7 2e2f e624 7059 4850                 .../.$pYHP
\$\endgroup\$
  • \$\begingroup\$ You can combine your last two lines for two bytes saving Try it online! \$\endgroup\$ – nmjcman101 Jun 14 '17 at 17:37
  • \$\begingroup\$ @nmjcman101 Ah, good point. Thanks! \$\endgroup\$ – DJMcMayhem Jun 14 '17 at 17:39
1
\$\begingroup\$

MATL, 26 23 22 20 18 bytes

2/t:<sPtPh!Vt!2$X>

Input is a column vector [a; b; c]. Output uses characters 2, 1, 0.

Try it online!

As an aside, it works for up to ten boxes, not just three Here's an example with five boxes.

\$\endgroup\$
1
\$\begingroup\$

Mathematica, 49 bytes

Print@@@Fold[#~CenterArray~{#2,#2}+1&,{{}},{##}]&

Takes input [c, b, a]. The output is a=1, b=2, c=3.

How?

Print@@@Fold[#~CenterArray~{#2,#2}+1&,{{}},{##}]&
                                                &  (* Function *)
        Fold[                        ,{{}},{##}]   (* Begin with an empty 2D array.
                                                      iterate through the input: *)
                                    &              (* Function *)
             #~CenterArray~{#2,#2}                 (* Create a 0-filled array, size
                                                      (input)x(input), with the array
                                                      from the previous iteration
                                                      in the center *)
                                  +1               (* Add one *)
Print@@@                                           (* Print the result *)
\$\endgroup\$
  • \$\begingroup\$ @Jenny_mathy In the question: *functions may return string with newlines, string array, or print it." Grid does not make a String nor does it Print it. \$\endgroup\$ – JungHwan Min Jun 15 '17 at 1:34
0
\$\begingroup\$

PHP>=7.1, 180 bytes

In this case i hate that variables begin with a $ in PHP

for([,$x,$y,$z]=$argv;$i<$x*$x;$p=$r%$x)echo XYZ[($o<($l=$x-$a=($x-$y)/2)&$o>($k=$a-1)&$p>$k&$p<$l)+($o>($m=$k+$b=($y-$z)/2)&$o<($n=$l-$b)&$p>$m&$p<$n)],($o=++$i%$x)?"":"\n".!++$r;

PHP Sandbox Online

\$\endgroup\$
  • \$\begingroup\$ In this case, paint before print is a lot shorter. :D Or is it because I use $argv as an array? Have you tried that? Have You tried separate ternaries? \$\endgroup\$ – Titus Jun 15 '17 at 10:03
  • \$\begingroup\$ @Titus I don't know but my approch correct the input of invalid odd numbers \$\endgroup\$ – Jörg Hülsermann Jun 15 '17 at 11:06
0
\$\begingroup\$

Mathematica, 173 bytes

(d=((a=#1)-(b=#2))/2;e=(b-(c=#3))/2;z=1+d;x=a-d;h=Table["*",a,a];h[[z;;x,z;;x]]=h[[z;;x,z;;x]]/.{"*"->"#"};h[[z+e;;x-e,z+e;;x-e]]=h[[z+e;;x-e,z+e;;x-e]]/.{"#"->"@"};Grid@h)&

input

[12,6,2]

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

Python 2, 87 bytes

a,_,_=t=input();r=~a
exec"r+=2;print sum(10**x/9*10**((a-x)/2)*(r*r<x*x)for x in t);"*a

Try it online!

Arithmetically computes the numbers to print by adding numbers of the form 111100. There's a lot of ugliness, probably room for improvement.

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

Java 8, 265 252 bytes

 a->b->c->{int r[][]=new int[a][a],x=0,y,t;for(;x<a;x++)for(y=0;y<a;r[x][y++]=0);for(t=(a-b)/2,x=t;x<b+t;x++)for(y=t;y<b+t;r[x][y++]=1);for(t=(a-c)/2,x=t;x<c+t;x++)for(y=t;y<c+t;r[x][y++]=8);String s="";for(int[]q:r){for(int Q:q)s+=Q;s+="\n";}return s;}

-13 bytes by replacing characters with digits.

Can definitely be golfed by using a different approach.

Explanation:

Try it here.

a->b->c->{                         // Method with three integer parameters and String return-type
  int r[][]=new int[a][a],         //  Create a grid the size of `a` by `a`
      x=0,y,t;                     //  Some temp integers
  for(;x<a;x++)for(y=0;y<a;r[x][y++]=0);
                                   //  Fill the entire grid with zeros
  for(t=(a-b)/2,x=t;               //  Start at position `(a-b)/2` (inclusive)
      x<b+t;x++)                   //  to position `b+((a-b)/2)` (exclusive)
    for(y=t;y<b+t;r[x][y++]=1);    //   And replace the zeros with ones
  for(t=(a-c)/2,x=t;               //  Start at position `(a-c)/2` (inclusive)
      x<c+t;x++)                   //  to position `c+((a-b)/2)` (exclusive)
    for(y=t;y<c+t;r[x][y++]=8);    //   And replace the ones with eights
  String s="";                     //  Create a return-String
  for(int[]q:r){                   //  Loop over the rows
    for(int Q:q)                   //   Inner loop over the columns
      s+=Q;                        //    and append the result-String with the current digit
                                   //   End of columns-loop (implicit / single-line body)
    s+="\n";                       //   End add a new-line after every row
  }                                //  End of rows-loop
  return s;                        //  Return the result-String
}                                  // End of method
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 112

Anonymous function returning a multi line string. Characters 0,1,2

(a,b,c)=>eval("for(o='',i=-a;i<a;o+=`\n`,i+=2)for(j=-a;j<a;j+=2)o+=(i>=c|i<-c|j>=c|j<-c)+(i>=b|i<-b|j>=b|j<-b)")

Less golfed

(a,b,c)=>{
  for(o='',i=-a;i<a;o+=`\n`,i+=2)
    for(j=-a;j<a;j+=2)
      o+=(i>=c|i<-c|j>=c|j<-c)+(i>=b|i<-b|j>=b|j<-b)
  return o
}  

var F=
(a,b,c)=>eval("for(o='',i=-a;i<a;o+=`\n`,i+=2)for(j=-a;j<a;j+=2)o+=(i>=c|i<-c|j>=c|j<-c)+(i>=b|i<-b|j>=b|j<-b)")

function update()
{
  var [a,b,c]=I.value.match(/\d+/g)
  O.textContent=F(a,b,c)
}

update()
  
a,b,c <input id=I value='10 6 2' oninput='update()'>
<pre id=O></pre>

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

PHP >= 5.6, 121 bytes

for($r=A;$p?:$p=($z=$argv[++$i])**2;)$r[((--$p/$z|0)+$o=($w=$w?:$z)-$z>>1)*$w+$p%$z+$o]=_BCD[$i];echo chunk_split($r,$w);

Run with -nr or test it online.

Combined loops again ... I love them!

breakdown

for($r=A;                           # initialize $r (result) to string
    $p?:$p=($z=$argv[++$i])**2;)    # loop $z through arguments, loop $p from $z**2-1 to 0
    $r[((--$p/$z|0)+$o=
        ($w=$w?:$z)                     # set $w (total width) to first argument
        -$z>>1)*$w+$p%$z+$o]            # calculate position: (y+offset)*$w+x+offset
        =_BCD[$i];                      # paint allowed character (depending on $i)
echo chunk_split($r,$w);            # insert newline every $w characters and print
\$\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.