Résoudre trois problèmes ouverts avec un Oracle en arrêt

23

On vous donne les fonctions: h1 (f, * args) et h2 (f, * args)

Les deux sont des méthodes qui sont déjà définies pour vous (ici l'astérisque indique un nombre variable d'arguments)

f est une fonction, * args est une liste de paramètres à passer à cette fonction

h1 renvoie une valeur booléenne: True si la fonction f s'arrête jamais lorsqu'elle est appelée * args et False dans le cas contraire (en supposant que la machine en cours d'exécution dispose de temps et de mémoire infinis et que l'interpréteur / compilateur pour la langue dans laquelle vous écrivez sait gérer le temps et la mémoire infinis).

Si f (* args) appelle un jour h1 ou h2, h1 lève une exception

h2 se comporte exactement comme h1 sauf que si f fait des appels à h1, alors h2 ne lèvera pas d'exception

En aussi peu de caractères que possible, écrivez un programme qui ne prend aucune entrée et devrait sortir:

The Collatz Conjecture is {True/False}
Goldbach's Conjecture is {True/False}
The Twin Primes Conjecture is {True/False}

sur la base de la validité de chacune de ces conjectures.

Voici des liens wikipedia expliquant chacune des conjectures:

http://en.wikipedia.org/wiki/Collatz_conjecture

http://en.wikipedia.org/wiki/Goldbach%27s_conjecture

http://en.wikipedia.org/wiki/Twin_prime

Vous pouvez supposer que n'importe quelle grande bibliothèque d'entiers dans la langue que vous choisissez d'utiliser représentera avec succès de grands entiers arbitraires. En d'autres termes, nous supposerons que tout langage / bibliothèque capable d'exprimer 3**(3**10)est également capable d'exprimer 3**(3**(3**10))sur une machine suffisamment puissante.

De toute évidence, puisqu'il est impossible d'exécuter votre programme, veuillez fournir une explication de son fonctionnement avec le code

dspyz
la source
Cela nécessite encore un critère de notation objectif. De plus, prouver que le pseudo-programme fonctionne peut être très difficile.
M. Llama
J'ai dit le moins de personnages. C'est un problème de codegolf.
dspyz
Il s'agit d'une procédure de notation intéressante pour ce problème. "Résolvez la conjecture principale jumelle avec le moins de caractères."
PyRulez
l'homme, quelle question cool
undergroundmonorail

Réponses:

4

J, 207

(('The Collatz';'Goldbach''s';'The Twin Primes'),.<'Conjecture is'),.((>:^:((((-:`>:@*&3)^:(~:&1))^:_)&f)^:_ g 2)((+&2)^:(+./@1&p:@(-p:@_1&p:))^:_ f 4)(>:^:((4&p:)^:(2&~:&(-~4&p:))&f)^:_ g 3){'True':'False')

J'ai choisi d'utiliser fet gà la place de h1et h2, comme selon la prime; deux lignes supplémentaires de 10 caractères au total suffisent pour commuter: f=:h1, g=:h2.

Et la logique réelle:

Collatz

>:^:((((-:`>:@*&3)^:(~:&1))^:_)&f)^:_ g 2

((-:`>:@*&3)^:(~:&1))^:_en est la viande; c'est essentiellement une boucle qui le fait while (x != 1) x = collatz(x). Si nous appelons cette phrase reduce:

>:^:(reduce&f)^:_ g 2

reduce&fest censé être un verbe monadique (voir fin), où reduce&f nest vrai ssi reduce(n)s'arrête. Les autres bits de boucle y >:^:()^:_, sont essentiellement une boucle infinie ( >:est un incrément, ^:peut être utilisé comme conditionnel et un itérateur) qui se rompt en rencontrant une réduction de Collatz qui ne s'arrête pas. Enfin, le gest appelé pour voir si la boucle infinie se termine jamais.

Goldbach

(+&2)^:(+./@1&p:@(-p:@_1&p:))^:_ f 4

La même logique, pour la plupart, la différence évidente étant le calcul de base est maintenant +./@1&p:@(-p:@_1&p:). -p:@_1&p:calcule la différence entre un nombre et tous les nombres premiers inférieurs à ce nombre, 1&p:est une isPrimefonction et +./est un OU logique. Par conséquent, si la différence entre un nombre et un nombre premier inférieur à ce nombre est également un nombre premier, alors la conjecture de Goldbach est satisfaite et la boucle infinie continue. Encore une fois, fest utilisé dans un test final de savoir si ladite boucle infinie est vraiment infinie.

Twin Primes

>:^:((4&p:)^:(2&~:@(-~4&p:))&f)^:_ g 3

Comme ci-dessus, sauf (4&p:)^:(2&~:@(-~4&p:)). 4&p:renvoie le premier plus grand suivant après un nombre donné. -~4&p:renvoie la différence entre un nombre et le premier plus grand nombre suivant. 2&~:est != 2. La boucle la plus intérieure est donc analogue à while (nextPrimeAfter(p) - p != 2) p = nextPrimeAfter(p).

Remarques

Il peut y avoir des erreurs de syntaxe, puisque je ne l' ai pas testé avec mannequin fet gencore. De plus, j'ai supposé cela fet gje prendrais une sorte de forme qui peut être composée d'un verbe à gauche et d'un nom à droite, ce qui ne correspond pas du tout à la grammaire J. Ce sont des fonctions intrinsèquement supérieures, et je suis trop fatigué pour rechercher une construction appropriée comme adverbes / conjonctions / ce que vous avez en ce moment, s'il existe même une construction appropriée.

Je n'ai pas vraiment utilisé la concaténation de chaînes appropriée, et j'ai plutôt choisi de laisser les chaînes individuelles en boîte. La sortie (en supposant que tout le reste est correct) serait donc un tableau à 3 colonnes, la colonne de gauche étant "The Collatz", etc., la colonne du milieu étant "Conjecture is", et la colonne de droite "True" / "False" .

Je suis également assez sûr que J ne convertit pas les entiers en précision arbitraire par défaut, et la fonction utilitaire cruciale de nombre premier p:n'a pas de domaine arbitrairement grand. D'un autre côté, étant donné que J prend en charge un type de nombre de précision arbitraire standard, je ne sais pas combien d'efforts il faudrait pour obtenir ce code à la hauteur.

rationalis
la source
Alors, prend-il en charge la précision arbitraire après tout? Je pense que le test principal est facilement réparable comme la réponse APL.
jimmy23013
Puisque j'ai déjà écrit cela dans les critères de prime (pour CJam), je pense que je vais suivre les règles et attribuer la réponse Haskell ... Mais +1 de ma part.
jimmy23013 du
7

Haskell, 242

p n=and[rem n r>0|r<-[2..n-1]]
c 1=1
c n|odd n=c$3*n+1|0<1=c$div n 2
s!f=putStr(s++" Conjecture is ")>>print(not$h2$all(h1.f)[4..])
main=do"The Collatz"!c;"Goldbach's"! \n->or[p$n-r|r<-[2..n-2],p r];"The Twin Primes"! \n->or[p$r+2|r<-[n..],p r]

car dans Haskell les variables peuvent contenir non seulement des valeurs, mais des calculs (c'est ce qu'on appelle la paresse) je me laisse faire h1, h2prendre un seul argument et retourner la météo ou non son évaluation s'arrêtera.

code quelque peu non golfé:

h1 = undefined
h2 = undefined

prime n=and[rem n r>0|r<-[2..n-1]]
collatz 1=1
collatz n
    |odd n=collatz (3*n+1)
    |0<1  =collatz (div n 2)

s!f=do
    putStr (s++" Conjecture is ")
    print$not$h2$all(h1.f)[4..]

main=do
    "The Collatz"!c                                         --collatz
    "Goldbach's"! \n->or[prime (n-r)|r<-[2..n-2],prime r]   --goldbach
    "The Twin Primes"! \n->or[prime (r+2)|r<-[n..],prime r] --twin primes

un peu d'explication:

lorsqu'il allest appliqué à une liste infinie, il s'arrêtera si l'un des éléments de la liste est False, en raison de la paresse (court-circuitage, pour tous les non-Haskell là-bas). nous l'utilisons pour calculer la conjecture collatz et la conjecture des nombres premiers jumeaux.

!conditionne cette ruse avec l'impression. le résultat est Truequand se ftermine sur tous les nombres 4... (cela n'a pas d'importance pour la conjecture collatz ou la conjecture des nombres premiers jumeaux, car nous savons déjà qu'ils sont vrais pour de si petits nombres).

le code de la conjecture collatz est "The Collatz"!c. il imprime "The Collatz Conjecture is" et le résultat, qui est la météo, se ctermine sur tous les nombres 4...

le code pour la conjecture de goldbach est "Goldbach's"! \n->or[p$n-r|r<-[2..n-2],p r]. \n->or[p$n-r|r<-[2..],p r,r<n+1]est une fonction qui n, si elle est une somme de deux nombres premiers, renvoie True, mais sinon boucle indéfiniment. ainsi, s'il s'arrête pour chaque 4..conjecture de Goldbach, c'est vrai.

le code de la conjecture des nombres premiers jumeaux est "The Twin Primes"! \n->or[p$r+2|r<-[n..],p r]. \n->or[p$r+2|r<-[n..],p r]est une fonction qui n, si il y a des nombres premiers jumeaux supérieurs à n, retourne True, mais sinon boucle indéfiniment. ainsi, si elle s'arrête pour chaque, 4..la conjecture principale jumelle est vraie.

fier haskeller
la source
Pourriez-vous également publier une version non golfée de cela? (avec un espacement correct et quelques signatures de type) Je ne savais pas que vous pouviez mettre toutes les barres sur une seule ligne comme vous l'avez fait pour c
dspyz
Le testeur de primalité ne devrait-il pas passer de [2..n-1]? (sinon tout est composite)
dspyz
oh, aussi, p teste-t-il la primalité ou la composition?
dspyz
J'aime l'extension naturelle de haskell: h1 détermine si l'évaluation de ce thunk va s'arrêter, ou mieux encore, h1 renvoie True pour tous les calculs qui ne sont pas _ | _ où il renvoie False (sauf si le calcul utilise h1 auquel cas le résultat lui-même est _ | _).
dspyz
@dspyz hmm. c'est bien. mais cela nous permettrait d'abuser du fait que les exceptions sont des fonds, et que h1 lève des exceptions quand il est mal utilisé ... Je me demande à quel point cela serait utile.
fier haskeller
3

Python (965 caractères)

Depuis ma question ne reçoit pas d'amour. Je publie ma solution (sans code) en Python:

def numCollatzSteps(n):
    numSteps=0
    while n>1:
        if n%2==0:
            n//=2
        else:
            n=3*n+1
        numSteps+=1
    return numSteps

def findNonHaltingN():
    for n in count(1):
        if not h1(numCollatzSteps,n):
            return n

print "The Collatz Conjecture is "+str(not h2(findNonHaltingN))

def isPrime(n):
    for i in range(2,n):
        if n%i==0:
            return False
    else:
        return True

def isSumOf2Primes(n):
    for i in range(2,n-2):
        if isPrime(i) and isPrime(n-i):
            return True
    else:
        return False

def findNonSum():
    for i in count(4,2):
        if not isSumOf2Primes(i):
            return i

print "Goldbach's Conjecture is "+str(not h1(findNonSum))

def isSmallTwinPrime(n):
    return isPrime(n) and isPrime(n+2)

def nextSmallTwinPrime(n):
    for i in count(n):
        if isSmallTwinPrime(i):
            return i

def largestTwinPrimes():
    for n in count(2):
        if not h1(nextSmallTwinPrime,n):
            return n-1,n+1

print "The Twin Primes Conjecture is "+str(not h2(largestTwinPrimes))

C'est assez simple.

numCollatzSteps (n) indique combien d'étapes la séquence Collatz pour un n particulier prend. Il s'exécute à l'infini si ladite séquence Collatz ne se termine pas.

findNonHaltingN () compte vers le haut en vérifiant que numCollatzSteps se termine pour chaque n. findNonHaltingN se termine si et seulement s'il existe un n pour lequel numCollatzSteps ne se termine pas.

Nous pouvons donc vérifier si la conjecture de Collatz est vraie en vérifiant que findNonHaltingN () ne s'arrête pas

isPrime (n) vérifie si un nombre est premier en voyant qu'aucun entier positif de 1 à n-1 ne le divise

isSumOf2Primes (n) itère sur tous les entiers positifs entre 2 et n-2 et vérifie qu'au moins un est premier avec son complément

findNonSum () compte les nombres pairs à partir de 4 jusqu'à ce qu'il atteigne le premier nombre qui n'est pas une somme de 2 nombres premiers, puis le renvoie. Si un tel nombre n'existe pas, il continuera indéfiniment.

Nous pouvons vérifier si la conjecture de Goldbach est vraie en voyant que findNonSum ne s'arrête pas.

isSmallTwinPrime (n) renvoie vrai si et seulement si n et n + 2 sont tous deux premiers

nextSmallTwinPrime (n) renvoie le nombre suivant> = n pour lequel isSmallTwinPrime est vrai

Le plus grandTwinPrimes () compte à partir de 2 en vérifiant que nextSmallTwinPrime s'arrête pour tous les n. Si jamais nextSmallTwinPrime ne s'arrête pas pour certains n, alors il s'ensuit que les plus grands nombres premiers jumeaux sont n-1 et n + 1 et nous nous arrêtons là

Ensuite, nous pouvons vérifier la validité de la conjecture des nombres premiers jumeaux en vérifiant que le plus grandTwinPrimes ne s'arrête jamais.

dspyz
la source
3

APL (234)

Ce n'est évidemment pas testé, mais la logique semble solide. Les commandes d'impression sont toutes incluses, la sortie est des 104caractères et la logique réelle l'est 130.

Z←' Conjecture is '∘,¨'True' 'False'
⎕←'The Collatz',Z[1+{~{1=⍵:⍬⋄2|⍵:∇1+3×⍵⋄∇⍵÷2}h1⍵:⍬⋄∇⍵+1}h2 1]
⎕←'Goldbach''s',Z[1+{~⍵∊∘.+⍨N/⍨~N∊∘.×⍨N←1+⍳⍵:⍬⋄∇⍵+2}h1 2]
⎕←'The Twin Primes',Z[1+{~(T←{∧/{2=+/(⌈=⌊)⍵÷⍳⍵}¨N←⍵+1:N⋄∇N})h1⍵:⍬⋄∇T⍵}h2 4 2]

Non golfé:

⍝ Environment assumptions: ⎕IO=1 ⎕ML=1
⍝ I've also assumed h1 and h2 are APL operators
⍝ i.e. x F y = f(x,y); x (F h1) y = h1(F,x,y)

⍝ 'Conjecture is True', 'Conjecture is False'
Z←' Conjecture is '∘,¨'True' 'False'

⍝⍝⍝ Collatz Conjecture
⍝ halts iff 1 is reached from given ⍵
collatzLoop←{
   1=⍵:⍬       ⍝ ⍵=1: halt
   2|⍵:∇1+3×⍵  ⍝ ⍵ uneven: loop with new val
   ∇⍵÷2        ⍝ ⍵ even: loop with new val
}

⍝ halts iff 1 is *not* reached from a value ≥ ⍵ (collatz false)
collatzHalt←{~collatzLoop h1 ⍵:⍬⋄∇⍵+1}

⍝ does it halt?
⎕←'The Collatz',Z[1+ collatzHalt h2 1]


⍝⍝⍝ Goldbach's Conjecture

⍝ Can ⍵ be expressed as a sum of two primes?
sumprimes←{
    N←1+⍳⍵         ⍝ N=[2..⍵+1]
    P←(~N∊N∘.×N)/N ⍝ P=primes up to ⍵+1×⍵+1
    ⍵∊P∘.+P        ⍝ can two P be summed to ⍵?
}

⍝ halts iff Goldbach is false
goldbachHalt←{
    ~sumprimes ⍵:⍬ ⍝ not a sum of primes: halt
    ∇⍵+2           ⍝ try next even number
}

⍝ does it halt?
⎕←'Goldbach''s',Z[1+ goldbachHalt h1 2]

⍝⍝⍝ Twin Primes

⍝ is it a prime?
isPrime←{
   2=+/(⌊=⌈)⍵÷⍳⍵    ⍝ ⍵ is a prime if ⍵ is divisible by exactly two
                   ⍝ numbers in [1..⍵] (i.e. 1 and ⍵)
}

⍝ find next twin
nextTwin←{
   N←⍵+1            ⍝ next possible twin
   ∧/ isPrime¨ N:N  ⍝ return it if twin
   ∇N               ⍝ not a twin, search on
}       

⍝ halts iff no next twin for ⍵
twinPrimeHalt←{
   ~nextTwin h1 ⍵: ⍬  ⍝ if no next twin for ⍵, halt
   ∇nextTwin ⍵        ⍝ otherwise try next twin
}

⍝ does it halt?
⎕←'The Twin Primes',Z[1+ twinPrimeHalt h2 4 2]
marinus
la source
Mais APL prend-il en charge les grands nombres entiers?
jimmy23013
@ user23013: En théorie, le format de nombre d'APL est un flotteur de précision arbitraire, donc, en théorie, il peut stocker n'importe quel nombre. Bien sûr, dans la pratique, il y a une limite, mais elle dépend de l'implémentation, et la question dit de supposer qu'elle peut gérer des nombres de taille arbitraire.
marinus
La question dit que seuls les grands entiers peuvent être arbitrairement grands.
jimmy23013
@ user23013: il n'a qu'un seul type de numéro
marinus
Les grands entiers signifient généralement des entiers de précision arbitraire. Comme précisé dans la question, il devrait être capable d'exprimer 3**(3**10)( 3*3*10en APL), ce qui donne une ERREUR DE DOMAINE dans tryapl.org.
jimmy23013