AoC Day 12, Part 1 (Solved - FINALLY)
This commit is contained in:
114
2023/12/code.go
114
2023/12/code.go
@@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -37,82 +36,87 @@ func run(part2 bool, input string) any {
|
|||||||
ci, _ := strconv.Atoi(c)
|
ci, _ := strconv.Atoi(c)
|
||||||
combo = append(combo, ci)
|
combo = append(combo, ci)
|
||||||
}
|
}
|
||||||
springs := make([]rune, 0)
|
|
||||||
for _, r := range strings.Split(spl[0], "") {
|
|
||||||
springs = append(springs, rune(r[0]))
|
|
||||||
}
|
|
||||||
p := iteratePossibilities(spl[0]+".", combo, 0)
|
|
||||||
|
|
||||||
sum += p
|
//fmt.Printf("\nLooking in %v %v\n", spl[0], combo)
|
||||||
|
poss := iteratePossibilities(spl[0], combo)
|
||||||
|
|
||||||
|
//fmt.Printf("In %v %v: %v\n", spl[0], combo, poss)
|
||||||
|
|
||||||
|
sum += poss
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
func iteratePossibilities(springs string, combo []int, depth int) int {
|
func iteratePossibilities(springs string, combo []int) int {
|
||||||
if len(combo) == 0 {
|
if len(combo) == 0 {
|
||||||
panic("Can't try find possibilities with empty combo list")
|
panic("Combo is empty")
|
||||||
}
|
}
|
||||||
sprlen := combo[0] + 1
|
|
||||||
|
|
||||||
print(fmt.Sprintf("%v:", springs), depth)
|
lenMatch := combo[0]
|
||||||
if len(springs) < sprlen {
|
|
||||||
// Can't fit, bad match
|
if len(springs) < lenMatch {
|
||||||
print(fmt.Sprintf("Cannot fit combo len %v in remaining springs %v", sprlen, springs), depth)
|
// Cannot match, not enough space
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
p := 0
|
p := 0
|
||||||
for i := 0; i <= len(springs)-sprlen; i++ {
|
for i := 0; i < len(springs)-lenMatch+1; i++ {
|
||||||
match := true
|
match := true
|
||||||
forcedMatch := true
|
forceMatch := false
|
||||||
checking := springs[i : i+sprlen]
|
for m := i; m < i+lenMatch; m++ {
|
||||||
print(fmt.Sprintf("Testing %v in %v", checking, springs), depth)
|
if rune(springs[m]) == '.' {
|
||||||
|
match = false
|
||||||
|
}
|
||||||
|
|
||||||
for c, r := range checking {
|
if rune(springs[m]) == '#' && i == m {
|
||||||
if rune(r) == '#' {
|
forceMatch = true
|
||||||
if c == sprlen-1 {
|
|
||||||
print("Failed match: ends with damaged (would be non-contiguous)", depth)
|
|
||||||
match = false
|
|
||||||
}
|
|
||||||
} else if rune(r) == '.' {
|
|
||||||
if c != sprlen-1 {
|
|
||||||
print("Failed match: contained undamaged", depth)
|
|
||||||
match = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if c != sprlen-1 {
|
|
||||||
print(fmt.Sprintf("NOT forced match at %v", c), depth)
|
|
||||||
forcedMatch = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if match {
|
if !match {
|
||||||
print(fmt.Sprintf("Found %v+1 match (forced=%v) in %v at %v-%v (%v) (remaining: %v)", combo[0], forcedMatch, springs, i, i+sprlen-1, springs[i:i+sprlen], combo[1:]), depth)
|
// Keep trying
|
||||||
|
if forceMatch {
|
||||||
if len(combo) > 1 {
|
|
||||||
p += iteratePossibilities(springs[i+sprlen:], combo[1:], depth+1)
|
|
||||||
} else {
|
|
||||||
p += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if forcedMatch {
|
|
||||||
print("Forced match, not trying any other combos for this", depth)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
matchFrom := i + lenMatch
|
||||||
|
if len(springs) > i+lenMatch {
|
||||||
|
if rune(springs[i+lenMatch]) == '#' {
|
||||||
|
// Would be contigious, does not work
|
||||||
|
if forceMatch {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
matchFrom += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cool! We are matched!
|
||||||
|
if len(combo) == 1 {
|
||||||
|
// Check, finally, that there are no possible # in the future (which would violate the requirements)
|
||||||
|
anyFuture := false
|
||||||
|
for j := matchFrom; j < len(springs); j++ {
|
||||||
|
if rune(springs[j]) == '#' {
|
||||||
|
anyFuture = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !anyFuture {
|
||||||
|
//fmt.Printf("MATCHED %v in %v from [%v;%v)\n", lenMatch, springs, i, i+lenMatch-1)
|
||||||
|
p += 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//fmt.Printf("Matched %v in %v from [%v;%v)\n", lenMatch, springs, i, i+lenMatch-1)
|
||||||
|
p += iteratePossibilities(springs[matchFrom:], combo[1:])
|
||||||
|
}
|
||||||
|
|
||||||
|
if forceMatch {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func print(pr string, depth int) {
|
|
||||||
print := false
|
|
||||||
if print {
|
|
||||||
for i := 0; i < depth; i++ {
|
|
||||||
fmt.Printf("> ")
|
|
||||||
}
|
|
||||||
fmt.Println(pr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,3 +4,6 @@
|
|||||||
????.#...#... 4,1,1
|
????.#...#... 4,1,1
|
||||||
????.######..#####. 1,6,5
|
????.######..#####. 1,6,5
|
||||||
?###???????? 3,2,1
|
?###???????? 3,2,1
|
||||||
|
???#???????? 3,2,1
|
||||||
|
???#??#???????? 3,2,1
|
||||||
|
|
||||||
|
|||||||
1000
2023/12/input-user.txt
Normal file
1000
2023/12/input-user.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user