Dennis' blog

On Technology and Business

Advent of code 2018 - Day 1

I’m trying to keep up with the Advent of Code this year in Go.

Day 1 - part 1: Calculating the frequency from a set of plus and minus inputs

Our first exercise doesn’t seem too difficult. We’re given a list with rows like +20 and -14 and are asked to calculate the sum across the full list. My - working but probably not optimal - solution below, which iterates over the file line by line, converts the input to an signed integer, sums the resulting values and provides the total.

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	var v, result int64

	// Import inputs file
	f, err := os.Open("input")
	check(err)
	defer f.Close()

	// read file line by line
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		n := scanner.Text()

		// Convert to int and add result
		if len(n) > 0 {
			v, err = strconv.ParseInt(n, 10, 64)
			check(err)
			result += v
		} else {
			break
		}
	}

	// Display frequency
	fmt.Println(result)

}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

Day 1 - part 2: Iterate continuously over the list until we find a fequency that we hit twice.

Our next challenge requires us to track which frequencies we’ve already visited before and keep iterating over the list until we hit a frequency twice. The first frequency to hit twice is the correct answer. I think storing the frequencies as keys in a map makes sense as it allows me to easily check if a frequency was visited before.

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	var input []int64

	// Import inputs file
	file, err := os.Open("input")
	check(err)
	defer file.Close()

	// read file line by line into a slice
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		n := scanner.Text()

		// Convert to int and add result to input slice
		if len(n) > 0 {
			v, err := strconv.ParseInt(n, 10, 64)
			check(err)
			input = append(input, v)
		} else {
			break
		}
	}

	// Find first dual visited frequency
	r := search(input)

	// Display frequency
	fmt.Println(r)
}

func search(input []int64) int64 {
	var f int64
	frequencies := make(map[int64]bool)

	// loop indefinitely over the list until we find a
	// frequency we already 'visited'
	for {
		for _, val := range input {
			frequencies[f] = true
			f += val
			if frequencies[f] {
				return f
			}
		}
	}
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}