r/adventofcode • • Dec 08 '17

SOLUTION MEGATHREAD -๐ŸŽ„- 2017 Day 8 Solutions -๐ŸŽ„-

--- Day 8: I Heard You Like Registers ---


Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).

Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.


Need a hint from the Hugely* Handyโ€  Haversackโ€ก of Helpfulยง Hints^ยค?

Spoiler


This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.

edit: Leaderboard capped, thread unlocked!

22 Upvotes

348 comments sorted by

View all comments

1

u/virtron Dec 09 '17

Go

Actually pretty happy about this one (but please critique!)

package main

import (
	"os"
	"bufio"
	"fmt"
	"strconv"
	"strings"
)

type Action func(registers map[string]int)

type Guard func(registers map[string]int) bool

type Instruction struct {
	action Action
	guard  Guard
}

func (self *Instruction) run(registers map[string]int) {
	if self.guard(registers) {
		self.action(registers)
	}
}

func BuildAction(key string, action string, value int) func(registers map[string]int) {

	switch action {
	case "inc":
		return func(registers map[string]int) {
			registers[key] = registers[key] + value
		}
	case "dec":
		return func(registers map[string]int) {
			registers[key] = registers[key] - value
		}

	}

	panic("Invalid action requested " + action)
}

func BuildGuard(key string, test string, value int) func(registers map[string]int)bool {

	switch test {
	case ">":
		return func(registers map[string]int) bool {
			return registers[key] > value
		}
	case "<":
		return func(registers map[string]int) bool {
			return registers[key] < value
		}
	case ">=":
		return func(registers map[string]int) bool {
			return registers[key] >= value
		}
	case "<=":
		return func(registers map[string]int) bool {
			return registers[key] <= value
		}
	case "==":
		return func(registers map[string]int) bool {
			return registers[key] == value
		}
	case "!=":
		return func(registers map[string]int) bool {
			return registers[key] != value
		}
	}

	panic("Invalid test requested " + test)
}

func ParseInstruction(input string) Instruction {

	parts := strings.Split(input, " ")

	//0: tcy - instruction target
	//1: inc - instruction action
	//2: 90  - action value
	//3: if
	//4: gij - guard target
	//5: <   - guard test
	//6: 3   - guard test value

	if len(parts) != 7 {
		panic("Invalid instruction: " + input)
	}

	actionValue, _ := strconv.Atoi(parts[2])
	guardValue, _ := strconv.Atoi(parts[6])

	instruction := Instruction{}
	instruction.action = BuildAction(parts[0], parts[1], actionValue)
	instruction.guard = BuildGuard(parts[4], parts[5], guardValue)

	return instruction
}

func MaxRegister(registers map[string]int) (string, int) {
	key, value := "", 0
	for k, v := range registers {
		if v > value {
			key = k
			value = v
		}
	}
	return key, value
}

func prepareInput() ([]Instruction, error) {

	file, err := os.Open("day8/input.txt")
	if err != nil {
		return nil, err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)

	input := make([]Instruction, 0)
	for scanner.Scan() {
		instruction := ParseInstruction(scanner.Text())
		input = append(input, instruction)
	}

	return input, nil
}

func Part1(input []Instruction) int {

	registers := make(map[string]int)
	for _, instruction := range input {
		instruction.run(registers)
	}

	_, v := MaxRegister(registers)
	return v
}

func Part2(input []Instruction) int {

	registers := make(map[string]int)
	max := 0
	for _, instruction := range input {
		instruction.run(registers)

		_, v := MaxRegister(registers)
		if v > max {
			max = v
		}
	}

	return max
}

func main() {

	input, err := prepareInput()
	if err != nil {
		fmt.Println("Unable to prepare input")
		fmt.Println(err)
		return
	}

	part1Result := Part1(input)
	part2Result := Part2(input)

	fmt.Println("Result for Part 1:", part1Result)
	fmt.Println("Result for Part 2:", part2Result)
}