Programme d'écriture qui vérifie la conjecture d'Erdős-Straus


15

Programme d'écriture, qui vérifie la conjecture Erdős – Straus .
Programme doit prendre en entrée un entier n( 3 <= n <= 1 000 000) et imprimer triple des nombres entiers satisfaisant l' identité 4/n = 1/x + 1/y + 1/z, 0 < x < y < z.

Le code le plus court gagne.

Quelques exemples:

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

Notez que votre programme peut imprimer d'autres résultats pour ces nombres car il existe plusieurs solutions.


Le programme doit-il générer toutes les solutions possibles ou une seule? Par exemple, il existe 2 possibilités pour n = 5.
izlin

1
Un seul suffit.
Somnium

2
Il est quelque peu trompeur que votre seul cas de test ne soit pas une entrée valide selon la spécification.
Peter Taylor

Je vais le changer, exemple ajouté durron597.
Somnium

J'ai ajouté cet exemple parce que mes recherches suggéraient qu'il était particulièrement difficile à faire. Les plus difficiles sont des nombres premiers qui sont congruents avec le {1, 121, 169, 289, 361, 529}modulo 840.
durron597

Réponses:


12

Rubis, 119106 caractères

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,[]]

Le code utilise des limites minimales pour chaque variable, par exemple n/4<x<3n/4, de manière similaire pour y. Même le dernier exemple renvoie instantané (essayez ici ).

Exemples:

> 12
[4, 13, 156]

> 123
[31, 3814, 14542782]

> 1234
[309, 190654, 36348757062]

> 40881241801
[10220310451, 139272994276206121600, 22828913614743204775214996005450198400]

Solution sympa, cependant les limites sont un peu serrées, car votre programme pour 1 000 000 trouve une meilleure solution (voir mon exemple).
Somnium

1
@ user2992539 Mon code renvoie la première solution lexicographique (250001 <500000).
Howard

7

Mathematica 62

Cette solution à base de vanille fonctionne très bien - la plupart du temps.

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

Exemples et délais (en secondes)

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}}}


Mais cela ne constitue pas une solution complète. Il y a quelques chiffres qu'il ne peut pas résoudre. Par exemple,

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

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


Le bon outil pour le bon travail. +1
William Barbosa

3
@WilliamBarbosa Je dirais que ce FindInstancen'est pas le bon outil car il ne peut garantir un résultat ...
Howard

2
@Howard, je parlais de Mathematica, en fait
William Barbosa

Reducesemble résoudre les cas tenaces, même si cela prend souvent du temps. Par exemple, 15 minutes pour trouver 82 solutions pour n = 10037.
DavidC

3

C #

Disclamer: ce n'est pas une réponse sérieuse

Cela force simplement toutes les possibilités de 1 à 1 << 30. C'est énorme, c'est lent, je ne sais même pas si cela fonctionne correctement, mais il suit les spécifications littéralement, car il vérifie l'état à chaque fois, donc c'est bien. Je n'ai pas testé cela car ideone a un délai de 5 secondes pour les programmes et donc cela ne finira pas de s'exécuter.

(Au cas où quelqu'un se demanderait: c'est un énorme 308 octets de long)

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;
}

Mise à jour: corrigé pour qu'il fonctionne réellement


2
Ne fonctionne pas (indice: division entière).
Howard

Cela ne fonctionnera probablement pas en raison d'erreurs d'arrondi.
Somnium

@ user2992539 cela fonctionne pour moi, je l'ai testé avec 5comme entrée et il a donné le bon résultat ( 2, 4, 20)
Christoph Böhmwalder

@HackerCow cela peut ne pas fonctionner pour les grands nombres entiers.
Somnium

1
@HackerCow, vous pouvez certainement gagner du temps en commençant par y = x + 1 et z = y + 1. Il sera probablement plus rapide d'utiliser la vérification équivalente 4xyz = n (xy + yz + xz), bien que j'accepte que cette expression soit plus longue et ait également des problèmes d'arrondi.
Alchymist

3

Python 2 , 171 octets

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

Essayez-le en ligne!

La première réponse suffisamment rapide pour être testée de manière exhaustive. Cela permet de trouver des solutions pour tous les 3 ≤ n ≤ 1000000 en un total d' environ 24 minutes , pour une moyenne d'environ 1,4 millisecondes chacune.

Comment ça fonctionne

Réécrivez 4 / n = 1 / x + 1 / y + 1 / z comme z = n · x · y / d , où d = 4 · x · y - n · x - n · y . Ensuite, nous pouvons factoriser 4 · d + n 2 = (4 · x - n ) · (4 · y - n ), ce qui nous donne un moyen beaucoup plus rapide de rechercher x et est petit. Étant donné x y tant que d < y < z , on peut au moins prouver d <3 · n 2 /4 (où la borne sur la boucle externe), bien que dans la pratique , il tend à être beaucoup plus petite 95% du temps, on peut utiliser d = 1, 2 ou 3. Le pire des cas est n = 769129, pour lequel le plus petit d est 1754 (ce cas prend environ 1 seconde).


1

Mathematica, 99 octets

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])

C'est une force brute assez naïve, donc ça ne va pas vraiment bien. Je vais certainement atteindre un million (alors n'hésitez pas à considérer cela comme invalide pour le moment). n = 100prend une demi-seconde, mais n = 300prend déjà 12 secondes.


1

Golflua 75

Lit à npartir de l'invite (après invocation dans le terminal), mais essentiellement comme la solution Hobbies de Calvin :

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$

Une version Lua non golfée de ce qui précède est

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

Exemples:

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()

Exemple:

16 --> 10 12 15

Rien de bien spécial.


1
Pourquoi définissez-vous une fonction si vous ne voulez l'appeler qu'une seule fois?
isaacg

@isaacg Il doit s'arrêter d'une manière ou d'une autre, mais son utilisation le exit()raccourcit.
Calvin's Hobbies

0

C # - 134

Eh bien, j'ai posté une réponse ici auparavant, mais ce n'était pas vraiment grave. En l'occurrence, je m'ennuie très souvent, alors je l'ai joué un peu au golf.

Il calcule tous les exemples techniquement correctement (je n'ai pas essayé les deux derniers parce que, encore une fois, ideone impose un délai de 5 secondes) mais les premiers donnent le résultat correct (pas nécessairement le résultat que vous avez calculé, mais un bon). Il affiche étrangement le numéro hors service (je n'ai aucune idée pourquoi) et il donne 10, 5, 2pour 5(ce qui est une réponse valide selon wikipedia).

134 octets pour l'instant, je pourrais probablement le jouer un peu plus.

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 caractères

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

Cela devrait fonctionner, mais je ne l'ai pas encore compilé. C'est certainement très très lent. Il vérifie chaque triplet possible d'entiers valides et doit s'arrêter lorsqu'il voit un ensemble qui fonctionne.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.