Reputation:
Lets say we need to extract values from range of (0..999_999_999)
. We need the sum of all numbers that returns true for our conditional statement. For example, the ones that have the sequence of "123" digits at the end of their numbers.
What would be the fastest way to get this sum without looping?
Edit: The conditional statement could be any, such as n.to_s.chars.map{|d| d = d.to_i}.inject(:+) % 12345 == 0 where n is the number within the range.
Edit2: Here is the code that I have trouble with:
def find_all(n, k)
arr = []
lower_limit = ("1" + "0" * (k - 1)).to_i
upper_limit = ("9" * k).to_i
while lower_limit <= upper_limit
if lower_limit.to_s.chars == lower_limit.to_s.chars.sort && lower_limit.to_s.chars.map{|v| v = v.to_i}.inject(:+) == n
arr << lower_limit
end
lower_limit += 1
end
arr.empty? ? [] : [arr.size, arr.min, arr.max]
end
where n
is the sum of all digits and k
is the # of digits in number.
My code should run on the server in less than 12000 ms with very huge numbers of k
several times with different (n,k)
. Even though my code works, its algorithm is too slow, looping will not result in success.
Upvotes: 0
Views: 61
Reputation: 110725
The range is
r = 0..10**9-1
r.size
#=> 1_000_000_000 (10**9)
For any given last three digits, this range contains 10**6
numbers ending in those three digits. Suppose those last three digits were 000
. Then the sum of those numbers would be the sum of the numbers in the range 0..10**6-1
multiplied by 10**3
:
s = (10**3) * (0 + 10**6-1)*(10**6)/2
#=> 499999500000000
If the last three digits of each of the 10**6
numbers in this sum were 123
, rather than 000
, 123
would be added to each of those numbers. Therefore, the sum of the numbers ending 123
is
s + 123 * (10**6)
#=> 499999746000000
Upvotes: 2