Napisz program weryfikujący hipotezę Erdősa – Strausa


15

Napisz program, który weryfikuje hipotezę Erdősa – Strausa .
Program powinien podjąć jako wejście jedną liczbę całkowitą n( 3 <= n <= 1 000 000) i wydrukować trójki liczb spełniających tożsamości 4/n = 1/x + 1/y + 1/z, 0 < x < y < z.

Najkrótszy kod wygrywa.

Kilka przykładów:

3 => {1, 4, 12}
4 => {2, 3, 6}
5 => {2, 4, 20}
1009 => {253, 85096, 1974822872}
999983 => {249996, 249991750069, 62495875102311369754692}
1000000 => {500000, 750000, 1500000}

Pamiętaj, że twój program może wydrukować inne wyniki dla tych liczb, ponieważ istnieje wiele rozwiązań.


Czy program musi wypisać każde możliwe rozwiązanie, czy tylko jedno? Na przykład istnieją 2 możliwości dla n = 5.
izlin

1
Wystarczy jeden.
Somnium

2
Jest nieco mylące, że twój jedyny przypadek testowy nie jest prawidłowym wejściem zgodnie ze specyfikacją.
Peter Taylor

Zmienię to, dodano przykład durron597.
Somnium

Dodałem ten przykład, ponieważ moje badania sugerowały, że jest to szczególnie trudne. Najtrudniejsze są liczby pierwsze zgodne z {1, 121, 169, 289, 361, 529}
modułem

Odpowiedzi:


12

Ruby, 119 106 znaków

f=->s,c,a{m=s.to_i;c<2?m<s||(p a+[m];exit):(1+m...c*s).map{|k|f[s/(1-s/k),c-1,a+[k]]}}
f[gets.to_r/4,3,[]]

Kod używa minimalnych granic dla każdej zmiennej, np. n/4<x<3n/4Podobnie dla y. Nawet ostatni przykład zwraca natychmiastowy (spróbuj tutaj ).

Przykłady:

> 12
[4, 13, 156]

> 123
[31, 3814, 14542782]

> 1234
[309, 190654, 36348757062]

> 40881241801
[10220310451, 139272994276206121600, 22828913614743204775214996005450198400]

Fajne rozwiązanie, jednak granice są trochę napięte, ponieważ twój program na 1 000 000 znajduje lepsze rozwiązanie (patrz mój przykład).
Somnium

1
@ user2992539 Mój kod zwraca pierwsze leksykograficzne rozwiązanie (250001 <500000).
Howard

7

Mathematica 62

To proste waniliowe rozwiązanie działa dobrze - przez większość czasu.

f@n_ := FindInstance[4/n == 1/x + 1/y + 1/z && 0 < x < y < z, {x, y, z}, Integers]

Przykłady i czasy (w sekundach)

AbsoluteTiming[f[63]]
AbsoluteTiming[f[123]]
AbsoluteTiming[f[1003]]
AbsoluteTiming[f[3003]]
AbsoluteTiming[f[999999]]
AbsoluteTiming[f[1000000]]

{0,313671, {{x -> 16, y -> 1009, z -> 1017072}}}
{0.213965, {{x -> 31, y -> 3814, z -> 14542782}}}
{0.212016, {{x -> 251, y -> 251754, z -> 63379824762}}}
0,431834, {{x -> 751, y -> 2255254, z -> 5086168349262}}}
{1.500332, {{x -> 250000, y - > 249999750052, z -> 1201920673328124750000}}}
{1.126821, {{x -> 375000, y -> 1125000, z -> 2250000}}}


Ale to nie jest kompletne rozwiązanie. Istnieje kilka liczb, których nie można rozwiązać. Na przykład,

AbsoluteTiming[f[30037]]
AbsoluteTiming[f[130037]]

{2.066699, FindInstance [4/30037 == 1 / x + 1 / y + 1 / z && 0 <x <y <z, {x, y, z},
liczby całkowite]} {1.981802, FindInstance [4/130037 = = 1 / x + 1 / y + 1 / z && 0 <x <y <z, {x, y, z}, liczby całkowite]}


Właściwe narzędzie do właściwej pracy. +1
William Barbosa

3
@WilliamBarbosa Twierdzę, że FindInstancenie jest to właściwe narzędzie, ponieważ nie może zagwarantować wyniku ...
Howard

2
@Jak mówiłem o Mathematica, w rzeczywistości
William Barbosa

Reducewydaje się rozwiązywać uparte przypadki, choć często zajmuje to trochę czasu. Np. 15 minut na znalezienie 82 rozwiązań dla n = 10037.
DavidC

3

DO#

Disclamer: to nie jest poważna odpowiedź

To po prostu brutalizuje wszystkie możliwości od 1 do 1 << 30. Jest ogromny, powolny, nawet nie wiem, czy działa poprawnie, ale jest zgodny ze specyfikacjami dosłownie, ponieważ za każdym razem sprawdza stan, więc to miłe. Nie testowałem tego, ponieważ ideone ma 5-sekundowy limit czasowy dla programów i dlatego nie zakończy się to.

(Na wypadek, gdyby ktoś się zastanawiał: jest to aż 308 bajtów )

static double[]f(double n)
{
    for(double x=1;x<1<<30;x++)
    {
        for(double y=1;y<1<<30;y++)
        {
            for(double z=1;z<1<<30;z++)
            {
                if(4/n==1/x+1/y+1/z)
                    return new[]{x,y,z};
            }
        }
    }
    return null;
}

Aktualizacja: naprawiono, aby faktycznie działał


2
Nie działa (wskazówka: dzielenie liczb całkowitych).
Howard

Prawdopodobnie nie zadziała z powodu błędów zaokrąglania.
Somnium

@ user2992539 to działa dla mnie, przetestowałem go 5jako dane wejściowe i dało poprawny wynik ( 2, 4, 20)
Christoph Böhmwalder

@HackerCow może nie działać dla dużych liczb całkowitych.
Somnium

1
@HackerCow możesz z pewnością zaoszczędzić czas, zaczynając od y = x + 1 i z = y + 1. Prawdopodobnie szybsze będzie użycie równoważnika 4xyz = n (xy + yz + xz), chociaż akceptuję to dłuższe wyrażenie i również problemy z zaokrąglaniem.
Alchymist

3

Python 2 , 171 bajtów

from sympy import*
def f(n):
 for d in xrange(1,n*n):
  for p in divisors(4*d+n*n):
   q=(4*d+n*n)/p;x=(n+p)/4;y=(n+q)/4
   if (n+p)%4+(n+q)%4+n*x*y%d<1:return x,y,n*x*y/d

Wypróbuj online!

Pierwsza odpowiedź jest wystarczająco szybka, aby zostać wyczerpująco przetestowana. To jest w stanie znaleźć rozwiązań dla wszystkich 3 ≤ n ≤ 1000000 w ciągu około 24 minut łącznie dla średnio około 1,4 ms każdy.

Jak to działa

Przepisz 4 / n = 1 / x + 1 / y + 1 / z jako z = n · x · y / d , gdzie d = 4 · x · y - n · x - n · y . Następnie można czynnik 4 · d + n 2 = (4 · x - n ) · (4 · r - n ), co daje znacznie szybszy sposób wyszukiwania X i Y , o ile djest mały. Biorąc pod uwagę x < y < oo , można przynajmniej okazać d <3 · n 2 /4 (stąd związana w zewnętrznej pętli), chociaż w praktyce wydaje się być dużo mniejsza, 95% czasu, można użyć d = 1, 2 lub 3. Najgorszy przypadek to n = 769129, dla którego najmniejszy d to 1754 (ten przypadek zajmuje około 1 sekundy).


1

Mathematica, 99 bajtów

f[n_]:=(x=1;(w=While)[1>0,y=1;w[y<=x,z=1;w[z<=y,If[4/n==1/x+1/y+1/z,Return@{x,y,z}];++z];++y];++x])

To dość naiwna brutalna siła, więc nie skaluje się zbyt dobrze. Zdecydowanie dostanę się do miliona (więc na razie uważam to za nieważne). n = 100zajmuje pół sekundy, ale n = 300już trwa 12 sekund.


1

Golflua 75

Odczytuje nz monitu (po wywołaniu w terminalu), ale w zasadzie iteruje jak rozwiązanie Calvina Hobbies :

n=I.r()z=1@1~@y=1,z-1~@x=1,y-1?4*x*y*z==n*(y*z+x*z+x*y)w(n,x,y,z)~$$$z=z+1$

Niegolfowana wersja Lua powyższego jest

n=io.read()
z=1
while 1 do
   for y=1,z-1 do
      for x=1,y-1 do
         if 4*x*y*z==n*(y*z+x*z+x*y) then
            print(n,x,y,z)
            return
         end
      end
   end
   z=z+1
end

Przykłady:

n=6     -->     3      4     12
n=12    -->     6     10     15
n=100   -->    60     75    100
n=1600  -->  1176   1200   1225

1

Python, 117

n=input();r=range;z=0
while 1:
 z+=1
 for y in r(z):
  for x in r(y):
    if 4*x*y*z==n*(y*z+x*z+x*y):print x,y,z;exit()

Przykład:

16 --> 10 12 15

Nic specjalnego.


1
Dlaczego definiujesz funkcję, jeśli chcesz wywołać ją tylko raz?
isaacg

@isaacg Musi jakoś się zatrzymać, ale użycie exit()zamiast tego go skraca.
Calvin's Hobbies

0

C # - 134

Cóż, zamieściłem tu wcześniej odpowiedź, ale nie była tak poważna. Tak się składa, że ​​bardzo często się nudzę, więc trochę grałem w golfa.

Oblicza wszystkie przykłady technicznie poprawnie (nie próbowałem dwóch ostatnich, ponieważ ponownie ideone osiąga 5-sekundowy limit czasowy), ale pierwsze z nich dają poprawny wynik (niekoniecznie wynik obliczony, ale poprawny). Dziwnie wyprowadza liczbę poza kolejnością (nie mam pojęcia, dlaczego) i daje 10, 5, 2za 5(co jest prawidłową odpowiedzią według wikipedii).

Na razie 134 bajty, prawdopodobnie mógłbym zagrać w golfa jeszcze trochę.

float[]f(float n){float x=1,y,z;for(;x<1<<30;x++)for(y=1;y<x;y++)for(z=1;z<y;z++)if(4/n==1/x+1/y+1/z)return new[]{x,y,z};return null;}

0

Haskell - 150 znaków

main = getLine >>= \n -> (return $ head $ [(x,y,z) | x <- [1..y], y <- [1..z], z <- [1..], (4/n') == (1/x) + (1/y) + (1/z)]) where n' = read n

To powinno zadziałać, ale jeszcze go nie skompilowałem. Jest prawie na pewno bardzo, bardzo wolny. Sprawdza każdą możliwą triolę prawidłowych liczb całkowitych i powinien zatrzymać się, gdy zobaczy zestaw, który działa.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.