Robot Has No Heart

Xavier Shay blogs here

A robot that does not have a heart

Let's go bowling

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class BowlingScorer
  def score(balls, frames = 10)
    return frames == 0 ? 0 : score_function(balls[0], balls[1]).call(balls) + score(balls, frames - 1)
  end
  
protected
  Component       = Struct.new(:condition, :number_to_score, :number_to_shift)
  ConditionIsTrue = lambda {|x| x[0].call }
  
  def score_function(s1, s2)
    p = Component.new *[
      [ lambda { s1 == 10},      3, 1], # Strike
      [ lambda { s1 + s2 == 10}, 3, 2], # Spare
      [ lambda { true },         2, 2]  # Default
    ].find(&ConditionIsTrue)
    return join_return_first(score_frame(p.number_to_score), multi_shift(p.number_to_shift))
  end
  
  def score_frame(n)
    lambda {|balls| n ? balls[0..n-1].inject(0) {|a, g| a + g } : 0 }
  end
  
  def multi_shift(count)
    lambda {|x| count.times { x.shift } }
  end
end

scorer = BowlingScorer.new
scorer.score([10] * 11) # => 300
scorer.score([5] * 21)  # => 150

Full source and tests – bowling_scorer.rb

EDIT: Refactored BowlingScorer#score_function

Eating with functions

1
2
3
4
5
6
7
8
9
# 3 Tasty treats, all the same!
edibles.each do |edible|
  edible.eat! if likes?(edible) || edible.is_healthy?
end

condition = lambda {|edible| likes?(edible) || edible.is_healthy?}
edibles.select(&condition).each(&:eat!)

edibles.select(disjoin(&method(:likes?), &:is_healthy?)).each(&:eat!)

Help: &:eat!, disjoin

A pretty flower Another pretty flower