package day12 import ( "fmt" "regexp" "strings" "gitea.paas.celticinfo.fr/oabrivard/aoc2023/utils" ) func generateConditions(condPattern []byte) [][]byte { result := [][]byte{} for i, b := range condPattern { if b == '?' { newPattern1 := make([]byte, len(condPattern)) copy(newPattern1, condPattern) newPattern1[i] = '.' result = append(result, generateConditions(newPattern1)...) newPattern2 := make([]byte, len(condPattern)) copy(newPattern2, condPattern) newPattern2[i] = '#' result = append(result, generateConditions(newPattern2)...) return result } } result = append(result, condPattern) return result } func SumArragements1(lines []string) int { result := 0 for l, line := range lines { line_parts := strings.Fields(line) gs := utils.ParseIntArray(line_parts[1], ",") // group sizes count := 0 // numberOfArrangements for the line var sb strings.Builder sb.WriteString(`^\.*`) for i, curr_gs := range gs { sb.WriteString(fmt.Sprintf("#{%d}?", curr_gs)) if i != len(gs)-1 { sb.WriteString(`\.+`) } } sb.WriteString(`\.*$`) reString := sb.String() var re = regexp.MustCompile(reString) conds := generateConditions([]byte(line_parts[0])) for _, cond := range conds { if re.Match(cond) { count++ } } fmt.Printf("Matching line %d : %d\n", l, count) result += count } return result } var solved map[string]int /* func CountArrangements(line []byte, gs []int, curr_gs int, previous byte, s string) int { if curr_gs == len(gs)-1 && gs[curr_gs] == 0 { for _, c := range line { if c == '#' { return 0 } } //fmt.Println(s) return 1 } if len(line) == 0 { return 0 } key := string(line) + fmt.Sprintf("%v-%v", gs, curr_gs) val, found := solved[key] if found { return val } count := 0 switch line[0] { case '?': line[0] = '.' count1 := CountArrangements(line, gs, curr_gs, previous, s) line[0] = '#' count2 := CountArrangements(line, gs, curr_gs, previous, s) line[0] = '?' count = count1 + count2 case '#': if previous == '.' || previous == 0 { if curr_gs >= 0 && gs[curr_gs] > 0 { return 0 } curr_gs++ } if curr_gs >= len(gs) { return 0 } if gs[curr_gs] == 0 { return 0 } gs[curr_gs]-- count = CountArrangements(line[1:], gs, curr_gs, '#', s+"#") gs[curr_gs]++ case '.': count = CountArrangements(line[1:], gs, curr_gs, '.', s+".") } solved[key] = count return count } */ func CountArrangements(conds []byte, gs []int) int { if len(gs) == 0 { for _, c := range conds { if c == '#' { return 0 } } return 1 } if len(conds) == 0 { return 0 } key := fmt.Sprintf("%v-%v", conds, gs) val, found := solved[key] if found { return val } count := 0 switch conds[0] { case '?': conds[0] = '.' count += CountArrangements(conds, gs) conds[0] = '#' count += CountArrangements(conds, gs) conds[0] = '?' case '#': first_gs := gs[0] if first_gs <= len(conds) && !strings.Contains(string(conds[0:first_gs]), ".") { if first_gs == len(conds) { count = CountArrangements(conds[first_gs:], gs[1:]) } else if conds[first_gs] != '#' { count = CountArrangements(conds[first_gs+1:], gs[1:]) } } case '.': count = CountArrangements(conds[1:], gs) } solved[key] = count return count } func SumArragements2(lines []string, expansion int) int { result := 0 for l, line := range lines { line_parts := strings.Fields(line) parsed_gs := utils.ParseIntArray(line_parts[1], ",") // group sizes gs := []int{} for i := 0; i < expansion+1; i++ { gs = append(gs, parsed_gs...) } var sb strings.Builder sb.WriteString(line_parts[0]) for i := 0; i < expansion; i++ { sb.WriteString("?") sb.WriteString(line_parts[0]) } s := sb.String() solved = map[string]int{} /* count := CountArrangements([]byte(s), gs, -1, 0, "") // numberOfArrangements for the line */ count := CountArrangements([]byte(s), gs) // numberOfArrangements for the line fmt.Printf("%d arrangements for %s on line %d\n", count, s, l) result += count } return result }