DEV Community

Discussion on: AoC Day 5: Alchemical Reduction

Collapse
 
bjarnemagnussen profile image
Bjarne Magnussen • Edited

I am using Advent of Code to learn Golang, and here is the solution I came up with. Suggestions for improvements are always welcome!

I was first using a list which would go from left to right and remove pairs as they were found reacting, shifting one step to the left and continue finding pairs that react. However, this could be simplified by using Ali Spittel's stack solution in Python.

With this inspiration, here is my Golang solution. I have added timing functions just to print out the running time as I have compared them to Python it is finally a speed up using Golang for the solution in this case!

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
    "time"
    "unicode"
)

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    var lines []string
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        lines = append(lines, scanner.Text())
    }
    return lines, scanner.Err()
}

func invertChar(c rune) rune {
    if unicode.ToUpper(c) == c {
        return unicode.ToLower(c)
    }
    return unicode.ToUpper(c)
}

func react(polymer string) int {
    stack := []rune{}
    var top rune
    for _, unit := range polymer {
        if len(stack) == 0 {
            // Initialise stack:
            stack = append(stack, unit)
            continue
        }
        top = stack[len(stack)-1]
        if top == invertChar(unit) {
            // Consume last unit:
            stack = stack[:len(stack)-1]
        } else {
            stack = append(stack, unit)
        }
    }
    return len(stack)
}

func main() {
    data, err := readLines("input")
    if err != nil {
        panic(err)
    }

    polymerString := data[0]

    // Part 1
    start := time.Now()
    fmt.Println(react(polymerString))
    elapsed := time.Since(start)
    fmt.Println(elapsed)

    // Part 2:
    start = time.Now()
    var reduced string
    minReact := -1
    charSet := "ABCDEFGHIJKLMNOPQRSTUVXYZ"
    for _, c := range charSet {
        reduced = strings.Replace(polymerString, string(c), "", -1)
        reduced = strings.Replace(reduced, string(unicode.ToLower(c)), "", -1)
        r := react(reduced)
        if minReact == -1 || r < minReact {
            minReact = r
        }
    }
    fmt.Println(minReact)
    elapsed = time.Since(start)
    fmt.Println(elapsed)

}
Collapse
 
rpalo profile image
Ryan Palo

Nice!