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:
parent
2b14c8d6f6
commit
73aac14025
8 changed files with 1026 additions and 31 deletions
16
source/app.d
16
source/app.d
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
42
source/day5.d
Normal 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);
|
||||
}
|
|
@ -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]();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue