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
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. ![]()
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.
j=1
#
j=2
##
##
j=3
###
###
###
j=4
####
####
####
####
j=5
#####
## ##
# # #
## ##
#####
j=6
######
## ##
# ## #
# ## #
## ##
######
j=7
#######
## ##
# # # #
# # #
# # # #
## ##
#######
j=8
########
## ##
# # # #
# ## #
# ## #
# # # #
## ##
########
That's mine:
{ f r=1:1:s w ! f c=1:1:s w $s(c=1!(r=1)!(r=s)!(c=s)!(c=r)!(s-r+1=c):"#",1:" ")}
Upd: 72
my code is disclosed above
My cheeky solution was
f r=1:1:s w ! f c=1:1:s w:r#s<2!(c#s<2)!(c=r)!(s-r+1=c) "#" w " "
I'm not sure if it will copy/paste properly, but there's a backspace character in the string before the #
I considered it cheeky because despite looking correct in the terminal it's definitely not if you compared it byte for byte ![]()
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)
Upd: 67
I like that
$lf($lb(1,s,y,s-y+1),x)
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>
###########
# #
# #
# #
#
# #
# #
# #
###########
FOO>d ##class(FOO.Boxes).main(20)
####################
## ##
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# ## #
# ## #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
# # # #
## ##
####################
FOO>w ##class(FOO.Boxes).length()
75
Still thinking, seems like it might go a bit smaller...
70 or 73, depending on how cheeky you'll let me be ![]()
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()
Let's finish this competition this Wednesday (so it would be a week) and publish our best efforts then.
ClassMethod main(s As %Integer = 10)
{ f i=1:1:s w ! f j=1:1:s w $S(j#s<2!(i#s<2)!(j=i)!(s-i+1=j):"#",1:" ") }
My solution and how I got there.
I started with this:
f r=1:1:s{f c=1:1:s{i r=1!(r=s)!(c=1)!(c=s)!(r=c)!(s=(c+r-1)){w "#"}else{w " "} i c=s{w !}}}First improvement was thanks to @Robert Cemper who suggested moving i c=s{w !}}} into a first for:
f r=1:1:s w ! f c=1:1:s i r=1!(r=s)!(c=1)!(c=s)!(r=c)!(s=(c+r-1)){w "#"}else{w " "}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)