My problem now is to find the number in form a**b a,b < 100 that its, sum of digits is the largest, and to do so I decided to use arrays! I make two arrays a, and b like so:
a = []
b = []
(1..100).map {|n| a << n}
(1..100).map {|n| b << n}
and I also decided to make a sum_of_digits method:
class Integer
def sum_of_digits
self.to_s.split("").map {|p| p.to_i}.reduce(:+)
end
end
So now I need to construct an array that contains all the combinations of a**b How could I do this? Thanks!
You could use the Array#product method:
a = [1,2,3]
b = [4,5,6]
a.product(b)
# => [[1, 4], [1, 5], [1, 6], [2, 4], ...]
a.product(b).map { |x, y| x ** y }
# => [1, 1, 1, 16, 32, 64, 81, 243, 729]
Then, given your Integer#sum_of_digits definition:
a.product(b).map { |x, y| x ** y }.max_by(&:sum_of_digits)
# => 729
Update: to compute the maximum digital sum of the numbers (a ** b), where a, b are natural numbers less or equal to 100, I'd do like this:
Array(1..100)
.repeated_permutation(2)
.map { |a, b| (a ** b).sum_of_digits }
.max
Skip the arrays and use the repeated_permutation helper on the range to get an enumerator:
(1..100).to_a.repeated_permutation(2)
Calling to_a on the enumerator will get you an array of all permutations. However, you can operate on the enumerator directly to work more efficiently:
(1..100).to_a.repeated_permutation(2).reduce([0]) do |m,(a,b)|
r = (a**b).sum_of_digits
r > m.last ? [[a,b],r] : m
end
=> [[99, 95], 972]
While you can call map and then find max. that will require actually holding all permutation results at once. Calling reduce on the enumerator will only require holding at any given time a single permutation and the result of the prior permutation.
Edit: @PinnyM correctly pointed out that I should have used Array#repeated_permutation rather than Array#permutation, because the latter does not include pairs [i,i]. Rather than making the correction I've fix it slightly differently, in the interest of diversity, by replacing a.permutation(2).to_a with a.permutation(2).to_a + a.zip(a).
a = (1..100).to_a
(a.permutation(2).to_a + a.zip(a)).map {|i,j| (i ** j).sum_of_digits}.max
# => 972
And the winner is:
(a.permutation(2).to_a + a.zip(a)).map \
{|i,j| [i, j, (i ** j).sum_of_digits]}.max_by(&:last)
# => [99, 95, 972] (99**95).sum_of_digits # => 972
If i <= 3, rather than i <= 100, the following steps are performed:
a = (1..3).to_a # => [1,2,3]
b = a.permutation(2) # => #<Enumerator: [1, 2, 3]:permutation(2)>
c = b.to_a # => [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
d = a.zip(a) # => [[1, 1], [2, 2], [3, 3]]
e = c + d # => [[1,2], [1,3], [2,1], [2,3], [3,1], [3,2], [1,1], [2,2], [3,3]]
f = e.map {|i,j| (i ** j).sum_of_digits} # => [1, 1, 2, 8, 3, 9, 1, 4, 9]
f.max # => 9
In Ruby 2.0 you can limit the use of the method sum_of_digits to your current context (e.g., class) by replacing class Integer with refine Integer do. If you think you might want to use that method elsewhere, you could put it in a module and include the module where needed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With