1
0
Fork 0
mirror of https://github.com/HenkKalkwater/aoc-2020 synced 2025-09-05 09:52:44 +00:00

Added day5 and brought more structure into days

This commit is contained in:
Chris Josten 2020-12-05 12:16:58 +01:00
parent 2b14c8d6f6
commit 73aac14025
Signed by: chris
GPG key ID: 1795A594046530AB
8 changed files with 1026 additions and 31 deletions

View file

@ -4,20 +4,23 @@ import std.conv;
import std.format;
import std.stdio;
import std.getopt;
import std.variant;
import day1;
import day2;
import day3;
import day4;
import day5;
import dayutil;
immutable string progName = "aoc-2020";
void function(string[])[] programs = [
Variant function(int, File, string[])[] programs = [
&day1.run,
&day2.run,
&day3.run,
&day4.run,
&day5.run,
];
void printUsage(string name) {
@ -34,7 +37,7 @@ void printUsage(string name, string message) {
void main(string[] args) {
int day;
if (args.length < 2) {
if (args.length < 3) {
printUsage(args[0]);
}
try {
@ -47,9 +50,16 @@ void main(string[] args) {
printUsage(args[0], "[day] must be between 1 and %d".format(programs.length - 1));
}
int part;
try {
part = to!int(args[2]);
} catch (ConvException e) {
printUsage(args[0], "[part] is not an integer");
}
try {
programs[day - 1](args[2..$]);
Variant result = programs[day - 1](part, stdin, args[3..$]);
writeln(result);
} catch(ArgumentException e) {
printUsage(args[0], e.msg);
}

View file

@ -6,22 +6,23 @@ import std.format;
import std.functional;
import std.range;
import std.stdio;
import std.variant;
import dayutil;
immutable string progName = "aoc-2020";
void run(string[] args) {
Variant run(int part, File input, string[] args) {
/* For each line on stdin, copy it, map it to an integer and sort it.
Sorting a range makes it a SortedRange and functions like contains(range, elem)
will make use of optimised implementations, in the case of contains(range, elem)
it will use a binary search instead of a linear search */
auto numbers = stdin.byLineCopy.map!(a => to!int(a)).array.sort;
auto numbers = input.byLineCopy.map!(a => to!int(a)).array.sort;
int solution = parts!int(args, partial!(part1, numbers), partial!(part2, numbers));
Variant solution = parts!int(part, partial!(part1, numbers), partial!(part2, numbers));
enforce(solution >= 0, "No solutions found");
writeln(solution);
return solution;
}
int part1(SortedRange!(int[]) numbers) {

View file

@ -2,15 +2,16 @@ import std.algorithm;
import std.format;
import std.functional;
import std.stdio;
import std.variant;
import dayutil;
void run(string[] args) {
ulong count = parts!ulong(args,
() => stdin.byLine.count!(l => isPasswordValid1(l)),
() => stdin.byLine.count!(l => isPasswordValid2(l)));
writeln(count);
Variant run(int day, File input, string[] args) {
auto lines = input.byLine;
Variant count = parts!ulong(day,
() => lines.count!(l => isPasswordValid1(l)),
() => lines.count!(l => isPasswordValid2(l)));
return count;
}
/// Part 1

View file

@ -5,18 +5,18 @@ import std.range;
import std.stdio;
import std.traits;
import std.uni;
import std.variant;
import dayutil;
void run(string[] args) {
auto input = stdin.byLineCopy.array;
ulong count = parts!ulong(args,
() => input.countTrees1,
Variant run(int part, File input, string[] args) {
auto inputData = stdin.byLineCopy.array;
Variant count = parts!size_t(part,
() => inputData.countTrees1,
() => [[1,1], [3,1], [5,1], [7,1], [1,2]]
.map!(x => input.save.enumerate.countTrees2(x[0], x[1]))
.map!(x => inputData.save.enumerate.countTrees2(x[0], x[1]))
.fold!((x, y) => x * y));
writeln(count);
return count;
}
ulong countTrees1(Range)(Range lines) if (isInputRange!Range && isSomeString!(ElementType!Range)) {

View file

@ -4,6 +4,7 @@ import std.functional;
import std.range;
import std.stdio;
import std.traits;
import std.variant;
import dayutil;
@ -46,12 +47,12 @@ struct Passport {
&& eyeColour.length > 0 && passwordId.length > 0;
}
}
void run(string[] args) {
auto lines = stdin.byLineCopy.array;
size_t result = parts!size_t(args,
Variant run(int part, File input, string[] args) {
auto lines = input.byLineCopy.array;
Variant result = parts!size_t(part,
() => part1(lines),
() => part2(lines));
writeln(result);
return result;
}
size_t part1(Range)(Range range) if (isInputRange!Range) {

42
source/day5.d Normal file
View file

@ -0,0 +1,42 @@
import std.algorithm;
import std.array;
import std.conv;
import std.range;
import std.stdio;
import std.string;
import std.variant;
import dayutil;
Variant run(int part, File file, string[] args) {
auto lines = file.byLine;
Variant result = parts!int(part,
() => part1(lines));
return result;
}
int part1(Range)(Range range) if (isInputRange!Range) {
return range.map!(x => determineSeat(to!string(x.array))).maxElement;
}
int determineSeat(string code) {
int result = 0;
int marker = 0b1000000000;
foreach(char c; code[0..7]) {
if (c == 'B') result |= marker;
marker >>= 1;
}
//writeln("ROW: ", result >> 3);
foreach(char c; code[7..10]) {
if (c == 'R') result |= marker;
marker >>= 1;
}
//writeln("COL: ", result & 0x7);
return result;
}
unittest {
assert(determineSeat("BFFFBBFRRR") == 567);
assert(determineSeat("FFFBBBFRRR") == 119);
assert(determineSeat("BBFFBBFRLL") == 820);
}

View file

@ -13,17 +13,12 @@ class ArgumentException : Exception{
goes out bounds.
*
* Params:
* args = Reference to string with arguments, usually from main.
* part = The part to run.
* dgs = list of delegates. Which one will be called depends on args[0]
*/
R parts(R)(ref string[] args, R delegate()[] dgs ...) {
R parts(R)(int part, R delegate()[] dgs ...) {
ulong len = dgs.length;
enforce!ArgumentException(args.length >= 1, "Please provide a part to run as a command line argument");
int part = to!int(args[0]);
enforce!ArgumentException(part > 0 && part <= len, "This day supports parts %d to %d".format(1, len));
// Remove the first argument
args = args[1..$];
return dgs[part - 1]();
}