package main import ( "bufio" "fmt" "os" "strings" "time" ) func main() { start := time.Now() partOne() duration := time.Since(start) partTwo() duration2 := time.Since(start) fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration) } func partOne() { f, _ := os.Open("input") reader := bufio.NewReader(f) scanner := bufio.NewScanner(reader) // naive implementation scanner.Scan() numbers := strings.Split(scanner.Text(), ",") for { i := len(numbers) - 1 lastNumber := numbers[i] // walk backward through the list, looking for a match for j := range numbers { if len(numbers) == 2020 { fmt.Println(numbers[2019]) return } if i-j == 0 { // made it to the head of the list, no matches; append 0 numbers = append(numbers, "0") break } else if numbers[i-j-1] == lastNumber { // a number matched; insert the difference between the last number and when we last saw it numbers = append(numbers, fmt.Sprintf("%d", len(numbers)-1-(i-j-1))) break } } } } func partTwo() { f, _ := os.Open("input") reader := bufio.NewReader(f) scanner := bufio.NewScanner(reader) // caching implementation. It's still slow, but it at least finishes...! scanner.Scan() numbers := strings.Split(scanner.Text(), ",") seen := make(map[string]int) // load in numbers for i, v := range numbers[:len(numbers)-1] { seen[v] = i } for { i := len(numbers) - 1 lastNumber := numbers[i] if len(numbers) == 30000000 { fmt.Println(numbers[30000000-1]) return } if v, ok := seen[lastNumber]; !ok { // never seen that before numbers = append(numbers, "0") seen[lastNumber] = i continue } else { // a number matched; insert the difference between the last number and when we last saw it n := fmt.Sprintf("%d", i-v) numbers = append(numbers, n) seen[lastNumber] = i continue } } }