github.com/agrigoryan/aoc_2023_go@v0.0.0-20231216221323-4ace361ec685/day5/d5p1.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  type mappingRule struct {
    14  	src   int
    15  	dst   int
    16  	count int
    17  }
    18  
    19  type mapping struct {
    20  	srcCode string
    21  	dstCode string
    22  	rules   []mappingRule
    23  }
    24  
    25  var mappings = map[string]mapping{}
    26  
    27  func (m *mapping) mapValue(src int) int {
    28  	for _, rule := range m.rules {
    29  		if src >= rule.src && src < rule.src+rule.count {
    30  			return rule.dst + src - rule.src
    31  		}
    32  	}
    33  	return src
    34  }
    35  
    36  func doMappings(srcCode string, dstCode string, srcValue int) int {
    37  	mapping := mappings[srcCode]
    38  	result := srcValue
    39  	for mapping.srcCode != dstCode {
    40  		result = mapping.mapValue(result)
    41  		dstMapping, ok := mappings[mapping.dstCode]
    42  		if !ok {
    43  			break
    44  		}
    45  		mapping = dstMapping
    46  	}
    47  	return result
    48  }
    49  
    50  func d5p1(input string) int {
    51  	lines := strings.Split(input, "\n")
    52  
    53  	toNumbersMapper := aocutils.Mapper(func(str string) int {
    54  		res, err := strconv.Atoi(str)
    55  		if err != nil {
    56  			log.Fatal("failed to map to numbers")
    57  		}
    58  		return res
    59  	})
    60  
    61  	seeds := toNumbersMapper(strings.Split(strings.Split(lines[0], ": ")[1], " "))
    62  
    63  	lines = lines[1:]
    64  
    65  	var activeMapping *mapping
    66  	for _, line := range lines {
    67  		if len(strings.TrimSpace(line)) == 0 {
    68  			if activeMapping != nil {
    69  				mappings[activeMapping.srcCode] = *activeMapping
    70  				activeMapping = nil
    71  			}
    72  			continue
    73  		}
    74  		if activeMapping == nil {
    75  			// reading a new mapping details
    76  			parts := strings.Split(strings.Split(line, " ")[0], "-")
    77  			activeMapping = &mapping{
    78  				srcCode: parts[0],
    79  				dstCode: parts[2],
    80  			}
    81  		} else {
    82  			// parsing new mapping rule here
    83  			numbers := toNumbersMapper(strings.Split(line, " "))
    84  			activeMapping.rules = append(activeMapping.rules, mappingRule{
    85  				src:   numbers[1],
    86  				dst:   numbers[0],
    87  				count: numbers[2],
    88  			})
    89  		}
    90  	}
    91  	if activeMapping != nil {
    92  		mappings[activeMapping.srcCode] = *activeMapping
    93  	}
    94  
    95  	fmt.Println(mappings)
    96  
    97  	var minLocation int = math.MaxInt
    98  
    99  	for _, seed := range seeds {
   100  		location := doMappings("seed", "location", seed)
   101  		if location < minLocation {
   102  			minLocation = location
   103  		}
   104  	}
   105  
   106  	fmt.Println(minLocation)
   107  	return minLocation
   108  }