2018-12-05 14:57:22 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
2018-12-05 15:12:29 +00:00
|
|
|
"bytes"
|
2018-12-05 14:57:22 +00:00
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2018-12-05 15:12:29 +00:00
|
|
|
inp := []byte(StdinToString())
|
2018-12-05 14:57:22 +00:00
|
|
|
fmt.Println("= Part 1 =")
|
|
|
|
fmt.Println(part1(inp))
|
|
|
|
fmt.Println("\n= Part 2 =")
|
|
|
|
fmt.Println(part2(inp))
|
|
|
|
}
|
|
|
|
|
2018-12-05 15:12:29 +00:00
|
|
|
func part1(inp []byte) int {
|
2018-12-05 14:57:22 +00:00
|
|
|
last := inp
|
|
|
|
curr := react(last)
|
2018-12-05 15:12:29 +00:00
|
|
|
for !bytes.Equal(last, curr) {
|
2018-12-05 14:57:22 +00:00
|
|
|
last = curr
|
|
|
|
curr = react(last)
|
|
|
|
}
|
|
|
|
return len(curr)
|
|
|
|
}
|
|
|
|
|
|
|
|
// useShortest will skip runs where there are fewer letters in the input than the current shortest...
|
|
|
|
// It reduced _my_ runtime by about 3 minutes, but may fail depending on your input
|
|
|
|
var useShortest bool
|
|
|
|
|
2018-12-05 15:12:29 +00:00
|
|
|
func part2(inp []byte) int {
|
2018-12-05 14:57:22 +00:00
|
|
|
// If yours fails, try setting this to false
|
|
|
|
useShortest = true
|
|
|
|
shortest := len(inp)
|
|
|
|
var shortestCount int
|
|
|
|
var count int
|
|
|
|
for i := 65; i <= 90; i++ {
|
2018-12-05 15:12:29 +00:00
|
|
|
var try []byte
|
2018-12-05 14:57:22 +00:00
|
|
|
if useShortest {
|
2018-12-05 15:12:29 +00:00
|
|
|
count = countByte(inp, byte(i))
|
2018-12-05 14:57:22 +00:00
|
|
|
if count < shortestCount {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for j := range inp {
|
|
|
|
if int(inp[j]) == i || int(inp[j]) == i+32 {
|
|
|
|
continue
|
|
|
|
}
|
2018-12-05 15:12:29 +00:00
|
|
|
try = append(try, inp[j])
|
2018-12-05 14:57:22 +00:00
|
|
|
}
|
|
|
|
v := part1(try)
|
|
|
|
if v < shortest {
|
|
|
|
shortest = v
|
|
|
|
shortestCount = count
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return shortest
|
|
|
|
}
|
|
|
|
|
2018-12-05 15:12:29 +00:00
|
|
|
func countByte(h []byte, n byte) int {
|
|
|
|
var ret int
|
|
|
|
for i := range h {
|
|
|
|
if h[i] == n {
|
|
|
|
ret++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
func react(v []byte) []byte {
|
|
|
|
var ret []byte
|
2018-12-05 14:57:22 +00:00
|
|
|
for i := 0; i < len(v); i++ {
|
2018-12-05 15:39:41 +00:00
|
|
|
if i < len(v)-1 && sameDecase(v[i], v[i+1]) {
|
2018-12-05 14:57:22 +00:00
|
|
|
i++
|
|
|
|
continue
|
|
|
|
}
|
2018-12-05 15:12:29 +00:00
|
|
|
ret = append(ret, v[i])
|
2018-12-05 14:57:22 +00:00
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
func StdinToString() string {
|
|
|
|
var input string
|
|
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
|
|
for scanner.Scan() {
|
|
|
|
input += scanner.Text()
|
|
|
|
}
|
|
|
|
return input
|
|
|
|
}
|
|
|
|
|
|
|
|
func Atoi(i string) int {
|
|
|
|
var ret int
|
|
|
|
var err error
|
|
|
|
if ret, err = strconv.Atoi(i); err != nil {
|
|
|
|
log.Fatal("Invalid Atoi")
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2018-12-05 15:39:41 +00:00
|
|
|
func sameDecase(val1, val2 byte) bool {
|
|
|
|
return val1+32 == val2 || val2+32 == val1
|
2018-12-05 14:57:22 +00:00
|
|
|
}
|