package main
import (
"bufio"
"fmt"
"math"
"os"
)
func findPrevNonSpace(buf []byte) int {
for t := len(buf) - 1; t >= 0; t-- {
if buf[t] != ' ' {
return t
}
}
return -1
}
func findNextNonSpace(buf []byte) int {
for t := 0; t < len(buf); t++ {
if buf[t] != ' ' {
return t
}
}
return -1
}
func reactChain(chain []byte) []byte {
t := findNextNonSpace(chain)
for {
i := t
u := findNextNonSpace(chain[t+1:])
if u == -1 {
break
}
t += u + 1
j := t
a := chain[i]
b := chain[j]
if a-b == 32 || b-a == 32 {
chain[i] = ' '
chain[j] = ' '
t = findPrevNonSpace(chain[:i])
if t == -1 {
t = findNextNonSpace(chain)
if t == -1 {
break
}
}
}
}
return chain
}
type Puzzle struct {
Chain []byte
}
func countBufLength(buf []byte) int {
count := 0
t := findNextNonSpace(buf)
for {
b := findNextNonSpace(buf[t+1:])
if b == -1 {
if buf[t] != ' ' {
count++
}
break
}
t += b + 1
count++
}
return count
}
func (p *Puzzle) Solution1() int {
buf := make([]byte, len(p.Chain))
copy(buf, p.Chain)
return countBufLength(reactChain(buf))
}
func (p *Puzzle) Solution2() int {
var a, b byte
shortest := math.MaxInt32
for a = 'A'; a <= 'Z'; a++ {
b = a + 32
buf := make([]byte, len(p.Chain))
copy(buf, p.Chain)
t := 0
for {
u := findNextNonSpace(buf[t+1:])
if u == -1 {
break
}
if buf[t] == a || buf[t] == b {
buf[t] = ' '
}
t += u + 1
}
length := countBufLength(reactChain(buf))
if length < shortest {
shortest = length
}
}
return shortest
}
func main() {
input, err := os.Open("input.txt")
if err != nil {
panic(err.Error())
}
defer input.Close()
scanner := bufio.NewScanner(input)
p := Puzzle{}
for scanner.Scan() {
p.Chain = scanner.Bytes()
}
if err := scanner.Err(); err != nil {
panic(err.Error())
}
fmt.Println(p.Solution1())
fmt.Println(p.Solution2())
}