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