Skip to content

Commit 793c9c3

Browse files
committedDec 3, 2023
day3
1 parent 3e8d8db commit 793c9c3

File tree

10 files changed

+462
-1112
lines changed

10 files changed

+462
-1112
lines changed
 

‎.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,10 @@ classes/
3939
/out
4040
/out-tsc/
4141
**/ui/out-tsc/
42+
43+
######################
44+
# Maven
45+
######################
46+
/log/
47+
**/target/
48+
.mvn/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package fr.nbrouand.aoc2023;
2+
3+
public class AocTools {
4+
5+
public static boolean isInteger(String strNum) {
6+
if (strNum == null) {
7+
return false;
8+
}
9+
try {
10+
Integer.parseInt(strNum);
11+
} catch (NumberFormatException nfe) {
12+
return false;
13+
}
14+
return true;
15+
}
16+
}

‎src/main/java/fr/nbrouand/aoc2023/day1/Calibration.java

+3-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fr.nbrouand.aoc2023.day1;
22

3+
import fr.nbrouand.aoc2023.AocTools;
34
import org.apache.commons.lang3.tuple.Pair;
45

56
import java.util.Arrays;
@@ -48,7 +49,7 @@ public int getLastInt() {
4849

4950
private List<Integer> getIntegers(String input) {
5051
return Arrays.stream(input.split(""))
51-
.filter(this::isInteger)
52+
.filter(AocTools::isInteger)
5253
.map(Integer::parseInt)
5354
.toList();
5455
}
@@ -76,15 +77,5 @@ private String transformWordToInt(String input, BiFunction<String, String, Integ
7677
return input;
7778
}
7879

79-
private boolean isInteger(String strNum) {
80-
if (strNum == null) {
81-
return false;
82-
}
83-
try {
84-
Integer.parseInt(strNum);
85-
} catch (NumberFormatException nfe) {
86-
return false;
87-
}
88-
return true;
89-
}
80+
9081
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package fr.nbrouand.aoc2023.day3;
2+
3+
import org.apache.commons.lang3.tuple.Pair;
4+
5+
import java.awt.*;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Optional;
9+
import java.util.concurrent.atomic.AtomicInteger;
10+
import java.util.regex.Pattern;
11+
12+
public class Engine {
13+
Pattern patternNumber = Pattern.compile("\\d+");
14+
Pattern patterSymbol = Pattern.compile("\\D");
15+
List<EngineNumber> numbers = new ArrayList<>();
16+
List<EngineSymbol> symbols = new ArrayList<>();
17+
18+
19+
public Engine(String input) {
20+
AtomicInteger lineIndex = new AtomicInteger();
21+
input.lines().forEach(s -> {
22+
for (int i = 0; i < s.length(); i++) {
23+
char currentChar = s.charAt(i);
24+
if (Character.isDigit(currentChar)) {
25+
StringBuilder number = new StringBuilder();
26+
number.append(currentChar);
27+
List<Point> points = new ArrayList<>();
28+
points.add(new Point(i, lineIndex.get()));
29+
int j = i + 1;
30+
while (j < s.length() && Character.isDigit(s.charAt(j))) {
31+
points.add(new Point(j, lineIndex.get()));
32+
number.append(s.charAt(j));
33+
j++;
34+
}
35+
numbers.add(new EngineNumber(Integer.parseInt(number.toString()), points));
36+
i = j - 1;
37+
} else {
38+
if (!String.valueOf(currentChar).equals(".")) {
39+
symbols.add(new EngineSymbol(String.valueOf(currentChar), new Point(i, lineIndex.get())));
40+
}
41+
}
42+
}
43+
lineIndex.getAndIncrement();
44+
});
45+
}
46+
47+
/* public Engine(String input) {
48+
AtomicInteger lineIndex = new AtomicInteger();
49+
input.lines().forEach(s -> {
50+
Matcher matcher = patternNumber.matcher(s);
51+
while (matcher.find()) {
52+
String group = matcher.group();
53+
int number = Integer.parseInt(group);
54+
int start = s.indexOf(group);
55+
List<Point> points = new ArrayList<>();
56+
for (int i = 0; i < group.length(); i++) {
57+
points.add(new Point(start + i, lineIndex.get()));
58+
}
59+
numbers.add(new EngineNumber(number, points));
60+
}
61+
Matcher matcher2 = patterSymbol.matcher(s);
62+
while (matcher2.find()) {
63+
String group = matcher2.group();
64+
if (!group.equals(".")) {
65+
int start = s.indexOf(group);
66+
List<Point> points = new ArrayList<>();
67+
for (int i = 0; i < group.length(); i++) {
68+
points.add(new Point(start + i, lineIndex.get()));
69+
}
70+
symbols.add(new EngineSymbol(group, points));
71+
}
72+
}
73+
lineIndex.getAndIncrement();
74+
});
75+
}*/
76+
77+
public List<Integer> computeAdditiveAllSymbol() {
78+
List<Integer> result = new ArrayList<>();
79+
numbers.forEach(n -> {
80+
Optional<Integer> adjacent = searchIfAdjacent(n);
81+
adjacent.ifPresent(result::add);
82+
});
83+
return result;
84+
}
85+
86+
public List<Integer> computeMultiplicativeOnly() {
87+
List<Integer> result = new ArrayList<>();
88+
symbols.stream().filter(s -> s.symbol.equals("*")).forEach(s -> {
89+
Optional<Pair<Integer, Integer>> adjacent = searchTwoNumberAdjacent(s);
90+
adjacent.ifPresent(a -> {
91+
result.add(a.getLeft() * a.getRight());
92+
});
93+
});
94+
return result;
95+
}
96+
97+
private Optional<Integer> searchIfAdjacent(EngineNumber n) {
98+
for (int i = 0; i < n.points.size(); i++) {
99+
Point pointNumber = n.points.get(i);
100+
for (EngineSymbol symbol : symbols) {
101+
Point pointSymbol = symbol.point;
102+
if (areAdjacent(pointNumber, pointSymbol)) {
103+
return Optional.of(n.number);
104+
}
105+
}
106+
}
107+
return Optional.empty();
108+
}
109+
110+
private Optional<Pair<Integer, Integer>> searchTwoNumberAdjacent(EngineSymbol s) {
111+
List<Integer> integersFound = new ArrayList<>();
112+
for (EngineNumber number : numbers) {
113+
for (Point numberPoint : number.points) {
114+
if (areAdjacent(numberPoint, s.point)) {
115+
if (integersFound.size() < 2) {
116+
integersFound.add(number.number);
117+
break;
118+
} else {
119+
return Optional.empty();
120+
}
121+
}
122+
}
123+
}
124+
125+
if (integersFound.size() == 2) {
126+
return Optional.of(Pair.of(integersFound.get(0), integersFound.get(1)));
127+
} else {
128+
return Optional.empty();
129+
}
130+
}
131+
132+
public static boolean areAdjacent(Point p1, Point p2) {
133+
int xDiff = Math.abs(p1.x - p2.x);
134+
int yDiff = Math.abs(p1.y - p2.y);
135+
136+
return xDiff <= 1 && yDiff <= 1;
137+
}
138+
139+
140+
public List<EngineNumber> getNumbers() {
141+
return numbers;
142+
}
143+
144+
public List<EngineSymbol> getSymbols() {
145+
return symbols;
146+
}
147+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package fr.nbrouand.aoc2023.day3;
2+
3+
import java.awt.*;
4+
import java.util.List;
5+
import java.util.Objects;
6+
import java.util.StringJoiner;
7+
8+
public class EngineNumber {
9+
10+
int number;
11+
List<Point> points;
12+
13+
public EngineNumber(int number, List<Point> points) {
14+
this.number = number;
15+
this.points = points;
16+
}
17+
18+
@Override
19+
public String toString() {
20+
return new StringJoiner(", ", EngineNumber.class.getSimpleName() + "[", "]")
21+
.add("number=" + number)
22+
.toString();
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package fr.nbrouand.aoc2023.day3;
2+
3+
import java.awt.*;
4+
import java.util.List;
5+
6+
public class EngineSymbol {
7+
String symbol;
8+
Point point;
9+
10+
public EngineSymbol(String symbol, Point point) {
11+
this.symbol = symbol;
12+
this.point = point;
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package fr.nbrouand.aoc2023.day3;
2+
3+
import fr.nbrouand.aoc2023.day1.Day1Test;
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.io.IOException;
7+
import java.net.URISyntaxException;
8+
import java.net.URL;
9+
import java.nio.file.Files;
10+
import java.nio.file.Path;
11+
import java.util.List;
12+
13+
import static org.assertj.core.api.Assertions.assertThat;
14+
15+
public class Day3Test {
16+
17+
18+
@Test
19+
void acceptance_test() {
20+
String input = """
21+
467..114..
22+
...*......
23+
..35..633.
24+
......#...
25+
617*......
26+
.....+.58.
27+
..592.....
28+
......755.
29+
...$.*....
30+
.664.598..
31+
""";
32+
Engine engine = new Engine(input);
33+
34+
int result = engine.computeAdditiveAllSymbol().stream().mapToInt(Integer::intValue).sum();
35+
36+
assertThat(result).isEqualTo(4361);
37+
}
38+
@Test
39+
void parseInput() {
40+
String input = """
41+
467..114..
42+
...*......
43+
""";
44+
Engine engine = new Engine(input);
45+
46+
List<EngineNumber> engineNumbers = engine.getNumbers();
47+
List<EngineSymbol> engineSymbols = engine.getSymbols();
48+
49+
assertThat(engineNumbers).hasSize(2);
50+
assertThat(engineSymbols).hasSize(1);
51+
}
52+
53+
@Test
54+
void compute() {
55+
String input = """
56+
467..114..
57+
...*...#.2
58+
""";
59+
60+
Engine engine = new Engine(input);
61+
62+
int result = engine.computeAdditiveAllSymbol().stream().mapToInt(Integer::intValue).sum();
63+
64+
assertThat(result).isEqualTo(581);
65+
}
66+
67+
@Test
68+
void answer_day3_1() throws URISyntaxException, IOException {
69+
URL resource = Day1Test.class.getClassLoader().getResource("day3.input");
70+
String input = Files.readString(Path.of(resource.toURI()));
71+
72+
Engine engine = new Engine(input);
73+
74+
int result = engine.computeAdditiveAllSymbol().stream().mapToInt(Integer::intValue).sum();
75+
76+
assertThat(result).isEqualTo(544664);
77+
}
78+
79+
@Test
80+
void acceptance_test_2() {
81+
String input = """
82+
467..114..
83+
...*......
84+
..35..633.
85+
......#...
86+
617*......
87+
.....+.58.
88+
..592.....
89+
......755.
90+
...$.*....
91+
.664.598..
92+
""";
93+
Engine engine = new Engine(input);
94+
95+
int result = engine.computeMultiplicativeOnly().stream().mapToInt(Integer::intValue).sum();
96+
97+
assertThat(result).isEqualTo(467835);
98+
}
99+
100+
@Test
101+
void answer_day3_2() throws URISyntaxException, IOException {
102+
URL resource = Day1Test.class.getClassLoader().getResource("day3.input");
103+
String input = Files.readString(Path.of(resource.toURI()));
104+
105+
Engine engine = new Engine(input);
106+
107+
int result = engine.computeMultiplicativeOnly().stream().mapToInt(Integer::intValue).sum();
108+
109+
assertThat(result).isEqualTo(84495585);
110+
}
111+
}

0 commit comments

Comments
 (0)
Please sign in to comment.