advent-of-code/day12/main.go

123 lines
2.0 KiB
Go
Raw Normal View History

2023-12-13 08:32:53 -07:00
package main
import (
"bufio"
_ "embed"
"fmt"
"slices"
"strings"
aoc "go.sour.is/advent-of-code-2023"
)
// var log = aoc.Log
func main() { aoc.MustResult(aoc.Runner(run)) }
type result struct {
valuePT1 int
valuePT2 int
}
func (r result) String() string { return fmt.Sprintf("%#v", r) }
func run(scan *bufio.Scanner) (*result, error) {
var matches []int
for scan.Scan() {
text := scan.Text()
status, text, ok := strings.Cut(text, " ")
if !ok {
continue
}
grouping := aoc.SliceMap(aoc.Atoi, strings.Split(text, ",")...)
pattern := []rune(status)
missing := countQuestion(pattern)
s := spring{pattern: pattern, grouping: grouping, missingNo: missing}
matches = append(matches, s.findMatches())
}
return &result{valuePT1: aoc.Sum(matches...)}, nil
}
type spring struct {
pattern []rune
grouping []int
missingNo int
}
func (s *spring) findMatches() int {
matches := 0
for _, pattern := range s.genPatterns() {
pattern := []rune(pattern)
target := make([]rune, len(s.pattern))
i := 0
for j, r := range s.pattern {
if r == '?' {
target[j] = pattern[i]
i++
continue
}
target[j] = r
}
if slices.Equal(countGroupings(target), s.grouping) {
matches++
}
}
return matches
}
func (s *spring) genPatterns() []string {
buf := &strings.Builder{}
combinations := aoc.Power2(s.missingNo)
lis := make([]string, 0, combinations)
for i := 0; i < combinations; i++ {
for b := 0; b < s.missingNo; b++ {
if i>>b&0b1 == 1 {
buf.WriteRune('#')
} else {
buf.WriteRune('.')
}
}
lis = append(lis, buf.String())
buf.Reset()
}
return lis
}
func countQuestion(pattern []rune) int {
count := 0
for _, r := range pattern {
if r == '?' {
count++
}
}
return count
}
func countGroupings(pattern []rune) []int {
var groupings []int
inGroup := false
for _, r := range pattern {
if r == '#' {
if !inGroup {
groupings = append(groupings, 0)
}
inGroup = true
groupings[len(groupings)-1]++
}
if inGroup && r != '#' {
inGroup = false
}
}
return groupings
}