Files
2019/main.go
Parnic 2b554d1b3d Day 25 solution
Sort of...I mean, you have to play it yourself, but it works. This is a text-based adventure game. The goal is to go around picking up items (except for the 5 items that will kill you/end or hang the game) then find the right combination of items that lets you get through the pressure-sensitive room which terminates the game and gives you the code to enter on the website.

My understanding is that every item has a power-of-2 weight to it, and you have to reach the right set of items to have your weight match the target. The main problem I had was that the output for the pressure room's "heavier" and "lighter" words mean that _other_ droids are heavier/lighter than _you_. Which means if it says "lighter", you need to shed weight/drop stuff, but if it says "heavier", you need to add weight/pick up stuff.

This could be automated in several different ways, but my thought is you'd want to explore the maze, picking up everything that's not the blocked 5 items, find the pressure-sensitive room, and try every combination of items until the process exits, at which point you'd display the number after "by typing" in the final output string. I've stubbed out support for reading the program's output so that you could inspect it and automate if you really wanted to. Right now it just parses the answer from the final output line and prints that by itself.

Items that **should not** be picked up are:

    infinite loop (does what it says to your program)
    molten lava (kills you)
    escape pod (ends the game)
    photons (turns out the lights and causes you to get eaten by a grue)
    giant electromagnet (gets you stuck - no other input works and it cannot be dropped)

This commit's program lets you through if you're carrying:

- ornament
- astrolabe
- weather machine
- food ration

which results in a code of 4206594
2022-07-22 16:56:47 -05:00

157 lines
3.2 KiB
Go

package main
import (
"flag"
"fmt"
"log"
"os"
"runtime/pprof"
"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")
flagCpuProfile = flag.String("cpuprofile", "", "write cpu profile to file")
flagMemProfile = flag.String("memprofile", "", "write memory profile to file")
)
var dayMap = []day{
&days.Day01{},
&days.Day02{},
&days.Day03{},
&days.Day04{},
&days.Day05{},
&days.Day06{},
&days.Day07{},
&days.Day08{},
&days.Day09{},
&days.Day10{},
&days.Day11{},
&days.Day12{},
&days.Day13{},
&days.Day14{},
&days.Day15{},
&days.Day16{},
&days.Day17{},
&days.Day18{},
&days.Day19{},
&days.Day20{},
&days.Day21{},
&days.Day22{},
&days.Day23{},
&days.Day24{},
&days.Day25{},
}
func main() {
flag.Parse()
if *flagCpuProfile != "" {
f, err := os.Create(*flagCpuProfile)
if err != nil {
log.Fatal(err)
}
defer f.Close()
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
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])
}
if *flagMemProfile != "" {
f, err := os.Create(*flagMemProfile)
if err != nil {
log.Fatal(err)
}
pprof.WriteHeapProfile(f)
f.Close()
}
}
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)
if runPart1 {
fmt.Println(part1Header)
fmt.Println(">", part1Text)
fmt.Println()
}
part2Start := time.Now()
var part2Text string
if runPart2 {
part2Text = d.Part2()
}
part2Time := time.Since(part2Start)
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)
}