mirror of
https://github.com/Crocmagnon/advent-of-code.git
synced 2024-11-23 15:08:09 +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) {
|
func Day05Part2(input io.Reader) (int, error) {
|
||||||
scanner := bufio.NewScanner(input)
|
scanner := bufio.NewScanner(input)
|
||||||
|
|
||||||
|
scanner.Scan()
|
||||||
|
seedRanges := parseSeedRanges(lineToInts(strings.TrimPrefix(scanner.Text(), "seeds: ")))
|
||||||
|
|
||||||
|
scanner.Scan()
|
||||||
|
|
||||||
|
inMap := false
|
||||||
|
var currentMap day05Map
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Text()
|
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 {
|
func lineToInts(line string) []int {
|
||||||
|
@ -68,25 +119,61 @@ func lineToInts(line string) []int {
|
||||||
}
|
}
|
||||||
|
|
||||||
type day05Range struct {
|
type day05Range struct {
|
||||||
destination, source, length int
|
destStart, sourceStart, length int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDay05Range(line string) day05Range {
|
func newDay05Range(line string) day05Range {
|
||||||
ints := lineToInts(line)
|
ints := lineToInts(line)
|
||||||
return day05Range{
|
return day05Range{
|
||||||
destination: ints[0],
|
destStart: ints[0],
|
||||||
source: ints[1],
|
sourceStart: ints[1],
|
||||||
length: ints[2],
|
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) {
|
func (r day05Range) convert(n int) (int, bool) {
|
||||||
if n >= r.source && n < r.source+r.length {
|
if n >= r.sourceStart && n < r.sourceEnd() {
|
||||||
return n - r.source + r.destination, true
|
return r.mustConvert(n), true
|
||||||
}
|
}
|
||||||
return n, false
|
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
|
type day05Map []day05Range
|
||||||
|
|
||||||
func (m day05Map) convert(n int) int {
|
func (m day05Map) convert(n int) int {
|
||||||
|
@ -97,3 +184,19 @@ func (m day05Map) convert(n int) int {
|
||||||
}
|
}
|
||||||
return n
|
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) {
|
func TestDay05Part2(t *testing.T) {
|
||||||
tests := []testCase{
|
tests := []testCase{
|
||||||
{"inputs/day05_test2", 0},
|
{"inputs/day05_test2", 46},
|
||||||
{"inputs/day05", 0},
|
{"inputs/day05", 78775051},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.filename, check(test, Day05Part2))
|
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