Quantcast
Channel: Adam Cameron's Dev Blog
Viewing all articles
Browse latest Browse all 1333

Weekend quiz: my answer (Ruby version)

$
0
0
G'day:
I'll move on from this topic soon, rest assured. Having come up with a CFML answer for my quiz question ("Weekend quiz: my answer (CFML version)"), I decided to stretch myself (albeit slightly) and work out how to do it in Ruby too.

For the sake of completeness, here it is.


# getSubseries.rb

def getSubseries(series, threshold)
working = []
series.inject [] do |reduction, current|
working.push current
working.shift while working.inject(0, &:+) > threshold

workingIsBetterForLength = working.length > reduction.length
workingIsBetterForTotal = working.length == reduction.length && working.inject(0, &:+)> reduction.inject(0, &:+)

workingIsBetterForLength || workingIsBetterForTotal ? working.clone : reduction
end
end

This is the same logic as the CFML one. Observations:


  • the reduction / folding operation on Ruby is called inject for some reason.
  • this indecipherable mess - working.inject(0, &:+) - is shorthand for this:

    array.inject{|sum,x| sum + x }

    IE: the Ruby equivalent of .sum(). Ruby has no inbuilt method for summing arrays.

    I have no idea what it means (and, lazily, I have not checked yet), or how that works.
  • Of my own code, I like this version the best. It's clearer code IMO.
  • I like how Ruby method calls don't need parentheses, too.
I don't have a testing framework installed for Ruby, so I just did the tests for this by hand. These are the same tests as done for PHP and CFML:

# getSubseriesTest.rb

load "getSubseries.rb"

result = getSubseries [], 0
puts "Should return an array\n" unless result.is_a? Array

result = getSubseries [100], 100
puts "Should return elements if there are any within the threshold\n" unless result == [100]

result = getSubseries [100,100], 500
puts "Should return a multi-element subseries\n" unless result == [100,100]

result = getSubseries [100,100,100,100,100,100], 500
puts "Total of elements should not be greater than threshold\n" unless result.inject(0){|sum,x| sum + x } <= 500

result = getSubseries [600,100,100,100,600,100,100,100,100,600], 500
puts "Should return a subsequent larger subseries\n" unless result == [100,100,100,100]

result = getSubseries [600,100,100,100,600,200,100,100,100,100,100,600], 500
puts "Should return a longer adjacent subseries\n" unless result == [100,100,100,100,100]

result = getSubseries [600,700,800,900], 500
puts "Should work when threshold is less than all items\n" unless result == []

result = getSubseries [600,700,800,900], 1000
puts "Should work when threshold is greater than all items\n" unless result == [900]

result = getSubseries [600,700,800,900], 5000
puts "Should work when threshold is greater than sum of all items\n" unless result == [600,700,800,900]

result = getSubseries [100,50,50,50,50,50,500,100,60,60,60,60,60,500], 500
unless result == [100,60,60,60,60,60] then
puts "Should return subseries with highest tally when there are two equal-length subseries (second subseries is higher)\n"
end

result = getSubseries [100,60,60,60,60,60,500,100,50,50,50,50,50,500], 500
unless result == [100,60,60,60,60,60]
puts "Should return subseries with highest tally when there are two equal-length subseries (first subseries is higher)\n"
end

That's quite nice-looking code too.

Anyway, that's all I have to say on that. I had better crack on with some work.

If you know Ruby and see how I've messed things up, or could have done better: please let me know! I'm definitely a newbie when it comes to Ruby.

--
Adam

Viewing all articles
Browse latest Browse all 1333

Trending Articles