commit README + Day1-13
This commit is contained in:
commit
9890182ea1
|
|
@ -0,0 +1,75 @@
|
|||
package dev.forstenlechner.aoc;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class Day10 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new Day10().solve();
|
||||
}
|
||||
|
||||
public record Jolts (int previous, int countOneJolts, int countTwoJolts,int countThreeJolts) {};
|
||||
|
||||
private long calcCombinations(List<Integer> joltJunk) {
|
||||
return switch (joltJunk.size()) {
|
||||
case 3 -> 2;
|
||||
case 4 -> 4;
|
||||
case 5 -> 7;
|
||||
default -> 1;
|
||||
};
|
||||
}
|
||||
|
||||
public void solve() throws Exception {
|
||||
System.out.println("Solve");
|
||||
Stream<String> lines = Files.lines(Paths.get("day10/input"));
|
||||
List<Integer> sortedJolts = Stream.concat(Stream.of(0), lines.map(Integer::parseInt).sorted()).collect(toList());
|
||||
Jolts jolts = sortedJolts.stream().reduce(new Jolts(0, 0, 0, 1),
|
||||
(jolt, next) ->
|
||||
new Jolts(next, jolt.countOneJolts() + (next - jolt.previous() == 1 ? 1 : 0), jolt.countTwoJolts() + (next - jolt.previous() == 2 ? 1 : 0), jolt.countThreeJolts() + (next - jolt.previous() == 3 ? 1 : 0))
|
||||
, (j1, j2) -> j1);
|
||||
|
||||
System.out.println(jolts.countOneJolts * jolts.countThreeJolts);
|
||||
// 1690
|
||||
|
||||
System.out.println(jolts.countOneJolts);
|
||||
System.out.println(jolts.countTwoJolts);
|
||||
System.out.println(jolts.countThreeJolts);
|
||||
|
||||
List<List<Integer>> junks = new ArrayList<>();
|
||||
List<Integer> currentJunk = new ArrayList<>();
|
||||
int expected = 0;
|
||||
for (Integer jolt : sortedJolts) {
|
||||
if (expected == jolt) {
|
||||
currentJunk.add(jolt);
|
||||
expected++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentJunk.isEmpty()) {
|
||||
currentJunk.add(jolt);
|
||||
expected = jolt + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
junks.add(currentJunk);
|
||||
currentJunk = new ArrayList<>();
|
||||
currentJunk.add(jolt);
|
||||
expected = jolt + 1;
|
||||
}
|
||||
|
||||
if (!currentJunk.isEmpty()) {
|
||||
junks.add(currentJunk);
|
||||
}
|
||||
|
||||
System.out.println(junks);
|
||||
|
||||
Long reduce = junks.stream().map(this::calcCombinations).reduce(1L, (a, b) -> a * b);
|
||||
System.out.println(reduce);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
package dev.forstenlechner.aoc;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class Day11 {
|
||||
|
||||
private enum SeatState {
|
||||
EMPTY {
|
||||
@Override
|
||||
void print() {
|
||||
System.out.print("L");
|
||||
}
|
||||
}, OCCUPIED {
|
||||
@Override
|
||||
void print() {
|
||||
System.out.print("#");
|
||||
}
|
||||
}, FLOOR {
|
||||
@Override
|
||||
void print() {
|
||||
System.out.print(".");
|
||||
}
|
||||
};
|
||||
|
||||
abstract void print();
|
||||
|
||||
static SeatState from(char c) {
|
||||
return switch (c) {
|
||||
case 'L' -> EMPTY;
|
||||
case '#' -> OCCUPIED;
|
||||
default -> FLOOR;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private record Location(int row, int col) {};
|
||||
|
||||
private enum Directon {
|
||||
UP {
|
||||
@Override
|
||||
Location next(Location cur) {
|
||||
return new Location(cur.row() -1, cur.col);
|
||||
}
|
||||
}, DOWN {
|
||||
@Override
|
||||
Location next(Location cur) {
|
||||
return new Location(cur.row() +1, cur.col);
|
||||
}
|
||||
}, LEFT{
|
||||
@Override
|
||||
Location next(Location cur) {
|
||||
return new Location(cur.row(), cur.col -1);
|
||||
}
|
||||
}, RIGHT{
|
||||
@Override
|
||||
Location next(Location cur) {
|
||||
return new Location(cur.row(), cur.col +1);
|
||||
}
|
||||
}, LEFT_UP {
|
||||
@Override
|
||||
Location next(Location cur) {
|
||||
return new Location(cur.row() -1, cur.col -1);
|
||||
}
|
||||
}, LEFT_DOWN {
|
||||
@Override
|
||||
Location next(Location cur) {
|
||||
return new Location(cur.row() +1, cur.col -1);
|
||||
}
|
||||
}, RIGHT_UP {
|
||||
@Override
|
||||
Location next(Location cur) {
|
||||
return new Location(cur.row() -1, cur.col +1);
|
||||
}
|
||||
}, RIGHT_DOWN {
|
||||
@Override
|
||||
Location next(Location cur) {
|
||||
return new Location(cur.row() +1, cur.col +1);
|
||||
}
|
||||
};
|
||||
|
||||
abstract Location next(Location cur);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new Day11().solve();
|
||||
}
|
||||
|
||||
private List<List<SeatState>> copySeatMap(List<List<SeatState>> seatMap) {
|
||||
return seatMap.stream().map(ArrayList::new).collect(toList());
|
||||
}
|
||||
|
||||
private void solve() throws Exception {
|
||||
Stream<String> lines = Files.lines(Paths.get("day11/input"));
|
||||
List<List<SeatState>> seatMap = lines
|
||||
.map(l -> l.chars().mapToObj(c -> (char) c).map(SeatState::from).collect(toList()))
|
||||
.collect(toList());
|
||||
|
||||
solveFirst(seatMap);
|
||||
|
||||
solveSecond(seatMap);
|
||||
}
|
||||
|
||||
private void printMap(List<List<SeatState>> seatMap) {
|
||||
seatMap.forEach(row -> {
|
||||
row.forEach(SeatState::print);
|
||||
System.out.println();
|
||||
});
|
||||
}
|
||||
|
||||
private void solveSecond(List<List<SeatState>> seatMap) {
|
||||
boolean changed = true;
|
||||
while (changed) {
|
||||
// printMap(seatMap);
|
||||
// System.out.println();
|
||||
changed = false;
|
||||
var nextSeatMap = copySeatMap(seatMap);
|
||||
for (int row = 0; row < seatMap.size(); row++) {
|
||||
for (int column = 0; column < seatMap.get(row).size(); column++) {
|
||||
SeatState prev = seatMap.get(row).get(column);
|
||||
SeatState next = calcSeatWithDirection(seatMap, row, column);
|
||||
changed |= prev != next;
|
||||
nextSeatMap.get(row).set(column, next);
|
||||
}
|
||||
}
|
||||
seatMap = nextSeatMap;
|
||||
}
|
||||
|
||||
Long occupiedSeats = seatMap.stream().map(col -> col.stream().filter(state -> state == SeatState.OCCUPIED).count()).reduce(0L, Long::sum);
|
||||
System.out.println(occupiedSeats);
|
||||
}
|
||||
|
||||
private void solveFirst(List<List<SeatState>> seatMap) {
|
||||
boolean changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
var nextSeatMap = copySeatMap(seatMap);
|
||||
for (int row = 0; row < seatMap.size(); row++) {
|
||||
for (int column = 0; column < seatMap.get(row).size(); column++) {
|
||||
SeatState prev = seatMap.get(row).get(column);
|
||||
SeatState next = calcSeat(seatMap, row, column);
|
||||
changed |= prev != next;
|
||||
nextSeatMap.get(row).set(column, next);
|
||||
}
|
||||
}
|
||||
seatMap = nextSeatMap;
|
||||
}
|
||||
|
||||
Long occupiedSeats = seatMap.stream().map(col -> col.stream().filter(state -> state == SeatState.OCCUPIED).count()).reduce(0L, Long::sum);
|
||||
System.out.println(occupiedSeats);
|
||||
}
|
||||
|
||||
private SeatState calcSeat(List<List<SeatState>> seatMap, int row, int column) {
|
||||
int occupiedSeatsAround = 0;
|
||||
occupiedSeatsAround += isSeatOccupiedInt(seatMap, row-1, column-1);
|
||||
occupiedSeatsAround += isSeatOccupiedInt(seatMap, row-1, column);
|
||||
occupiedSeatsAround += isSeatOccupiedInt(seatMap, row-1, column+1);
|
||||
occupiedSeatsAround += isSeatOccupiedInt(seatMap, row+1, column-1);
|
||||
occupiedSeatsAround += isSeatOccupiedInt(seatMap, row+1, column);
|
||||
occupiedSeatsAround += isSeatOccupiedInt(seatMap, row+1, column+1);
|
||||
occupiedSeatsAround += isSeatOccupiedInt(seatMap, row, column-1);
|
||||
occupiedSeatsAround += isSeatOccupiedInt(seatMap, row, column+1);
|
||||
|
||||
if (seatMap.get(row).get(column) == SeatState.EMPTY && occupiedSeatsAround == 0) {
|
||||
return SeatState.OCCUPIED;
|
||||
}
|
||||
if (seatMap.get(row).get(column) == SeatState.OCCUPIED && occupiedSeatsAround >= 4) {
|
||||
return SeatState.EMPTY;
|
||||
}
|
||||
return seatMap.get(row).get(column);
|
||||
}
|
||||
|
||||
private int isSeatOccupiedInt(List<List<SeatState>> seatMap, int row, int column) {
|
||||
if (row >= 0 && row < seatMap.size()
|
||||
&& column >= 0 && column < seatMap.get(row).size()) {
|
||||
return seatMap.get(row).get(column) == SeatState.OCCUPIED ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private SeatState calcSeatWithDirection(List<List<SeatState>> seatMap, int row, int column) {
|
||||
int occupiedSeatsAround = 0;
|
||||
occupiedSeatsAround += isSeatOccupiedIntWithDirection(seatMap, row, column, Directon.UP);
|
||||
occupiedSeatsAround += isSeatOccupiedIntWithDirection(seatMap, row, column, Directon.DOWN);
|
||||
occupiedSeatsAround += isSeatOccupiedIntWithDirection(seatMap, row, column, Directon.LEFT);
|
||||
occupiedSeatsAround += isSeatOccupiedIntWithDirection(seatMap, row, column, Directon.RIGHT);
|
||||
occupiedSeatsAround += isSeatOccupiedIntWithDirection(seatMap, row, column, Directon.LEFT_UP);
|
||||
occupiedSeatsAround += isSeatOccupiedIntWithDirection(seatMap, row, column, Directon.LEFT_DOWN);
|
||||
occupiedSeatsAround += isSeatOccupiedIntWithDirection(seatMap, row, column, Directon.RIGHT_UP);
|
||||
occupiedSeatsAround += isSeatOccupiedIntWithDirection(seatMap, row, column, Directon.RIGHT_DOWN);
|
||||
|
||||
if (seatMap.get(row).get(column) == SeatState.EMPTY && occupiedSeatsAround == 0) {
|
||||
return SeatState.OCCUPIED;
|
||||
}
|
||||
if (seatMap.get(row).get(column) == SeatState.OCCUPIED && occupiedSeatsAround >= 5) { // change in rule!
|
||||
return SeatState.EMPTY;
|
||||
}
|
||||
return seatMap.get(row).get(column);
|
||||
}
|
||||
|
||||
private int isSeatOccupiedIntWithDirection(List<List<SeatState>> seatMap, int row, int column, Directon directon) {
|
||||
return isSeatOccupiedIntWithDirection(seatMap, new Location(row, column), directon);
|
||||
}
|
||||
|
||||
private int isSeatOccupiedIntWithDirection(List<List<SeatState>> seatMap, Location test, Directon directon) {
|
||||
test = directon.next(test);
|
||||
while (test.row() >= 0 && test.row() < seatMap.size()
|
||||
&& test.col() >= 0 && test.col() < seatMap.get(test.row()).size()
|
||||
&& seatMap.get(test.row).get(test.col()) == SeatState.FLOOR) {
|
||||
test = directon.next(test);
|
||||
}
|
||||
if (test.row() >= 0 && test.row() < seatMap.size()
|
||||
&& test.col() >= 0 && test.col() < seatMap.get(test.row()).size()) {
|
||||
return seatMap.get(test.row()).get(test.col()) == SeatState.OCCUPIED ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package dev.forstenlechner.aoc;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Day12 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new Day12().solve();
|
||||
}
|
||||
|
||||
private enum Orientation {
|
||||
N(0), E(1), S(2), W(3);
|
||||
|
||||
int value;
|
||||
Orientation(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
static Orientation from(int value) {
|
||||
return switch (value) {
|
||||
case 1 -> E;
|
||||
case 2 -> S;
|
||||
case 3 -> W;
|
||||
default -> N;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private enum Instruction {
|
||||
N {
|
||||
@Override
|
||||
LocationFacing move(LocationFacing current, int value) {
|
||||
return new LocationFacing(current.east, current.north + value, current.orientation);
|
||||
}
|
||||
},
|
||||
S {
|
||||
@Override
|
||||
LocationFacing move(LocationFacing current, int value) {
|
||||
return new LocationFacing(current.east, current.north - value, current.orientation);
|
||||
}
|
||||
},
|
||||
E {
|
||||
@Override
|
||||
LocationFacing move(LocationFacing current, int value) {
|
||||
return new LocationFacing(current.east + value, current.north, current.orientation);
|
||||
}
|
||||
},
|
||||
W {
|
||||
@Override
|
||||
LocationFacing move(LocationFacing current, int value) {
|
||||
return new LocationFacing(current.east - value, current.north, current.orientation);
|
||||
}
|
||||
},
|
||||
L {
|
||||
@Override
|
||||
LocationFacing move(LocationFacing current, int value) {
|
||||
value = (value % 360) / 90;
|
||||
int newValue = (current.orientation.getValue() - value + 4) % 4;
|
||||
return new LocationFacing(current.east, current.north, Orientation.from(newValue));
|
||||
}
|
||||
},
|
||||
R {
|
||||
@Override
|
||||
LocationFacing move(LocationFacing current, int value) {
|
||||
value = (value % 360) / 90;
|
||||
int newValue = (current.orientation.getValue() + value + 4) % 4;
|
||||
return new LocationFacing(current.east, current.north, Orientation.from(newValue));
|
||||
}
|
||||
},
|
||||
F {
|
||||
@Override
|
||||
LocationFacing move(LocationFacing current, int value) {
|
||||
if (current.orientation == Orientation.N) {
|
||||
return N.move(current, value);
|
||||
}
|
||||
if (current.orientation == Orientation.S) {
|
||||
return S.move(current, value);
|
||||
}
|
||||
if (current.orientation == Orientation.E) {
|
||||
return E.move(current, value);
|
||||
}
|
||||
if (current.orientation == Orientation.W) {
|
||||
return W.move(current, value);
|
||||
}
|
||||
throw new IllegalArgumentException("not implemented");
|
||||
}
|
||||
};
|
||||
|
||||
abstract LocationFacing move(LocationFacing current, int value);
|
||||
}
|
||||
|
||||
private record NavigationInstruction(Instruction ins, int value) {};
|
||||
|
||||
private record LocationFacing(int east, int north, Orientation orientation) {};
|
||||
|
||||
private void solve() throws Exception {
|
||||
Stream<String> lines = Files.lines(Paths.get("day12/input"));
|
||||
|
||||
List<NavigationInstruction> navigationInstructions = lines
|
||||
.map(l -> new NavigationInstruction(Instruction.valueOf(l.substring(0, 1)), Integer.parseInt(l.substring(1))))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
LocationFacing result = navigationInstructions.stream().reduce(new LocationFacing(0, 0, Orientation.E), (l, n) -> {
|
||||
System.out.println(l);
|
||||
return n.ins().move(l, n.value());
|
||||
}, (l1, l2) -> l1);
|
||||
|
||||
System.out.println(Math.abs(result.east) + Math.abs(result.north));
|
||||
// 5641
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
package dev.forstenlechner.aoc;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Day12Part2 {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new Day12Part2().solve();
|
||||
}
|
||||
|
||||
private enum Orientation {
|
||||
N(0), E(1), S(2), W(3);
|
||||
|
||||
int value;
|
||||
Orientation(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
static Orientation from(int value) {
|
||||
return switch (value) {
|
||||
case 1 -> E;
|
||||
case 2 -> S;
|
||||
case 3 -> W;
|
||||
default -> N;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private enum Instruction {
|
||||
N {
|
||||
@Override
|
||||
Navigation move(Navigation current, int value) {
|
||||
return new Navigation(current.ship(), new WayPoint(current.waypoint().east(), current.waypoint().north() + value));
|
||||
}
|
||||
},
|
||||
S {
|
||||
@Override
|
||||
Navigation move(Navigation current, int value) {
|
||||
return new Navigation(current.ship(), new WayPoint(current.waypoint().east(), current.waypoint().north() - value));
|
||||
}
|
||||
},
|
||||
E {
|
||||
@Override
|
||||
Navigation move(Navigation current, int value) {
|
||||
return new Navigation(current.ship(), new WayPoint(current.waypoint().east() + value, current.waypoint().north()));
|
||||
}
|
||||
},
|
||||
W {
|
||||
@Override
|
||||
Navigation move(Navigation current, int value) {
|
||||
return new Navigation(current.ship(), new WayPoint(current.waypoint().east() - value, current.waypoint().north()));
|
||||
}
|
||||
},
|
||||
L {
|
||||
@Override
|
||||
Navigation move(Navigation current, int value) {
|
||||
WayPoint currentWayPoint = current.waypoint();
|
||||
WayPoint newWayPoint = switch (value) {
|
||||
case 90 -> new WayPoint(-currentWayPoint.north, currentWayPoint.east);
|
||||
case 180 -> new WayPoint(-currentWayPoint.east, -currentWayPoint.north);
|
||||
case 270 -> new WayPoint(currentWayPoint.north, -currentWayPoint.east);
|
||||
default -> {throw new IllegalArgumentException();}
|
||||
};
|
||||
|
||||
return new Navigation(current.ship(), newWayPoint);
|
||||
}
|
||||
},
|
||||
R {
|
||||
@Override
|
||||
Navigation move(Navigation current, int value) {
|
||||
WayPoint currentWayPoint = current.waypoint();
|
||||
WayPoint newWayPoint = switch (value) {
|
||||
case 90 -> new WayPoint(currentWayPoint.north, -currentWayPoint.east);
|
||||
case 180 -> new WayPoint(-currentWayPoint.east, -currentWayPoint.north);
|
||||
case 270 -> new WayPoint(-currentWayPoint.north, currentWayPoint.east);
|
||||
default -> {throw new IllegalArgumentException();}
|
||||
};
|
||||
|
||||
return new Navigation(current.ship(), newWayPoint);
|
||||
}
|
||||
},
|
||||
F {
|
||||
@Override
|
||||
Navigation move(Navigation current, int value) {
|
||||
Location shipLocation = current.ship();
|
||||
WayPoint wayPoint = current.waypoint();
|
||||
Location newLocation = new Location(shipLocation.east + (wayPoint.east * value), shipLocation.north + (wayPoint.north * value));
|
||||
return new Navigation(newLocation, wayPoint);
|
||||
}
|
||||
};
|
||||
|
||||
abstract Navigation move(Navigation navigation, int value);
|
||||
}
|
||||
|
||||
private record NavigationInstruction(Instruction ins, int value) {};
|
||||
|
||||
private record Location(int east, int north) {};
|
||||
|
||||
private record WayPoint(int east, int north) {};
|
||||
|
||||
private record Navigation(Location ship, WayPoint waypoint) {};
|
||||
|
||||
private void solve() throws Exception {
|
||||
Stream<String> lines = Files.lines(Paths.get("day12/input"));
|
||||
|
||||
List<NavigationInstruction> navigationInstructions = lines
|
||||
.map(l -> new NavigationInstruction(Instruction.valueOf(l.substring(0, 1)), Integer.parseInt(l.substring(1))))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Navigation starting = new Navigation(new Location(0, 0), new WayPoint(10, 1));
|
||||
Navigation result = navigationInstructions.stream().reduce(starting, (l, n) -> {
|
||||
return n.ins().move(l, n.value());
|
||||
}, (l1, l2) -> l1);
|
||||
|
||||
System.out.println(Math.abs(result.ship().east()) + Math.abs(result.ship().north()));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package dev.forstenlechner.aoc;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class Day13 {
|
||||
|
||||
record EarliestBus(long earliest, long bus) {}
|
||||
|
||||
record BusWithOffset(long bus, long offset) {}
|
||||
|
||||
record BusAsStringWithOffset(String bus, long offset) {}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new Day13().solve();
|
||||
}
|
||||
|
||||
private void solve() throws Exception {
|
||||
List<String> lines = Files.lines(Paths.get("day13/input")).collect(toList());
|
||||
|
||||
part1(lines);
|
||||
part2(lines.get(1));
|
||||
part2FromFusch(lines.get(1));
|
||||
}
|
||||
|
||||
private void part2(String busLine) {
|
||||
String[] busses = busLine.split(",");
|
||||
List<BusWithOffset> busWithOffsets = IntStream.range(0, busses.length)
|
||||
.mapToObj(offset -> new BusAsStringWithOffset(busses[offset], offset))
|
||||
.filter(bus -> !bus.bus().equals("x"))
|
||||
.map(bus -> new BusWithOffset(Long.parseLong(bus.bus()), bus.offset()))
|
||||
.collect(toList());
|
||||
|
||||
busWithOffsets.forEach(System.out::println);
|
||||
|
||||
long bus23 = 23;
|
||||
long minBusProduct = bus23 * 647 * 19 * 29 * 37;
|
||||
|
||||
long count = 1;
|
||||
while (true) {
|
||||
if (count % 1000 == 0) {
|
||||
System.out.println(count);
|
||||
}
|
||||
long possibleT = minBusProduct * count - bus23;
|
||||
if (busWithOffsets.stream().allMatch(bus -> ((possibleT + bus.offset()) % bus.bus()) == 0)) {
|
||||
System.out.println(possibleT);
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
System.out.println(count);
|
||||
}
|
||||
|
||||
private void part2FromFusch(String busLine) {
|
||||
List<BusWithOffset> busWithOffsets = getBussesWithOffset(busLine);
|
||||
|
||||
long count = 1;
|
||||
|
||||
long currentNumber = 1;
|
||||
long stepWidth = 1;
|
||||
for (BusWithOffset busWithOffset : busWithOffsets) {
|
||||
while ((currentNumber + busWithOffset.offset) % busWithOffset.bus != 0)
|
||||
{
|
||||
currentNumber += stepWidth;
|
||||
count++;
|
||||
}
|
||||
|
||||
// Found the number that fulfills the requirement.
|
||||
// Adapt step width, so all further steps also fulfill this requirement
|
||||
// KGV shouldn't be necessary, because input is all primes
|
||||
stepWidth *= busWithOffset.bus;
|
||||
}
|
||||
|
||||
System.out.println(count);
|
||||
System.out.println(currentNumber);
|
||||
}
|
||||
|
||||
private List<BusWithOffset> getBussesWithOffset(String busLine) {
|
||||
String[] busses = busLine.split(",");
|
||||
return IntStream.range(0, busses.length)
|
||||
.mapToObj(offset -> new BusAsStringWithOffset(busses[offset], offset))
|
||||
.filter(bus -> !bus.bus().equals("x"))
|
||||
.map(bus -> new BusWithOffset(Long.parseLong(bus.bus()), bus.offset()))
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
|
||||
private void part1(List<String> lines) {
|
||||
long earliestDeparture = Long.parseLong(lines.get(0));
|
||||
Stream<Long> busTimes = Arrays.stream(lines.get(1).split(",")).filter(x -> !x.equals("x")).map(Long::parseLong);
|
||||
EarliestBus earliestBus = busTimes.map(t -> earliestDepartureForBus(earliestDeparture, t)).min(Comparator.comparing(EarliestBus::earliest)).orElseThrow();
|
||||
System.out.println(earliestBus.bus() * (earliestBus.earliest() - earliestDeparture));
|
||||
}
|
||||
|
||||
private EarliestBus earliestDepartureForBus(long earliestDeparture, long bus) {
|
||||
if (earliestDeparture % bus == 0) {
|
||||
return new EarliestBus(earliestDeparture, bus);
|
||||
}
|
||||
|
||||
return new EarliestBus((earliestDeparture / bus + 1) * bus, bus);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace AoC {
|
||||
|
||||
internal class Day6 {
|
||||
|
||||
internal void Solve() {
|
||||
var readLines = File.ReadAllText("day6/input").Split("\n\n", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
static ISet<char> UniqueCharactersExceptNewline(string s) => s.Where(c => c != '\n').ToImmutableHashSet();
|
||||
int part1 = readLines.Select(UniqueCharactersExceptNewline).Sum(s => s.Count);
|
||||
|
||||
Console.WriteLine(part1);
|
||||
|
||||
static IEnumerable<IImmutableSet<char>> GroupToUniqueCharacters(string s) => s
|
||||
.Split('\n', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(s => s.ToImmutableHashSet());
|
||||
|
||||
static IImmutableSet<char> Intersection(IImmutableSet<char> first, IImmutableSet<char> second) =>
|
||||
first.Intersect(second);
|
||||
|
||||
static IImmutableSet<char> IntersectAll(IEnumerable<IImmutableSet<char>> group) => group
|
||||
.Skip(1)
|
||||
.Aggregate(group.First(), Intersection);
|
||||
|
||||
int part2 = readLines
|
||||
.Select(GroupToUniqueCharacters)
|
||||
.Select(IntersectAll)
|
||||
.Sum(s => s.Count);
|
||||
|
||||
Console.WriteLine(part2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
namespace AoC {
|
||||
|
||||
internal class Day7 {
|
||||
|
||||
private record BagCount(string color, int count);
|
||||
|
||||
private Regex rx = new Regex(@"^(?<count>\d+) (?<color>\w+ \w+)");
|
||||
|
||||
private string ShinyGold = "shiny gold";
|
||||
|
||||
|
||||
internal void Solve() {
|
||||
var readLines = File.ReadAllText("day7/inputTest").Split("\n", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var rules = new Dictionary<string, List<BagCount>>();
|
||||
foreach (var line in readLines) {
|
||||
var strings = line.Split(" bags contain ");
|
||||
var bagRule = strings[0];
|
||||
|
||||
if (strings[1].Equals("no other bags.")) {
|
||||
rules.Add(bagRule, new List<BagCount>());
|
||||
continue;
|
||||
}
|
||||
|
||||
var bagCounts = new List<BagCount>();
|
||||
var bagsContained = strings[1].Split(", ");
|
||||
foreach (var bagOption in bagsContained) {
|
||||
var groups = rx.Match(bagOption).Groups;
|
||||
bagCounts.Add(new BagCount(groups["color"].Value, Int32.Parse(groups["count"].Value)));
|
||||
}
|
||||
|
||||
rules.Add(bagRule, bagCounts);
|
||||
}
|
||||
|
||||
Console.WriteLine(rules);
|
||||
|
||||
Dictionary<string, List<string>> containedIn = new Dictionary<string, List<string>>();
|
||||
foreach (var rule in rules) {
|
||||
foreach (var bagCount in rule.Value) {
|
||||
if (!containedIn.ContainsKey(bagCount.color)) {
|
||||
containedIn.Add(bagCount.color, new List<string>());
|
||||
}
|
||||
containedIn[bagCount.color].Add(rule.Key);
|
||||
}
|
||||
}
|
||||
|
||||
ISet<string> res = new HashSet<string>();
|
||||
Queue<String> q = new Queue<string>();
|
||||
q.Enqueue(ShinyGold);
|
||||
|
||||
while (q.TryDequeue(out string bag)) {
|
||||
if (!containedIn.ContainsKey(bag)) {
|
||||
continue;
|
||||
}
|
||||
var contained = containedIn[bag];
|
||||
contained.ForEach(c => q.Enqueue(c));
|
||||
contained.ForEach(c => res.Add(c));
|
||||
}
|
||||
|
||||
Console.WriteLine(res.Count);
|
||||
|
||||
// second part
|
||||
long CountBagsRecursive(string color) {
|
||||
var bagCounts = rules[color];
|
||||
if (bagCounts.Count == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
long res = 1;
|
||||
foreach (var bagCount in bagCounts) {
|
||||
res += bagCount.count * CountBagsRecursive(bagCount.color);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Console.WriteLine(CountBagsRecursive(ShinyGold) - 1);
|
||||
// wrong
|
||||
// 1141
|
||||
// 1251
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
namespace AoC {
|
||||
|
||||
internal class Day8 {
|
||||
|
||||
private enum Instruction {
|
||||
ACC, JMP, NOP
|
||||
}
|
||||
|
||||
private record Command(Instruction ins, int value);
|
||||
|
||||
private ImmutableDictionary<string, Instruction> InstructionFromString =
|
||||
new Dictionary<string, Instruction> {
|
||||
{ "acc", Instruction.ACC },
|
||||
{ "jmp", Instruction.JMP },
|
||||
{ "nop", Instruction.NOP }
|
||||
}.ToImmutableDictionary();
|
||||
|
||||
private Regex rx = new(@"^(?<ins>\w+) (?<value>(\+|\-)\d+)");
|
||||
|
||||
private bool DoesItLoop(List<Command> commands, int index, ref int accumulator) {
|
||||
ISet<int> commandIndices = new HashSet<int>();
|
||||
while (index >= 0 && index < commands.Count && !commandIndices.Contains(index)) {
|
||||
commandIndices.Add(index);
|
||||
|
||||
var command = commands[index];
|
||||
(accumulator, index) = command.ins switch {
|
||||
Instruction.ACC => (accumulator + command.value, index + 1),
|
||||
Instruction.JMP => (accumulator, index + command.value),
|
||||
Instruction.NOP => (accumulator, index + 1),
|
||||
_ => throw new ArgumentException("Du doofer Hund!")
|
||||
};
|
||||
}
|
||||
|
||||
return commandIndices.Contains(index);
|
||||
}
|
||||
|
||||
internal void Solve() {
|
||||
var readLines = File.ReadAllText("day8/input").Split("\n", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
Command LineToCommandSelector(string line) {
|
||||
var groups = rx.Match(line).Groups;
|
||||
return new Command(InstructionFromString[groups["ins"].Value], int.Parse(groups["value"].Value));
|
||||
}
|
||||
|
||||
var commands = readLines.Select(LineToCommandSelector).ToList();
|
||||
|
||||
SortedSet<int> commandIndices = new SortedSet<int>();
|
||||
int index = 0;
|
||||
int accumulator = 0;
|
||||
while (!commandIndices.Contains(index)) {
|
||||
commandIndices.Add(index);
|
||||
|
||||
var command = commands[index];
|
||||
(accumulator, index) = command.ins switch {
|
||||
Instruction.ACC => (accumulator + command.value, index + 1),
|
||||
Instruction.JMP => (accumulator, index + command.value),
|
||||
Instruction.NOP => (accumulator, index + 1),
|
||||
_ => throw new ArgumentException("Du doofer Hund!")
|
||||
};
|
||||
}
|
||||
|
||||
Console.WriteLine(accumulator);
|
||||
|
||||
foreach (var commandIndex in commandIndices.Reverse()) {
|
||||
index = 0;
|
||||
accumulator = 0;
|
||||
if (commands[commandIndex].ins == Instruction.ACC) {
|
||||
continue;
|
||||
}
|
||||
if (commands[commandIndex].ins == Instruction.JMP) {
|
||||
commands[commandIndex] = new Command(Instruction.NOP, commands[commandIndex].value);
|
||||
if (!DoesItLoop(commands, index, ref accumulator)) {
|
||||
break;
|
||||
}
|
||||
commands[commandIndex] = new Command(Instruction.JMP, commands[commandIndex].value);
|
||||
} else {
|
||||
commands[commandIndex] = new Command(Instruction.JMP, commands[commandIndex].value);
|
||||
if (!DoesItLoop(commands, index, ref accumulator)) {
|
||||
break;
|
||||
}
|
||||
commands[commandIndex] = new Command(Instruction.NOP, commands[commandIndex].value);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine(accumulator);
|
||||
}
|
||||
|
||||
private record Info(int index, int accumulator);
|
||||
|
||||
private static void ExecuteInstruction(List<Command> commands, ref int index, ref int accumulator) {
|
||||
var command = commands[index];
|
||||
(accumulator, index) = command.ins switch {
|
||||
Instruction.ACC => (accumulator + command.value, index + 1),
|
||||
Instruction.JMP => (accumulator, index + command.value),
|
||||
Instruction.NOP => (accumulator, index + 1),
|
||||
_ => throw new ArgumentException("Du doofer Hund!")
|
||||
};
|
||||
}
|
||||
|
||||
private bool DoesItLoop(List<Command> commands, int index, ref int accumulator, ISet<int> visitedInstructions) {
|
||||
while (index >= 0 && index < commands.Count && !visitedInstructions.Contains(index)) {
|
||||
visitedInstructions.Add(index);
|
||||
ExecuteInstruction(commands, ref index, ref accumulator);
|
||||
}
|
||||
return visitedInstructions.Contains(index);
|
||||
}
|
||||
|
||||
internal void SolveOn() {
|
||||
|
||||
var readLines = File.ReadAllText("day8/input").Split("\n", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
Command LineToCommandSelector(string line) {
|
||||
var groups = rx.Match(line).Groups;
|
||||
return new Command(InstructionFromString[groups["ins"].Value], int.Parse(groups["value"].Value));
|
||||
}
|
||||
|
||||
var commands = readLines.Select(LineToCommandSelector).ToList();
|
||||
|
||||
ISet<int> commandIndices = new HashSet<int>();
|
||||
Stack<Info> commandInfo = new Stack<Info>();
|
||||
int index = 0;
|
||||
int accumulator = 0;
|
||||
while (!commandIndices.Contains(index)) {
|
||||
commandIndices.Add(index);
|
||||
commandInfo.Push(new Info(index, accumulator));
|
||||
|
||||
ExecuteInstruction(commands, ref index, ref accumulator);
|
||||
}
|
||||
|
||||
Console.WriteLine(accumulator);
|
||||
|
||||
Instruction switchInstruction(Instruction ins) => ins == Instruction.NOP ? Instruction.JMP : Instruction.NOP;
|
||||
|
||||
int tempAccumulator = -1;
|
||||
while (commandInfo.Count > 0) {
|
||||
var current = commandInfo.Pop();
|
||||
if (commands[current.index].ins == Instruction.ACC) {
|
||||
continue;
|
||||
}
|
||||
|
||||
commands[current.index] = new Command(switchInstruction(commands[current.index].ins), commands[current.index].value);
|
||||
tempAccumulator = current.accumulator;
|
||||
commandIndices.Remove(current.index);
|
||||
if (!DoesItLoop(commands, current.index, ref tempAccumulator, commandIndices)) {
|
||||
break;
|
||||
}
|
||||
commands[current.index] = new Command(switchInstruction(commands[current.index].ins), commands[current.index].value);
|
||||
}
|
||||
|
||||
Console.WriteLine(tempAccumulator);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
namespace AoC {
|
||||
|
||||
internal class Day9 {
|
||||
|
||||
private const int preamble = 25;
|
||||
|
||||
internal void Solve() {
|
||||
var numbers = File.ReadAllText("day9/input")
|
||||
.Split("\n", StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(long.Parse)
|
||||
.ToList();
|
||||
|
||||
bool ExistTwo(ISet<long> current, long target) =>
|
||||
current.Any(c => current.Contains(target - c));
|
||||
|
||||
Queue<long> currentQueue = new Queue<long>();
|
||||
ISet<long> currentSet = new HashSet<long>();
|
||||
numbers.Take(preamble).ToList().ForEach(i => {
|
||||
currentQueue.Enqueue(i);
|
||||
currentSet.Add(i);
|
||||
});
|
||||
|
||||
foreach (var n in numbers.Skip(preamble)) {
|
||||
if (!ExistTwo(currentSet, n)) {
|
||||
Console.WriteLine(n);
|
||||
break;
|
||||
}
|
||||
|
||||
long firstInserted = currentQueue.Dequeue();
|
||||
currentQueue.Enqueue(n);
|
||||
currentSet.Remove(firstInserted);
|
||||
currentSet.Add(n);
|
||||
}
|
||||
|
||||
// part two
|
||||
const long contiguousNumber = 69316178;
|
||||
|
||||
long sum = 0;
|
||||
Queue<long> contiguousQueue = new Queue<long>();
|
||||
foreach (var n in numbers) {
|
||||
if (sum < contiguousNumber) {
|
||||
contiguousQueue.Enqueue(n);
|
||||
sum += n;
|
||||
}
|
||||
while (sum > contiguousNumber) {
|
||||
sum -= contiguousQueue.Dequeue();
|
||||
}
|
||||
if (sum == contiguousNumber) {
|
||||
long res = contiguousQueue.Min() + contiguousQueue.Max();
|
||||
Console.WriteLine(res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
expense_report = []
|
||||
|
||||
with open('day1/input') as reader:
|
||||
expense_report.extend([int(l) for l in reader.readlines()])
|
||||
|
||||
expense_report.sort()
|
||||
|
||||
def calc_two(sub_set, absolute):
|
||||
first_i = 0
|
||||
second_i = len(sub_set) - 1
|
||||
first = sub_set[first_i]
|
||||
second = sub_set[second_i]
|
||||
|
||||
while first_i < second_i and first + second + absolute != 2020:
|
||||
if first + second + absolute > 2020:
|
||||
second_i -= 1
|
||||
second = sub_set[second_i]
|
||||
else:
|
||||
first_i += 1
|
||||
first = sub_set[first_i]
|
||||
if first_i < second_i:
|
||||
return (first_i, second_i, first, second)
|
||||
return None
|
||||
|
||||
# part one
|
||||
# first_i = 0
|
||||
# second_i = len(expense_report) - 1
|
||||
# first = expense_report[first_i]
|
||||
# second = expense_report[second_i]
|
||||
#
|
||||
# while first + second != 2020:
|
||||
# if first + second > 2020:
|
||||
# second_i -= 1
|
||||
# second = expense_report[second_i]
|
||||
# else:
|
||||
# first_i += 1
|
||||
# first = expense_report[first_i]
|
||||
|
||||
first_i, second_i, first, second = calc_two(expense_report, 0)
|
||||
|
||||
print(first, second)
|
||||
print(first * second)
|
||||
|
||||
# second part
|
||||
|
||||
for i in range(len(expense_report) - 1):
|
||||
res = calc_two(expense_report[i+1:], expense_report[i])
|
||||
if res is not None:
|
||||
print(res[2], res[3], expense_report[i])
|
||||
print(res[2] * res[3] * expense_report[i])
|
||||
break
|
||||
|
||||
# second part better?
|
||||
# does not work! and probably never will!
|
||||
|
||||
# first_i = 0
|
||||
# second_i = 1
|
||||
# third_i = len(expense_report) - 1
|
||||
# first = expense_report[first_i]
|
||||
# second = expense_report[second_i]
|
||||
# third = expense_report[third_i]
|
||||
#
|
||||
# up_with_second = first + second + third < 2020
|
||||
#
|
||||
# while first + second + third != 2020:
|
||||
# if first + second + third > 2020:
|
||||
# if up_with_second:
|
||||
# if second_i+1 == third_i:
|
||||
# second_i -= 1
|
||||
# second = expense_report[second_i]
|
||||
# third_i -= 1
|
||||
# third = expense_report[third_i]
|
||||
# else:
|
||||
# if second_i-1 != first_i:
|
||||
# second_i -= 1
|
||||
# second = expense_report[second_i]
|
||||
# else:
|
||||
# third_i -= 1
|
||||
# third = expense_report[third_i]
|
||||
# up_with_second = True
|
||||
# else:
|
||||
# if up_with_second:
|
||||
# if second_i+1 != third_i:
|
||||
# second_i += 1
|
||||
# second = expense_report[second_i]
|
||||
# else:
|
||||
# first_i += 1
|
||||
# first = expense_report[first_i]
|
||||
# up_with_second = False
|
||||
# else:
|
||||
# if second_i-1 == first_i:
|
||||
# second_i += 1
|
||||
# second = expense_report[second_i]
|
||||
# first_i += 1
|
||||
# first = expense_report[first_i]
|
||||
#
|
||||
#
|
||||
# print(first, second, third)
|
||||
# print(first * second * third)
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
pw_db = []
|
||||
|
||||
with open('day2/input') as reader:
|
||||
for l in reader.readlines():
|
||||
s = l.split()
|
||||
split_restriction = s[0].index("-")
|
||||
restriction_min = int(s[0][:split_restriction])
|
||||
restriction_max = int(s[0][split_restriction+1:])
|
||||
c = s[1][:-1]
|
||||
p = s[2]
|
||||
|
||||
pw_db.append(((restriction_min, restriction_max), c, p))
|
||||
|
||||
valids = 0
|
||||
for pw in pw_db:
|
||||
count = pw[2].count(pw[1])
|
||||
if pw[0][0] <= count <= pw[0][1]:
|
||||
valids += 1
|
||||
|
||||
print(valids)
|
||||
|
||||
valids2 = 0
|
||||
for pw in pw_db:
|
||||
first = pw[0][0]
|
||||
second = pw[0][1]
|
||||
c = pw[1]
|
||||
p = pw[2]
|
||||
l = len(p)
|
||||
if (first <= l and p[first-1] == c) is not (second <= l and p[second-1] == c):
|
||||
valids2 += 1
|
||||
|
||||
print(valids2)
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import functools
|
||||
|
||||
slope_map = []
|
||||
|
||||
with open('day3/input') as reader:
|
||||
slope_map.extend(reader.read().splitlines())
|
||||
|
||||
|
||||
def check_slope(right, down):
|
||||
global slope_map
|
||||
pos = 0
|
||||
y = 1
|
||||
trees = 0
|
||||
for l in slope_map[1:]:
|
||||
if y % down == 0:
|
||||
pos = (pos + right) % len(l)
|
||||
if l[pos] == '#':
|
||||
trees += 1
|
||||
y += 1
|
||||
|
||||
return trees
|
||||
|
||||
|
||||
def check_slope_short(right, down):
|
||||
global slope_map
|
||||
trees = 0
|
||||
for (i, l) in enumerate(slope_map):
|
||||
if i % down == 0:
|
||||
pos = (i // down * right) % len(l)
|
||||
if l[pos] == '#':
|
||||
trees += 1
|
||||
|
||||
return trees
|
||||
|
||||
|
||||
def check_slope_even_short(right, down):
|
||||
global slope_map
|
||||
return len(list(filter(lambda b: b, map(lambda en: en[1][(en[0] // down * right) % len(en[1])] == '#', filter(lambda en: en[0] % down == 0, enumerate(slope_map))))))
|
||||
|
||||
slopes = [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
|
||||
|
||||
total_trees = functools.reduce(lambda prev, slope: prev * check_slope_even_short(*slope), slopes, 1)
|
||||
|
||||
print(total_trees)
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
import re
|
||||
passports = []
|
||||
|
||||
with open('day4/input') as reader:
|
||||
cur = ''
|
||||
for line in reader.read().splitlines():
|
||||
if line != '':
|
||||
if cur == '':
|
||||
cur += line
|
||||
else:
|
||||
cur += ' ' + line
|
||||
else:
|
||||
passports.append(cur)
|
||||
cur = ''
|
||||
|
||||
if cur != '':
|
||||
passports.append(cur)
|
||||
|
||||
def byr(s):
|
||||
return re.match('^\d{4}$', s) is not None and (1920 <= int(s) <= 2002)
|
||||
|
||||
def iyr(s):
|
||||
return re.match('^\d{4}$', s) is not None and (2010 <= int(s) <= 2020)
|
||||
|
||||
def eyr(s):
|
||||
return re.match('^\d{4}$', s) is not None and (2020 <= int(s) <= 2030)
|
||||
|
||||
def hgt(s):
|
||||
return (re.match('^\d+cm$', s) is not None and (150 <= int(s[:-2]) <= 193)) \
|
||||
or (re.match('^\d+in$', s) is not None and (59 <= int(s[:-2]) <= 76))
|
||||
|
||||
def hcl(s):
|
||||
return re.match('^#[0-9a-f]{6}$', s) is not None
|
||||
|
||||
def ecl(s):
|
||||
return s in {'amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'}
|
||||
|
||||
def pid(s):
|
||||
return re.match('^[0-9]{9}$', s) is not None
|
||||
|
||||
verify = {'byr': byr,
|
||||
'iyr': iyr,
|
||||
'eyr': eyr,
|
||||
'hgt': hgt,
|
||||
'hcl': hcl,
|
||||
'ecl': ecl,
|
||||
'pid': pid,
|
||||
'cid': lambda s: True
|
||||
}
|
||||
|
||||
valid = set(verify.keys())
|
||||
|
||||
count_valids = 0
|
||||
for p in passports:
|
||||
props = set()
|
||||
failed = False
|
||||
for prop in p.split(' '):
|
||||
key, value = prop.split(':')
|
||||
props.add(key)
|
||||
if not verify[key](value):
|
||||
failed = True
|
||||
break
|
||||
|
||||
if failed:
|
||||
continue
|
||||
missing = valid.difference(props)
|
||||
if missing == set() or missing == {'cid'}:
|
||||
count_valids += 1
|
||||
|
||||
print(count_valids)
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
boarding_passes = []
|
||||
|
||||
with open('day5/input') as reader:
|
||||
boarding_passes.extend(reader.read().splitlines())
|
||||
|
||||
|
||||
def seat_id(boarding):
|
||||
binary = boarding \
|
||||
.replace('F', '0') \
|
||||
.replace('B', '1') \
|
||||
.replace('L', '0') \
|
||||
.replace('R', '1')
|
||||
|
||||
return int(binary, 2)
|
||||
|
||||
|
||||
res = max(map(seat_id, boarding_passes))
|
||||
|
||||
print(res)
|
||||
|
||||
# second part
|
||||
all_seats = sorted(map(seat_id, boarding_passes))
|
||||
for i in range(len(all_seats)):
|
||||
if all_seats[i] + 2 == all_seats[i + 1]:
|
||||
print(all_seats[i] + 1)
|
||||
break
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
expense_report = []
|
||||
|
||||
with open('day1/input') as reader:
|
||||
expense_report.extend([int(l) for l in reader.readlines()])
|
||||
|
||||
expense_report.sort()
|
||||
|
||||
def calc_two(sub_set, absolute):
|
||||
first_i = 0
|
||||
second_i = len(sub_set) - 1
|
||||
first = sub_set[first_i]
|
||||
second = sub_set[second_i]
|
||||
|
||||
while first_i < second_i and first + second + absolute != 2020:
|
||||
if first + second + absolute > 2020:
|
||||
second_i -= 1
|
||||
second = sub_set[second_i]
|
||||
else:
|
||||
first_i += 1
|
||||
first = sub_set[first_i]
|
||||
if first_i < second_i:
|
||||
return (first, second)
|
||||
return None
|
||||
|
||||
|
||||
for i in range(len(expense_report) - 1):
|
||||
res = calc_two(expense_report[i+1:], expense_report[i])
|
||||
if res is not None:
|
||||
print(res[0], res[1], expense_report[i])
|
||||
print(res[0] * res[1] * expense_report[i])
|
||||
break
|
||||
Loading…
Reference in New Issue