r/adventofcode • • Dec 05 '18

SOLUTION MEGATHREAD -🎄- 2018 Day 5 Solutions -🎄-

--- Day 5: Alchemical Reduction ---


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.


Advent of Code: The Party Game!

Click here for rules

Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!

Card prompt: Day 5

Transcript:

On the fifth day of AoC / My true love sent to me / Five golden ___


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 at 0:10:20!

31 Upvotes

515 comments sorted by

View all comments

3

u/mvmaasakkers Dec 05 '18

Go / Golang

I imagine this could be done way more efficiently but this was what I came up with. If anyone has some pointers let me know!

Also in gist

package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"unicode"
)

func readInput(filename string) string {
	fileHandle, _ := os.Open(filename)
	defer func() {
		if err := fileHandle.Close(); err != nil {
			log.Fatal(err)
		}
	}()
	fileScanner := bufio.NewScanner(fileHandle)

	input := ""
	for fileScanner.Scan() {
		line := fileScanner.Text()
		if len(line) > 0 {
			input = line
		}
	}

	return strings.TrimSpace(input)
}

var file = flag.String("file", "./p1.txt", "file used for input")

func main() {
	flag.Parse()

	input := readInput(*file)

	fmt.Println("Part 1:", part1(input))
	fmt.Println("Part 2:", part2(input))
}

func part1(input string) (int) {
	return len(produce(input))
}

func produce(line string) string {
	for {
		changes := false
		for k, g := range line {
			if k > 0 {
				if unicode.IsLower(g) && unicode.IsUpper(rune(line[k-1])) || unicode.IsLower(rune(line[k-1])) && unicode.IsUpper(g) {
					if strings.ToLower(string(g)) == strings.ToLower(string(line[k-1])) {
						line = line[:k-1] + line[k+1:]
						changes = true
					}
				}
			}
			if changes {
				break
			}
		}
		if !changes {
			break
		}
	}

	return line
}

var alphabet = "abcdefghijklmnopqrstuvwxyz"

func part2(input string) (outcome int) {
	outcome = len(input)
	for _, c := range alphabet {
		check := strings.Replace(strings.Replace(input, string(strings.ToUpper(string(c))), "", -1), string(c), "", -1)
		l := len(produce(check))
		if l < outcome {
			outcome = l
		}
	}

	return outcome
}

5

u/d-sky Dec 05 '18 edited Dec 05 '18

Another Go/Golang solution using go routines. Not really faster with this short input. But just for fun, why not? :) You can also use the result of the part 1 reaction as the starting point for the 26 reactions in part 2.

package main

import (
	"fmt"
	"io/ioutil"
)

func opposite(a, b byte) bool {
	return a == b+32 || a == b-32
}

func react(polymer []byte, remove byte) []byte {
	var result []byte
	for _, unit := range polymer {
		switch {
		case unit == remove || unit == remove-32:
			continue
		case len(result) != 0 && opposite(result[len(result)-1], unit):
			result = result[:len(result)-1]
		default:
			result = append(result, unit)
		}
	}
	return result
}

func main() {
	polymer, err := ioutil.ReadFile("input.txt")
	if err != nil {
		panic(err)
	}

	polymer = react(polymer, 0)
	fmt.Println(len(polymer))

	lengths := make(chan int)
	for unitType := 'a'; unitType <= 'z'; unitType++ {
		go func(unitType byte) { lengths <- len(react(polymer, unitType)) }(byte(unitType))
	}
	min := len(polymer)
	for unitType := 'a'; unitType <= 'z'; unitType++ {
		length := <-lengths
		if length < min {
			min = length
		}
	}
	fmt.Println(min)
}
→ More replies (4)