Skip to content

Commit

Permalink
Add solution for 2023 Day 12 P2
Browse files Browse the repository at this point in the history
  • Loading branch information
scottmckendry committed Dec 14, 2023
1 parent cddd053 commit f7193b3
Show file tree
Hide file tree
Showing 4 changed files with 1,103 additions and 66 deletions.
143 changes: 83 additions & 60 deletions 2023/12p1.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,89 +8,112 @@ import (
"aoc2023/utils"
)

type springRow struct {
validPermutations []int
springs []rune
permutationsCount int
}
var springCache = make(map[string]int)

func D12P1() {
lines := utils.ReadLines("inputs/12.txt")
springRows := parseSpringRows(lines)

for i := 0; i < len(springRows); i++ {
springRows[i].permutationsCount = calculatePermutations(
springRows[i].springs,
springRows[i].validPermutations,
0,
)
}
springs, groups := parseSprings(lines, false)

permutationTotal := 0
for _, springRow := range springRows {
permutationTotal += springRow.permutationsCount
for i := 0; i < len(springs); i++ {
permutationTotal += calculatePermutations(springs[i], groups[i])
}

fmt.Printf("There are %d permutations\n", permutationTotal)
fmt.Printf("Total possible spring arrangements: %d\n", permutationTotal)
}

func parseSpringRows(lines []string) []springRow {
springRows := make([]springRow, len(lines))
func parseSprings(lines []string, unfold bool) ([]string, [][]int) {
springs := make([]string, len(lines))
groups := make([][]int, len(lines))
for i, line := range lines {
springRows[i] = parseSpringRow(line)
springs[i], groups[i] = parseSpringRow(line, unfold)
}
return springRows
return springs, groups
}

func parseSpringRow(line string) springRow {
springRow := springRow{}
springsString := strings.Split(line, " ")[0]
for _, char := range springsString {
springRow.springs = append(springRow.springs, char)
}
func parseSpringRow(line string, unfold bool) (string, []int) {
spring := strings.Split(line, " ")[0]
groupsString := strings.Split(line, " ")[1]
groupsStringValues := strings.Split(groupsString, ",")

validPermutationString := strings.Split(line, " ")[1]
validPermutations := strings.Split(validPermutationString, ",")
groups := make([]int, len(groupsStringValues))
for i := 0; i < len(groups); i++ {
groups[i], _ = strconv.Atoi(groupsStringValues[i])
}

for _, permutation := range validPermutations {
permutationInt, _ := strconv.Atoi(permutation)
springRow.validPermutations = append(springRow.validPermutations, permutationInt)
newSpring := ""
newGroups := []int{}
if unfold {
for i := 0; i < 5; i++ {
newSpring += spring + "?"
newGroups = append(newGroups, groups...)
}
} else {
newSpring = spring
newGroups = groups
}
return springRow

// remove the last ? from the row
newSpring = newSpring[:len(newSpring)-1]

return newSpring, newGroups
}

func calculatePermutations(springs []rune, validPermutations []int, start int) int {
for i := start; i < len(springs); i++ {
if springs[i] == '?' {
springs[i] = '#'
permutationsCount := calculatePermutations(springs, validPermutations, i+1)
springs[i] = '.'
permutationsCount += calculatePermutations(springs, validPermutations, i+1)
springs[i] = '?'
return permutationsCount
func calculatePermutations(springRow string, groups []int) int {
key := springRow
for _, group := range groups {
key += strconv.Itoa(group) + ","
}

if v, ok := springCache[key]; ok {
return v
}

if len(springRow) == 0 {
if len(groups) == 0 {
return 1
} else {
return 0
}
}
if isValidPermutation(springs, validPermutations) {
return 1

if strings.HasPrefix(springRow, "?") {
return calculatePermutations(strings.Replace(springRow, "?", ".", 1), groups) +
calculatePermutations(strings.Replace(springRow, "?", "#", 1), groups)
}
if strings.HasPrefix(springRow, ".") {
res := calculatePermutations(strings.TrimPrefix(springRow, "."), groups)
springCache[key] = res
return res
}
return 0
}

func isValidPermutation(springs []rune, validPermutations []int) bool {
permutationIndex := 0
for i := 0; i < len(springs); i++ {
if springs[i] == '#' {
springStart := i
for i < len(springs) && springs[i] == '#' {
i++
}
if permutationIndex < len(validPermutations) &&
i-springStart != validPermutations[permutationIndex] {
return false
} else {
permutationIndex++
if strings.HasPrefix(springRow, "#") {
if len(groups) == 0 {
springCache[key] = 0
return 0
}
if len(springRow) < groups[0] {
springCache[key] = 0
return 0
}
if strings.Contains(springRow[0:groups[0]], ".") {
springCache[key] = 0
return 0
}
if len(groups) > 1 {
if len(springRow) < groups[0]+1 || string(springRow[groups[0]]) == "#" {
springCache[key] = 0
return 0
}
res := calculatePermutations(springRow[groups[0]+1:], groups[1:])
springCache[key] = res
return res
} else {
res := calculatePermutations(springRow[groups[0]:], groups[1:])
springCache[key] = res
return res
}
}
return permutationIndex == len(validPermutations)

return 0
}
19 changes: 19 additions & 0 deletions 2023/12p2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import (
"fmt"

"aoc2023/utils"
)

func D12P2() {
lines := utils.ReadLines("inputs/12.txt")
springs, groups := parseSprings(lines, true)

permutationTotal := 0
for i := 0; i < len(springs); i++ {
permutationTotal += calculatePermutations(springs[i], groups[i])
}

fmt.Printf("Total possible spring arrangements: %d\n", permutationTotal)
}
Loading

0 comments on commit f7193b3

Please sign in to comment.