Day 15
This commit is contained in:
parent
914f1d590b
commit
296a1c2e4c
2 changed files with 146 additions and 1 deletions
137
days/day15.st
Normal file
137
days/day15.st
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
Object subclass: Transaction [
|
||||
| updates |
|
||||
initialize [ updates := LookupTable new. ]
|
||||
updates [^updates]
|
||||
|
||||
putAll: o
|
||||
[ o updates keysAndValuesDo: [
|
||||
:pos :new | self at: pos put: new ]]
|
||||
|
||||
at: pos put: new
|
||||
[ | old |
|
||||
old := updates at: pos ifAbsent: [nil].
|
||||
(old isNil or: [old = $.]) ifTrue: [^updates at: pos put: new].
|
||||
(new = $. or: [old = new]) ifTrue: [^nil].
|
||||
self error: ('Contradictory transaction %1 <- %2: already %3'
|
||||
% {pos . new . old}) ]
|
||||
|
||||
performOn: grid
|
||||
[ updates keysAndValuesDo: [
|
||||
:pos :new | grid at: pos put: new ] ]
|
||||
]
|
||||
|
||||
Object subclass: Warehouse [
|
||||
| grid insns robot insnMap |
|
||||
|
||||
initialize
|
||||
[ insnMap := LookupTable new.
|
||||
insnMap at: $< put: Posn left;
|
||||
at: $> put: Posn right;
|
||||
at: $v put: Posn down;
|
||||
at: $^ put: Posn up. ]
|
||||
|
||||
grid: g [grid := g. self findRobot]
|
||||
insns: i [insns := i]
|
||||
|
||||
printOn: st [ st << grid. ]
|
||||
|
||||
findRobot
|
||||
[ grid allPosnsDo: [
|
||||
:it | (grid at: it) = $@ ifTrue: [
|
||||
^robot := it. ]].
|
||||
self error: 'No robot' ]
|
||||
|
||||
tryMove: src by: off
|
||||
[ | dst blk |
|
||||
blk := grid at: src.
|
||||
blk = $. ifTrue: [^true].
|
||||
blk = $# ifTrue: [^false].
|
||||
dst := src + off.
|
||||
(self tryMove: dst by: off)
|
||||
ifFalse: [^false]
|
||||
ifTrue: [
|
||||
grid at: src put: $..
|
||||
grid at: dst put: blk.
|
||||
^true ] ]
|
||||
|
||||
tryMoveTrans: src by: off
|
||||
[ | dst blk |
|
||||
blk := grid at: src.
|
||||
blk = $. ifTrue: [^Transaction new].
|
||||
blk = $# ifTrue: [^nil].
|
||||
|
||||
off x = 0 ifTrue: [
|
||||
blk = $[ ifTrue: [^self tryMoveTrans0: src and: src + Posn right by: off].
|
||||
blk = $] ifTrue: [^self tryMoveTrans0: src and: src + Posn left by: off].
|
||||
].
|
||||
^self tryMoveTrans0: src by: off ]
|
||||
|
||||
tryMoveTrans0: src1 and: src2 by: off
|
||||
[ | dst1 dst2 blk1 blk2 |
|
||||
dst1 := src1 + off. dst2 := src2 + off.
|
||||
blk1 := grid at: src1. blk2 := grid at: src2.
|
||||
^(self tryMoveTrans: dst1 by: off) ifNotNil: [
|
||||
:th | (self tryMoveTrans: dst2 by: off) ifNotNil: [
|
||||
:th2 |
|
||||
th putAll: th2.
|
||||
th at: src1 put: $..
|
||||
th at: src2 put: $..
|
||||
th at: dst1 put: blk1.
|
||||
th at: dst2 put: blk2.
|
||||
th ]]]
|
||||
|
||||
tryMoveTrans0: src by: off
|
||||
[ | dst blk |
|
||||
dst := src + off.
|
||||
blk := grid at: src.
|
||||
^(self tryMoveTrans: dst by: off) ifNotNil: [
|
||||
:th |
|
||||
th at: src put: $..
|
||||
th at: dst put: blk.
|
||||
th ]]
|
||||
|
||||
followInsn: insn
|
||||
[ | dir |
|
||||
dir := insnMap at: insn ifAbsent: [^false].
|
||||
(self tryMoveTrans: robot by: dir) ifNotNil: [
|
||||
:th | th performOn: grid. robot := robot + dir] ]
|
||||
|
||||
runInsns [ insns do: [:it | self followInsn: it] ]
|
||||
|
||||
sumGps
|
||||
[ | total | total := 0.
|
||||
grid allPosnsDo: [
|
||||
:it | | tile | tile := grid at: it.
|
||||
(tile = $O or: [tile = $[]) ifTrue: [
|
||||
total := total + it gpsCoord ] ].
|
||||
^total ]
|
||||
|
||||
copyExpand: expand
|
||||
[ ^expand ifFalse: [ ^self copy ]
|
||||
ifTrue: [ ^self copyExpand ] ]
|
||||
|
||||
postCopy [ grid := grid copy ]
|
||||
|
||||
copyExpand
|
||||
[ | expandMap rows |
|
||||
expandMap := LookupTable new.
|
||||
expandMap at: $# put: '##';
|
||||
at: $O put: '[]';
|
||||
at: $@ put: '@.';
|
||||
at: $. put: '..'.
|
||||
rows := grid rows collect: [
|
||||
:row | (row toList collect: [:c | expandMap at: c]) join ].
|
||||
self grid: (Grid new rows: rows) ]
|
||||
]
|
||||
|
||||
Posn extend [
|
||||
gpsCoord [ ^self y * 100 + x - 101 ]
|
||||
]
|
||||
|
||||
AOC input: [ stdin contents splitDoubleNl letArrayInBlock: [
|
||||
:rows :insns |
|
||||
Warehouse new grid: (Grid new rows: rows lines);
|
||||
insns: insns ] ];
|
||||
part1: false; part2: true;
|
||||
result: [ :input :part | (input copyExpand: part) runInsns sumGps ];
|
||||
finish
|
||||
|
|
@ -177,12 +177,18 @@ Stream extend [
|
|||
whileTrue: [ block value: self next ] ]
|
||||
]
|
||||
|
||||
String extend [
|
||||
CharacterArray extend [
|
||||
scanf: fmt [ ^(ReadStream on: self) scanf: fmt ]
|
||||
scanf: fmt with: block [ ^(ReadStream on: self) scanf: fmt with: block ]
|
||||
|
||||
trim [ ^self copyReplacingRegex: '\s*(.*)\s*' asRegex with: [:m | m at: 1] ]
|
||||
trimLines [ ^(self lines collect: [:it | it trim]) join: ' ' ]
|
||||
|
||||
splitWords [ ^self tokenize: ' ' ]
|
||||
splitDoubleNl [ ^self tokenize: String doubleNl ]
|
||||
]
|
||||
CharacterArray class extend [
|
||||
doubleNl [ ^self with: $<10> with: $<10> ]
|
||||
]
|
||||
|
||||
BlockClosure extend [
|
||||
|
|
@ -309,6 +315,8 @@ Object subclass: Grid [
|
|||
:p | block value: p value: (self at: p) ] ]
|
||||
|
||||
printOn: st [ rows do: [ :r | st << r; nl ] ]
|
||||
|
||||
postCopy [ rows := rows collect: [:it | it copy] ]
|
||||
]
|
||||
Grid class extend [
|
||||
width: w height: h initWith: block
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue