1
0
Fork 0
mirror of https://github.com/HenkKalkwater/aoc-2020 synced 2024-12-22 16:35:18 +00:00

Make code more reusable

This commit is contained in:
Chris Josten 2020-12-01 15:42:11 +01:00
parent c6f7df0bf3
commit f6a49daaf9
Signed by: chris
GPG key ID: 1795A594046530AB
3 changed files with 60 additions and 12 deletions

View file

@ -6,6 +6,7 @@ import std.stdio;
import std.getopt;
import day1;
import dayutil;
immutable string progName = "aoc-2020";
@ -13,25 +14,38 @@ void function(string[])[] programs = [
&day1.run
];
void printUsage(string name) {
printUsage(name, null);
}
void printUsage(string name, string message) {
stderr.writeln("USAGE: %s [day] [part]".format(name));
if (message != null) {
stderr.writeln(message);
}
exit(-1);
}
void main(string[] args) {
int day;
if (args.length < 2) {
stderr.writeln("USAGE: %s [day]".format(args[0]));
exit(-1);
printUsage(args[0]);
}
try {
day = to!int(args[1]);
} catch (ConvException e) {
stderr.writeln("[day] is not an integer");
exit(-1);
printUsage(args[0], "[day] is not an integer");
}
if (day <= 0 || day > programs.length) {
stderr.writeln("Day must be between 1 and %d".format(programs.length - 1));
exit(-1);
printUsage(args[0], "[day] must be between 1 and %d".format(programs.length - 1));
}
programs[day - 1](args[2..$]);
try {
programs[day - 1](args[2..$]);
} catch(ArgumentException e) {
printUsage(args[0], e.msg);
}
}

View file

@ -3,20 +3,25 @@ import std.array;
import std.conv;
import std.exception;
import std.format;
import std.functional;
import std.range;
import std.stdio;
import dayutil;
immutable string progName = "aoc-2020";
void run(string[] args) {
enforce(args.length == 1, "Please provide a part to run %s 1 [part]".format(progName));
int part = to!int(args[0]);
enforce(part > 0 && part <= 2, "Parts %d to %d supported".format(1, 2));
/* 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 fun = part == 1 ? &part1 : &part2;
writeln(fun(numbers));
int solution = parts!int(args, partial!(part1, numbers), partial!(part2, numbers));
enforce(solution >= 0, "No solutions found");
writeln(solution);
}
int part1(SortedRange!(int[]) numbers) {

29
source/dayutil.d Normal file
View file

@ -0,0 +1,29 @@
import std.conv;
import std.exception;
import std.format;
class ArgumentException : Exception{
mixin basicExceptionCtors;
}
/**
* Helper function for implementing
*
* Looks at the first argument string, and calls the delegate dgs[i + 1], while making sure nothing
goes out bounds.
*
* Params:
* args = Reference to string with arguments, usually from main.
* dgs = list of delegates. Which one will be called depends on args[0]
*/
R parts(R)(ref string[] args, 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]();
}