package main import ( "bufio" "fmt" "log" "os" ) var ( tree = "#" snow = "." ) func proccessLines(path string, f func(string) (stop bool, err error)) error { file, err := os.Open(path) if err != nil { return err } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { stop, err := f(scanner.Text()) if stop || err != nil { return err } } if err := scanner.Err(); err != nil { return err } return nil } type world struct { x, y int dx, dy int worldMap []string } func (w *world) move(dx, dy int) string { result := w.peek(dx, dy) w.x += dx w.y += dy return result } func (w world) peek(dx, dy int) string { row := w.worldMap[w.y+dy] return string(row[(w.x+dx)%len(row)]) } func (w world) atEnd() bool { return w.y >= len(w.worldMap)-1 } func (w *world) setSlope(dx, dy int) { w.dx = dx w.dy = dy } func (w *world) ski() int { trees := 0 for !w.atEnd() { space := w.move(w.dx, w.dy) if space == tree { trees++ } } return trees } func (w *world) takeLift() { w.x, w.y = 0, 0 } func readMap() world { worldMap := []string{} err := proccessLines("input.txt", func(line string) (stop bool, err error) { worldMap = append(worldMap, line) return }) if err != nil { log.Fatal(err) } return world{worldMap: worldMap} } func part1() { theWorld := readMap() theWorld.setSlope(3, 1) trees := theWorld.ski() fmt.Printf("Total trees: %d\n", trees) } func part2() { trees := []int{} theWorld := readMap() product := 1 for _, slope := range [][]int{ []int{1, 1}, []int{3, 1}, []int{5, 1}, []int{7, 1}, []int{1, 2}, } { theWorld.setSlope(slope[0], slope[1]) count := theWorld.ski() product *= count trees = append(trees, count) theWorld.takeLift() } fmt.Printf("Total trees: %v, product: %d\n", trees, product) } func main() { part1() part2() }