-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay05.java
101 lines (89 loc) · 3.15 KB
/
Day05.java
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
import static java.lang.Math.min;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
/**
* @author Zachary Cockshutt
* @since 2023-12-05
*/
public class Day05 extends Day
{
@Override
public String partOne() throws IOException
{
var almanac = this.parseAlmanac(false);
var location = almanac.getMinLocation();
return String.valueOf(location);
}
@Override
public String partTwo() throws IOException
{
var almanac = this.parseAlmanac(true);
var location = almanac.getMinLocation();
return String.valueOf(location);
}
private Almanac parseAlmanac(boolean isPartTwo) throws IOException
{
var input = this.input();
var n = input.length;
var seeds = isPartTwo ? parseSeedsAsRanges(input[0]) : parseSeeds(input[0]);
var categories = new ArrayList<AlmanacMap[]>();
for (int i = 2; i < n; i++)
{
if (isAlpha(input[i].charAt(0))) { continue; }
var maps = new ArrayList<AlmanacMap>();
while (i < n && !input[i].isEmpty()) { maps.add(this.parseMap(input[i++])); }
categories.add(maps.toArray(new AlmanacMap[0]));
}
return new Almanac(seeds, categories.toArray(new AlmanacMap[0][]));
}
private Seed[] parseSeeds(String s)
{
return Stream.of(s.substring(7).split(" +"))
.map(x->new Seed(Long.parseLong(x), Long.parseLong(x)))
.toArray(Seed[]::new);
}
private Seed[] parseSeedsAsRanges(String s)
{
var seeds = new ArrayList<Seed>();
var numbers = Stream.of(s.substring(7).split(" +")).mapToLong(Long::parseLong).toArray();
for (int i = 0; i < numbers.length; i+=2) { seeds.add(new Seed(numbers[i], (numbers[i]+numbers[i+1]))); }
return seeds.stream().toArray(Seed[]::new);
}
private AlmanacMap parseMap(String s)
{
var arr = Stream.of(s.split(" ")).mapToLong(Long::parseLong).toArray();
return new AlmanacMap(arr[0], arr[1], arr[2]);
}
private boolean isAlpha(char ch)
{
return ch >= 'a'
&& ch <= 'z';
}
private record Almanac(Seed[] seeds, AlmanacMap[][] categories)
{
private long getMinLocation()
{
var location = new AtomicLong(Long.MAX_VALUE);
Stream.of(seeds).parallel().forEach(seed ->
{
for (long i = seed.start(); i <= seed.end(); i++)
location.set(min(location.get(), this.getLocation(i)));
});
return location.longValue();
}
private long getLocation(long seed)
{
for (var category : this.categories)
for (var map : category)
{
boolean isMapped = seed >= map.source && seed < map.source + map.range();
if (isMapped) { seed = map.dest + (seed - map.source); break; }
}
return seed;
}
}
private record AlmanacMap(long dest, long source, long range) {}
private record Seed(long start, long end) {}
}