Legend:
w - work day
w - weekend
wwwwwww
Legend:
w - work day
w - weekend
wwwwwww
there's nothing open about OpenAI
Never heard about it, but seems like it is, indeed. Thank you.
cool 👍
Not sure where I fall into this chart =)
Favorite OS: OpenSuse Tumbleweed
Favorite browser: Librewolf
Favorite Apps: Vim/Neovim (not even close to anything else)
Least cluttered Windows Desktop:
Duck me in the ark tonight
Goated movie. They don't make them like that anymore.
Very fiddly solution with lots of debugging required.
Code
type
Vec2 = tuple[x,y: int]
Box = array[2, Vec2]
Dir = enum
U = "^"
R = ">"
D = "v"
L = "<"
proc convertPart2(grid: seq[string]): seq[string] =
for y in 0..grid.high:
result.add ""
for x in 0..grid[0].high:
result[^1] &= (
if grid[y][x] == 'O': "[]"
elif grid[y][x] == '#': "##"
else: "..")
proc shiftLeft(grid: var seq[string], col: int, range: HSlice[int,int]) =
for i in range.a ..< range.b:
grid[col][i] = grid[col][i+1]
grid[col][range.b] = '.'
proc shiftRight(grid: var seq[string], col: int, range: HSlice[int,int]) =
for i in countDown(range.b, range.a+1):
grid[col][i] = grid[col][i-1]
grid[col][range.a] = '.'
proc box(pos: Vec2, grid: seq[string]): array[2, Vec2] =
if grid[pos.y][pos.x] == '[':
[pos, (pos.x+1, pos.y)]
else:
[(pos.x-1, pos.y), pos]
proc step(grid: var seq[string], bot: var Vec2, dir: Dir) =
var (x, y) = bot
case dir
of U:
while (dec y; grid[y][x] != '#' and grid[y][x] != '.'): discard
if grid[y][x] == '#': return
if grid[bot.y-1][bot.x] == 'O': swap(grid[bot.y-1][bot.x], grid[y][x])
dec bot.y
of R:
while (inc x; grid[y][x] != '#' and grid[y][x] != '.'): discard
if grid[y][x] == '#': return
if grid[bot.y][bot.x+1] == 'O': swap(grid[bot.y][bot.x+1], grid[y][x])
inc bot.x
of L:
while (dec x; grid[y][x] != '#' and grid[y][x] != '.'): discard
if grid[y][x] == '#': return
if grid[bot.y][bot.x-1] == 'O': swap(grid[bot.y][bot.x-1], grid[y][x])
dec bot.x
of D:
while (inc y; grid[y][x] != '#' and grid[y][x] != '.'): discard
if grid[y][x] == '#': return
if grid[bot.y+1][bot.x] == 'O': swap(grid[bot.y+1][bot.x], grid[y][x])
inc bot.y
proc canMoveVert(box: Box, grid: seq[string], boxes: var HashSet[Box], dy: int): bool =
boxes.incl box
var left, right = false
let (lbox, rbox) = (box[0], box[1])
let lbigBox = box((lbox.x, lbox.y+dy), grid)
let rbigBox = box((rbox.x, lbox.y+dy), grid)
if grid[lbox.y+dy][lbox.x] == '#' or
grid[rbox.y+dy][rbox.x] == '#': return false
elif grid[lbox.y+dy][lbox.x] == '.': left = true
else:
left = canMoveVert(box((lbox.x,lbox.y+dy), grid), grid, boxes, dy)
if grid[rbox.y+dy][rbox.x] == '.': right = true
elif lbigBox == rbigBox: right = left
else:
right = canMoveVert(box((rbox.x, rbox.y+dy), grid), grid, boxes, dy)
left and right
proc moveBoxes(grid: var seq[string], boxes: var HashSet[Box], d: Vec2) =
for box in boxes:
grid[box[0].y][box[0].x] = '.'
grid[box[1].y][box[1].x] = '.'
for box in boxes:
grid[box[0].y+d.y][box[0].x+d.x] = '['
grid[box[1].y+d.y][box[1].x+d.x] = ']'
boxes.clear()
proc step2(grid: var seq[string], bot: var Vec2, dir: Dir) =
case dir
of U:
if grid[bot.y-1][bot.x] == '#': return
if grid[bot.y-1][bot.x] == '.': dec bot.y
else:
var boxes: HashSet[Box]
if canMoveVert(box((x:bot.x, y:bot.y-1), grid), grid, boxes, -1):
grid.moveBoxes(boxes, (0, -1))
dec bot.y
of R:
var (x, y) = bot
while (inc x; grid[y][x] != '#' and grid[y][x] != '.'): discard
if grid[y][x] == '#': return
if grid[bot.y][bot.x+1] == '[': grid.shiftRight(bot.y, bot.x+1..x)
inc bot.x
of L:
var (x, y) = bot
while (dec x; grid[y][x] != '#' and grid[y][x] != '.'): discard
if grid[y][x] == '#': return
if grid[bot.y][bot.x-1] == ']': grid.shiftLeft(bot.y, x..bot.x-1)
dec bot.x
of D:
if grid[bot.y+1][bot.x] == '#': return
if grid[bot.y+1][bot.x] == '.': inc bot.y
else:
var boxes: HashSet[Box]
if canMoveVert(box((x:bot.x, y:bot.y+1), grid), grid, boxes, 1):
grid.moveBoxes(boxes, (0, 1))
inc bot.y
proc solve(input: string): AOCSolution[int, int] =
let chunks = input.split("\n\n")
var grid = chunks[0].splitLines()
let movements = chunks[1].splitLines().join().join()
var robot: Vec2
for y in 0..grid.high:
for x in 0..grid[0].high:
if grid[y][x] == '@':
grid[y][x] = '.'
robot = (x,y)
block p1:
var grid = grid
var robot = robot
for m in movements:
let dir = parseEnum[Dir]($m)
step(grid, robot, dir)
for y in 0..grid.high:
for x in 0..grid[0].high:
if grid[y][x] == 'O':
result.part1 += 100 * y + x
block p2:
var grid = grid.convertPart2()
var robot = (robot.x*2, robot.y)
for m in movements:
let dir = parseEnum[Dir]($m)
step2(grid, robot, dir)
#grid.inspect(robot)
for y in 0..grid.high:
for x in 0..grid[0].high:
if grid[y][x] == '[':
result.part2 += 100 * y + x
Part 1: there's no need to simulate each step, final position for each robot is
(position + velocity * iterations) modulo grid
Part 2: I solved it interactively: Maybe I just got lucky, but my input has certain pattern: after 99th iteration every 101st iteration looking very different from other. I printed first couple hundred iterations, noticed a pattern and started looking only at "interesting" grids. It took 7371 iterations (I only had to check 72 manually) to reach an easter egg.
type
Vec2 = tuple[x,y: int]
Robot = object
pos, vel: Vec2
var
GridRows = 101
GridCols = 103
proc examine(robots: seq[Robot]) =
for y in 0..<GridCols:
for x in 0..<GridRows:
let c = robots.countIt(it.pos == (x, y))
stdout.write if c == 0: '.' else: char('0'.ord + c)
stdout.write '\n'
stdout.flushFile()
proc solve(input: string): AOCSolution[int, int] =
var robots: seq[Robot]
for line in input.splitLines():
let parts = line.split({' ',',','='})
robots.add Robot(pos: (parts[1].parseInt,parts[2].parseInt),
vel: (parts[4].parseInt,parts[5].parseInt))
block p1:
var quads: array[4, int]
for robot in robots:
let
newX = (robot.pos.x + robot.vel.x * 100).euclmod GridRows
newY = (robot.pos.y + robot.vel.y * 100).euclmod GridCols
relRow = cmp(newX, GridRows div 2)
relCol = cmp(newY, GridCols div 2)
if relRow == 0 or relCol == 0: continue
inc quads[int(relCol>0)*2 + int(relRow>0)]
result.part1 = quads.foldl(a*b)
block p2:
if GridRows != 101: break p2
var interesting = 99
var interval = 101
var i = 0
while true:
for robot in robots.mitems:
robot.pos.x = (robot.pos.x + robot.vel.x).euclmod GridRows
robot.pos.y = (robot.pos.y + robot.vel.y).euclmod GridCols
inc i
if i == interesting:
robots.examine()
echo "Iteration #", i, "; Do you see an xmas tree?[N/y]"
if stdin.readLine().normalize() == "y":
result.part2 = i
break
interesting += interval
https://youtu.be/DrYRpPxBEaU