Files
2019/main.go
Parnic d7836f4e59 Day 9 solution
This day showed me that when the input instruction was introduced and said "write addresses will never be in immediate mode", that didn't mean "so don't bother handling modes for input addresses", it meant "handle the mode, but assert if it's immediate mode". It was super helpful that this program contained a bootstrap sequence to validate each instruction.

Memory expansion came with a few caveats: obviously reads and writes needed to handle expanding the memory space, but a Reset also can no longer get away with simply copying the program into memory again because we need to ensure that any additional memory is cut off (or at least zeroed), so the quickest way to handle that in Go is to simply allocate a new buffer; I'd rather manipulate the existing buffer, but I'm having a hard time finding the best way to do that.

And finally, make sure you reset your relativeBase when resetting the program...that one was ugly to track down.
2022-06-20 08:54:52 -05:00

120 lines
2.4 KiB
Go

package main
import (
"flag"
"fmt"
"log"
"os"
"strconv"
"strings"
"time"
"parnic.com/aoc2019/days"
"parnic.com/aoc2019/utilities"
)
type day interface {
Parse()
Num() int
Part1() string
Part2() string
}
const (
part1Header = utilities.ColorGreen + "Part1:" + utilities.TextReset
part2Header = utilities.ColorGreen + "Part2:" + utilities.TextReset
)
var (
flagPart1 = flag.Bool("part1", false, "whether to run part1 or not; if no flags are present, all parts are run")
flagPart2 = flag.Bool("part2", false, "whether to run part2 or not; if no flags are present, all parts are run")
)
var dayMap = []day{
&days.Day01{},
&days.Day02{},
&days.Day03{},
&days.Day04{},
&days.Day05{},
&days.Day06{},
&days.Day07{},
&days.Day08{},
&days.Day09{},
}
func main() {
flag.Parse()
arg := strconv.Itoa(len(dayMap))
flagArgs := flag.Args()
if len(flagArgs) > 0 && len(flagArgs[0]) > 0 {
arg = flagArgs[0]
}
if strings.ToLower(arg) == "all" {
startTime := time.Now()
for _, v := range dayMap {
solve(v)
}
fmt.Printf("%sAll days completed in %v%s\n", utilities.ColorBrightBlack, time.Since(startTime), utilities.TextReset)
} else {
iArg, err := strconv.Atoi(arg)
if err != nil {
log.Fatalf("Invalid day " + utilities.ColorCyan + arg + utilities.TextReset)
}
if iArg < 0 || iArg > len(dayMap) {
log.Fatalf("Unknown day " + utilities.ColorCyan + arg + utilities.TextReset)
}
solve(dayMap[iArg-1])
}
os.Exit(0)
}
func solve(d day) {
fmt.Printf("%sDay %d%s\n", utilities.ColorCyan, d.Num(), utilities.TextReset)
fmt.Printf("----%s\n", strings.Repeat("-", len(strconv.Itoa(d.Num()))))
runPart1 := (!*flagPart1 && !*flagPart2) || *flagPart1
runPart2 := (!*flagPart1 && !*flagPart2) || *flagPart2
parseStart := time.Now()
d.Parse()
parseTime := time.Since(parseStart)
part1Start := time.Now()
var part1Text string
if runPart1 {
part1Text = d.Part1()
}
part1Time := time.Since(part1Start)
part2Start := time.Now()
var part2Text string
if runPart2 {
part2Text = d.Part2()
}
part2Time := time.Since(part2Start)
if runPart1 {
fmt.Println(part1Header)
fmt.Println(">", part1Text)
fmt.Println()
}
if runPart2 {
fmt.Println(part2Header)
fmt.Println(">", part2Text)
fmt.Println()
}
fmt.Print(utilities.ColorBrightBlack)
fmt.Println("Parsed in", parseTime)
if runPart1 {
fmt.Println("Part01 in", part1Time)
}
if runPart2 {
fmt.Println("Part02 in", part2Time)
}
fmt.Println(utilities.TextReset)
}