mirror of
https://github.com/HenkKalkwater/aoc-2020
synced 2024-11-22 19:15: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 std.getopt;
|
||||||
|
|
||||||
import day1;
|
import day1;
|
||||||
|
import dayutil;
|
||||||
|
|
||||||
immutable string progName = "aoc-2020";
|
immutable string progName = "aoc-2020";
|
||||||
|
|
||||||
|
@ -13,25 +14,38 @@ void function(string[])[] programs = [
|
||||||
&day1.run
|
&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) {
|
void main(string[] args) {
|
||||||
int day;
|
int day;
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
stderr.writeln("USAGE: %s [day]".format(args[0]));
|
printUsage(args[0]);
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
day = to!int(args[1]);
|
day = to!int(args[1]);
|
||||||
} catch (ConvException e) {
|
} catch (ConvException e) {
|
||||||
stderr.writeln("[day] is not an integer");
|
printUsage(args[0], "[day] is not an integer");
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (day <= 0 || day > programs.length) {
|
if (day <= 0 || day > programs.length) {
|
||||||
stderr.writeln("Day must be between 1 and %d".format(programs.length - 1));
|
printUsage(args[0], "[day] must be between 1 and %d".format(programs.length - 1));
|
||||||
exit(-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.conv;
|
||||||
import std.exception;
|
import std.exception;
|
||||||
import std.format;
|
import std.format;
|
||||||
|
import std.functional;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
|
||||||
|
import dayutil;
|
||||||
|
|
||||||
immutable string progName = "aoc-2020";
|
immutable string progName = "aoc-2020";
|
||||||
|
|
||||||
void run(string[] args) {
|
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 numbers = stdin.byLineCopy.map!(a => to!int(a)).array.sort;
|
||||||
|
|
||||||
auto fun = part == 1 ? &part1 : &part2;
|
int solution = parts!int(args, partial!(part1, numbers), partial!(part2, numbers));
|
||||||
writeln(fun(numbers));
|
enforce(solution >= 0, "No solutions found");
|
||||||
|
writeln(solution);
|
||||||
}
|
}
|
||||||
|
|
||||||
int part1(SortedRange!(int[]) numbers) {
|
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