24
\$\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\$
4
  • 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\$ Jun 14, 2017 at 11:16
  • \$\begingroup\$ Quite similar to Show tree rings age. \$\endgroup\$
    – manatwork
    Jun 14, 2017 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, 2017 at 11:23
  • \$\begingroup\$ @StefanDelport Right you are, I missed that. Thanks. \$\endgroup\$ Jun 14, 2017 at 12:09

18 Answers 18

8
\$\begingroup\$

Charcoal, 14 bytes

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

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

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Verbose mode should work now \$\endgroup\$
    – ASCII-only
    Jun 17, 2017 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\$
0
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\$
4
  • \$\begingroup\$ You seem to have regained your mind, j + m <= n + c can become n + c > j + m \$\endgroup\$
    – LiefdeWen
    Jun 14, 2017 at 14:20
  • \$\begingroup\$ As well then as i + m >= n to n < i + m \$\endgroup\$
    – LiefdeWen
    Jun 14, 2017 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, 2017 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\$ Jun 14, 2017 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\$
0
3
\$\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|.{[email protected].....
00000020: 0ae7 2e2f e624 7059 4850                 .../.$pYHP
\$\endgroup\$
2
  • \$\begingroup\$ You can combine your last two lines for two bytes saving Try it online! \$\endgroup\$
    – nmjcman101
    Jun 14, 2017 at 17:37
  • \$\begingroup\$ @nmjcman101 Ah, good point. Thanks! \$\endgroup\$
    – DJMcMayhem
    Jun 14, 2017 at 17:39
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\$

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\$
1
  • \$\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\$ Jun 15, 2017 at 1:34
1
\$\begingroup\$

Japt -h, 19 bytes

Takes input in reverse (c,b,a) and outputs an array of lines using = for the outer box, ! for the middle one and - for the inner one.

Æç-
4Æ=Õû¦gXz)NÅgXz

Try it

Æç-\n4Æ=Õû¦gXz)NÅgXz     :Implicit input of integers U=c, V=b & W=a
Æ                        :Map the range [0,U)
 ç-                      :  Repeat "-" U times
   \n                    :Reassign to U
     4Æ                  :Map each X in the range [0,4)
       =                 :  Reassign to U ...
        Õ                :  Transpose U
         û               :  Centre pad each element with (1) to length (2)
          ¦              :    "!=" (1)
           g             :    Get character at index (1)
            Xz           :    X floor divided by 2 (1)
               )         :    End index (1)
                N        :    Array of all inputs, i.e. [U,V,W] (2)
                 Å       :    Slice off the first element (2)
                  gXz    :    As above (2)
                         :Implicit output of last element of resulting array
\$\endgroup\$
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\$
2
  • \$\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, 2017 at 10:03
  • \$\begingroup\$ @Titus I don't know but my approch correct the input of invalid odd numbers \$\endgroup\$ Jun 15, 2017 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\$

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\$
0
\$\begingroup\$

Java 10, 265 252 218 181 172 bytes

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

-34 bytes thanks to @ceilingcat.

Explanation:

Try it online.

(a,b,c)->{                  // Method with three integer parameters and String return-type
  int r[][]=new int[a][a],  //  Create a grid with dimensions `a` by `a`,
                            //  filled with 0s by default
      t=a-b>>1,             //  Calculate (a-b)/2
      u=a-c>>1,             //  Calculate (a-c)/2 as well
  x=b*b;for(;x-->0;         //  Loop `x` in the range (b*b, 0]:
    r[x/b+t][x%b+t]=1;      //   Fill the cells for the second square with 1s
    if(x<c*c)               //   And if `x` is smaller than c*c:
      r[x/c+u][x%c+u]=8;    //    Also start filling the center square cells with 8s
  var s="";                 //  Then create a return-String, starting empty
  for(var q:r){             //  Loop over the rows of the matrix:
    for(int Q:q)            //   Inner loop over the columns of the row:
      s+=Q;                 //    Append the current digit to the result-String
    s+="\n";}               //   Append a trailing new-line after every row
  return s;}                //  Return the result-String
\$\endgroup\$
0
0
\$\begingroup\$

Canvas, 14 bytes

#*@H╶:*l⁸∔½:╋}

Try it here!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.