Need a 40 LOC (ignoring comments) to be shorter -- suggestions wanted

Hi All,

My middle-school granddaughter posed the following challenge to me:

Within 10 minutes, Use the digits 3 to 7 in any order
to form a three-digit multiplicand and a two-digit multiplier
such that their product is minimal.

Out of curiosity as to whether my guess was right,
and with a view toward eliciting an interest in her
for Ruby programming, I wrote the program posted at
http://www.pastie.org/266447

The program reveals that I was wrong, but it took me about 40 lines of
code,
ignoring comments. That would probably overwhelm her. I was hoping
that
the code could be condensed with Ruby-isms. BTW, I left some put’s in
there
intended to give her a sense of the programs functionality.

Any ideas/suggestions?

Thanks in Advance,
Richard

From: RichardOnRails

My middle-school granddaughter posed the following challenge to me:

cool daughter. me, only sons, very terrible when they fight each other
:))

Within 10 minutes, Use the digits 3 to 7 in any order

to form a three-digit multiplicand and a two-digit multiplier

such that their product is minimal.

Out of curiosity as to whether my guess was right,

and with a view toward eliciting an interest in her

for Ruby programming, I wrote the program posted at

http://www.pastie.org/266447

The program reveals that I was wrong, but it took me about 40 lines of

code, ignoring comments. That would probably overwhelm her.

I was hoping that the code could be condensed with Ruby-isms.

BTW, I left some put’s in there

intended to give her a sense of the programs functionality.

my try,

botp@botp-desktop:~$ cat test.rb

digits = [3,4,5,6,7]
min_product=1/0.0
min_multiplicand = 0
min_multiplier = 0

digits.permutation(3).each do |multiplicand_digits|
h,t,ones = multiplicand_digits
multiplicand = h100 + t10 + ones

(digits-multiplicand_digits).permutation(2).each do
|multiplier_digits|
t,ones = multiplier_digits
multiplier = t*10 + ones
prod = multiplicand * multiplier
if prod < min_product
min_product = prod
min_multiplicand = multiplicand
min_multiplier = multiplier
end
end

end
puts “#{min_multiplicand} * #{min_multiplier} = #{min_product}”

botp@botp-desktop:~$ ruby test.rb
467 * 35 = 16345

is that ok?
kind regards -botp

On Sep 4, 9:40 pm, RichardOnRails
[email protected] wrote:

for Ruby programming, I wrote the program posted athttp://www.pastie.org/266447

The program reveals that I was wrong, but it took me about 40 lines of
code,
ignoring comments. That would probably overwhelm her. I was hoping
that
the code could be condensed with Ruby-isms. BTW, I left some put’s in
there
intended to give her a sense of the programs functionality.

Any ideas/suggestions?

Here’s one solution that requires the ‘permutation’ gem:

====

require ‘rubygems’
require ‘permutation’

perm = Permutation.for((3…7).to_a)

min_product = 10**5
min_values = nil

perm.map do |p|
a = p.project
v1 = a[0, 3].to_s.to_i
v2 = a[3, 2].to_s.to_i
product = v1 * v2
if product < min_product
min_product = product
min_values = [v1, v2]
end
end

puts “#{min_values.first} * #{min_values.last} = #{min_product}”

====

Eric

====

Are you interested in on-site Ruby or Ruby on Rails training
that uses well-designed, real-world, hands-on exercises?
http://LearnRuby.co

I believe it can easily be seen that a number of form xy or abc where
xy and abc are not ordered in ascending order
cannot yield a solution hence:

ruby -e ‘p (3…7).map{|x|([*3…7]-[x]).map{|y| three=[*3…7]-[x,y];
two=[x,y]; [three.join.to_s.to_i * two.join.to_s.to_i, three,
two]}}.sort.first.sort.first’
[16345, [4, 6, 7], [3, 5]]

HTH
Robert


C’est véritablement utile puisque c’est joli.

Antoine de Saint Exupéry

2008/9/5 RichardOnRails [email protected]:

for Ruby programming, I wrote the program posted at
Any ideas/suggestions?

Here is a simple and stupid solution.

a = [3,4,5,6,7]
d = {}
(a[0,3].to_s.to_i … a.reverse[0,3].to_s.to_i).each{|i|
(a[0,2].to_s.to_i … a.reverse[0,2].to_s.to_i).each{|j|
d[[i,j]]=i*j if a.to_s==((i.to_s+j.to_s).split(//).sort.to_s)
}
}
p d.sort{|a,b| a[1]<=>b[1]}[0]

Regards,

Park H.

On Sep 5, 1:34 am, “Eric I.” [email protected] wrote:

to form a three-digit multiplicand and a two-digit multiplier
the code could be condensed with Ruby-isms. BTW, I left some put’s in
require ‘permutation’
product = v1 * v2
Eric

====

Are you interested in on-site Ruby or Ruby on Rails training
that uses well-designed, real-world, hands-on exercises?http://LearnRuby.co

Thanks, Eric,

I should have thought of looking for that. I certainly know I was
analyzing 5! permutations.

My granddaughter is much more likely to delve into that a little
ways. I doesn’t look so intimidating :slight_smile:

Best wishes,
Richard

On Sep 5, 7:34 am, “Eric I.” [email protected] wrote:

On Sep 4, 9:40 pm, RichardOnRails

Any ideas/suggestions?

Here’s one solution that requires the ‘permutation’ gem:

Ruby 1.8.7 and 1.9 has Array#permutation:

(3…7).to_a.permutation.sort_by { |a| a[0…2].to_s.to_i *
a[3…4].to_s.to_i }.first

Golf anyone? :slight_smile:

Lars

On Fri, Sep 5, 2008 at 9:29 AM, Lars C. [email protected]
wrote:

Golf anyone? :slight_smile:
(i) A trivial trick is to replace (3…7).to_a with [*3…7]
(ii) sort_by( &blk ).first can be replaced with min_by( &blk )

R

C’est véritablement utile puisque c’est joli.

Antoine de Saint Exupéry

On Sep 4, 11:40 pm, RichardOnRails
[email protected] wrote:

for Ruby programming, I wrote the program posted athttp://www.pastie.org/266447

Thanks in Advance,
Richard

min = 1_000_000
answer = nil
“34567”.upto(“76543”){|s|
next if s !~ /^[3-7]+$/
next if s.split(“”).uniq.size < 5
m1,m2 = s[0,3].to_i, s[3,2].to_i
if m1 * m2 < min
min = m1 * m2
answer = m1, m2
end
}
p answer

p (“34567”…“76543”).select{|s|
s =~ /^[3-7]+$/ and s.split(“”).uniq.size == 5 }.
sort_by{|s| s[0,3].to_i * s[3,2].to_i }.first

On Fri, Sep 5, 2008 at 2:26 AM, Robert D. [email protected]
wrote:

I believe it can easily be seen that a number of form xy or abc where
xy and abc are not ordered in ascending order
cannot yield a solution hence:

Building on that observation:

#!/usr/bin/env ruby

digits = [3, 4, 5, 6, 7]

digits.sort!

multiplier = “#{digits.shift}”
multiplicand = “#{digits.shift}”

multiplier << “#{digits.shift}”
multiplicand << “#{digits.shift}”

multiplicand << “#{digits.shift}”

product = multiplicand.to_i * multiplier.to_i

puts “#{multiplicand} * #{multiplier} = #{product}”

=> 467 * 35 = 16345

On Sep 5, 3:30 am, Lars C. [email protected] wrote:

a[3…4].to_s.to_i }.first

Golf anyone? :slight_smile:

Lars

Hi Lars,

If this were the Olympics for succinct Ruby, you’d get the Gold!!
Thanks for this expression.

Ruby 1.8.7 and 1.9 has Array#permutation:

I’m running ruby 1.8.6, so of course “(3…7).to_a.permutation” failed

My work-around (which produced a correct result) is:

a=[]; Permutation.new(5).each { |p| a << ((p.value.to_s.to_i +
3333).to_s)
=> 34567, 34576, 34657, 34675, 34756, 34765, 35467, [snip]
a.sort_by { |a| (a[0…2].to_s.to_i )*(a[3…4].to_s.to_i) }.first
=> 46735

Note that I compensated for the (3…7) … construct not working by
adding 33333 to each permutation.
Also, I had to fix one blemish: parentheses were needed around the
multiplicative factors; a radix diagnostic was issued without them…
Maybe it’s another 1.8.6 problem

Again, thanks for this neat construct. I’m going to introduce to my
granddaughter as a first step of a programmed solution to the problem
she presented. But then, I’ll admit it takes a Ruby pro to achieve
that level of brevity. I’ll follow that with my more mundane approach
and see whether she’ll hang in there until achieving a glimmer of
insight into Ruby programming.

If you have any more enlightenment on these issues, I’d be pleased to
receive them.

Best wishes,
Richard

Is using a computer a requirement?

The simplest method to me seems (building on what Robert D. wrote) is
to
recognize that you want the lowest possible numbers for both the
multiplier
and multiplicand, so you only need to test these 4 pairs of numbers:

356 x 47
367 x 46
456 x 37
467 x 35

Of course, trying to write a computer program to solve it is more
challenging.

Randy K.

“I didn’t have time to write a short letter, so I created a video
instead.”–with apologies to Cicero, et.al.