`snail`

, running it with a number argument (for the square size) should look like this:$ ./snail 5 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9

So, the solution is straightforward: do alternating row and column sweeps, from the outside going inwards, while incrementing the value to be written into a matrix element.

But first, we have to be able to get the input size of the matrix. For that we'll use the

`flag`

and `strconv`

packages. For the print out, we'll use the `fmt`

package. Here's what I came up with.package main import ( "fmt" "flag" "strconv" ) func main() { // Determine the matrix size, n. var n int = 1 flag.Parse() if len(flag.Args()) > 0 { n, _ = strconv.Atoi(flag.Arg(0)) } if n < 1 { n = 1 } // No need to be complicated for n=1 if n == 1 { fmt.Println(n) return } // Create the matrix values := make([][]int, n) for i := 0; i < n; i++ { values[i] = make([]int, n) } // Fill the matrix with values avalue := 0 for ifill := 0; ifill < n; ifill++ { fstart := ifill fend := n-ifill // upper x forward sweep for ixf := fstart; ixf < fend-1; ixf++ { avalue++ values[fstart][ixf] = avalue } // right y forward sweep for iyf := fstart; iyf < fend-1; iyf++ { avalue++ values[iyf][fend-1] = avalue } // lower x backward sweep for ixb := fend-1; ixb > fstart; ixb-- { avalue++ values[fend-1][ixb] = avalue } // left y backward sweep for iyb := fend-1; iyb > fstart; iyb-- { avalue++ values[iyb][fstart] = avalue } } // Take care of the last value for odd n if avalue < n*n { avalue++ values[n/2][n/2] = avalue } // Ensure the same spacing for each element places := int(n*n/10) entry_width := 1 for places > 0 { entry_width++ places /= 10 } format := fmt.Sprintf("%%%dd ", entry_width) // Print out the snail for i := 0; i < n; i++ { for j := 0; j < n ; j++ { fmt.Printf(format, values[i][j]) } fmt.Println("") } }

*What about you? Have you tried solving this problem in golang? How would you do it better?*

can't this be solved as a sequence? i.e 1, 2, 3, 4, 5, 16, 17, 18, 19, 6, etc.

ReplyDeletehrrmmmm... it's possible but not easy. a good mathematical exercise :-)

ReplyDeleteOOP style(pretty bad one)

ReplyDeletehttp://pastebin.com/raw.php?i=TxQkUbWd

A somewhat obscure version using image.Point and image.Rectangle:

ReplyDeletehttp://pastie.org/1503814

Here's my version (ran across your page while google surfing)

ReplyDeletehttp://pastebin.com/TePiJYAt

I've made this for Project Euler (not exactly the same): https://github.com/franciscosouza/euler/blob/master/problem_028/28.go#L119

ReplyDeleteHere's a version that uses a function to calculate each element based on the size of the grid and its position in it, rather than traversing a multidimensional array in Worm order. It uses two flags, -n and -m to specify the size of the grid.

ReplyDeletehttp://pastie.org/2300048

//Thanks for getting me to write my first go program:

ReplyDeletepackage main

import (

"fmt"

"flag"

"strconv"

"math"

)

func main() {

var n int

flag.Parse()

if len(flag.Args()) > 0 {

n,_ = strconv.Atoi(flag.Arg(0))

}

values := make([]int, n*n)

position:=0; s:=0; l:=2*n-1; m:=0

for value := 0; value < n*n; value++ {

values [ position ] = value + 1

m+=2

if m >= l { s++; m=0; l-- }

if s % 2 == 0 {

position += 1 - s % 4

} else {

position += n * ( 2 - s %4 )

}

}

format := fmt.Sprintf("%%%dd ", int ( math.Log ( float64( n * n ) ) / math.Ln10 ) + 1)

for i := 0; i < n*n; i++ {

fmt.Printf(format, values[i])

if ( i + 1 ) % n == 0 {

fmt.Println("")

}

}

}

I took a stab at writing something clean using some of my favorite Go idioms. I exploit the pattern in the spiral's side lengths. I think the ideas have already been shown, mostly. And, it's not very concise. But it's nice and readable.

ReplyDeletehttps://github.com/bmatsuo/snail/blob/master/snail.go

Note: I made sure that the output of my program is always flush-left with no excess space on the right. Many of the solutions posted begin to show a gap on the left side of the matrix when the sides are longer than 10.

@Gabriel: Your code works great. Being an amateur programmer (using my skills mainly for scientific programming) I am wondering what the m variable is doing since its switching between value 0 and 2 in such a way that the if m >= 1 condition is always true. I tried removing it and obviously the indexing went out of bounds. I am just not figuring out how m is controlling that.

ReplyDelete