Saturday, September 4, 2010

The Snail in Golang

It's been some time since I last played with Golang so I decided to spend a bit of time getting to actually know golang by solving the classic snail problem, that is, to write a sequence of numbers in a square matrix of a given size n. Let's say we have a program called 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?

Tuesday, May 4, 2010

Test for the Go syntax highlighter

I got some feedback from the Go Nuts mailing list, particularly from Russ Cox who pointed out that predefined identifiers like true, nil, int, and float are not reserved keywords.  So I decided to have two kinds of highlighted keywords:
  1. those that start a type or start a declaration, including for packages:
    struct func interface map chan package import type const var
  2. those that control the flow of the code:
    goto break continue if else switch default case for range go select return fallthrough defer

Then I use the code from $GOROOT/test/rename.go and rename1.go to see the effect of this color scheme:
// $G $D/$F.go && $L $F.$A && ./$A.out

// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import "fmt"

func main() {
   n :=
      bool +
         byte +
         float +
         float32 +
         float64 +
         int +
         int8 +
         int16 +
         int32 +
         int64 +
         uint +
         uint8 +
         uint16 +
         uint32 +
         uint64 +
         uintptr +
         true +
         false +
         iota +
         nil +
         cap +
         len +
         make +
         new +
         panic +
         print +
         println
   if n != 27*28/2 {
      fmt.Println("BUG: wrong n", n, 27*28/2)
   }

   var n byte       // ERROR "not a type|expected type"
   var y = float(0) // ERROR "cannot call|expected function"
   const (
      a = 1 + iota // ERROR "string|incompatible types"
   )
}

const (
   bool    = 1
   byte    = 2
   float   = 3
   float32 = 4
   float64 = 5
   int     = 6
   int8    = 7
   int16   = 8
   int32   = 9
   int64   = 10
   uint    = 11
   uint8   = 12
   uint16  = 13
   uint32  = 14
   uint64  = 15
   uintptr = 16
   true    = 17
   false   = 18
   iota    = 19
   nil     = 20
   cap     = 21
   len     = 22
   make    = 23
   new     = 24
   panic   = 25
   print   = 26
   println = 27
)

In the end, if it doesn't suit your aesthetic tastes, you could always download the script and tweak it.

Monday, May 3, 2010

Syntax highlighting for golang

I've been using Alex Gorbatchev's SyntaxHighlighter to ease the task of presenting code on this blog. Seeing that there's currently no "brush" for golang, I decided to create one. I posted the code here for anyone interested. To use it, simply put the following line where you'd normally do it for SyntaxHighlighter brushes (usually before the <head> tag):
<script src='https://raw.github.com/axx/GolangHighlighter/master/shBrushGo.js' type='text/javascript'/>
Then use either "go" or "golang" as alias when you insert golang code on your blog:
<pre class="brush: go">package main
import "fmt"
func main() {
    fmt.Printf("yoohoo!")
}</pre>
This will be rendered as:
package main
import "fmt"
func main() {
    fmt.Printf("yoohoo!")
}
I hope someone else finds it useful. Please drop a comment if you have some suggestions on how to improve it.
EDIT (05AUG2012): I've lost my old server so I had to reconstruct the script and placed it on GitHub. I therefore updated the example and links above.

Sunday, May 2, 2010

Installing golang on Ubuntu Linux

In your $HOME/.bashrc, set the necessary environment variables:
export GOROOT=$HOME/go
export GOOS=linux      # target operating system
export GOARCH=386      # target compiling architecture

Note that with golang, you are always "cross-compiling".  So the values for $GOOS and $GOARCH are not necessarily corresponding to your Linux box.

Make sure you have the tools needed to build the golang compilers from source:
sudo apt-get install python-setuptools python-dev build-essential gcc mercurial

Then get the golang source code using mercurial:
cd $HOME && hg clone -r release https://go.googlecode.com/hg/ $GOROOT

Now let's build golang from the downloaded source code:
cd $GOROOT/src && ./all.bash

The golang executables will be built and placed into $HOME/bin (you can customize this by setting the environment variable $GOBIN). This will also run some tests on the build. In the end you should see something like:
--- cd ../test
N known bugs; 0 unexpected bugs

Here, N changes from version to version of golang. That's it! So now it's time for the customary "Hello, World". Open your favorite text editor and create a simple text file called hello.go:
package main

import "fmt"

func main() {
    fmt.Printf("hello, world!\n")
}

Then build our executable (note that we're compiling for linux-386):
8g hello.go
8l hello.8
./8.out

In the end, you'll see a nice little "hello, world!"

Hacking with Go

Hi everyone! I've just learned about Google's Go language and I think it'll be interesting to write software with it. I'm using this blog to record my experiences with Golang, so check it out from time to time!