advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

main.go (1632B)

    1 package main
    2 
    3 import (
    4 	"bufio"
    5 	"fmt"
    6 	"os"
    7 	"strconv"
    8 	"strings"
    9 )
   10 
   11 const (
   12 	X = 0
   13 )
   14 
   15 func readInput(filename string) (res []int) {
   16 	file, _ := os.Open(filename)
   17 	defer file.Close()
   18 
   19 	scanner := bufio.NewScanner(file)
   20 	for scanner.Scan() {
   21 		row := scanner.Text()
   22 		for _, elem := range strings.Split(row, ",") {
   23 			num, err := strconv.Atoi(elem)
   24 			if err == nil {
   25 				res = append(res, num)
   26 			} else {
   27 				res = append(res, X)
   28 			}
   29 		}
   30 	}
   31 	return
   32 }
   33 
   34 func main() {
   35 	input := readInput("./input.txt")
   36 	// 5257
   37 	fmt.Println(part1(input))
   38 	// 538703333547789
   39 	fmt.Println(part2(input))
   40 }
   41 
   42 func part1(input []int) (res int) {
   43 	minWait := input[0]
   44 	for _, bus := range input[1:] {
   45 		if bus != X {
   46 			wait := (bus - (input[0] % bus)) % bus
   47 			if wait < minWait {
   48 				minWait = wait
   49 				res = bus * wait
   50 			}
   51 		}
   52 	}
   53 	return
   54 }
   55 
   56 func modInv(a, n int64) (inv int64) {
   57 	// Extended Euclidean algorithm
   58 	// Finds modulo inverse: inv * a == 1 (mod n)
   59 	var (
   60 		t    int64 = 0
   61 		tNew int64 = 1
   62 		r    int64 = n
   63 		rNew int64 = a
   64 	)
   65 	for rNew != 0 {
   66 		q := r / rNew
   67 		t, tNew = tNew, t-q*tNew
   68 		r, rNew = rNew, r-q*rNew
   69 	}
   70 	return (t + n) % n
   71 }
   72 
   73 func part2(input []int) (res int64) {
   74 	// Chinese remainder theorem, note bus IDs are coprime
   75 	var (
   76 		lcm int64 = 1
   77 		fct       = []int64{}
   78 		rem       = []int64{}
   79 	)
   80 	for i, bus := range input[1:] {
   81 		if bus != X {
   82 			lcm *= int64(bus)
   83 			fct = append(fct, int64(bus))
   84 			rem = append(rem, int64((bus-i%bus)%bus))
   85 		}
   86 	}
   87 	for i, _ := range fct {
   88 		pp := lcm / fct[i]
   89 		inv := modInv(pp, fct[i])
   90 		// Change res (mod id[i]) without affecting others
   91 		res = (res + pp*inv*rem[i]) % lcm
   92 	}
   93 	return
   94 }