Problem 9

Problem 9

A Pythagorean triplet is a set of three natural numbers, a < b < c, for which,
a^(2) + b^(2) = c^(2)

For example, 3^(2) + 4^(2) = 9 + 16 = 25 = 5^(2).

There exists exactly one Pythagorean triplet for which a + b + c = 1000.
Find the product abc.

[code]MAX=1000

1.upto(MAX) do |i|
a = i
a.upto(MAX) do |j|
b = j
c = Math.sqrt(aa + bb)
puts “#{a} #{b} #{c.to_i}” if (a+b+c==1000)
end
end[/code]
=> 200 375 425

Inaczej nie mam pomysłu, chętnie przeczytam bardziej “ruby way” rozwiązanie :slight_smile:

Tomash, mała poprawka ode mnie (nie widzę potrzeby dla zmiennych a i b + szukane jest abc):

[code=ruby]MAX=1000

1.upto(MAX) do |a|
a.upto(MAX) do |b|
c = Math.sqrt(aa + bb)
puts a * b * c.to_i if (a+b+c==1000)
end[/code]
Chociaż nie podoba mi się, że porównujesz liczbę float z fixnum (a+b+c zwróci liczbę float):

irb(main):023:0> 5.00000000000000000000000000000001 == 5 => true
Moja wersja:

code=ruby.each do |a|
(a…1000).each do |b|
next if a + b >= 1000
c = 1000 - a - b
puts a * b * c if a ** 2 + b ** 2 == c ** 2
end
end[/code]

No tak, zapis “product abc” był odrobinę dwuznaczny, więc pograłem bezpiecznie i na pałę wypisałem całą trójkę.

Podoba mi się to:

next if a + b >= 1000

tj. nie wpadłem na to i włączyłem do swojego.

Co do Twojej uwagi: wiem i zrobiłem to specjalnie: pierwiastki liczb całkowitych mają taką postać (tak mało zer po przecinku, if any), że nie ma co bać się błędu przy porównywaniu.

Benchmark obu podejść, tj. co jest szybsze: liczeniem c z pierwiastka czy liczeniem c z różnicy 1000,a,b?

user system total real radarka 0.420000 0.050000 0.470000 ( 0.477962) tomasha 0.500000 0.040000 0.540000 ( 0.535020) radarka2 0.400000 0.070000 0.470000 ( 0.476215) tomasha2 0.470000 0.070000 0.540000 ( 0.546534)
Czyli wygrałeś, lepiej liczyć c = 1000-a-b i sprawdzać kwadrat :slight_smile:

Proponuję teraz trochę odpuścić (mam na myśli Hosiawaka, Radarka i siebie) i dać szansę innym forumowiczom :slight_smile:

Ja tam na wydajność praktycznie nie patrzę. Jest konkretny problem a ja mam go rozwiązać (powiedzmy w “rozsądnym” czasie) :).
Btw:

irb(main):026:0> Math.sqrt(100000000000001) => 10000000.0000001
Lepiej jednak uważać (chociaż działając na liczbach z zadania pewnie nie ma niebezpieczeństwa).

Kluczowa jest chyba informacja, że a<b<c. Co daje nam a<b<(1000-a-b).
A to chyba prowadzi nas do wniosku, że b < 500 - (a/2) oraz (co pewnie też jest ważne), że a < (1000/3).
Te pętelki można zatem jeszcze ograniczyć, nie? :wink:

O to, że druga pętla powinna być od a+1 nie będę już się czepiał :wink:

Troche z innej strony

[codeRuby]def is_pit_tri?(a)
a.sort!
return true if a[0]**2 + a[1]**2 == a[2]**2
return false
end

def oblicz
wynik = 0
1.upto(500) do |a|
1.upto(999 - a) do |b|
c = 1000 - a - b
tab = [a , b , c]
return [abc, a, b, c] if is_pit_tri?(tab)
end
end
return wynik
end

puts oblicz[/code]

1.upto(1000) {|a| a.upto(1000) {|b| p "a=#{a}, b=#{b}, c=#{Math.sqrt(a*a + b*b).to_i}" if a + b + Math.sqrt(a*a + b*b) == 1000}}

a=200, b=375, c=425