Object subclass: DoubleLinkedNode [
| value nextNode previousNode |
DoubleLinkedNode class >> new [
<category: 'Instance Creation'>
| o |
o := super new.
o init.
^o.
]
DoubleLinkedNode class >> new: newValue [
| o |
o := self new.
o value: newValue.
^o.
]
init [
value := nil.
nextNode := nil.
previousNode := nil.
]
value [
^value.
]
value: newValue [
value := newValue.
]
nextNode [
^nextNode.
]
nextNode: newValue [
(nextNode == newValue) | (newValue == nil) ifFalse: [
nextNode := newValue.
nextNode previousNode: self.
]
]
previousNode [
^previousNode.
]
previousNode: newValue [
(previousNode == newValue) | (newValue == nil) ifFalse: [
previousNode := newValue.
previousNode nextNode: self.
]
]
printOn: stream [
super printOn: stream.
stream nextPutAll: ' with value: '.
value printOn: stream.
]
]
SequenceableCollection subclass: CircularDoublyLinkedList [
| firstNode size |
CircularDoublyLinkedList class >> new [
<category: 'Instance creation'>
| o |
o := super new.
o init.
^o.
]
init [
firstNode := nil.
]
at: index [
^(self nodeAt: index) value.
]
nodeAt: index [
| currentNode i |
i := 0.
currentNode := firstNode.
[ index > i ] whileTrue: [
currentNode := currentNode nextNode.
i := i + 1.
].
^currentNode.
]
addAtEnd: value [
| node |
node := DoubleLinkedNode new: value.
(firstNode == nil) ifTrue: [
firstNode := node.
node nextNode: node.
] ifFalse: [
firstNode previousNode nextNode: node.
node nextNode: firstNode.
]
]
addAtStart: value [
| node |
node := DoubleLinkedNode new: value.
(firstNode == nil) ifTrue: [
firstNode := node.
node nextNode: node.
] ifFalse: [
firstNode previousNode nextNode: node.
node nextNode: firstNode.
firstNode := node.
]
]
size [
"This is a really poor implementation because it purposefully walks the entire node graph"
| calculatedSize currentNode |
calculatedSize := 1.
currentNode := firstNode nextNode.
[ firstNode == currentNode ] whileFalse: [
currentNode := currentNode nextNode.
calculatedSize := calculatedSize + 1.
].
^ calculatedSize.
]
]
Object subclass: Lock [
| rotationIncrements currentNode dial totalDigits |
Lock class >> new: size [
<category: 'Instance Creation'>
| o |
o := super new.
o init.
o totalDigits: size.
o currentNode: (o dial nodeAt: 0).
^o.
]
init [
rotationIncrements := 0.
currentNode := nil.
dial := CircularDoublyLinkedList new.
]
dial [
^dial.
]
currentNode [
^currentNode.
]
currentNode: value [
<category: 'Private'>
^currentNode := value.
]
rotationIncrements [
^rotationIncrements
]
totalDigits [
^totalDigits.
]
totalDigits: value [
<category: 'Private'>
(totalDigits == 0) ifFalse: [
0 to: (value - 1) do: [ :x |
dial addAtEnd: x.
].
totalDigits := value.
]
]
rotateRight [
currentNode := currentNode nextNode.
rotationIncrements := rotationIncrements + 1.
]
rotateRight: steps [
1 to: steps do: [ :x |
self rotateRight.
]
]
rotateRightUntil: value [
[ currentNode value == value] whileFalse: [
self rotateRight.
]
]
rotateLeft [
currentNode := currentNode previousNode.
rotationIncrements := rotationIncrements + 1.
]
rotateLeft: steps [
1 to: steps do: [ :x |
self rotateLeft.
]
]
rotateLeftUntil: value [
[ currentNode value == value ] whileFalse: [
self rotateLeft.
]
]
resetLock [
self rotateLeft: 2 * totalDigits.
]
]
line := FileStream stdin nextLine.
parts := line subStrings: ' '.
lock := Lock new: ((parts removeAtIndex: 1) asInteger).
clockwise := true.
firstRotation := true.
lock resetLock.
[ parts size == 0 ] whileFalse: [
| next |
next := parts removeFirst asInteger.
clockwise ifTrue: [
clockwise := clockwise not.
lock rotateRightUntil: next.
] ifFalse: [
clockwise := clockwise not.
lock rotateLeftUntil: next.
].
firstRotation ifTrue: [
firstRotation := firstRotation not.
lock rotateRight: (lock dial size).
].
].
lock rotationIncrements printNl.