Go

Anagramizer, a simple anagram solver in Go

This weekend I took the family to celebrate Father’s Day away from town. We went around getting to know parts of the province we live in and never been to.

We came back yesterday and the plan today was for a nice, calm day at home (it’s a holiday of some sort here.) Then I got engaged in a game called Hanging with Friends, a mix of the traditional hangman with a bit of Scrabble.

Since English isn’t my first language, I have a limited vocabulary, which leaves me at a disadvantage against my English-speaking friends. I can handle the “hangman” part of the game where I have to guess the word my friends come up with; but when it becomes “Scrabble” and I’ve got to form words using only a given set of letters and still make them difficult enough that a native English speaker will have problems figuring them out, then it’s tough.

An itch that needed some scratching. Enter Anagramizer.

When I woke up this morning, I decided to write a little program to help me. You call it cheating, I call it having a bit of nerd fun.

Being that I’m currently in love with Go, I decided to write in that language and it was really easy and quick to do it. It took me about half an hour to write the program that did what I needed. But then…

I succumbed to the temptation and started adding bells and whistles. Admittedly it was mostly for my own amusement and trying stuff in Go, but by the time we were leaving for lunch, the program had more options than the KDE audio volume utility (see what I did just there?)

I decided to make it available to anyone who wants to play with it. It served its purpose of entertaining me for about half a day 🙂

It’s now available on Github and released under a BSD licence.

Euler 9 in Go

For fun I picked one of the Euler algorithms I had played with before and rewrote it in Go. Instead of carrying over the nested-loop search, this version first eliminates c using the fixed sum and solves the Pythagorean equation for b. Only a remains to search.

package main

import (
	"fmt"
	"os"
)

func main() {
	const sum = 1000

	for a := 1; a < sum/3; a++ {
		numerator := sum * (sum - 2*a)
		denominator := 2 * (sum - a)

		if numerator%denominator != 0 {
			continue
		}

		b := numerator / denominator
		c := sum - a - b
		if a < b && b < c {
			fmt.Println(a * b * c)
			return
		}
	}

	fmt.Fprintln(os.Stderr, "no solution")
	os.Exit(1)
}

The divisibility check rejects values of a that would produce a fractional b. The program uses constant space, examines fewer than sum / 3 candidates, and prints 31875000.

Living on Go weekly snapshots

I rebuilt Go this morning because a small program stopped compiling after I pulled the latest sources. That sounds like a complaint, but it was exactly the experiment I wanted. Go is still young enough that a weekly snapshot can change a familiar corner of the language before I have finished becoming familiar with it.

The simplest way I have found to stay sane is to keep the experiment small:

package main

import "fmt"

func main() {
	fmt.Println("hello from this week's Go")
}

I build that first, then my real code. If this fails, my tree or environment is wrong. If it works and the real program does not, I have a migration to understand rather than a mysterious compiler disaster.

The surprising part is how useful the release number becomes. A report that says “tip is broken” has a shelf life measured in minutes. A report that includes the release.r57 family, the compiler, the operating system, and a reduced program gives everybody something concrete to compare. The weekly tags are not decoration; they are coordinates on moving ground.

There is a mechanical reason for the churn. The language, compilers, runtime, and libraries live together and are being designed together. A syntax adjustment can therefore arrive beside the library changes needed to use it. That is convenient for the project and occasionally inconvenient for the person who pulled five minutes before lunch.

I prefer snapshots to copying a random revision from the main repository. A named snapshot gives me a point I can return to and makes two machines easier to compare. I also keep Go code outside the source tree and rebuild from a clean checkout when results become implausible.

That record helps with library changes too. When a package function moves or changes shape, I can read the notes between two known points instead of searching the entire repository history. Small coordinates turn a broad question into a short diff.

The caveat is obvious: weekly does not mean stable. I would not quietly update a production compiler and hope for character-building surprises. For experiments, however, the snapshots make the cost of change visible while the changes are still small. My program broke, I learned why, and lunch was only slightly delayed.

Making the Scheduler Show Its Work

Scheduler discussions become folklore quickly, so I built a few experiments that force observable events instead of inferring everything from total runtime.

The first launches workers that announce when they start, wait on a gate, perform fixed CPU work, and announce completion. A channel carries each announcement to one logger goroutine. That gives me a trace without concurrent writes making the output resemble ransom typography.

func worker(id int, gate <-chan bool, events chan<- Event) {
    events <- Event{id, "ready"}
    <-gate
    burnCPU()
    events <- Event{id, "done"}
}

I run the same executable with different GOMAXPROCS values. With one processor thread allowed, CPU-bound completion is serialized even though all workers are runnable. With two, completions overlap in wall time on my dual-core machine. More than two adds runnable work but no additional cores, and eventually loses to scheduling overhead.

The second experiment replaces CPU work with pipe reads. Many goroutines can wait for I/O while the runtime arranges for other work to proceed. Increasing the processor allowance barely changes throughput because the external producer is the limit. This is why one benchmark cannot characterize “goroutine performance.”

The third experiment is intentionally rude: one goroutine runs a tight arithmetic loop with no communication while another tries to report periodically. On this early runtime, the reporter can be delayed noticeably. Scheduling behavior is under active development, and I should not assume the preemption properties of a mature operating-system scheduler.

Adding explicit communication points makes the test cooperative and reflects real pipeline code better. I do not sprinkle meaningless calls into production loops merely to influence today’s runtime; I break large work into units with natural channel operations or function calls, then measure again.

The event channel affects the experiment, of course. Observing a scheduler changes timing by adding synchronization. I keep messages outside the inner loop and compare against an uninstrumented wall-clock run. The trace explains ordering; it does not provide cycle-accurate truth.

These results belong to the May 2011 snapshot and my machine. They are not a specification of future Go scheduling, and I am deliberately avoiding an internal diagram that will expire before the ink dries. The practical findings are modest: concurrency is not parallelism, blocking and CPU work stress different paths, and processor settings should follow measurements. Schedulers are quite willing to show their work, but only if the experiment asks a specific question.

Reflection and a Tiny Config Decoder

My programs often begin with three configuration fields and end with a parser that believes it is a database. I tried using reflection to make one small key-value decoder reusable without building another private language.

The input is deliberately boring:

host=buildbox
workers=4
verbose=true

The destination is a structure. The decoder walks exported fields with the early reflect package, matches lowercased field names, converts the text according to each field’s kind, and sets the value. The exact calls have changed across weekly snapshots, so the important part is the control flow rather than names copied from my May 2011 tree:

parse lines
  -> find structure field
  -> inspect field kind
  -> convert text
  -> set addressable field or return os.Error

Passing a pointer is required because the decoder must modify the original structure. It checks that the argument points to a structure before examining fields. A non-pointer, unknown key, unsupported kind, or failed conversion returns an ordinary failure value with the key name.

I initially ignored unknown keys for forward compatibility. That converted a misspelled workres setting into a silent default of zero workers. Strict input is friendlier here: configuration is written by a person who would rather receive a precise complaint now than investigate strange behavior later.

The decoder supports strings, booleans, and signed integers. That is all this program needs. Slices, nested structures, aliases, default tags, and custom conversion hooks can wait until an actual configuration requires them. Reflection makes adding features easy in the same way an empty notebook makes writing a trilogy easy.

There is runtime cost, but startup configuration is not a hot path. The larger cost is weaker static checking inside the decoder, which I address with table tests over valid and invalid input. The application still uses an ordinary typed structure after startup.

I would not use this mechanism for a protocol or large data stream. Gob already solves typed Go-to-Go encoding, and explicit parsing is clearer for a public format. For a dozen local settings, a constrained reflective decoder removes repetitive assignment while keeping failures visible. The constraint is the feature, not an embarrassing first release.