@snoozer05 のボウリングスコア集計 Ruby 写経版を Squeak Smalltalk に逆翻訳
@snoozer05 なるほど。Ruby にない PositionableStream の動きは配列とカーソルの組み合わせで再現しましたか。すばらしいですね。
@sumim 12月15日
ということで、Squeak Smalltalk から Ruby への意訳である score1 を Squeak Smalltalk に逆翻訳。
| score1 | score1 := [:pins | | cursor framePoints | cursor := 1. framePoints := OrderedCollection new. 9 timesRepeat: [ framePoints add: (pins copyFrom: cursor to: cursor + 2) asOrderedCollection. cursor := cursor + 2. framePoints last first = 10 ifTrue: [cursor := cursor - 1] ifFalse: [ ((framePoints last first: 2) reduce: #+) ~= 10 ifTrue: [framePoints last removeLast] ] ]. framePoints add: (pins last: pins size - cursor + 1). (framePoints collect: [:points | points reduce: #+]) reduce: #+ ]. score1 value: #(10 10 10 10 10 10 10 10 10 10 10 10). "=> 300 " score1 value: #(10 10 10 10 10 10 10 10 10 3 3). "=> 255 " score1 value: #(0 0 10 8 2 10 10 10 5 3 8 2 10 2 3). "=> 161 " score1 value: #(5 3 7 2 8 2 10 7 1 9 0 6 2 10 6 4 8 0). "=> 126 "
cursor を破壊的な操作で代替。
| score1bis | score1bis := [:pins | | framePoints | pins := pins asOrderedCollection. framePoints := OrderedCollection new. 9 timesRepeat: [ framePoints add: (pins first: 3) asOrderedCollection. framePoints last first = 10 ifTrue: [pins removeFirst: 1] ifFalse: [ pins removeFirst: 2. (framePoints last first: 2) sum ~= 10 ifTrue: [framePoints last removeLast] ] ]. framePoints add: pins. (framePoints collect: #sum) sum ]. score1bis value: #(10 10 10 10 10 10 10 10 10 10 10 10). "=> 300 " score1bis value: #(10 10 10 10 10 10 10 10 10 3 3). "=> 255 " score1bis value: #(0 0 10 8 2 10 10 10 5 3 8 2 10 2 3). "=> 161 " score1bis value: #(5 3 7 2 8 2 10 7 1 9 0 6 2 10 6 4 8 0). "=> 126 "
見通しをよくするために整理。
| score1bis2 | score1bis2 := [:pins | | framePoints | pins := pins asOrderedCollection. framePoints := (1 to: 9) collect: [:idx | pins first = 10 ifTrue: [(pins removeFirst: 1), (pins first: 2)] ifFalse: [pins first + pins second = 10 ifTrue: [(pins removeFirst: 2), (pins first: 1)] ifFalse: [pins removeFirst: 2]]]. framePoints := framePoints, {pins}. (framePoints collect: #sum) sum ]. score1bis2 value: #(10 10 10 10 10 10 10 10 10 10 10 10). "=> 300 " score1bis2 value: #(10 10 10 10 10 10 10 10 10 3 3). "=> 255 " score1bis2 value: #(0 0 10 8 2 10 10 10 5 3 8 2 10 2 3). "=> 161 " score1bis2 value: #(5 3 7 2 8 2 10 7 1 9 0 6 2 10 6 4 8 0). "=> 126 "
参考のため、最後のを Ruby に変換。
def score1bis2(pins) framePoints = (1 .. 9).collect{ | idx | if pins.first == 10 then pins.shift(1) + pins.first(2) elsif pins[0] + pins[1] == 10 pins.shift(2) + pins.first(1) else pins.shift(2) end } framePoints << pins framePoints.collect{ |ea| ea.inject(&:+) }.inject(&:+) end score1bis2 [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10] #=> 300 score1bis2 [10, 10, 10, 10, 10, 10, 10, 10, 10, 3, 3] #=> 255 score1bis2 [0, 0, 10, 8, 2, 10, 10, 10, 5, 3, 8, 2, 10, 2, 3] #=> 161 score1bis2 [5, 3, 7, 2, 8, 2, 10, 7, 1, 9, 0, 6, 2, 10, 6, 4, 8, 0] #=> 126