diff --git a/days/day06.st b/days/day06.st index 904fd03..867499a 100644 --- a/days/day06.st +++ b/days/day06.st @@ -3,56 +3,72 @@ Grid extend [ 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 ] + dir [^dir] guard [^guard] - resetGuard [ guard := origGuard. dir := Posn up. ] + initGuard + [ self allPosnsDo: [ + :pos | + ((self at: pos) = $^) ifTrue: [ + origGuard := pos. + self at: pos put: $.. + self resetGuard. + ^guard. + ]]] + + resetGuard + [ origGuard ifNil: [self initGuard]. + guard := origGuard. + dir := Posn up. ] isSolid: p [ ^(self at: p) = $# ] + isEmpty: p [ ^(self at: p) = $. ] copy [ ^Grid new rows: rows; restore: self state ] stepGuard - [ self guard. - [self isSolid: (guard + dir)] whileTrue: + [ [self isSolid: guard + dir] whileTrue: [ dir := dir rotateCcw. ]. guard := guard + dir. ] - state [^{self guard . self dir}] + state [^{guard . dir}] restore: st [guard := st at: 1. dir := st at: 2] - guardOob [^(self at: self guard) isNil] + guardOob [^(self at: 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]]. + stepToTurn + [ guard := guard copy. + [self isSolid: guard + dir] whileTrue: [dir := dir rotateCcw]. + [self isEmpty: guard] whileTrue: [guard += dir]. + (self isSolid: guard) ifTrue: [guard -= dir] ] + + hasCycleFrom: state + [ | seen st | + seen := Set new. + self restore: state. + [self guardOob] whileFalse: + [self stepToTurn. st := self state. + (seen includes: st) ifTrue: [^true]. + seen add: st]. ^false ] ] AOC input: [ Grid new rows: stdin toLines asArray ]; - part1: [ :grid | | posns | - posns := Set new. - grid walkDo: [posns add: grid guard]. + part1: [ :grid | | posns prev | + posns := Dictionary new. prev := nil. + grid walkDo: [ + posns at: grid guard ifAbsentPut: [prev]. + prev := grid state]. grid visitedPosns: posns. - posns ]; + posns size ]; 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 ]; + grid visitedPosns removeKey: grid guard. + grid visitedPosns associations count: + [ :ass | + grid at: ass key put: $#. + [grid hasCycleFrom: ass value] + ensure: [grid at: ass key put: $.] ] ]; + result: [ :grid :part | part value: grid resetGuard ]; finish. diff --git a/days/day07.st b/days/day07.st new file mode 100644 index 0000000..26d92b9 --- /dev/null +++ b/days/day07.st @@ -0,0 +1,47 @@ +Object subclass: AddOp +[ tryDo: n target: tgt [ ^tgt - n ] ] +Object subclass: MulOp +[ tryDo: n target: tgt + [ (tgt rem: n) = 0 ifFalse: [^nil]. + ^tgt quo: n ] ] +MulOp subclass: CatOp +[ tryDo: n target: tgt + [ | p10 | p10 := 10 raisedTo: ((n + 1) log: 10) ceiling. + ^super tryDo: p10 target: tgt - n ] ] + +Object subclass: Equation [ + | target numbers | + target: n [target:=n] numbers: n [numbers:=n] + + testValue [^target] + + printOn: dst [dst << target << ': ' << numbers] + + canSolveFrom: idx target: tgt with: ops + [ | n | n := numbers at: idx. + idx = 1 ifTrue: [^n = tgt]. + tgt < n ifTrue: [^false]. + ops do: [ + :op | + (op tryDo: n target: tgt) ifNotNil: + [:it|(self canSolveFrom: idx - 1 target: it with: ops) ifTrue: [^true]]]. + ^false ] + canSolveWith: ops [^self canSolveFrom: numbers size target: target with: ops] +] + +Equation class extend [ + parse: line + [ ^(line tokenize: ': ') letArrayInBlock: + [ :target :numbers | + Equation new target: target asNumber; + numbers: ((numbers tokenize: ' ') collect: [:it|it asNumber]) ] ] +] + +AOC input: [ stdin toLines collect: [:line | Equation parse: line] ]; + part1: {MulOp new. AddOp new}; + part2: {CatOp new. MulOp new. AddOp new}; + result: [ :eqns :part | + eqns chain select: [:eqn | eqn canSolveWith: part]; + collect: [:it|it testValue]; + sum ]; + finish. diff --git a/days/utils.st b/days/utils.st index b214eea..b5883d2 100644 --- a/days/utils.st +++ b/days/utils.st @@ -7,7 +7,7 @@ AOC class extend [ part2: p2Block [ savedP2 := p2Block ] result: mapBlock [ mapper := mapBlock ] - output: value part: part [ stdout << 'Part ' << part << ': ' << value; nl. ] + output: value part: part [ stdout << 'Part ' << part << ': ' << value; nl; flush. ] runPart: saved part: part arg: arg [ saved ifNotNil: [ @@ -192,8 +192,14 @@ Object extend [ chain [ ^MessageChain new pipelineValue: self ] ] Object subclass: Posn [ | 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 [ self 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. ] * n [ ^Posn x: x * n y: y * n ] + rotateCw [ ^Posn x: y y: x negated ] rotateCcw [ ^Posn x: y negated y: x ] rotate180 [ ^Posn x: x negated y: y negated ]