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.