day 12,13
This commit is contained in:
136
2023/go/day12/day12.go
Normal file
136
2023/go/day12/day12.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package day12
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"adventofcode2023/utils"
|
||||
"adventofcode2023/utils/inputs"
|
||||
)
|
||||
|
||||
var cache = make(map[string]int)
|
||||
|
||||
type memoized struct {
|
||||
f func(int) int
|
||||
cache map[string]int
|
||||
}
|
||||
|
||||
func Part1(input string) int {
|
||||
ans := 0
|
||||
lines := strings.Split(input, "\n")
|
||||
for _, line := range lines {
|
||||
slices := strings.Split(line, " ")
|
||||
record := slices[0]
|
||||
groups := inputs.ToInts(slices[1], ",")
|
||||
ans += calc(record, groups)
|
||||
}
|
||||
return ans
|
||||
}
|
||||
|
||||
func Part2(input string) int {
|
||||
ans := 0
|
||||
lines := strings.Split(input, "\n")
|
||||
for i, line := range lines {
|
||||
slices := strings.Split(line, " ")
|
||||
record := slices[0] + "?" + slices[0] + "?" + slices[0] + "?" + slices[0] + "?" + slices[0]
|
||||
groups := inputs.ToInts(slices[1] + "," + slices[1] + "," + slices[1] + "," + slices[1] + "," + slices[1] , ",")
|
||||
ans += calc(record, groups)
|
||||
fmt.Printf("running total after lines %v = %v\n",i, ans)
|
||||
}
|
||||
return ans
|
||||
}
|
||||
|
||||
func calc(record string, groups []int) int {
|
||||
key := record + fmt.Sprint(groups)
|
||||
if v, ok := cache[key]; ok {
|
||||
return v
|
||||
}
|
||||
// ADD LOGIC HERE ... Base-case logic will go here
|
||||
// Did we run out of groups? We might still be valid
|
||||
if len(groups) == 0 {
|
||||
// Make sure there aren't any more damaged springs, if so, we're valid
|
||||
if ! strings.Contains(record, "#") {
|
||||
cache[key] = 1
|
||||
return 1
|
||||
} else {
|
||||
// Not valid to runout of groups and still have damaged springs "#"
|
||||
cache[key] = 0
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
if len(record) == 0 {
|
||||
// Already know there are more groups but no records
|
||||
cache[key] = 0
|
||||
return 0
|
||||
}
|
||||
|
||||
// Look at the next element in each record and group
|
||||
next_character := record[0]
|
||||
next_group := groups[0]
|
||||
out := 0
|
||||
|
||||
if next_character == '#' {
|
||||
// Test pound logic
|
||||
out = pound(record, groups, next_group)
|
||||
} else if next_character == '.' {
|
||||
// Test dot logic
|
||||
out = dot(record, groups)
|
||||
} else if next_character == '?' {
|
||||
// This character could be either character, so we'll explore both
|
||||
//possibilities
|
||||
out = dot(record, groups) + pound(record, groups, next_group)
|
||||
} else {
|
||||
utils.PanicOnErr(fmt.Errorf("RuntimeError"))
|
||||
|
||||
}
|
||||
// Help with debugging
|
||||
// fmt.Println(record, groups, out)
|
||||
cache[key] = out
|
||||
return out
|
||||
}
|
||||
|
||||
// Logic that treats the first character as pound-sign "#"
|
||||
func pound(record string, groups []int, next_group int) int {
|
||||
|
||||
// If the first is a pound, then the first n characters must be
|
||||
// able to be treated as a pound, where n is the first group number
|
||||
if next_group > len(record) {
|
||||
return 0
|
||||
}
|
||||
this_group := record[:next_group]
|
||||
this_group = strings.Replace(this_group, "?", "#", -1)
|
||||
|
||||
// If the next group can't fit all the damaged springs, then abort
|
||||
if this_group != strings.Repeat("#", next_group) {
|
||||
return 0
|
||||
}
|
||||
|
||||
// If the rest of the record is just the last group, then we're
|
||||
// done and there's only one possibility
|
||||
if len(record) == next_group {
|
||||
// Make sure this is the last group
|
||||
if len(groups) == 1 {
|
||||
//We are valid
|
||||
return 1
|
||||
} else {
|
||||
// There's more groups, we can't make it work
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the character that follows this group can be a seperator
|
||||
if record[next_group] == '?' || record[next_group] == '.' {
|
||||
// It can be seperator, so skip it and reduce to the next group
|
||||
return calc(record[next_group+1:], groups[1:])
|
||||
}
|
||||
// Can't be handled, there are no possibilites
|
||||
return 0
|
||||
}
|
||||
|
||||
// Logic that treats the first character as dot "."
|
||||
func dot(record string, groups []int) int {
|
||||
// ADD LOGIC HERE ... need to process this character and call
|
||||
// We just skip over the dot looking for the next pound
|
||||
return calc(record[1:], groups)
|
||||
}
|
||||
29
2023/go/day12/day12_test.go
Normal file
29
2023/go/day12/day12_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package day12
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPart1(t *testing.T) {
|
||||
r := Part1(
|
||||
`???.### 1,1,3
|
||||
.??..??...?##. 1,1,3
|
||||
?#?#?#?#?#?#?#? 1,3,1,6
|
||||
????.#...#... 4,1,1
|
||||
????.######..#####. 1,6,5
|
||||
?###???????? 3,2,1`)
|
||||
require.Equal(t, 21, r)
|
||||
}
|
||||
|
||||
func TestPart2(t *testing.T) {
|
||||
r := Part2(
|
||||
`???.### 1,1,3
|
||||
.??..??...?##. 1,1,3
|
||||
?#?#?#?#?#?#?#? 1,3,1,6
|
||||
????.#...#... 4,1,1
|
||||
????.######..#####. 1,6,5
|
||||
?###???????? 3,2,1`)
|
||||
require.Equal(t, 525152, r)
|
||||
}
|
||||
1000
2023/go/day12/input.txt
Normal file
1000
2023/go/day12/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user