This was my O(n) prototype in Haskell. Which helped me to find an O(1) solution. It is not very haskellish to iterate many IO actions, but I deliberately chose a Challenge that is not very natural to Haskell. Well, to keep the data structure in O(n) I had to give the data linewise to IO:
importText.PrintftypeSize=InttypeLine=Intspiral::Size->Line->[Int]spiralnline-- even spirals add a top line and a right column to the smaller odd spiral|evenn&&line==0=[sqr-1,sqr-2..sqr-n]-- top line|evenn&&line>0=spiral(n-1)(line-1)++[sqr-n-line]-- odd spirals add a left column and a bottom line to the smaller even spiral|oddn&&line<n-1=[sqr-2*n+1+line]++spiral(n-1)line|otherwise=[sqr-n..sqr-1]-- bottom linewheresqr=n^2printLine::Size->Line->IO()printLinenl=(putStrLn.unwords.map(printf"%*v"len))(spiralnl)wherelen=(length.show)(n^2-1)printSpiral::Size->IO()printSpiraln=mapM_(printLinen)[0..n-1]main=printSpiral10
It catched my eye, that the spiral structure is represented in the 'spiral' function. I was in a veeery playful mood and worked this out much further by embedding the interesting part in an ASCII graphic of the spiral structure: :-)
importText.PrintftypeSize=InttypeLine=Intspiral::Size->Line->[Int]spiralnline-- even spirals add a top line and a right column to the smaller odd spiral-- +------------------------------+|evenn&&line==0=[sqr-1,sqr-2..sqr-n]-- top line-- +------------------------+-----+-- | | |-- | | |-- | | ||evenn&&line>0=spiral(n-1)(line-1)++rce-- rce: right col element-- | | |-- | | |-- | | |-- +------------------------+-----+---- odd spirals add a left column and a bottom line to the smaller even spiral---- +-----+------------------------+-- | | |-- | | |-- | | ||oddn&&line<n-1=lce++spiral(n-1)line-- lce: left col element-- | | |-- | | |-- | | |-- +-----+------------------------+|otherwise=[sqr-n..sqr-1]-- bottom line-- +------------------------------+wheresqr=n^2rce=[sqr-n-line]-- right column elementlce=[sqr-n-(n-1)+line]-- left column elementprintLine::Size->Line->IO()printLinenline=(putStrLn.unwords.map(printf"%*v"len))(spiralnline)wherelen=(length.show)(n^2-1)printSpiral::Size->IO()printSpiraln=mapM_(printLinen)[0..n-1]main=printSpiral10
Literate Programming? That's old hat! This is graphical programming! :-D (Don't take me serious.)
Maybe we see some more recursive solutions?
P.S.: Not programming tail recursive (like the above example) is no problem in O(n), but if you aim for O(1) it is a different story.
Six cases, four of them with explicit return values (at the edges), two of them recursive:
importText.PrintftypeSize=InttypeRow=InttypeColumn=Int-- top row: count down from sqr - 1 with col-- right column: count down from sqr - n with row-- bottom row: count up from sqr - n with col-- left column: count up from sqr - n - (n - 1) with rowelement::Size->Row->Column->Intelementnrowcol|evenn&&row==0=sqr-1-col|evenn&&col==n-1=sqr-n-row|evenn=element(n-1)(row-1)col|oddn&&row==n-1=sqr-n+col|oddn&&col==0=sqr-n-(n-1)+row|otherwise=element(n-1)row(col-1)wheresqr=n^2printElement::Size->Row->Column->IO()printElementnrowcol=printf("%*v"++end)len(elementnrowcol)wherelen=(length.show)(n^2-1)end=ifcol==n-1then"\n"else" "printSpiraln=sequence_$printElementn<$>[0..n-1]<*>[0..n-1]main=printSpiral10
I didn't expect printing elementwise to be so easy in Haskell. The classical nested for loop for printing 2-dimensional array in one line:
Lifting the printElement function into the list functor, getting a list of IO actions back and sequencing this list. That is more intuitive to read than what I used to do with the 'unwords' and 'unlines' functions in similar cases.
I do functorial lifting every day, but although I knew of the sequence function, I never found a use case. Until this puzzle came along. :-) Using sequence in similar cases is the lesson I learned here. :-)
But wait!
The sequence function takes a list of IO actions, one for each element of the spiral. So there's a list of size n2 in memory! :-)
The logic of the element function is O(1), the printing function is not.
So, at first, I'm doing it in good old C:
Instead of functorial lifting into the list (resulting in O( n2 )) I use the loop function iterateUntilM to iterate the slightly modified printElement function until the spiral is printed: O(1)
In the printElement function, elements are indexed by a counter from 0 to n2 - 1, their position in the spiral can be derived from the index by division modulo n: (row,col) = quotRem counter n.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
This was my O(n) prototype in Haskell. Which helped me to find an O(1) solution. It is not very haskellish to iterate many IO actions, but I deliberately chose a Challenge that is not very natural to Haskell. Well, to keep the data structure in O(n) I had to give the data linewise to IO:
It catched my eye, that the spiral structure is represented in the 'spiral' function. I was in a veeery playful mood and worked this out much further by embedding the interesting part in an ASCII graphic of the spiral structure: :-)
Literate Programming? That's old hat! This is graphical programming! :-D (Don't take me serious.)
Maybe we see some more recursive solutions?
P.S.: Not programming tail recursive (like the above example) is no problem in O(n), but if you aim for O(1) it is a different story.
Six cases, four of them with explicit return values (at the edges), two of them recursive:
I didn't expect printing elementwise to be so easy in Haskell. The classical nested for loop for printing 2-dimensional array in one line:
Lifting the printElement function into the list functor, getting a list of IO actions back and sequencing this list. That is more intuitive to read than what I used to do with the 'unwords' and 'unlines' functions in similar cases.
I do functorial lifting every day, but although I knew of the sequence function, I never found a use case. Until this puzzle came along. :-) Using sequence in similar cases is the lesson I learned here. :-)
But wait!
The sequence function takes a list of IO actions, one for each element of the spiral. So there's a list of size n2 in memory! :-)
The logic of the element function is O(1), the printing function is not.
So, at first, I'm doing it in good old C:
What was most fun to learn for me, here, was a failure regarding the problem. :-D
Instead of functorial lifting into the list (resulting in O( n2 )) I use the loop function iterateUntilM to iterate the slightly modified printElement function until the spiral is printed: O(1)
In the printElement function, elements are indexed by a counter from 0 to n2 - 1, their position in the spiral can be derived from the index by division modulo n: (row,col) = quotRem counter n.