patternrubyMinor
Solution to Max Range Sum challenge on CodeEval
Viewed 0 times
codeevalchallengerangemaxsumsolution
Problem
The challenge in CodeEval is to take a number of days and iterate over the gains and losses and determine which lengths will yield the highest possible profit. I'm wondering if I could write this any better? It seems like sort of clunky code to me.
file = ARGV[0]
File.open(file).each do |line|
duration, days = line.chomp.split(";")
days = days.split(" ").map! { |num| num = num.to_i }
duration = duration.to_i - 1
profit = 0
max_profit = 0
days[0..(days.length - duration)].each_with_index do |day, index|
days[index..(index + duration)].inject(0) do |change, total|
profit = change + total
end
max_profit = profit if profit > max_profit
end
puts max_profit
endSolution
Just for clarity, I'd split the code into a couple of methods. One to parse input, and one to find the best yield.
To tackle the latter first: Have a look at
Given an array of gains/losses (values) and the length to examine (days), you can find the "best streak" like so:
In English: Take each consecutive "streak" of
There are two other things to handle, to solve the task: Return zero if the best gain is actually a loss, or if there are not enough values to satisfy
In all, you might do something like:
As for parsing the input, your current code is ok, though I'd still handle it separately.
This basically just splits the line in to its parts, treating the first number as the number of days, and the rest as the values.
To put it all together, you can do something like:
However, it seem that in the CodeEval context, input is passed on STDIN; not in a file. So really it should probably be:
There may be a more efficient way to do all this, but this is probably the most readable.
To tackle the latter first: Have a look at
Enumerable#each_cons, and Enumerable#reduce (aka inject).Given an array of gains/losses (values) and the length to examine (days), you can find the "best streak" like so:
values.each_cons(days).map { |streak| streak.reduce(&:+) }.maxIn English: Take each consecutive "streak" of
days values; map each of these streaks to its sum; take the maximum of these sums. As an example:days = 3
values = [1, 2, -1, 3, 4]
streaks = values.each_cons(days).to_a # => [ [1, 2, -1], [2, -1, 3], [-1, 3, 4] ]
sums = streaks.map { |streak| streak.reduce(&:+) } # => [2, 4, 6]
max = sums.max # => 6There are two other things to handle, to solve the task: Return zero if the best gain is actually a loss, or if there are not enough values to satisfy
days.In all, you might do something like:
def best_streak(days, values)
return 0 if values.count 0 ? gain : 0
endAs for parsing the input, your current code is ok, though I'd still handle it separately.
def parse_line(line)
days, *values = line.strip.split(/[;\s]/)
[days.to_i, values.map(&:to_i)]
endThis basically just splits the line in to its parts, treating the first number as the number of days, and the rest as the values.
To put it all together, you can do something like:
File.open(ARGV[0]).each do |line|
days, values = parse_line(line)
puts best_streak(days, values)
endHowever, it seem that in the CodeEval context, input is passed on STDIN; not in a file. So really it should probably be:
STDIN.each_line do |line|
days, values = parse_line(line)
puts best_streak(days, values)
endThere may be a more efficient way to do all this, but this is probably the most readable.
Code Snippets
values.each_cons(days).map { |streak| streak.reduce(&:+) }.maxdays = 3
values = [1, 2, -1, 3, 4]
streaks = values.each_cons(days).to_a # => [ [1, 2, -1], [2, -1, 3], [-1, 3, 4] ]
sums = streaks.map { |streak| streak.reduce(&:+) } # => [2, 4, 6]
max = sums.max # => 6def best_streak(days, values)
return 0 if values.count < days
gain = values.each_cons(days).map { |streak| streak.reduce(&:+) }.max
gain > 0 ? gain : 0
enddef parse_line(line)
days, *values = line.strip.split(/[;\s]/)
[days.to_i, values.map(&:to_i)]
endFile.open(ARGV[0]).each do |line|
days, values = parse_line(line)
puts best_streak(days, values)
endContext
StackExchange Code Review Q#83434, answer score: 3
Revisions (0)
No revisions yet.