commit README + Day1-13

This commit is contained in:
Stefan Forstenlechner 2020-12-16 20:25:26 +01:00
commit 9890182ea1
16 changed files with 1337 additions and 0 deletions

75
Day10.java Normal file
View File

@ -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);
}
}

246
Day11.java Normal file
View File

@ -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;
}
}

119
Day12.java Normal file
View File

@ -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
}
}

126
Day12Part2.java Normal file
View File

@ -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()));
}
}

109
Day13.java Normal file
View File

@ -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);
}
}

39
Day6.cs Normal file
View File

@ -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);
}
}
}

91
Day7.cs Normal file
View File

@ -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
}
}
}

163
Day8.cs Normal file
View File

@ -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);
}
}
}

64
Day9.cs Normal file
View File

@ -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;
}
}
}
}
}

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Advent of Code 2020
by Stefan Forstenlechner

99
day1.py Normal file
View File

@ -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)

32
day2.py Normal file
View File

@ -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)

44
day3.py Normal file
View File

@ -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)

70
day4.py Normal file
View File

@ -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)

26
day5.py Normal file
View File

@ -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

31
day_1.py Normal file
View File

@ -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