124 lines
2.7 KiB
Go
124 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
var input []string
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
for scanner.Scan() {
|
|
input = append(input, scanner.Text())
|
|
}
|
|
|
|
transforms := make(map[string][]string)
|
|
var stMolecule string
|
|
|
|
for i := range input {
|
|
if strings.Contains(input[i], "=>") {
|
|
parts := strings.Split(input[i], " => ")
|
|
transforms[parts[0]] = append(transforms[parts[0]], parts[1])
|
|
} else if len(input[i]) > 0 {
|
|
// Must be the calibration molecule
|
|
stMolecule = input[i]
|
|
}
|
|
}
|
|
|
|
fmt.Println("*** CALIBRATION ***")
|
|
res := calibrate(stMolecule, transforms)
|
|
fmt.Println("Found " + strconv.Itoa(len(res)) + " combinations")
|
|
fmt.Println("\n")
|
|
fmt.Println("*** MANUFACTURING ***")
|
|
backTrans := reverseTransforms(transforms)
|
|
manufacture(stMolecule, backTrans, 0)
|
|
}
|
|
|
|
// stepBack takes an ending string and a reversed list of the transformations
|
|
func manufacture(molecule string, transforms map[string][]string, steps int) {
|
|
fmt.Println(molecule)
|
|
|
|
if molecule == "e" {
|
|
fmt.Println("Found in " + strconv.Itoa(steps) + " steps")
|
|
os.Exit(0)
|
|
}
|
|
|
|
for k, v := range transforms {
|
|
if strings.Contains(molecule, k) {
|
|
for i := range v {
|
|
tstVal := strings.Replace(molecule, k, v[i], 1)
|
|
manufacture(tstVal, transforms, steps+1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func reverseTransforms(t map[string][]string) map[string][]string {
|
|
ret := make(map[string][]string)
|
|
for v := range t {
|
|
for j := range t[v] {
|
|
ret[t[v][j]] = append(ret[t[v][j]], v)
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func calibrate(molecule string, transforms map[string][]string) []string {
|
|
var ret []string
|
|
atoms := getAtomsFromMolecule(molecule)
|
|
|
|
for i := range atoms {
|
|
// Build a string of atoms before i
|
|
start := strings.Join(atoms[:i], "")
|
|
// And all after i too
|
|
end := strings.Join(atoms[i+1:], "")
|
|
// Find all transforms for atoms[i]
|
|
if v, ok := transforms[atoms[i]]; ok {
|
|
for j := range v {
|
|
ret = uniqueInsert(ret, start+v[j]+end)
|
|
//ret = append(ret, start+v[j]+end)
|
|
}
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func getAtomsFromMolecule(molecule string) []string {
|
|
var atoms []string
|
|
var bldAtom string
|
|
|
|
for i := range molecule {
|
|
if molecule[i] >= 'A' && molecule[i] <= 'Z' {
|
|
if len(bldAtom) > 0 {
|
|
atoms = append(atoms, bldAtom)
|
|
}
|
|
bldAtom = string(molecule[i])
|
|
continue
|
|
}
|
|
bldAtom = bldAtom + string(molecule[i])
|
|
}
|
|
return append(atoms, bldAtom)
|
|
}
|
|
|
|
func uniqueInsert(curr []string, ins string) []string {
|
|
for i := range curr {
|
|
if curr[i] == ins {
|
|
return curr
|
|
}
|
|
}
|
|
return append(curr, ins)
|
|
}
|
|
|
|
func mustAtoi(s string) int {
|
|
var i int
|
|
var err error
|
|
if i, err = strconv.Atoi(s); err != nil {
|
|
fmt.Println("Tried to atoi " + s)
|
|
os.Exit(1)
|
|
}
|
|
return i
|
|
}
|