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? ;)
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 77726967 so far.
Class ITPlanet.Task4 [ Abstract ]
{
ClassMethod main(s As %Integer = 10)
{
f x=1:1:s w ! f y=1:1:s 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(class, method).Implementation.Size
}
}
USER>w ##class(ITPlanet.Task4).length()
67
USER>d ##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...
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.
{ 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)