github.com/agrigoryan/aoc_2023_go@v0.0.0-20231216221323-4ace361ec685/day10/d10p2.go (about) 1 package day10 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 func d10p2(input string) int { 9 lines := strings.Split(input, "\n") 10 11 type pos struct { 12 i, j int 13 } 14 type cell struct { 15 pos 16 d int 17 r rune 18 } 19 20 runes := make([][]rune, len(lines)) 21 22 var startCell cell 23 for i, line := range lines { 24 runes[i] = []rune(line) 25 for j, r := range runes[i] { 26 if r == 'S' { 27 startCell = cell{pos{i, j}, 0, r} 28 } 29 } 30 } 31 32 visited := map[pos]*cell{} 33 toVisit := []cell{startCell} 34 35 addToVisit := func(n pos, d int) { 36 if visited[n] != nil { 37 visited[n].d = min(visited[n].d, d) 38 } else { 39 toVisit = append(toVisit, cell{ 40 n, d, runes[n.i][n.j], 41 }) 42 } 43 } 44 45 for len(toVisit) > 0 { 46 c := toVisit[0] 47 toVisit = toVisit[1:] 48 visited[c.pos] = &c 49 n := pos{c.i - 1, c.j} 50 var nu, nd, nl, nr bool 51 if n.i >= 0 && pipeDirections[c.r].u && pipeDirections[runes[n.i][n.j]].d { 52 nu = true 53 addToVisit(n, c.d+1) 54 } 55 n = pos{c.i, c.j - 1} 56 if n.j >= 0 && pipeDirections[c.r].l && pipeDirections[runes[n.i][n.j]].r { 57 nl = true 58 addToVisit(n, c.d+1) 59 } 60 n = pos{c.i, c.j + 1} 61 if n.i < len(runes) && pipeDirections[c.r].r && pipeDirections[runes[n.i][n.j]].l { 62 nr = true 63 addToVisit(n, c.d+1) 64 } 65 n = pos{c.i + 1, c.j} 66 if n.j < len(runes[0]) && pipeDirections[c.r].d && pipeDirections[runes[n.i][n.j]].u { 67 nd = true 68 addToVisit(n, c.d+1) 69 } 70 71 // replace S with actual pipe type 72 if c == startCell { 73 var actual rune 74 if nd && nl { 75 actual = '7' 76 } else if nr && nl { 77 actual = '-' 78 } else if nd && nu { 79 actual = '|' 80 } else if nl && nu { 81 actual = 'J' 82 } else if nr && nd { 83 actual = 'F' 84 } else if nr && nu { 85 actual = 'L' 86 } 87 fmt.Println(actual) 88 runes[startCell.i][startCell.j] = actual 89 } 90 } 91 92 numCellsInside := 0 93 94 for i, row := range runes { 95 inside := false 96 marker := 0 97 for j, r := range row { 98 if (visited[pos{i, j}] != nil) { 99 if pipeDirections[r].u { 100 marker -= 1 101 } 102 if pipeDirections[r].d { 103 marker += 1 104 } 105 if marker == 0 { 106 inside = !inside 107 } else if marker < -1 || marker > 1 { 108 marker = 0 109 } 110 } else if inside { 111 fmt.Println(i, j) 112 numCellsInside += 1 113 } 114 } 115 } 116 117 fmt.Println(numCellsInside) 118 return numCellsInside 119 }