package main import ( "fmt" "sort" "strings" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) func main() { inp := h.StdinToStringSlice() part1(inp) fmt.Println() part2(inp) } func part1(input []string) { var bricks [][]int for _, line := range input { values := strings.Split(strings.ReplaceAll(line, "~", ","), ",") var brick []int for _, v := range values { num := 0 fmt.Sscanf(v, "%d", &num) brick = append(brick, num) } bricks = append(bricks, brick) } sort.Slice(bricks, func(i, j int) bool { return bricks[i][2] < bricks[j][2] }) for index, brick := range bricks { maxZ := 1 for _, check := range bricks[:index] { if overlaps(brick, check) { maxZ = max(maxZ, check[5]+1) } } brick[5] -= brick[2] - maxZ brick[2] = maxZ } sort.Slice(bricks, func(i, j int) bool { return bricks[i][2] < bricks[j][2] }) kSupportsV := make(map[int]map[int]struct{}) vSupportsK := make(map[int]map[int]struct{}) for i := range bricks { kSupportsV[i] = make(map[int]struct{}) vSupportsK[i] = make(map[int]struct{}) } for j, upper := range bricks { for i, lower := range bricks[:j] { if overlaps(lower, upper) && upper[2] == lower[5]+1 { kSupportsV[i][j] = struct{}{} vSupportsK[j][i] = struct{}{} } } } total := 0 for i := range bricks { satisfies := true for j := range kSupportsV[i] { if len(vSupportsK[j]) < 2 { satisfies = false break } } if satisfies { total++ } } fmt.Println("# Part 1") fmt.Println(total) } func part2(input []string) { var bricks [][]int for _, line := range input { values := strings.Split(strings.ReplaceAll(line, "~", ","), ",") var brick []int for _, v := range values { num := 0 fmt.Sscanf(v, "%d", &num) brick = append(brick, num) } bricks = append(bricks, brick) } sort.SliceStable(bricks, func(i, j int) bool { return bricks[i][2] < bricks[j][2] }) for index, brick := range bricks { maxZ := 1 for _, check := range bricks[:index] { if overlaps(brick, check) { maxZ = max(maxZ, check[5]+1) } } brick[5] -= brick[2] - maxZ brick[2] = maxZ } sort.SliceStable(bricks, func(i, j int) bool { return bricks[i][2] < bricks[j][2] }) kSupportsV := make(map[int]map[int]struct{}) vSupportsK := make(map[int]map[int]struct{}) for i := range bricks { kSupportsV[i] = make(map[int]struct{}) vSupportsK[i] = make(map[int]struct{}) } for j, upper := range bricks { for i, lower := range bricks[:j] { if overlaps(lower, upper) && upper[2] == lower[5]+1 { kSupportsV[i][j] = struct{}{} vSupportsK[j][i] = struct{}{} } } } total := 0 for i := range bricks { q := make([]int, 0) for j := range kSupportsV[i] { if len(vSupportsK[j]) == 1 { q = append(q, j) } } falling := make(map[int]struct{}) for _, j := range q { falling[j] = struct{}{} } falling[i] = struct{}{} for len(q) > 0 { j := q[0] q = q[1:] for k := range kSupportsV[j] { if _, ok := falling[k]; !ok { if isSubset(vSupportsK[k], falling) { q = append(q, k) falling[k] = struct{}{} } } } } total += len(falling) - 1 } fmt.Println("# Part 2") fmt.Println(total) } func isSubset(set1, set2 map[int]struct{}) bool { for key := range set1 { if _, ok := set2[key]; !ok { return false } } return true } func overlaps(a, b []int) bool { return max(a[0], b[0]) <= min(a[3], b[3]) && max(a[1], b[1]) <= min(a[4], b[4]) } func max(a, b int) int { if a > b { return a } return b } func min(a, b int) int { if a < b { return a } return b }