(function :Array parseLines [file] (for textLine (Util.readLines file) (let [[p1 p2] (textLine.split " -> ") [x1 y1] (map (p1.split ",") Std.parseInt) [x2 y2] (map (p2.split ",") Std.parseInt)] (objectWith x1 y1 x2 y2)))) // An inclusive range whose start may be greater than its end (function :Array inclusiveRange [start end] (let [s (min start end) e (max start end)] (let [r (collect (range s (+ e 1)))] (if (> start end) (reverse r) r)))) (function :Array pointsCoveredBy [:Line line :Bool part2] (cond ((= line.x1 line.x2) (for y (inclusiveRange line.y1 line.y2) [line.x1 y])) ((= line.y1 line.y2) (for x (inclusiveRange line.x1 line.x2) [x line.y1])) // Diagonal lines: (part2 (cast (zipThrow (inclusiveRange line.x1 line.x2) (inclusiveRange line.y1 line.y2)))) (true []))) (function :Map ventsByPos [file :Bool part2] (let [lines (parseLines file) :Map theMap (new Map)] (doFor line lines (doFor point (pointsCoveredBy line part2) (dictInc theMap (Std.string point) 1))) theMap)) (function :Int numHotPositions [file &opt :Bool part2] (let [theMap (ventsByPos file ?part2) two (Int64Helper.fromFloat 2)] (count theMap ->vents #{ vents >= two; }#)))