From 4902daebaf10e19d103d06c5481dcdf8c1dea4dc Mon Sep 17 00:00:00 2001 From: Henk Kalkwater Date: Thu, 10 Dec 2020 09:37:13 +0100 Subject: [PATCH] Improve framework --- source/app.d | 159 +++++++++++++++++++++++++++++++++----------------- source/day1.d | 3 +- source/day3.d | 2 +- 3 files changed, 110 insertions(+), 54 deletions(-) diff --git a/source/app.d b/source/app.d index 0222835..252b291 100644 --- a/source/app.d +++ b/source/app.d @@ -3,8 +3,9 @@ import core.stdc.stdlib; import std.conv; import std.exception; import std.format; -import std.stdio; import std.getopt; +import std.range; +import std.stdio; import std.variant; import day1; @@ -20,6 +21,10 @@ import dayutil; immutable string progName = "aoc-2020"; +version(Unix) { + extern(C) int isatty(int); +} + Variant function(int, File, bool, string[])[] programs = [ &day1.run, &day2.run, @@ -32,68 +37,118 @@ Variant function(int, File, bool, string[])[] programs = [ &day9.run, ]; -void printUsage(string name) { - printUsage(name, null); -} - -void printUsage(string name, string message) { - stderr.writeln("USAGE: %s [DAY] [PART] ".format(name)); - stderr.writeln(" DAY = int between 1 and 25 (inclusive), specifiying the day to run"); - stderr.writeln(" PART = int between 1 and 2 (inclusive), specifiying the part to run"); - stderr.writeln(" INPUT_FILE = file to read from. '-' or missing implies stdin"); +void printUsage(string message = null) { + import core.runtime; + string name = Runtime.args[0]; + stderr.writeln("USAGE: %s [OPTIONS...] DAY PART [INPUT_FILE] (to run a specific day)".format(name)); + stderr.writeln(" OR: %s [OPTIONS...] all (to run each day)".format(name)); + stderr.writeln(); + stderr.writeln(" DAY = int between 1 and 25 (inclusive), specifiying the day to run"); + stderr.writeln(" PART = int between 1 and 2 (inclusive), specifiying the part to run"); + stderr.writeln(" INPUT_FILE = file to read from. '-' for stdin. If not specified, use in/[DAY].txt"); + stderr.writeln(); + stderr.writeln("OPTIONS:"); + stderr.writeln(" --bigboy, -B = use bigboy challenges"); + stderr.writeln(" --benchmark, -b = record time it took to execute "); if (message != null) { + stderr.writeln(); stderr.writeln(message); } exit(-1); } +File getDefaultFile(int day, bool bigboy) { + if (bigboy) { + return File("in/bigboy/%d.txt".format(day), "rb"); + } else { + return File("in/%d.txt".format(day), "rb"); + } +} + void main(string[] args) { bool bigboy = false; - int day; - getopt(args, - "bigboy", "Execute the so-named 'biboy' variant of this exercise", &bigboy); - if (args.length < 3) { - printUsage(args[0]); - } - try { - day = to!int(args[1]); - } catch (ConvException e) { - printUsage(args[0], "[day] is not an integer"); - } + bool benchmark = false; - if (day <= 0 || day > programs.length) { - printUsage(args[0], "[day] must be between 1 and %d".format(programs.length)); - } - - int part; try { - part = to!int(args[2]); - } catch (ConvException e) { - printUsage(args[0], "[part] is not an integer"); - } - - File file; - try { - if (args.length < 4) { - if (bigboy) { - file = File("in/bigboy/%d.txt".format(day), "rb"); - } else { - file = File("in/%d.txt".format(day), "rb"); - } - } else if(args[3] == "-") { - file = stdin; - } else { - file = File(args[3], "rb"); + auto opts = getopt(args, + "bigboy|B", &bigboy, + "benchmark|b", &benchmark); + if (opts.helpWanted) { + printUsage(); } - } catch (ErrnoException e) { - printUsage(args[0], "Error %d while opening input file: %s".format(e.errno, e.message)); + } catch (GetOptException e) { + printUsage(e.msg); + } + if (args.length < 2) { + printUsage(); } - - try { - Variant result = programs[day - 1](part, file, bigboy, args[3..$]); - writeln(result); - } catch(ArgumentException e) { - printUsage(args[0], e.msg); - } + bool runAll = false; + if (args[1] == "all") { + /+version(Posix) { + bool tty = cast(bool) isatty(stdout.fileNo); + } else {+/ + bool tty = false; + //} + runAll = true; + writeln(tty); + writeln("STATUS\tDAY\tPART\tRESULT"); + foreach (dayNo, day; programs.enumerate(1)) { + File file = getDefaultFile(dayNo, bigboy); + foreach(part; 1..3) { + if (tty) { + write("RUNNING\t%d\t%d\t...\r".format(dayNo, part)); + stdout.flush(); + } + Variant result = day(part, file, bigboy, []); + writeln("DONE \t%d\t%d\t%s ".format(dayNo, part, std.conv.to!string(result))); + file.rewind(); + } + } + } else { + if (args.length < 3) { + printUsage(); + } + + int day; + try { + day = to!int(args[1]); + } catch (ConvException e) { + printUsage("DAY is not an integer"); + } + + if (day <= 0 || day > programs.length) { + printUsage("DAY must be between 1 and %d".format(programs.length)); + } + + int part; + try { + part = to!int(args[2]); + } catch (ConvException e) { + printUsage("PART is not an integer"); + } + + File file; + try { + if (args.length < 4) { + file = getDefaultFile(day, bigboy); + } else if(args[3] == "-") { + file = stdin; + } else { + file = File(args[3], "rb"); + } + } catch (ErrnoException e) { + printUsage("Error %d while opening input file: %s".format(e.errno, e.message)); + + } + try { + Variant result = programs[day - 1](part, file, bigboy, args[3..$]); + writeln(result); + } catch(ArgumentException e) { + printUsage(e.msg); + } catch(Exception e) { + stderr.writeln("Fatal error occurred: " ~ e.msg); + exit(-1); + } + } } diff --git a/source/day1.d b/source/day1.d index 6466e82..cdc3d53 100644 --- a/source/day1.d +++ b/source/day1.d @@ -19,7 +19,8 @@ Variant run(int part, File input, bool bigboy, string[] args) { 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 = input.byLineCopy.map!(a => to!int(a)).array.sort; - int target = bigboy ? 99920044 : 2020; + int target = 2020; + if(bigboy) target = 2020; Variant solution = parts!int(part, () => part1(numbers, target), diff --git a/source/day3.d b/source/day3.d index 2184b20..0b2b454 100644 --- a/source/day3.d +++ b/source/day3.d @@ -10,7 +10,7 @@ import std.variant; import dayutil; Variant run(int part, File input, bool bigboy, string[] args) { - auto inputData = stdin.byLineCopy.array; + auto inputData = input.byLineCopy.array; Variant count = parts!size_t(part, () => inputData.countTrees1, () => [[1,1], [3,1], [5,1], [7,1], [1,2]]