commit 36746b69e4913315ff0de8aec569639b776ab621 Author: Stefan Harmuth Date: Mon Dec 21 21:12:33 2020 +0100 copy from aoc2020 diff --git a/aoclib/aoclib.go b/aoclib/aoclib.go new file mode 100644 index 0000000..392b05e --- /dev/null +++ b/aoclib/aoclib.go @@ -0,0 +1,80 @@ +package aoclib + +import ( + "bufio" + "fmt" + "log" + "os" + "strconv" + "time" +) + +type Puzzle struct { + FromFile string + RawInput []string + RawInputInt []int +} + +func (p *Puzzle) ReadInputFromFile() { + fh, err := os.Open(p.FromFile) + if err != nil { + log.Fatal("fopen error:", err) + } + defer fh.Close() + + p.RawInput = []string{} + scanner := bufio.NewScanner(fh) + for scanner.Scan() { + p.RawInput = append(p.RawInput, scanner.Text()) + } + + if err := scanner.Err(); err != nil { + log.Fatal("scanner error:", err) + } +} + +func (p *Puzzle) GetInputArray() []string { + if len(p.RawInput) == 0 && len(p.FromFile) != 0 { + p.ReadInputFromFile() + } + + return p.RawInput +} + +func (p *Puzzle) GetInputArrayInt() []int { + if len(p.RawInputInt) == 0 { + for _, v := range p.GetInputArray() { + value, err := strconv.Atoi(v) + if err != nil { + log.Fatal("Cannot convert string to int:", v) + } else { + p.RawInputInt = append(p.RawInputInt, value) + } + } + } + + return p.RawInputInt +} + +func (p Puzzle) Solve(partFunction func(p Puzzle) interface{}, day int, part int, timeit bool, timeitNumber int) { + var result interface{} + if !timeit { + result = partFunction(p) + fmt.Printf( + "Result for day %d, part %d: %#v\n", + day, part, result, + ) + } else { + start := time.Now() + for i := 0; i < timeitNumber; i++ { + result = partFunction(p) + } + elapsed := time.Duration(int64(time.Since(start)) / int64(timeitNumber)) + + fmt.Printf( + "Result for day %d, part %d: %#v (avg over %d runs: %s)\n", + day, part, result, timeitNumber, elapsed, + ) + } + +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..f322a3c --- /dev/null +++ b/main.go @@ -0,0 +1,79 @@ +package main + +import ( + "aoc2020/aoclib" + "aoc2020/day01" + "aoc2020/day02" + "aoc2020/day03" + "aoc2020/day17" + "aoc2020/day18" + "flag" + "fmt" + "os" + "path/filepath" +) + +var dayFunctions map[int]map[int]func(puzzle aoclib.Puzzle) interface{} +var day int +var part int +var test bool +var timeit bool +var timeitNumber int +var myDir, _ = filepath.Abs(filepath.Dir(os.Args[0])) + +func initDayFunctions() { + dayFunctions = make(map[int]map[int]func(puzzle aoclib.Puzzle) interface{}) + dayFunctions[1] = make(map[int]func(puzzle aoclib.Puzzle) interface{}) + dayFunctions[1][1] = day01.Part1 + dayFunctions[1][2] = day01.Part2 + dayFunctions[2] = make(map[int]func(puzzle aoclib.Puzzle) interface{}) + dayFunctions[2][1] = day02.Part1 + dayFunctions[2][2] = day02.Part2 + dayFunctions[3] = make(map[int]func(puzzle aoclib.Puzzle) interface{}) + dayFunctions[3][1] = day03.Part1 + dayFunctions[3][2] = day03.Part2 + dayFunctions[17] = make(map[int]func(puzzle aoclib.Puzzle) interface{}) + dayFunctions[17][1] = day17.Part1 + dayFunctions[17][2] = day17.Part2 + dayFunctions[18] = make(map[int]func(puzzle aoclib.Puzzle) interface{}) + dayFunctions[18][1] = day18.Part1 + dayFunctions[18][2] = day18.Part2 +} + +func execute(thisDay int) { + p := aoclib.Puzzle{} + if test { + p.FromFile = fmt.Sprintf("%s/inputs/%d_test", myDir, thisDay) + } else { + p.FromFile = fmt.Sprintf("%s/inputs/%d", myDir, thisDay) + } + p.ReadInputFromFile() + if part == -1 || part == 1 { + p.Solve(dayFunctions[thisDay][1], thisDay, 1, timeit, timeitNumber) + } + if part == -1 || part == 2 { + p.Solve(dayFunctions[thisDay][2], thisDay, 2, timeit, timeitNumber) + } +} + +func main() { + initDayFunctions() + flag.IntVar(&day, "day", -1, "day to execute; -1 = all") + flag.IntVar(&part, "part", -1, "part to execute; -1 = all") + flag.BoolVar(&test, "test", false, "run the test case") + flag.BoolVar(&timeit, "timeit", false, "measure execution time") + flag.IntVar(&timeitNumber, "timeitNumber", 50, "build time average of this many runs") + flag.Parse() + + if day != -1 { + if _, ok := dayFunctions[day]; !ok { + fmt.Printf("ERROR: unknown/invalid day: %d\n", day) + os.Exit(1) + } + execute(day) + } else { + for thisDay := range dayFunctions { + execute(thisDay) + } + } +}