Task
Produce a graphical or ASCII-art representation of a Sierpinski carpet of order   N.



For example, the Sierpinski carpet of order   3   should look like this:

###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################
#########         #########
# ## ## #         # ## ## #
#########         #########
###   ###         ###   ###
# #   # #         # #   # #
###   ###         ###   ###
#########         #########
# ## ## #         # ## ## #
#########         #########
###########################
# ## ## ## ## ## ## ## ## #
###########################
###   ######   ######   ###
# #   # ## #   # ## #   # #
###   ######   ######   ###
###########################
# ## ## ## ## ## ## ## ## #
###########################

The use of the   #   character is not rigidly required for ASCII art.

The important requirement is the placement of whitespace and non-whitespace characters.



Related task

   Sierpinski triangle


declare
  %% A carpet is a list of lines.
  fun {NextCarpet Carpet}
     {Flatten
      [{Map Carpet XXX}
       {Map Carpet X_X}
       {Map Carpet XXX}
      ]}
  end
 
  fun {XXX X} X#X#X end
  fun {X_X X} X#{Spaces {VirtualString.length X}}#X end
  fun {Spaces N} if N == 0 then nil else & |{Spaces N-1} end end
 
  fun lazy {Iterate F X}
     X|{Iterate F {F X}}
  end
 
  SierpinskiCarpets = {Iterate NextCarpet ["#"]}
in
  %% print all lines of the Sierpinski carpet of order 3
  {ForAll {Nth SierpinskiCarpets 4} System.showInfo}