github.com/agrigoryan/aoc_2023_go@v0.0.0-20231216221323-4ace361ec685/day5/d5p2.go (about)

     1  package day5
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"math"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/agrigoryan/aoc_2023_go/aocutils"
    11  )
    12  
    13  func d5p2(input string) int {
    14  	lines := strings.Split(input, "\n")
    15  
    16  	toNumbersMapper := aocutils.Mapper(func(str string) int {
    17  		res, err := strconv.Atoi(str)
    18  		if err != nil {
    19  			log.Fatal("failed to map to numbers")
    20  		}
    21  		return res
    22  	})
    23  
    24  	seedRanges := toNumbersMapper(strings.Split(strings.Split(lines[0], ": ")[1], " "))
    25  
    26  	lines = lines[1:]
    27  
    28  	var activeMapping *mapping
    29  	for _, line := range lines {
    30  		if len(strings.TrimSpace(line)) == 0 {
    31  			if activeMapping != nil {
    32  				mappings[activeMapping.srcCode] = *activeMapping
    33  				activeMapping = nil
    34  			}
    35  			continue
    36  		}
    37  		if activeMapping == nil {
    38  			// reading a new mapping details
    39  			parts := strings.Split(strings.Split(line, " ")[0], "-")
    40  			activeMapping = &mapping{
    41  				srcCode: parts[0],
    42  				dstCode: parts[2],
    43  			}
    44  		} else {
    45  			// parsing new mapping rule here
    46  			numbers := toNumbersMapper(strings.Split(line, " "))
    47  			activeMapping.rules = append(activeMapping.rules, mappingRule{
    48  				src:   numbers[1],
    49  				dst:   numbers[0],
    50  				count: numbers[2],
    51  			})
    52  		}
    53  	}
    54  	if activeMapping != nil {
    55  		mappings[activeMapping.srcCode] = *activeMapping
    56  	}
    57  
    58  	rangeMinimums := make(chan int, len(seedRanges)/2)
    59  
    60  	for i := 0; i < len(seedRanges); i += 2 {
    61  		rangeStart := seedRanges[i]
    62  		rangeEnd := rangeStart + seedRanges[i+1]
    63  		go func() {
    64  			fmt.Println(rangeStart, rangeEnd)
    65  			var minLocation int = math.MaxInt
    66  			for seed := rangeStart; seed < rangeEnd; seed++ {
    67  				location := doMappings("seed", "location", seed)
    68  				if location < minLocation {
    69  					minLocation = location
    70  				}
    71  			}
    72  			rangeMinimums <- minLocation
    73  		}()
    74  	}
    75  
    76  	totalMin := math.MaxInt
    77  	resultsRead := 0
    78  	for rangeMin := range rangeMinimums {
    79  		if rangeMin < totalMin {
    80  			totalMin = rangeMin
    81  		}
    82  		resultsRead += 1
    83  		if resultsRead == len(seedRanges)/2 {
    84  			break
    85  		}
    86  	}
    87  
    88  	fmt.Println(totalMin)
    89  	return totalMin
    90  }