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 }