Day 16
This commit is contained in:
parent
45b4c6ccca
commit
37df7bfc61
3 changed files with 110 additions and 7 deletions
|
|
@ -4,21 +4,21 @@ Object subclass: Transaction [
|
||||||
updates [^updates]
|
updates [^updates]
|
||||||
|
|
||||||
putAll: o
|
putAll: o
|
||||||
[ o updates keysAndValuesDo: [
|
[ o updates keysAndValuesDo: [:pos :new | self at: pos put: new]]
|
||||||
:pos :new | self at: pos put: new ]]
|
|
||||||
|
|
||||||
movedFrom: pos [ self at: pos put: $. ]
|
movedFrom: pos [ self at: pos put: $. ]
|
||||||
at: pos put: new
|
at: pos put: new
|
||||||
[ | old |
|
[ | old |
|
||||||
old := updates at: pos ifAbsent: [nil].
|
old := updates at: pos ifAbsent: [$.].
|
||||||
(old isNil or: [old = $.]) ifTrue: [^updates at: pos put: new].
|
old = $. ifTrue: [^updates at: pos put: new].
|
||||||
(new = $. or: [old = new]) ifTrue: [^nil].
|
(new = $. or: [old = new]) ifTrue: [^nil].
|
||||||
self error: ('Contradictory transaction %1 <- %2: already %3'
|
self error: ('Contradictory transaction %1 <- %2: already %3'
|
||||||
% {pos . new . old}) ]
|
% {pos . new . old}) ]
|
||||||
|
|
||||||
|
hasMovedFrom: pos [ ^(updates at: pos ifAbsent: [nil]) notNil ]
|
||||||
|
|
||||||
performOn: grid
|
performOn: grid
|
||||||
[ updates keysAndValuesDo: [
|
[ updates keysAndValuesDo: [:pos :new | grid at: pos put: new] ]
|
||||||
:pos :new | grid at: pos put: new ] ]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
Object subclass: Warehouse [
|
Object subclass: Warehouse [
|
||||||
|
|
@ -42,6 +42,7 @@ Object subclass: Warehouse [
|
||||||
|
|
||||||
tryMoveIn: trans from: src by: off
|
tryMoveIn: trans from: src by: off
|
||||||
[ | blk |
|
[ | blk |
|
||||||
|
"(trans hasMovedFrom: src) ifTrue: [^true]. -- just makes it slower"
|
||||||
blk := grid at: src.
|
blk := grid at: src.
|
||||||
blk = $. ifTrue: [^true].
|
blk = $. ifTrue: [^true].
|
||||||
blk = $# ifTrue: [^false].
|
blk = $# ifTrue: [^false].
|
||||||
|
|
|
||||||
103
days/day16.st
Normal file
103
days/day16.st
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
Object subclass: Maze [
|
||||||
|
| grid start end bestScore
|
||||||
|
seen queue |
|
||||||
|
|
||||||
|
rows: r [ grid := Grid new rows: r. self findLandmarks ]
|
||||||
|
|
||||||
|
findLandmarks
|
||||||
|
[ grid allPosnsDo: [
|
||||||
|
:pos | | tile | tile := grid at: pos.
|
||||||
|
(tile = $S or: [tile = $E]) ifTrue: [
|
||||||
|
tile = $S ifTrue: [start := pos]
|
||||||
|
ifFalse: [end := pos].
|
||||||
|
grid at: pos put: $.. ]] ]
|
||||||
|
|
||||||
|
bestPath
|
||||||
|
[ "seen[pos][dir] -> {score . Set(previous-states ...)}"
|
||||||
|
seen := grid collect: [:i | LookupTable new].
|
||||||
|
"queue: score -> {pos . facing}"
|
||||||
|
queue := SortedCollection new.
|
||||||
|
|
||||||
|
self enqueuePos: start dir: Posn right withScore: 0 fromState: nil.
|
||||||
|
self enqueuePos: start dir: Posn up withScore: 1000 fromState: nil.
|
||||||
|
|
||||||
|
[ queue isEmpty ] whileFalse: [
|
||||||
|
| entry state |
|
||||||
|
entry := queue removeFirst.
|
||||||
|
entry value letArrayInBlock: [
|
||||||
|
:pos :dir |
|
||||||
|
self stepPathAt: pos dir: dir score: entry key ]].
|
||||||
|
|
||||||
|
bestScore := FloatD infinity.
|
||||||
|
(seen at: end) do: [:it | bestScore := bestScore min: (it at: 1)].
|
||||||
|
^bestScore ]
|
||||||
|
|
||||||
|
stepPathAt: oldPos dir: dir score: oldScore
|
||||||
|
[ | rots pos nextPos score |
|
||||||
|
rots := { dir rotateCw . dir rotateCcw }.
|
||||||
|
pos := oldPos.
|
||||||
|
score := oldScore.
|
||||||
|
|
||||||
|
[ nextPos := pos + dir.
|
||||||
|
(self isOpen: nextPos) ifFalse: [^nil].
|
||||||
|
score := score + 1.
|
||||||
|
self addPos: nextPos dir: dir withScore: score
|
||||||
|
fromState: { pos . dir }.
|
||||||
|
pos := nextPos.
|
||||||
|
|
||||||
|
rots do: [
|
||||||
|
:rot | | rotPos |
|
||||||
|
rotPos := pos + rot.
|
||||||
|
(self isOpen: rotPos) ifTrue: [
|
||||||
|
self enqueuePos: rotPos dir: rot
|
||||||
|
withScore: score + 1001
|
||||||
|
fromState: { pos . dir }.
|
||||||
|
]]
|
||||||
|
] repeat ]
|
||||||
|
|
||||||
|
addPos: pos dir: dir withScore: score fromState: oldState
|
||||||
|
[ | seenState oldScore cameFrom seenDirState |
|
||||||
|
seenDirState := seen at: pos.
|
||||||
|
seenState := seenDirState at: dir ifAbsent: [
|
||||||
|
seenDirState at: dir put: {FloatD infinity . Set new}
|
||||||
|
].
|
||||||
|
oldScore := seenState at: 1.
|
||||||
|
cameFrom := seenState at: 2.
|
||||||
|
|
||||||
|
score > oldScore ifTrue: [^false].
|
||||||
|
score < oldScore ifTrue: [
|
||||||
|
seenState at: 1 put: score.
|
||||||
|
cameFrom empty ].
|
||||||
|
oldState ifNotNil: [ cameFrom add: oldState ].
|
||||||
|
^score ~= oldScore ]
|
||||||
|
|
||||||
|
enqueuePos: pos dir: dir withScore: score fromState: oldState
|
||||||
|
[ | ok |
|
||||||
|
ok := self addPos: pos dir: dir withScore: score fromState: oldState.
|
||||||
|
ok ifTrue: [queue add: score -> {pos . dir}].
|
||||||
|
^ok ]
|
||||||
|
|
||||||
|
isOpen: pos [ ^(grid at: pos) = $. ]
|
||||||
|
printOn: st [ st << grid ]
|
||||||
|
|
||||||
|
bestPathCount
|
||||||
|
[ | bestPathSet |
|
||||||
|
bestPathSet := Set new.
|
||||||
|
(seen at: end) keysAndValuesDo: [
|
||||||
|
:dir :i | (i at: 1) = bestScore ifTrue: [
|
||||||
|
self traceBackFrom: end dir: dir into: bestPathSet]].
|
||||||
|
^bestPathSet size ]
|
||||||
|
|
||||||
|
traceBackFrom: pos dir: dir into: set
|
||||||
|
[ set add: pos.
|
||||||
|
grid at: pos put: $O.
|
||||||
|
(((seen at: pos) at: dir ifAbsent: [^nil]) at: 2) do: [
|
||||||
|
:nPos :nDir | self traceBackFrom: nPos dir: nDir into: set
|
||||||
|
] asSpreader ]
|
||||||
|
]
|
||||||
|
|
||||||
|
AOC input: [ Maze new rows: stdin toLines asArray ];
|
||||||
|
part1: [ :maze | maze bestPath ];
|
||||||
|
part2: [ :maze | maze bestPathCount ];
|
||||||
|
result: [ :maze :part | part value: maze ];
|
||||||
|
finish.
|
||||||
|
|
@ -212,7 +212,6 @@ Object extend [ chain [ ^MessageChain new pipelineValue: self ] ]
|
||||||
|
|
||||||
Object subclass: Posn [
|
Object subclass: Posn [
|
||||||
| x y | x [^x] y [^y] x: n [x:=n] y: n [y:=n]
|
| x y | x [^x] y [^y] x: n [x:=n] y: n [y:=n]
|
||||||
copy [ ^Posn x: x y: y ]
|
|
||||||
|
|
||||||
+ o [ ^Posn x: x + o x y: y + o y ]
|
+ o [ ^Posn x: x + o x y: y + o y ]
|
||||||
+= o [ self x: x + o x; y: y + o y. ]
|
+= o [ self x: x + o x; y: y + o y. ]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue