From bbaedda944e0d3d207c3f8e5bd63c24a7ba24b53 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Tue, 13 Dec 2022 21:58:56 -0800 Subject: [PATCH] Add day 14 solution in Chapel --- day14.chpl | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 day14.chpl diff --git a/day14.chpl b/day14.chpl new file mode 100644 index 0000000..12ccbc3 --- /dev/null +++ b/day14.chpl @@ -0,0 +1,67 @@ +use IO, Set; + +proc parseCoord(s: string) { + const (x, _, y) = s.partition(","); + return (x : int, y : int); +} + +proc (set((int,int))).draw((x1, y1), (x2, y2)) { + for x in (min(x1,x2)..max(x1,x2)) { + for y in (min(y1,y2)..max(y1,y2)) { + this.add((x,y)); + } + } +} + +iter ((int,int)).nextPositions() { + yield this + (0,1); + yield this + (-1,1); + yield this + (1,1); +} + +var occupied = new set((int, int)); +for line in stdin.lines().strip() { + const coords = parseCoord(line.split(" -> ")); + for idx in 0..#(coords.size-1) { + occupied.draw(coords[idx], coords[idx+1]); + } +} + +const maxHeight = max reduce [(x, y) in occupied] y; +const initialPos = (500, 0); +config const hasWall = false; +var grainCount = 0; + +do { + // Start a new grain of sand, but give up if there's already one there. + var pos = initialPos; + if occupied.contains(pos) then break; + + // Make the grain fall + var abyss = false; + do { + var moved = false; + for checkPos in pos.nextPositions() { + // Check for falling past the floor + if checkPos[1] > maxHeight + 10 { + abyss = true; + break; + } + // Try moving, but only if the position is clear and not on the floor. + if !occupied.contains(checkPos) && + !(hasWall && checkPos[1] == maxHeight + 2) { + pos = checkPos; + moved = true; + break; + } + } + } while moved; + + // If we stopped because we fell off, don't count the last grain. + if !abyss { + grainCount += 1; + occupied.add(pos); + } +} while !abyss; + +writeln(grainCount);