Question
· Apr 5, 2018

Drawing boxes

Hello, Community!

Here's an interesting task I found on the Internet.

Problem description

Write a method that would draw a box of a specified size.

The goal is to write the shortest method.

Here's a method signature (it can't be modified):

ClassMethod main(s As %Integer = 10)

And call sample:

>do ##class(ITPlanet.Task4).main(5)
#####
## ##
# # #
## ##
#####

>do ##class(ITPlanet.Task4).main(10)
##########
##      ##
# #    # #
#  #  #  #
#   ##   #
#   ##   #
#  #  #  #
# #    # #
##      ##
##########
 
>do ##class(ITPlanet.Task4).main(20)
####################
##                ##
# #              # #
#  #            #  #
#   #          #   #
#    #        #    #
#     #      #     #
#      #    #      #
#       #  #       #
#        ##        #
#        ##        #
#       #  #       #
#      #    #      #
#     #      #     #
#    #        #    #
#   #          #   #
#  #            #  #
# #              # #
##                ##
####################

Also, here's the code to  check your result length:

ClassMethod length(class = {$classname()}, method = "main") As %Integer
{
    #dim methodObj As %Dictionary.MethodDefinition
    set methodObj = ##class(%Dictionary.MethodDefinition).IDKEYOpen(class, method)
    quit methodObj.Implementation.Size
}

My best result is 91 76 so far.

What's yours? ;)

Discussion (15)2
Log in or sign up to continue

Sorry to be late. I was busy today:

Thanks to  @Eduard Lebedyuk

I did it in a traditional one-liner: 79  77 char.   + 4 char extra to read the size.

I'll wrap it into a method later to see how much waste of space this generates. devil

5 min. later:
OK. Method consumes 3 char. extra {} to enclose it + blank at the start   =>>> 82   80  ~3.9% overhead

s=1...4 looks odd but it improves.

f j=1:1:15 zw j d ##class(DC.size).main(j) 

j=1
#
j=2
##
##
j=3
###
###
###
j=4
####
####
####
####
j=5
#####
## ##
# # #
## ##
#####
j=6
######
##  ##
# ## #
# ## #
##  ##
######
j=7
#######
##   ##
# # # #
#  #  #
# # # #
##   ##
#######
j=8
########
##    ##
# #  # #
#  ##  #
#  ##  #
# #  # #
##    ##
########

My cheeky solution was 

 r=1:1:! c=1:1:w:r#s<2!(c#s<2)!(c=r)!(s-r+1=c) "#" " "

I'm not sure if it will copy/paste properly, but there's a backspace character in the string before the #  laugh I considered it cheeky because despite looking correct in the terminal it's definitely not if you compared it byte for byte wink

My best result is 77 72 69 67 so far.

Class ITPlanet.Task4 Abstract ]
{

ClassMethod main(As %Integer 10)
{
 x=1:1:y=1:1:w $c(y#s<2!$lf($lb(1,s,y,s-y+1),x)*3+32)
}

ClassMethod length(
  class = {$classname()},
  method "main"As %Integer CodeMode = expression ]
{
##class(%Dictionary.MethodDefinition).IDKEYOpen(classmethod).Implementation.Size
}

}

USER>##class(ITPlanet.Task4).length()
67
USER>##class(ITPlanet.Task4).main(11)

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

FOO>d ##class(FOO.Boxes).main(20)
 
####################
##                ##
# #              # #
#  #            #  #
#   #          #   #
#    #        #    #
#     #      #     #
#      #    #      #
#       #  #       #
#        ##        #
#        ##        #
#       #  #       #
#      #    #      #
#     #      #     #
#    #        #    #
#   #          #   #
#  #            #  #
# #              # #
##                ##
####################


FOO>w ##class(FOO.Boxes).length()
75

Still thinking, seems like it might go a bit smaller...

My solution and how I got there.

I started with this:

  r=1:1:s{c=1:1:s{r=1!(r=s)!(c=1)!(c=s)!(r=c)!(s=(c+r-1)){"#"}else{" "c=s{!}}}

First improvement was thanks to @Robert.Cemper who suggested moving i c=s{w !}}} into a first for:

  r=1:1:! c=1:1:r=1!(r=s)!(c=1)!(c=s)!(r=c)!(s=(c+r-1)){"#"}else{" "}

Finally got the idea of using $lb/$lf to get my best result of 76:

 f r=1:1:s w ! f c=1:1:s w $s($lf($lb(c,r,r=s,c=s,c=r,r+c-s),1):"#",1:" ")

Some other ideas that didn't pan out.

First of all I thought about replacing $lf($lb)) with $f() but -1 and 1x numbers became a problem:

  f r=1:1:s w ! f c=1:1:s w $s($f(c_r_(r=s)_(c=s)_(c=r)_$replace(r+c-s,-1,""),1):"#",1:" ")

Other idea was using $translate:

  f r=1:1:s w ! f c=1:1:s w $tr(''$lf($lb(c,r,r=s,c=s,c=r,r+c-s),1),10,"# ")

Interestingly if we allow the box to be made of any symbols, some other solutions became possible. For example binary box (63 symbols):

  f r=1:1:s w ! f c=1:1:s w '$lf($lb(c,r,r=s,c=s,c=r,r+c-s),1)