chore: add day12 part 1
This commit is contained in:
parent
927fabebfc
commit
fa2e7fedd9
6
day12/example.txt
Normal file
6
day12/example.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
???.### 1,1,3
|
||||||
|
.??..??...?##. 1,1,3
|
||||||
|
?#?#?#?#?#?#?#? 1,3,1,6
|
||||||
|
????.#...#... 4,1,1
|
||||||
|
????.######..#####. 1,6,5
|
||||||
|
?###???????? 3,2,1
|
1000
day12/input.txt
Normal file
1000
day12/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
122
day12/main.go
Normal file
122
day12/main.go
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
70
day12/main_test.go
Normal file
70
day12/main_test.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
_ "embed"
|
||||||
|
|
||||||
|
aoc "go.sour.is/advent-of-code-2023"
|
||||||
|
|
||||||
|
"github.com/matryer/is"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed example.txt
|
||||||
|
var example []byte
|
||||||
|
|
||||||
|
//go:embed input.txt
|
||||||
|
var input []byte
|
||||||
|
|
||||||
|
func TestExample(t *testing.T) {
|
||||||
|
is := is.New(t)
|
||||||
|
scan := bufio.NewScanner(bytes.NewReader(example))
|
||||||
|
|
||||||
|
result, err := run(scan)
|
||||||
|
is.NoErr(err)
|
||||||
|
|
||||||
|
t.Log(result)
|
||||||
|
is.Equal(result.valuePT1, 21)
|
||||||
|
is.Equal(result.valuePT2, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSolution(t *testing.T) {
|
||||||
|
is := is.New(t)
|
||||||
|
scan := bufio.NewScanner(bytes.NewReader(input))
|
||||||
|
|
||||||
|
result, err := run(scan)
|
||||||
|
is.NoErr(err)
|
||||||
|
|
||||||
|
t.Log(result)
|
||||||
|
is.Equal(result.valuePT1, 8193)
|
||||||
|
is.Equal(result.valuePT2, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPower2(t *testing.T) {
|
||||||
|
is := is.New(t)
|
||||||
|
|
||||||
|
is.Equal(aoc.Power2(1), 2)
|
||||||
|
is.Equal(aoc.Power2(2), 4)
|
||||||
|
is.Equal(aoc.Power2(3), 8)
|
||||||
|
is.Equal(aoc.Power2(4), 16)
|
||||||
|
is.Equal(aoc.Power2(5), 32)
|
||||||
|
is.Equal(aoc.Power2(6), 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCountGroupings(t *testing.T) {
|
||||||
|
is := is.New(t)
|
||||||
|
is.Equal([]int{1, 3, 1}, countGroupings([]rune(".#.###.#")))
|
||||||
|
is.Equal([]int{1, 3, 1}, countGroupings([]rune(".#.###...#.")))
|
||||||
|
is.Equal([]int{1, 3, 1}, countGroupings([]rune("#.###...#.")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCombination(t *testing.T) {
|
||||||
|
s := spring{
|
||||||
|
pattern: []rune("???"),
|
||||||
|
grouping: []int{1},
|
||||||
|
missingNo: 3,
|
||||||
|
}
|
||||||
|
s.findMatches()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user