18
\$\begingroup\$

Inpsired by a youtube video from a fellow PPCG user...

You challenge is to use ASCII-art draw a Minecraft castle wall of Andesite and Diorite. The shape of the wall is the Cantor Set. For reference, the Cantor Set is made by repeating the following N times:

  • Triple the current step
  • Replace the middle one with blank space
  • Add a full line below it

This creates the following for the first four steps:

*

* *
***

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

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

However, your challenge is not quite that simple. You see, after the cantor set gets really big, it becomes boring to look at the same character repeated over and over and over. So we're going to change that by overlaying an alternating series of asterisks * and pound signs #. You should alternate on every three characters horizontally, and on every row vertically. (Of course leaving the spaces the same) For example, the second example will become:

* *
###

and the third example will become:

* *   * *
###   ###
***###***

For completeness, here are examples four and five:

#4
* *   * *         * *   * *
###   ###         ###   ###
***###***         ***###***
###***###***###***###***###

#5
* *   * *         * *   * *                           * *   * *         * *   * *
###   ###         ###   ###                           ###   ###         ###   ###
***###***         ***###***                           ***###***         ***###***
###***###***###***###***###                           ###***###***###***###***###
***###***###***###***###***###***###***###***###***###***###***###***###***###***

And one mega example, the 6th iteration:

* *   * *         * *   * *                           * *   * *         * *   * *                                                                                 * *   * *         * *   * *                           * *   * *         * *   * * 
###   ###         ###   ###                           ###   ###         ###   ###                                                                                 ###   ###         ###   ###                           ###   ###         ###   ###
***###***         ***###***                           ***###***         ***###***                                                                                 ***###***         ***###***                           ***###***         ***###***
###***###***###***###***###                           ###***###***###***###***###                                                                                 ###***###***###***###***###                           ###***###***###***###***###
***###***###***###***###***###***###***###***###***###***###***###***###***###***                                                                                 ***###***###***###***###***###***###***###***###***###***###***###***###***###***
###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###***###

The challenge

You must write a full program or function that accepts a positive integer for input, and outputs the N'th generation of this minecraft castle fractal. You can take Input and output by any reasonable method, and you do not have to worry about invalid inputs (such as numbers less than 1, floating point numbers, non-numbers, etc.).

The shortest answer, measured in bytes wins!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Related \$\endgroup\$
    – DJMcMayhem
    Commented Sep 18, 2016 at 2:07

6 Answers 6

5
\$\begingroup\$

Jelly, 43 36 35 bytes

ḶṚ3*µ5B¤xЀṁ€Ṁ×\Ṛ©1,‘xS$¤ṁ×®ị“*# ”Y

Just a start, I'm sure this could be shorter.

Try it online!

*For n > 5, your browser might wrap the output but if you copy-paste it into a non-wrapping editor, you will see the proper output.

Explanation

ḶṚ3*µ5B¤xЀṁ€Ṁ×\Ṛ©1,‘xS$¤ṁ×®ị“*# ”Y  Input: integer n
Ḷ                                    Create the range [0, n)
 Ṛ                                   Reverse it
  3*                                 Raise 3 to the power of each
    µ                                Begin a new monadic chain on the powers of 3
     5B¤                             Nilad. Get the binary digits of 5 = [1, 0, 1]
        xЀ                          Duplicate each of [1, 0, 1] to a power of 3 times
             Ṁ                       Get the maximum of the powers of 3
           ṁ€                        Reshape each to a length of that value
              ×\                     Cumulative products
                Ṛ©                   Reverse and save the result
                  1,‘xS$¤            Niladic chain.
                  1                    Start with 1
                    ‘                  Increment it
                   ,                   Pair them to get [1, 2]
                       $               Operate on [1, 2]
                      S                  Sum it to get 3
                     x                   Repeat each 3 times to get [1, 1, 1, 2, 2, 2]
                         ṁ           Reshape that to the saved table
                          ×®         Multiply elementwise with the saved table
                            ị“*# ”   Use each to as an index to select from "*# "
                                  Y  Join using newlines
                                     Return and print implicitly
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES7), 132 125 bytes

n=>[...Array(n)].map((_,i)=>[...Array(3**~-n)].map((_,j)=>/1/.test((j/3**i|0).toString(3))?" ":`*#`[j/3+i&1]).join``).join`\n`

Where \n represents the literal newline characer. ES6 version for 141 bytes:

f=
n=>[...Array(n)].map((_,i)=>[...Array(Math.pow(3,n-1))].map((_,j)=>/1/.test((j*3).toString(3).slice(0,~i))?" ":`*#`[j/3+i&1]).join``).join`
`
;
<input type=number min=1 oninput=o.textContent=f(+this.value)><pre id=o>

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

Python 2, 142 138 136 bytes

r=range
def f(n):
 for i in r(n+1):
  s="";d=i%2<1
  for k in r(3**i):s+="#*"[(6+d-1+k*(d*2-1))%6<3]
  exec"s+=len(s)*' '+s;"*(n-i);print s

This is the piece of code from here, and then edited for this challenge.

Will post an explanation later.

Also, BTW, two spaces are tabs.

Edit 1: 4 bytes saved thanks to @DJMcMayhem.

Edit 2: 2 bytes saved thanks to @daHugLenny.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Since it's Python 2, can't you remove the parentheses in exec("s+=len(s)*' '+s;"*(n-i))? \$\endgroup\$
    – acrolith
    Commented Sep 18, 2016 at 18:31
  • \$\begingroup\$ @daHugLenny Ah yeah, thanks! (Sorry for not replying soon enough) \$\endgroup\$
    – clismique
    Commented Sep 22, 2016 at 21:31
1
\$\begingroup\$

Ruby, 115 103 102 bytes

->n{g=->{T.tr"*#","#*"}
*s=?*
(n-1).times{|i|T=s[-1]
s=s.map{|l|l+' '*3**i+l}+[i<1??#*3:g[]+T+g[]]}
s}

Based on jsvnm's solution to the standard Cantor set golf.

-12 bytes thanks to Jordan.

\$\endgroup\$
4
  • \$\begingroup\$ g=->{T.tr"*#","#*"} \$\endgroup\$
    – Jordan
    Commented Sep 18, 2016 at 16:49
  • \$\begingroup\$ Also, s.map!{...} instead of s=s.map{...};s. \$\endgroup\$
    – Jordan
    Commented Sep 18, 2016 at 16:50
  • \$\begingroup\$ @Jordan s.map! would require the + to change to <<, and it'd end up the same length. I believe the s is still necessary at the end either way - the map is inside of a .times loop. \$\endgroup\$
    – m-chrzan
    Commented Sep 18, 2016 at 18:08
  • \$\begingroup\$ Ah, right you are. \$\endgroup\$
    – Jordan
    Commented Sep 18, 2016 at 18:15
1
\$\begingroup\$

J, 47 45 bytes

' *#'{~3(]*$@]$1 2#~[)(,:1)1&(,~],.0&*,.])~<:

Based on my solution to the Cantor set challenge.

Usage

   f =: ' *#'{~3(]*$@]$1 2#~[)(,:1)1&(,~],.0&*,.])~<:
   f 1
*
   f 2
* *
###
   f 3
* *   * *
###   ###
***###***

Explanation

' *#'{~3(]*$@]$1 2#~[)(,:1)1&(,~],.0&*,.])~<:  Input: n
                                           <:  Decrement n
                      (,:1)                    A constant [1]
                           1&(           )~    Repeating n-1 times on x starting
                                               with x = [1]
                                        ]        Identity function, gets x
                                   0&*           Multiply x elementwise by 0
                                      ,.         Join them together by rows
                                ]                Get x
                                 ,.              Join by rows
                           1  ,~                 Append a row of 1's and return
       3                                       The constant 3
        (                 )                    Operate on 3 and the result
                    [                          Get LHS = 3
               1 2                             The constant [1, 2]
                  #~                           Duplicate each 3 times
                                               Forms [1, 1, 1, 2, 2, 2]
           $@]                                 Get the shape of the result
              $                                Shape the list of [1, 2] to
                                               the shape of the result
         ]                                     Get the result
          *                                    Multiply elementwise between the
                                               result and the reshaped [1, 2]
' *#'                                        The constant string ' *#'
     {~                                       Select from it using the result
                                             as indices and return
\$\endgroup\$
1
\$\begingroup\$

PHP, 159 bytes

for($r=($n=--$argv[1])?["* *","###"]:["*"];++$i<$n;$r[]=$a.$b.$a){$a=strtr($b=end($r),"#*","*#");foreach($r as&$s)$s.=str_pad("",3**$i).$s;}echo join("\n",$r);

breakdown

for(
    $r=($n=--$argv[1])  // pre-decrease argument, initialize result
    ?["* *","###"]      // shorter than handling the special iteration 2 in the loop
    :["*"]              // iteration 1
    ;
    ++$i<$n             // further iterations:
    ;
    $r[]=$a.$b.$a       // 3. concatenate $a, $b, $a and add to result
)
{
                        // 1. save previous last line to $b, swap `*` with `#` to $a
    $a=strtr($b=end($r),"#*","*#"); 
                        // 2. duplicate all lines with spaces of the same length inbetween
    foreach($r as&$s)$s.=str_pad("",3**$i).$s;  # strlen($s)==3**$i
}
// output
echo join("\n",$r);
\$\endgroup\$

Your Answer

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

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