mirror of
https://github.com/Crocmagnon/advent-of-code.git
synced 2024-11-27 00:48:08 +01:00
solve day 5 part 2
This commit is contained in:
parent
908c7a9d29
commit
fa66368b91
3 changed files with 173 additions and 9 deletions
|
@ -46,12 +46,63 @@ func Day05Part1(input io.Reader) (int, error) {
|
|||
func Day05Part2(input io.Reader) (int, error) {
|
||||
scanner := bufio.NewScanner(input)
|
||||
|
||||
scanner.Scan()
|
||||
seedRanges := parseSeedRanges(lineToInts(strings.TrimPrefix(scanner.Text(), "seeds: ")))
|
||||
|
||||
scanner.Scan()
|
||||
|
||||
inMap := false
|
||||
var currentMap day05Map
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
_ = line
|
||||
if line == "" {
|
||||
var newRanges []day05SeedRange
|
||||
for _, sRange := range seedRanges {
|
||||
newRanges = append(newRanges, currentMap.convertRange(sRange)...)
|
||||
}
|
||||
seedRanges = newRanges
|
||||
inMap = false
|
||||
currentMap = nil
|
||||
} else if strings.HasSuffix(line, "map:") {
|
||||
inMap = true
|
||||
} else if inMap {
|
||||
currentMap = append(currentMap, newDay05Range(line))
|
||||
}
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
if inMap {
|
||||
// Convert one last time if necessary
|
||||
var newRanges []day05SeedRange
|
||||
for _, sRange := range seedRanges {
|
||||
newRanges = append(newRanges, currentMap.convertRange(sRange)...)
|
||||
}
|
||||
seedRanges = newRanges
|
||||
inMap = false
|
||||
currentMap = nil
|
||||
}
|
||||
|
||||
mini := int(^uint(0) >> 1) // highest int
|
||||
for _, r := range seedRanges {
|
||||
if r.start < mini {
|
||||
mini = r.start
|
||||
}
|
||||
}
|
||||
|
||||
return mini, nil
|
||||
}
|
||||
|
||||
func parseSeedRanges(ints []int) []day05SeedRange {
|
||||
ranges := make([]day05SeedRange, len(ints)/2)
|
||||
for i := 0; i < len(ints)-1; i += 2 {
|
||||
ranges[i/2] = day05SeedRange{start: ints[i], end: ints[i] + ints[i+1]}
|
||||
}
|
||||
return ranges
|
||||
}
|
||||
|
||||
// range is [start; end)
|
||||
// start is included, end is not.
|
||||
type day05SeedRange struct {
|
||||
start, end int
|
||||
}
|
||||
|
||||
func lineToInts(line string) []int {
|
||||
|
@ -68,25 +119,61 @@ func lineToInts(line string) []int {
|
|||
}
|
||||
|
||||
type day05Range struct {
|
||||
destination, source, length int
|
||||
destStart, sourceStart, length int
|
||||
}
|
||||
|
||||
func newDay05Range(line string) day05Range {
|
||||
ints := lineToInts(line)
|
||||
return day05Range{
|
||||
destination: ints[0],
|
||||
source: ints[1],
|
||||
destStart: ints[0],
|
||||
sourceStart: ints[1],
|
||||
length: ints[2],
|
||||
}
|
||||
}
|
||||
|
||||
func (r day05Range) sourceEnd() int {
|
||||
return r.sourceStart + r.length
|
||||
}
|
||||
|
||||
func (r day05Range) destEnd() int {
|
||||
return r.destStart + r.length
|
||||
}
|
||||
|
||||
func (r day05Range) convert(n int) (int, bool) {
|
||||
if n >= r.source && n < r.source+r.length {
|
||||
return n - r.source + r.destination, true
|
||||
if n >= r.sourceStart && n < r.sourceEnd() {
|
||||
return r.mustConvert(n), true
|
||||
}
|
||||
return n, false
|
||||
}
|
||||
|
||||
func (r day05Range) mustConvert(n int) int {
|
||||
return n - r.sourceStart + r.destStart
|
||||
}
|
||||
|
||||
func (r day05Range) convertRange(s day05SeedRange) (converted []day05SeedRange, notConverted []day05SeedRange) {
|
||||
if r.sourceStart <= s.start && s.end <= r.sourceEnd() {
|
||||
// s-----s
|
||||
// r--------r
|
||||
return []day05SeedRange{{start: r.mustConvert(s.start), end: r.mustConvert(s.end)}}, nil
|
||||
} else if s.start < r.sourceStart && r.sourceStart <= s.end && s.end <= r.sourceEnd() {
|
||||
// s-------s
|
||||
// r--------r
|
||||
return []day05SeedRange{{start: r.destStart, end: r.mustConvert(s.end)}}, []day05SeedRange{{start: s.start, end: r.sourceStart}}
|
||||
} else if r.sourceStart <= s.start && s.start <= r.sourceEnd() && r.sourceEnd() < s.end {
|
||||
// s-------s
|
||||
// r--------r
|
||||
return []day05SeedRange{{start: r.mustConvert(s.start), end: r.destEnd()}}, []day05SeedRange{{start: r.sourceEnd(), end: s.end}}
|
||||
} else if s.start <= r.sourceStart && r.sourceEnd() < s.end {
|
||||
// s------------s
|
||||
// r--------r
|
||||
return []day05SeedRange{{start: r.destStart, end: r.destEnd()}}, []day05SeedRange{{start: s.start, end: r.sourceStart}, {start: r.sourceEnd(), end: s.end}}
|
||||
} else {
|
||||
// s---s
|
||||
// r-----r
|
||||
return nil, []day05SeedRange{s}
|
||||
}
|
||||
}
|
||||
|
||||
type day05Map []day05Range
|
||||
|
||||
func (m day05Map) convert(n int) int {
|
||||
|
@ -97,3 +184,19 @@ func (m day05Map) convert(n int) int {
|
|||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m day05Map) convertRange(s day05SeedRange) []day05SeedRange {
|
||||
var converted []day05SeedRange
|
||||
toConvert := []day05SeedRange{s}
|
||||
for _, dRange := range m {
|
||||
var toConvertNext []day05SeedRange
|
||||
for _, c := range toConvert {
|
||||
var conv []day05SeedRange
|
||||
conv, toConvertNext = dRange.convertRange(c)
|
||||
converted = append(converted, conv...)
|
||||
}
|
||||
toConvert = toConvertNext
|
||||
}
|
||||
converted = append(converted, toConvert...)
|
||||
return converted
|
||||
}
|
||||
|
|
|
@ -26,10 +26,38 @@ func TestDay05Part1(t *testing.T) {
|
|||
|
||||
func TestDay05Part2(t *testing.T) {
|
||||
tests := []testCase{
|
||||
{"inputs/day05_test2", 0},
|
||||
{"inputs/day05", 0},
|
||||
{"inputs/day05_test2", 46},
|
||||
{"inputs/day05", 78775051},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.filename, check(test, Day05Part2))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDay05Ranges(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
dRange day05Range
|
||||
seedRange day05SeedRange
|
||||
expected []day05SeedRange
|
||||
}{
|
||||
{
|
||||
"seed included in range",
|
||||
day05Range{0, 5, 5},
|
||||
day05SeedRange{6, 8},
|
||||
[]day05SeedRange{{1, 3}},
|
||||
},
|
||||
{
|
||||
"range included in seed",
|
||||
day05Range{0, 10, 2},
|
||||
day05SeedRange{9, 13},
|
||||
[]day05SeedRange{{0, 2}, {9, 10}, {12, 13}},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got := day05Map{test.dRange}.convertRange(test.seedRange)
|
||||
assert.Equal(t, test.expected, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4
|
Loading…
Reference in a new issue