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