Skip to content

Commit 268632a

Browse files
committed
Advent of Code 2021 - Day 17
1 parent ffc5e7c commit 268632a

File tree

5 files changed

+237
-2
lines changed

5 files changed

+237
-2
lines changed

src/main/java/com/codingnagger/App.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.codingnagger.days.Day13;
88
import com.codingnagger.days.Day14;
99
import com.codingnagger.days.Day15;
10+
import com.codingnagger.days.Day17;
1011
import com.codingnagger.days.Day9;
1112
import com.codingnagger.utils.InputLoader;
1213

@@ -20,9 +21,9 @@ public class App {
2021
public static void main(String[] args) throws IOException {
2122
System.out.println("Advent of Code 2021");
2223

23-
List<String> input = InputLoader.Load("day15.txt");
24+
List<String> input = InputLoader.Load("day17.txt");
2425

25-
Day day = new Day15();
26+
Day day = new Day17();
2627

2728
System.out.println("Part 1:");
2829
System.out.println(day.partOne(input));
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
package com.codingnagger.days;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
import java.util.Objects;
6+
import java.util.Optional;
7+
import java.util.Vector;
8+
import java.util.stream.Collectors;
9+
10+
public class Day17 implements Day {
11+
int maxY = Integer.MIN_VALUE;
12+
13+
@Override
14+
public String partOne(List<String> input) {
15+
final Area targetArea = parseTargetArea(input.get(0));
16+
final Position origin = new Position(0,0);
17+
18+
Integer maxY = Integer.MIN_VALUE;
19+
Position probeVector = new Position(1, 0);
20+
Position finalPoint = new Position(Integer.MAX_VALUE, Integer.MIN_VALUE);
21+
22+
while (!targetArea.containsPosition(finalPoint) ) {
23+
Answer answer = highestYHittingTarget(targetArea, probeVector, origin);
24+
25+
if (answer.getMaxY().isPresent()) {
26+
finalPoint = answer.getFinalPosition();
27+
maxY = answer.getMaxY().get();
28+
} else {
29+
probeVector = probeVector.applyVector(new Position(1, 0));
30+
}
31+
}
32+
33+
int stepsToExplore = -targetArea.bottomRight.y - probeVector.y;
34+
probeVector = probeVector.applyVector(new Position(0, 1));
35+
36+
for (int i = 0; i < stepsToExplore; i++) {
37+
Answer answer = highestYHittingTarget(targetArea, probeVector, origin);
38+
39+
probeVector = probeVector.applyVector(new Position(0, 1));
40+
41+
if (answer.getMaxY().isPresent()) {
42+
maxY = answer.getMaxY().get();
43+
}
44+
}
45+
46+
return maxY.toString();
47+
}
48+
49+
@Override
50+
public String partTwo(List<String> input) {
51+
final Area targetArea = parseTargetArea(input.get(0));
52+
final Position origin = new Position(0,0);
53+
int counter = 0;
54+
55+
for (int x = 0; x <= targetArea.bottomRight.x; x++) {
56+
for (int y = targetArea.bottomRight.y; y <= -targetArea.bottomRight.y; y++) {
57+
if (highestYHittingTarget(targetArea, new Position(x,y), origin).getMaxY().isPresent()) {
58+
counter++;
59+
}
60+
}
61+
}
62+
return String.valueOf(counter);
63+
}
64+
65+
private Answer highestYHittingTarget(final Area targetArea, final Position vectorStart, final Position probeStart) {
66+
final Position frictionVector = new Position(-1, -1);
67+
final Position divingVector = new Position(0, -1);
68+
69+
Position probe = probeStart;
70+
Position vector = vectorStart;
71+
72+
int maxY = probe.y;
73+
74+
while (targetArea.canBeReachedBy(probe) && !targetArea.containsPosition(probe)) {
75+
probe = probe.applyVector(vector);
76+
77+
if (vector.x == 0) {
78+
vector = vector.applyVector(divingVector);
79+
} else {
80+
vector = vector.applyVector(frictionVector);
81+
}
82+
83+
maxY = Math.max(maxY, probe.y);
84+
}
85+
86+
return new Answer(probe, targetArea.containsPosition(probe) ? maxY : null);
87+
}
88+
89+
static Area parseTargetArea(String line) {
90+
List<String> s = Arrays.stream(line.split("x=")[1].split(", y=")).collect(Collectors.toList());
91+
List<Integer> xBounds = Arrays.stream(s.get(0).split("\\.\\.")).map(Integer::parseInt).collect(Collectors.toList());
92+
List<Integer> yBounds = Arrays.stream(s.get(1).split("\\.\\.")).map(Integer::parseInt).collect(Collectors.toList());
93+
94+
return new Area(
95+
new Position(Math.min(xBounds.get(0), xBounds.get(1)), Math.max(yBounds.get(0), yBounds.get(1))),
96+
new Position(Math.max(xBounds.get(0), xBounds.get(1)), Math.min(yBounds.get(0), yBounds.get(1))));
97+
}
98+
99+
public static class Answer {
100+
private final Position finalPosition;
101+
private final Integer maxY;
102+
103+
public Answer(Position finalPosition, Integer maxY) {
104+
this.finalPosition = finalPosition;
105+
this.maxY = maxY;
106+
}
107+
108+
public Position getFinalPosition() {
109+
return finalPosition;
110+
}
111+
112+
public Optional<Integer> getMaxY() {
113+
return Optional.ofNullable(maxY);
114+
}
115+
}
116+
117+
public static class Area {
118+
private final Position topLeft, bottomRight;
119+
120+
public Area(Position topLeft, Position bottomRight) {
121+
this.topLeft = topLeft;
122+
this.bottomRight = bottomRight;
123+
}
124+
125+
public Position getTopLeft() {
126+
return topLeft;
127+
}
128+
129+
public Position getBottomRight() {
130+
return bottomRight;
131+
}
132+
133+
@Override
134+
public boolean equals(Object o) {
135+
if (this == o) return true;
136+
if (o == null || getClass() != o.getClass()) return false;
137+
Area area = (Area) o;
138+
return Objects.equals(topLeft, area.topLeft) && Objects.equals(bottomRight, area.bottomRight);
139+
}
140+
141+
@Override
142+
public int hashCode() {
143+
return Objects.hash(topLeft, bottomRight);
144+
}
145+
146+
public boolean tooFar(Position p) {
147+
return p.x > bottomRight.x;
148+
}
149+
150+
public boolean tooLow(Position p) {
151+
return p.y < bottomRight.y;
152+
}
153+
154+
public boolean canBeReachedBy(Position p) {
155+
return !tooFar(p) && !tooLow(p);
156+
}
157+
158+
public boolean containsPosition(Position p) {
159+
return p.x >= topLeft.x && p.x <= bottomRight.x && p.y <= topLeft.y && p.y >= bottomRight.y;
160+
}
161+
162+
@Override
163+
public String toString() {
164+
return "Area{" +
165+
"topLeft=" + topLeft +
166+
", bottomRight=" + bottomRight +
167+
'}';
168+
}
169+
}
170+
171+
public static class Position {
172+
private final int x, y;
173+
174+
public Position(int x, int y) {
175+
this.x = x;
176+
this.y = y;
177+
}
178+
179+
public Position applyVector(Position v) {
180+
return new Position(x + v.x, y + v.y);
181+
}
182+
183+
@Override
184+
public boolean equals(Object o) {
185+
if (this == o) return true;
186+
if (o == null || getClass() != o.getClass()) return false;
187+
Position position = (Position) o;
188+
return x == position.x && y == position.y;
189+
}
190+
191+
@Override
192+
public int hashCode() {
193+
return Objects.hash(x, y);
194+
}
195+
196+
@Override
197+
public String toString() {
198+
return "Position{" +
199+
"x=" + x +
200+
", y=" + y +
201+
'}';
202+
}
203+
}
204+
}

src/main/resources/day17.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
target area: x=85..145, y=-163..-108
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
package com.codingnagger.days;
3+
4+
import com.codingnagger.utils.InputLoader;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.util.List;
8+
9+
import static org.assertj.core.api.Assertions.assertThat;
10+
11+
public class Day17Test {
12+
private static final List<String> INPUT = InputLoader.LoadTest("day17.txt");
13+
private static final Day DAY = new Day17();
14+
15+
@Test
16+
public void partOne_shoudlYieldCorrectResult() {
17+
String result = DAY.partOne(INPUT);
18+
19+
assertThat(result).isEqualTo("45");
20+
}
21+
22+
@Test
23+
public void partTwo_shoudlYieldCorrectResult() {
24+
String result = DAY.partTwo(INPUT);
25+
26+
assertThat(result).isEqualTo("112");
27+
}
28+
}

src/test/resources/day17.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
target area: x=20..30, y=-10..-5

0 commit comments

Comments
 (0)