Compare commits
4 Commits
d8a62d2eb4
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9cc95c447 | ||
|
|
8b7da0b751 | ||
|
|
bbaedda944 | ||
|
|
7fed659932 |
67
day14.chpl
Normal file
67
day14.chpl
Normal file
@@ -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);
|
||||
57
day14a.cr
Normal file
57
day14a.cr
Normal file
@@ -0,0 +1,57 @@
|
||||
require "advent"
|
||||
INPUT = input(2022, 14).lines
|
||||
|
||||
occupied = {} of Tuple(Int32, Int32) => Bool
|
||||
INPUT.each do |line|
|
||||
points = line.split("->").map &.split(",").map(&.to_i32)
|
||||
points.each_cons_pair do |p1,p2|
|
||||
x1, y1 = p1
|
||||
x2, y2 = p2
|
||||
dx = (x2-x1).sign
|
||||
dy = (y2-y1).sign
|
||||
((x2-x1).abs+1).times do |nx|
|
||||
((y2-y1).abs+1).times do |ny|
|
||||
pos = {x1 + nx*dx, y1 + ny*dy}
|
||||
occupied[pos] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
max_height = occupied.max_of do |k,v|
|
||||
x, y = k
|
||||
y
|
||||
end
|
||||
|
||||
puts "Max height: #{max_height}"
|
||||
|
||||
def each_place(pos, &block)
|
||||
x, y = pos
|
||||
yield ({x+1, y+1})
|
||||
yield ({x-1, y+1})
|
||||
yield ({x, y+1})
|
||||
end
|
||||
|
||||
puts occupied
|
||||
|
||||
count = 0
|
||||
overflow = false
|
||||
until overflow
|
||||
pos = {500, 0}
|
||||
moved = false
|
||||
loop do
|
||||
moved = false
|
||||
each_place(pos) do |check|
|
||||
next if occupied[check]?
|
||||
pos = check
|
||||
moved = true
|
||||
end
|
||||
overflow = true if pos[1] > max_height
|
||||
break unless moved
|
||||
break if overflow
|
||||
end
|
||||
occupied[pos] = true
|
||||
count += 1
|
||||
end
|
||||
|
||||
puts count-1
|
||||
54
day14b.cr
Normal file
54
day14b.cr
Normal file
@@ -0,0 +1,54 @@
|
||||
require "advent"
|
||||
INPUT = input(2022, 14).lines
|
||||
|
||||
occupied = {} of Tuple(Int32, Int32) => Bool
|
||||
INPUT.each do |line|
|
||||
points = line.split("->").map &.split(",").map(&.to_i32)
|
||||
points.each_cons_pair do |p1,p2|
|
||||
x1, y1 = p1
|
||||
x2, y2 = p2
|
||||
dx = (x2-x1).sign
|
||||
dy = (y2-y1).sign
|
||||
((x2-x1).abs+1).times do |nx|
|
||||
((y2-y1).abs+1).times do |ny|
|
||||
pos = {x1 + nx*dx, y1 + ny*dy}
|
||||
occupied[pos] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
max_height = occupied.max_of do |k,v|
|
||||
x, y = k
|
||||
y
|
||||
end
|
||||
|
||||
puts "Max height: #{max_height}"
|
||||
|
||||
def each_place(pos, &block)
|
||||
x, y = pos
|
||||
yield ({x+1, y+1})
|
||||
yield ({x-1, y+1})
|
||||
yield ({x, y+1})
|
||||
end
|
||||
|
||||
puts occupied
|
||||
|
||||
count = 0
|
||||
until occupied[{500,0}]?
|
||||
pos = {500, 0}
|
||||
moved = false
|
||||
loop do
|
||||
moved = false
|
||||
each_place(pos) do |check|
|
||||
next if occupied[check]? || check[1] == max_height+2
|
||||
pos = check
|
||||
moved = true
|
||||
end
|
||||
break unless moved
|
||||
end
|
||||
occupied[pos] = true
|
||||
count += 1
|
||||
end
|
||||
|
||||
puts count
|
||||
83
day15.chpl
Normal file
83
day15.chpl
Normal file
@@ -0,0 +1,83 @@
|
||||
use IO, Set, List;
|
||||
|
||||
iter data() {
|
||||
var x1, y1, x2, y2 = 0;
|
||||
while readf("Sensor at x=%i, y=%i: closest beacon is at x=%i, y=%i\n", x1, y1, x2, y2) {
|
||||
yield ((x1, y1), (x2, y2), abs(x1-x2) + abs(y1-y2));
|
||||
}
|
||||
}
|
||||
|
||||
record overlapping {
|
||||
var disjoint: list(range(int));
|
||||
|
||||
proc add(arg: range(int)) {
|
||||
// Don't pollute `disjoint`.
|
||||
if arg.isEmpty() then return;
|
||||
|
||||
var newRng = arg;
|
||||
do {
|
||||
var merged = false;
|
||||
for (rng, i) in zip(disjoint, 0..) {
|
||||
if newRng[rng].isEmpty() then continue;
|
||||
newRng = min(rng.lowBound, newRng.lowBound)..max(rng.highBound, newRng.highBound);
|
||||
disjoint.pop(i);
|
||||
merged = true;
|
||||
break;
|
||||
}
|
||||
} while merged;
|
||||
disjoint.append(newRng);
|
||||
}
|
||||
|
||||
iter these() { for rng in disjoint do yield rng; }
|
||||
proc size { return + [rng in this] rng.size; }
|
||||
proc boundedSize(bound) { return + reduce [rng in this] rng[bound].size; }
|
||||
proc contains(x) { return || reduce [rng in this] rng.contains(x); }
|
||||
}
|
||||
|
||||
enum axis { xAxis = 0, yAxis = 1 };
|
||||
proc ((int, int)).rangeAlong(axs: axis, reach: int, theXOrY: int) {
|
||||
const dim = axs : int;
|
||||
const dist = abs(this[dim]-theXOrY);
|
||||
|
||||
// Too far
|
||||
if dist > reach then return 0..<0;
|
||||
|
||||
// Get the range
|
||||
const remDist = max(0, reach-dist);
|
||||
return (this[1-dim]-remDist)..(this[1-dim]+remDist);
|
||||
}
|
||||
|
||||
|
||||
config const theY = 10;
|
||||
const searchSpace = 0..theY * 2;
|
||||
const input = data();
|
||||
|
||||
// Solve part 1
|
||||
var overlaps: overlapping;
|
||||
var occupied: set((int, int));
|
||||
for (sensor, beacon, reach) in input {
|
||||
occupied.add(sensor);
|
||||
occupied.add(beacon);
|
||||
overlaps.add(sensor.rangeAlong(axis.yAxis, reach, theY));
|
||||
}
|
||||
writeln(overlaps.size - (+ reduce [(x,y) in occupied] if y == theY then 1));
|
||||
|
||||
// Solve part 2
|
||||
forall checkY in searchSpace {
|
||||
var overlaps: overlapping;
|
||||
for (sensor, _, reach) in input {
|
||||
overlaps.add(sensor.rangeAlong(axis.yAxis, reach, checkY));
|
||||
}
|
||||
|
||||
if overlaps.boundedSize(searchSpace) != searchSpace.size {
|
||||
// Found the y-cordinate. Now find the x-coordinate.
|
||||
for checkX in searchSpace {
|
||||
if !overlaps.contains(checkX) {
|
||||
// x-coord isn't in the interval, so we found our answer.
|
||||
writeln("x = ", checkX, ", y = ", checkY, ", frequency = ", checkX * 4000000 + checkY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user