58 lines
1.7 KiB
Smalltalk
58 lines
1.7 KiB
Smalltalk
Grid extend [
|
|
| guard dir origGuard visitedPosns |
|
|
|
|
visitedPosns: n [visitedPosns:=n]
|
|
visitedPosns [^visitedPosns]
|
|
dir [^dir]
|
|
guard
|
|
[ guard ifNotNil: [:it|^it] ifNil:
|
|
[ self allPosnsDo:
|
|
[ :pos |
|
|
(self at: pos) = $^ ifTrue: [
|
|
origGuard := pos.
|
|
self at: pos put: $..
|
|
self resetGuard.
|
|
^guard.
|
|
]]].
|
|
^nil ]
|
|
|
|
resetGuard [ guard := origGuard. dir := Posn up. ]
|
|
|
|
isSolid: p [ ^(self at: p) = $# ]
|
|
|
|
copy [ ^Grid new rows: rows; restore: self state ]
|
|
|
|
stepGuard
|
|
[ self guard.
|
|
[self isSolid: (guard + dir)] whileTrue:
|
|
[ dir := dir rotateCcw. ].
|
|
guard := guard + dir. ]
|
|
|
|
state [^{self guard . self dir}]
|
|
restore: st [guard := st at: 1. dir := st at: 2]
|
|
|
|
guardOob [^(self at: self guard) isNil]
|
|
|
|
walkDo: block
|
|
[ [self guardOob] whileFalse: [block value. self stepGuard] ]
|
|
|
|
hasCycle
|
|
[ | fast | fast := self resetGuard copy.
|
|
[fast guardOob] whileFalse:
|
|
[self stepGuard. fast stepGuard stepGuard.
|
|
self state = fast state ifTrue: [^true]].
|
|
^false ]
|
|
]
|
|
|
|
AOC input: [ Grid new rows: stdin toLines asArray ];
|
|
part1: [ :grid | | posns |
|
|
posns := Set new.
|
|
grid walkDo: [posns add: grid guard].
|
|
grid visitedPosns: posns.
|
|
posns ];
|
|
part2: [ :grid | | i | i := 1.
|
|
grid visitedPosns select:
|
|
[ :p | grid at: p put: $#. i printNl. i := i + 1.
|
|
[grid hasCycle] ensure: [grid at: p put: $.] ] ];
|
|
result: [ :grid :part | (part value: grid resetGuard) size ];
|
|
finish.
|