-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
108 lines (92 loc) · 2.02 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main
import (
_ "embed"
"fmt"
"regexp"
"strconv"
"strings"
)
type Rule struct {
dst int
src int
length int
}
//go:embed input.txt
var input string
/**
* Day 4: Scratchcards - Part 1
* url: https://adventofcode.com/2023/day/5
*/
func main() {
lines := strings.Split(strings.TrimSpace(input), "\n")
current := ""
seeds := []int{}
rules := map[string][]*Rule{}
for _, s := range lines {
s = strings.TrimSpace(s)
if strings.Contains(s, ":") {
current = strings.Replace(strings.Split(s, ":")[0], " map", "", -1)
if current == "seeds" {
re := regexp.MustCompile(`\d+`)
numbers := []int{}
for _, val := range re.FindAllStringSubmatch(strings.Split(s, ":")[1], -1) {
num, _ := strconv.Atoi(val[0])
numbers = append(numbers, num)
}
seeds = numbers
continue
}
}
rule := parseNumbers(s)
if rule != nil {
rules[current] = append(rules[current], rule)
}
}
min := 0
for _, val := range seeds {
res := resolve(rules, val)
if min == 0 || res["location"] < min {
min = res["location"]
}
}
fmt.Println("Part 1 = ", min)
}
func resolve(rules map[string][]*Rule, seed int) map[string]int {
res := map[string]int{"seed": seed}
resolveRule(rules, seed, "seed", res)
return res
}
func resolveRule(rules map[string][]*Rule, id int, name string, res map[string]int) {
for key, ranges := range rules {
if !strings.Contains(key, name+"-") {
continue
}
keySplit := strings.Split(key, "-")
to := keySplit[2]
idMap := id
for _, rule := range ranges {
if id >= rule.src && id <= rule.src+rule.length {
idMap = rule.dst + (id - rule.src)
break
}
}
res[to] = idMap
resolveRule(rules, idMap, to, res)
}
}
func parseNumbers(s string) *Rule {
re := regexp.MustCompile(`\d+`)
numbers := []int{}
for _, val := range re.FindAllStringSubmatch(s, -1) {
num, _ := strconv.Atoi(val[0])
numbers = append(numbers, num)
}
if len(numbers) != 3 {
return nil
}
return &Rule{
dst: numbers[0],
src: numbers[1],
length: numbers[2],
}
}