I did a very small thing in Go a while ago, and then I contributed a fix to the tutorial I was following, and that’s all I ever did. Time to give it another try!
So, Advent of Code, day 8: You are given a grid of 50×6 pixels and input consisting of the following commands:
Here is some example input:
rect 1x5 rotate row y=0 by 3 rotate row y=1 by 3 rotate row y=2 by 3 rotate row y=3 by 3 rotate row y=4 by 3 rotate column x=3 by 1 rect 1x5 rotate column x=0 by 1 rect 2x1 rotate row y=0 by 1 rotate column x=1 by 2 rotate column x=2 by 2 rect 2x1 rotate row y=0 by 1
The result:
.##............................................... #..#.............................................. ####.............................................. #..#.............................................. #..#.............................................. #..#..............................................
Part 2: The code also helps you solve part 2 which is to type the text shown. In the example above, that would be “A”.
package main import ( "bytes" "bufio" "log" "os" "regexp" "strconv" "fmt" ) const maxX= 50 const maxY = 6 type display struct { runes [maxY][maxX]rune } func (d *display) initialize() { for y := 0; y < maxY; y++ { for x := 0; x < maxX; x++ { d.runes[y][x] = '.' } } } func (d *display) string() string { var buf bytes.Buffer for y := 0; y < maxY; y++ { for x := 0; x < maxX; x++ { buf.WriteRune(d.runes[y][x]) } buf.WriteString("\n") } return buf.String() } func (d *display) print() { print(d.string()) } func (d *display) rect(a, b int) { for y := 0; y < b; y++ { for x := 0; x < a; x++ { d.runes[y][x] = '#' } } } func (d *display) rotateColumn(x, n int) { result := make([]rune, maxY) for y := 0; y < maxY; y++ { result[(y + n) % maxY] = d.runes[y][x] } for y := 0; y < maxY; y++ { d.runes[y][x] = result[y] } } func (d *display) rotateRow(y, n int) { result := make([]rune, maxX) for x := 0; x < maxX; x++ { result[(x + n) % maxX] = d.runes[y][x] } for x := 0; x < maxX; x++ { d.runes[y][x] = result[x] } } func (d *display) count() int { n := 0 for y := 0; y < maxY; y++ { for x := 0; x < maxX; x++ { if d.runes[y][x] == '#' { n++ } } } return n } func readStdin() display { var d display d.initialize() // rect 3x2 reRect := regexp.MustCompile(`^(rect) (\d+)x(\d+)`) reRotRow := regexp.MustCompile(`^(rotate row) y=(\d+) by (\d+)`) reRotColumn := regexp.MustCompile(`^(rotate column) x=(\d+) by (\d+)`) scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { // identify the command s := scanner.Text() match := reRect.FindStringSubmatch(s) if match == nil { match = reRotRow.FindStringSubmatch(s) } if match == nil { match = reRotColumn.FindStringSubmatch(s) } if match == nil { log.Fatal("Unknown command: ", s) } command := match[1] // convert the parameters to integers param := make([]int, len(match) - 1) for i := range match[2:] { n, err := strconv.Atoi(match[i+2]) if err != nil { log.Fatal(match[i+1], " cannot be converted to an integer") } param[i] = n } // run the commands switch command { case "rect": d.rect(param[0], param[1]) case "rotate row": d.rotateRow(param[0], param[1]) case "rotate column": d.rotateColumn(param[0], param[1]) default: log.Fatal("Matching regular expression is not handled: ", s) } // debug fmt.Println(s) d.print() } if err := scanner.Err(); err != nil { log.Fatal(err) } fmt.Println("Pixels:", d.count()) return d } func main() { d := readStdin() d.print() }
I even wrote some test code to go along with it. I like how writing tests is totally part of how you learn the language.
#Go #Advent of Code #Programming