diff --git a/projects/advent-of-code/src/year2020/Solutions.kiss b/projects/advent-of-code/src/year2020/Solutions.kiss index 610268e7..ee86db18 100644 --- a/projects/advent-of-code/src/year2020/Solutions.kiss +++ b/projects/advent-of-code/src/year2020/Solutions.kiss @@ -41,12 +41,7 @@ (assert (= 2 (Toboggan.pathTrees exampleHillTile 0 0 1 2))) (assert (= 289 (Util.countChar "#" (Toboggan.pathString (Util.readLines "src/year2020/inputs/day3-1.txt") 0 0 3 1)))) (assert (= 5522401584 (let [hillTile (Util.readLines "src/year2020/inputs/day3-1.txt")] - (* - (Toboggan.pathTrees hillTile 0 0 1 1) - (Toboggan.pathTrees hillTile 0 0 3 1) - (Toboggan.pathTrees hillTile 0 0 5 1) - (Toboggan.pathTrees hillTile 0 0 7 1) - (Toboggan.pathTrees hillTile 0 0 1 2)))))) + (apply * (for args [[0 0 1 1] [0 0 3 1] [0 0 5 1] [0 0 7 1] [0 0 1 2]] (apply (Toboggan.pathTrees.bind hillTile) args))))))) (defun :kiss.List pairWithSum [sum :kiss.List numbers] // Put the numbers in a map for random access. This gives an O(n) solution diff --git a/src/kiss/Macros.hx b/src/kiss/Macros.hx index edb69b37..3a234bf7 100644 --- a/src/kiss/Macros.hx +++ b/src/kiss/Macros.hx @@ -20,14 +20,6 @@ class Macros { public static function builtins() { var macros:Map = []; - macros["+"] = variadicMacro("Prelude.add"); - - macros["-"] = variadicMacro("Prelude.subtract"); - - macros["*"] = variadicMacro("Prelude.multiply"); - - macros["/"] = variadicMacro("Prelude.divide"); - macros["%"] = (wholeExp:ReaderExp, exps:Array, k) -> { wholeExp.checkNumArgs(2, 2, '(% [divisor] [dividend])'); CallExp(Symbol("Prelude.mod").withPosOf(wholeExp), [exps[1], exps[0]]).withPosOf(wholeExp); @@ -38,6 +30,14 @@ class Macros { CallExp(Symbol("Prelude.pow").withPosOf(wholeExp), [exps[1], exps[0]]).withPosOf(wholeExp); }; + macros["+"] = variadicMacro("Prelude.add"); + + macros["-"] = variadicMacro("Prelude.subtract"); + + macros["*"] = variadicMacro("Prelude.multiply"); + + macros["/"] = variadicMacro("Prelude.divide"); + macros["min"] = variadicMacro("Prelude.min"); macros["max"] = variadicMacro("Prelude.max"); @@ -48,6 +48,46 @@ class Macros { macros["="] = variadicMacro("Prelude.areEqual"); + // the (apply [func] [args]) macro keeps its own list of aliases for the math operators + // that can't just be function aliases because they emulate &rest behavior + var opAliases = [ + "+" => "Prelude.add", + "-" => "Prelude.subtract", + "*" => "Prelude.multiply", + "/" => "Prelude.divide", + ">" => "Prelude.greaterThan", + ">=" => "Prelude.greaterEqual", + "<" => "Prelude.lessThan", + "<=" => "Prelude.lesserEqual", + "=" => "Prelude.areEqual" + ]; + + macros["apply"] = (wholeExp:ReaderExp, exps:Array, k) -> { + wholeExp.checkNumArgs(2, 2, '(apply [func] [argList])'); + + var callOn = switch (exps[0].def) { + case FieldExp(field, exp): + exp; + default: + Symbol("null").withPosOf(wholeExp); + }; + var func = switch (exps[0].def) { + case Symbol(sym) if (opAliases.exists(sym)): + Symbol(opAliases[sym]).withPosOf(wholeExp); + default: + exps[0]; + }; + var args = switch (exps[0].def) { + case Symbol(sym) if (opAliases.exists(sym)): + ListExp([ + CallExp(FieldExp("map", exps[1]).withPosOf(wholeExp), [Symbol("kiss.Operand.fromDynamic").withPosOf(wholeExp)]).withPosOf(wholeExp) + ]).withPosOf(wholeExp); + default: + exps[1]; + }; + CallExp(Symbol("Reflect.callMethod").withPosOf(wholeExp), [callOn, func, args]).withPosOf(wholeExp); + }; + function bodyIf(formName:String, negated:Bool, wholeExp:ReaderExp, args:Array, k) { wholeExp.checkNumArgs(2, null, '($formName [condition] [body...])'); var condition = if (negated) { diff --git a/src/test/cases/BasicTestCase.hx b/src/test/cases/BasicTestCase.hx index 33b9e8f0..8dc5eeca 100644 --- a/src/test/cases/BasicTestCase.hx +++ b/src/test/cases/BasicTestCase.hx @@ -221,4 +221,8 @@ class BasicTestCase extends Test { function testAssert() { _testAssert(); } + + function testApply() { + _testApply(); + } } diff --git a/src/test/cases/BasicTestCase.kiss b/src/test/cases/BasicTestCase.kiss index 02eb0b37..965397eb 100644 --- a/src/test/cases/BasicTestCase.kiss +++ b/src/test/cases/BasicTestCase.kiss @@ -299,4 +299,7 @@ (Assert.equals "Assertion false failed: false should have been true" message))) (assert true) - (assert ![])) \ No newline at end of file + (assert ![])) + +(defun _testApply [] + (Assert.equals 6 (apply + [1 2 3]))) \ No newline at end of file