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:
parent
c6f7df0bf3
commit
f6a49daaf9
28
source/app.d
28
source/app.d
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
29
source/dayutil.d
Normal 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]();
|
||||
}
|
Loading…
Reference in a new issue