Written by

Senior Cloud Architect at InterSystems
MOD
Question Eduard Lebedyuk · 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.MethodDefinitionset methodObj = ##class(%Dictionary.MethodDefinition).IDKEYOpen(class, method)
    quit methodObj.Implementation.Size
}

My best result is 9176 so far.

What's yours? ;)

Comments

Robert Cemper · Apr 5, 2018

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
########
##    ##
# #  # #
#  ##  #
#  ##  #
# #  # #
##    ##
########
0
Robert Cemper  Apr 9, 2018 to Robert Cemper

That's mine:

ClassMethod main(As %Integer = 10)
r=1:1:! c=1:1:$s(c=1!(r=1)!(r=s)!(c=s)!(c=r)!(s-r+1=c):"#",1:" ")}
0
Sean Connelly  Apr 11, 2018 to Sean Connelly
i=1:1:! j=1:1:$c(i=1!(i=s)!(j=1)!(j=s)!(j=i)!(s-i+1=j)*3+32)
0
Sebastian Patane  Apr 11, 2018 to Sebastian Patane

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

0
John Murray  Apr 10, 2018 to Zenkov Artem

Nice! And you can shave off 3 characters by using $EXTRACT instead of $SELECT

f i=1:1:s w ! f j=1:1:s w $e(" #",j#s<2!(i#s<2)!(j=i)!(s-i+1=j)+1)

0
Robert Cemper  Apr 11, 2018 to Vitaliy Serdtsev

I like that    

$lf($lb(1,s,y,s-y+1),x)
0
Vitaliy Serdtsev · Apr 6, 2018

My best result is <FONT COLOR=red>77726967</FONT> so far.

<FONT COLOR="#000080">Class ITPlanet.Task4 </FONT><FONT COLOR="#000000">[ </FONT><FONT COLOR="#000080">Abstract </FONT><FONT COLOR="#000000">]
{

</FONT><FONT COLOR="#000080">ClassMethod </FONT><FONT COLOR="#000000">main(</FONT><FONT COLOR="#ff00ff">s </FONT><FONT COLOR="#000080">As %Integer </FONT><FONT COLOR="#000000">= </FONT><FONT COLOR="#000080">10</FONT><FONT COLOR="#000000">) {  </FONT><FONT COLOR="#0000ff">f </FONT><FONT COLOR="#800000">x</FONT><FONT COLOR="#000000">=1:1:</FONT><FONT COLOR="#800000">s </FONT><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#000000">! </FONT><FONT COLOR="#0000ff">f </FONT><FONT COLOR="#800000">y</FONT><FONT COLOR="#000000">=1:1:</FONT><FONT COLOR="#800000">s </FONT><FONT COLOR="#0000ff">w $c</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">y</FONT><FONT COLOR="#000000">#</FONT><FONT COLOR="#800000">s</FONT><FONT COLOR="#000000"><2!</FONT><FONT COLOR="#0000ff">$lf</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#0000ff">$lb</FONT><FONT COLOR="#000000">(1,</FONT><FONT COLOR="#800000">s</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">y</FONT><FONT COLOR="#000000">,</FONT><FONT COLOR="#800000">s</FONT><FONT COLOR="#000000">-</FONT><FONT COLOR="#800000">y</FONT><FONT COLOR="#000000">+1),</FONT><FONT COLOR="#800000">x</FONT><FONT COLOR="#000000">)*3+32)</FONT> <FONT COLOR="#000000">}

</FONT><FONT COLOR="#000080">ClassMethod </FONT><FONT COLOR="#000000">length(   </FONT><FONT COLOR="#ff00ff">class </FONT><FONT COLOR="#000000">= {</FONT><FONT COLOR="#0000ff">$classname</FONT><FONT COLOR="#000000">()},   </FONT><FONT COLOR="#ff00ff">method </FONT><FONT COLOR="#000000">= </FONT><FONT COLOR="#800080">"main"</FONT><FONT COLOR="#000000">) </FONT><FONT COLOR="#000080">As %Integer </FONT><FONT COLOR="#000000">[ </FONT><FONT COLOR="#000080">CodeMode </FONT><FONT COLOR="#000000">= expression ] { </FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">%Dictionary.MethodDefinition</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">IDKEYOpen</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#800000">class</FONT><FONT COLOR="#000000">, </FONT><FONT COLOR="#800000">method</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">Implementation</FONT><FONT COLOR="#000000">.</FONT><FONT COLOR="#0000ff">Size </FONT><FONT COLOR="#000000">}

}</FONT>

USER><FONT COLOR="#0000ff">w </FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">ITPlanet.Task4</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">length</FONT><FONT COLOR="#000000">()</FONT> 67 USER><FONT COLOR="#0000ff">d </FONT><FONT COLOR="#000080">##class</FONT><FONT COLOR="#000000">(</FONT><FONT COLOR="#008080">ITPlanet.Task4</FONT><FONT COLOR="#000000">).</FONT><FONT COLOR="#0000ff">main</FONT><FONT COLOR="#000000">(11)</FONT>

###########

# #

# #

# #

#

# #

# #

# #

###########

0
Sean Connelly · Apr 7, 2018

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


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

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

0
Sebastian Patane · Apr 9, 2018

70 or 73, depending on how cheeky you'll let me be wink

edit: 69 for my cheeky solution, the other one was the same as Zenkov's below but I wasted a character on a for bracket because I foolishly put my newline on the other side of the $s()

0
Eduard Lebedyuk · Apr 9, 2018

Let's finish this competition this Wednesday (so it would be a week) and publish our best efforts then.

0
Zenkov Artem · Apr 9, 2018

ClassMethod main(As %Integer = 10)
 i=1:1:! j=1:1:$S(j#s<2!(i#s<2)!(j=i)!(s-i+1=j):"#",1:" "}

0
Eduard Lebedyuk · Apr 11, 2018

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)
0