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  }