Skip to content

Commit dfab3a8

Browse files
committed
Days 1 through 20
0 parents  commit dfab3a8

23 files changed

+2522
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.classpath
2+
.idea
3+
.project
4+
.settings
5+
advent-of-code.iml
6+
target/

pom.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.macasaet</groupId>
8+
<artifactId>advent-of-code</artifactId>
9+
<version>0.2020.0-SNAPSHOT</version>
10+
11+
<name>Advent of Code 2020</name>
12+
13+
<properties>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
<maven.compiler.source>14</maven.compiler.source>
16+
<maven.compiler.target>14</maven.compiler.target>
17+
</properties>
18+
19+
</project>

src/test/java/com/macasaet/Day01.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.macasaet;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
import java.util.Spliterator;
7+
import java.util.stream.StreamSupport;
8+
9+
10+
public class Day01 {
11+
12+
public static void main(String[] args) throws IOException {
13+
try( var spliterator = new LineSpliterator(Day01.class.getResourceAsStream("/day-1-input.txt")) ) {
14+
// part1(spliterator);
15+
part2(spliterator);
16+
}
17+
}
18+
19+
protected static void part1(final Spliterator<String> spliterator) {
20+
final var items = StreamSupport.stream(spliterator, false)
21+
.mapToInt(Integer::parseInt)
22+
.filter(candidate -> candidate <= 2020) // filter out the obvious
23+
.sorted() // sort to ensure the complement is to the left
24+
.collect(ArrayList<Integer>::new, List::add, List::addAll);
25+
for( int i = items.size(); --i >= 0; ) {
26+
final int x = items.get(i);
27+
for( int j = i; --j >= 0; ) { // avoid retrying combinations
28+
final int y = items.get(j);
29+
if( x + y == 2020 ) {
30+
System.out.println( "" + ( x * y ) );
31+
return;
32+
}
33+
}
34+
}
35+
}
36+
37+
protected static void part2(final Spliterator<String> spliterator) {
38+
final var items = StreamSupport.stream(spliterator, false)
39+
.mapToInt(Integer::parseInt)
40+
.filter(candidate -> candidate <= 2020) // filter out the obvious
41+
.sorted() // sort to ensure the complements are to the left
42+
.collect(ArrayList<Integer>::new, List::add, List::addAll);
43+
for( int i = items.size(); --i >= 0; ) {
44+
final int x = items.get(i);
45+
for( int j = i; --j >= 0; ) {
46+
final int y = items.get(j);
47+
for( int k = j; --k >= 0; ) {
48+
final int z = items.get(k);
49+
if( x + y + z == 2020 ) {
50+
System.out.println( "" + ( x * y * z ) );
51+
return;
52+
}
53+
}
54+
55+
}
56+
}
57+
}
58+
}

src/test/java/com/macasaet/Day02.java

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.macasaet;
2+
3+
import java.io.IOException;
4+
import java.util.regex.Pattern;
5+
import java.util.stream.StreamSupport;
6+
7+
public class Day02 {
8+
9+
public static void main(String[] args) throws IOException {
10+
try( var spliterator = new LineSpliterator( Day02.class.getResourceAsStream("/day-2-input.txt" ) ) ) {
11+
final long count = StreamSupport.stream(spliterator, false)
12+
// .map(SledEntry::build) // part 1
13+
.map(TobogganEntry::build) // part 2
14+
.filter(Entry::isValid).count();
15+
System.out.println("" + count);
16+
}
17+
18+
}
19+
20+
public static abstract class Entry {
21+
22+
// TODO consider a more robust pattern:
23+
// https://stackoverflow.com/a/4731164/914887
24+
protected static final Pattern separator = Pattern.compile("\\s");
25+
protected static final Pattern rangeSeparator = Pattern.compile("-");
26+
protected final char c; // TODO support code points
27+
protected final String password;
28+
29+
protected Entry(final char c, final String password) {
30+
this.c = c;
31+
this.password = password;
32+
}
33+
34+
public abstract boolean isValid();
35+
36+
}
37+
38+
public static class SledEntry extends Entry {
39+
private final long minIterations;
40+
private final long maxIterations;
41+
42+
public SledEntry( final char c, final String password, final long minIterations, final long maxIterations ) {
43+
super(c, password);
44+
this.minIterations = minIterations;
45+
this.maxIterations = maxIterations;
46+
}
47+
48+
public static Entry build(final String line) {
49+
final var components = separator.split(line, 3);
50+
final var range = components[0];
51+
final var rangeComponents = rangeSeparator.split(range, 2);
52+
return new SledEntry(components[1].charAt(0),
53+
components[2],
54+
Long.parseLong(rangeComponents[ 0 ]),
55+
Long.parseLong(rangeComponents[ 1 ] ));
56+
}
57+
58+
public boolean isValid() {
59+
final var count = password.chars()
60+
.filter(candidate -> (char) candidate == this.c)
61+
.count();
62+
return count >= minIterations && count <= maxIterations;
63+
}
64+
}
65+
66+
public static class TobogganEntry extends Entry {
67+
private final int firstPosition;
68+
private final int secondPosition;
69+
70+
public TobogganEntry( final char c, final String password, final int firstPosition, final int secondPosition ) {
71+
super( c, password );
72+
this.firstPosition = firstPosition;
73+
this.secondPosition = secondPosition;
74+
}
75+
76+
public static Entry build( final String line ) {
77+
final var components = separator.split( line, 3 );
78+
final var positionComponents = rangeSeparator.split( components[ 0 ], 2 );
79+
return new TobogganEntry( components[ 1 ].charAt( 0 ),
80+
components[ 2 ],
81+
Integer.parseInt( positionComponents[ 0 ] ),
82+
Integer.parseInt( positionComponents[ 1 ] ) );
83+
}
84+
85+
public boolean isValid() {
86+
final var x = password.charAt(firstPosition - 1);
87+
final var y = password.charAt(secondPosition - 1);
88+
return x == c ^ y == c;
89+
}
90+
}
91+
}

src/test/java/com/macasaet/Day03.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.macasaet;
2+
3+
import java.io.IOException;
4+
import java.math.BigInteger;
5+
import java.util.Arrays;
6+
import java.util.stream.Collectors;
7+
import java.util.stream.StreamSupport;
8+
9+
public class Day03 {
10+
11+
public static void main(String[] args) throws IOException {
12+
try( var spliterator = new LineSpliterator( Day03.class.getResourceAsStream("/day-3-input.txt" ) ) ) {
13+
final var rowList = StreamSupport.stream(spliterator, false)
14+
.map(String::toCharArray)
15+
.collect(Collectors.toUnmodifiableList());
16+
final var matrix = new char[rowList.size()][];
17+
for (int i = rowList.size(); --i >= 0; matrix[i] = rowList.get(i));
18+
19+
final var slopes = new int[][] {
20+
new int[] { 1, 1 },
21+
new int[] { 3, 1 }, // uncomment all but this for "part 1"
22+
new int[] { 5, 1 },
23+
new int[] { 7, 1 },
24+
new int[] { 1, 2 },
25+
};
26+
final var totalTrees = Arrays.stream(slopes)
27+
.mapToLong(pair -> {
28+
final int slopeRight = pair[0];
29+
final int slopeDown = pair[1];
30+
31+
long numTrees = 0;
32+
int rowIndex = 0;
33+
int columnIndex = 0;
34+
35+
do {
36+
final var row = matrix[rowIndex];
37+
final var cell = row[columnIndex];
38+
if (cell == '#') {
39+
numTrees += 1l;
40+
}
41+
rowIndex += slopeDown;
42+
columnIndex = columnIndex + slopeRight;
43+
columnIndex = columnIndex % row.length; // "These aren't the only trees, though; due to
44+
// something you read about once involving
45+
// arboreal genetics and biome stability, the
46+
// same pattern repeats to the right many times"
47+
} while( rowIndex < matrix.length );
48+
return numTrees;
49+
}).mapToObj(BigInteger::valueOf) // I wasn't sure how large these (multiplied) values could get, in retrospect, `long` would have been fine
50+
.reduce(BigInteger::multiply)
51+
.get();
52+
System.out.println("" + totalTrees.toString());
53+
}
54+
55+
}
56+
57+
}

src/test/java/com/macasaet/Day04.java

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.macasaet;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.HashMap;
6+
import java.util.Set;
7+
import java.util.stream.Collectors;
8+
import java.util.stream.StreamSupport;
9+
10+
public class Day04 {
11+
12+
public static void main(String[] args) throws IOException {
13+
try (var spliterator = new LineSpliterator( Day04.class.getResourceAsStream( "/day-4-input.txt" ) ) ) {
14+
final var rawLines = StreamSupport.stream(spliterator, false)
15+
.collect(Collectors.toUnmodifiableList());
16+
String current = "";
17+
// collect all the text blocks into entries (separated by empty lines)
18+
final var entries = new ArrayList<String>();
19+
for (final var line : rawLines) {
20+
if (line.isBlank()) {
21+
if (!current.isBlank()) {
22+
entries.add(current);
23+
current = "";
24+
}
25+
} else {
26+
current += " " + line;
27+
}
28+
}
29+
if (!current.isBlank()) {
30+
entries.add(current);
31+
}
32+
int numValid = 0;
33+
for (final var entry : entries) {
34+
final var pairs = entry.split("\\s");
35+
final var map = new HashMap<String, String>();
36+
for (final var pair : pairs) {
37+
if (pair.isBlank()) {
38+
continue;
39+
}
40+
final var components = pair.split(":", 2);
41+
map.put(components[0].trim(), components[1].trim());
42+
}
43+
final var birthYearString = map.get("byr");
44+
final var issueYearString = map.get("iyr");
45+
final var expirationYearString = map.get("eyr");
46+
final var heightString = map.get("hgt");
47+
final var hairColour = map.get("hcl");
48+
final var eyeColour = map.get("ecl");
49+
final var validEyeColours = Set.of("amb", "blu", "brn", "gry", "grn", "hzl", "oth");
50+
final var passportId = map.get("pid");
51+
if (birthYearString == null) continue;
52+
final int birthYear = Integer.parseInt(birthYearString);
53+
if (birthYear < 1920 || birthYear > 2002) continue;
54+
if (issueYearString == null) continue;
55+
final int issueYear = Integer.parseInt(issueYearString);
56+
if (issueYear < 2010 || issueYear > 2020) continue;
57+
if (expirationYearString == null) continue;
58+
final int expirationYear = Integer.parseInt(expirationYearString);
59+
if (expirationYear < 2020 || expirationYear > 2030) continue;
60+
if (heightString == null) continue;
61+
if (heightString.endsWith("cm")) {
62+
final int centimetres = Integer.parseInt(heightString.replace("cm", ""));
63+
if (centimetres < 150 || centimetres > 193) continue;
64+
} else if (heightString.endsWith("in")) {
65+
final int inches = Integer.parseInt(heightString.replace("in", ""));
66+
if (inches < 59 || inches > 76) continue;
67+
} else {
68+
continue;
69+
}
70+
if (hairColour == null) continue;
71+
if (!hairColour.matches("#[0-9a-f]{6}")) continue;
72+
if (eyeColour == null) continue;
73+
if (!validEyeColours.contains(eyeColour)) continue;
74+
if (passportId == null) continue;
75+
if (!passportId.matches("[0-9]{9}")) continue;
76+
numValid++;
77+
}
78+
System.out.println(numValid);
79+
}
80+
81+
}
82+
83+
}

src/test/java/com/macasaet/Day05.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.macasaet;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
import java.util.stream.StreamSupport;
7+
8+
public class Day05 {
9+
10+
public static void main(String[] args) throws IOException {
11+
try (var spliterator = new LineSpliterator( Day05.class.getResourceAsStream( "/day-5-input.txt" ) ) ) {
12+
final var seatIds = StreamSupport.stream(spliterator, false)
13+
.mapToInt(id -> {
14+
int maxRowExclusive = 128;
15+
int row = 0;
16+
for( int i = 0; i < 7; i++ ) {
17+
final char partition = id.charAt(i);
18+
if( partition == 'B' ) {
19+
row = ( ( maxRowExclusive - row ) / 2 ) + row;
20+
} else if( partition == 'F' ) {
21+
maxRowExclusive = maxRowExclusive - ( ( maxRowExclusive - row ) / 2 );
22+
} else {
23+
throw new IllegalArgumentException("Invalid row partition: " + partition);
24+
}
25+
}
26+
int column = 0;
27+
int maxColumnExclusive = 8;
28+
for( int i = 7; i < 10; i++ ) {
29+
final char half = id.charAt(i);
30+
if( half == 'R' ) {
31+
column = ( ( maxColumnExclusive - column ) / 2 ) + column;
32+
} else if( half == 'L' ) {
33+
maxColumnExclusive = maxColumnExclusive - ( ( maxColumnExclusive - column ) / 2 );
34+
} else {
35+
throw new IllegalArgumentException("Invalid column partition: " + half);
36+
}
37+
}
38+
final int seatId = row * 8 + column;
39+
return seatId;
40+
})
41+
.sorted()
42+
.collect(ArrayList<Integer>::new, List::add, List::addAll);
43+
System.out.println("part 1: " + seatIds.get(seatIds.size() - 1));
44+
for( int i = seatIds.size(); --i >= 1; ) {
45+
final int x = seatIds.get( i - 1 );
46+
final int y = seatIds.get( i );
47+
if( y - x > 1 ) {
48+
System.out.println("part 2: " + ( x + 1 ) );
49+
return;
50+
}
51+
}
52+
}
53+
54+
}
55+
56+
}

0 commit comments

Comments
 (0)