Resolviendo tres problemas abiertos con un oráculo detenido

23

Tiene las funciones: h1 (f, * args) y h2 (f, * args)

Ambos son métodos que ya están definidos para usted (aquí el asterisco indica un número variable de argumentos)

f es una función, * args es una lista de parámetros que se pasarán a esa función

h1 devuelve un valor booleano: Verdadero si la función f se detiene cuando se invoca * args y Falso si no lo hace (suponiendo que la máquina en ejecución tenga tiempo y memoria infinitos y que el intérprete / compilador para el idioma en el que está escribiendo sabe cómo manejar el tiempo y la memoria infinitos).

Si f (* args) realizara una llamada a h1 o h2, h1 arroja una excepción

h2 se comporta exactamente como h1, excepto que si f hace llamadas a h1, entonces h2 no arrojará una excepción

En la menor cantidad de caracteres posible, escriba un programa que no tenga entrada y que debería mostrar:

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

basado en la validez de cada una de esas conjeturas.

Aquí hay enlaces de Wikipedia que explican cada una de las conjeturas:

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

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

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

Puede suponer que cualquier biblioteca de enteros grandes en cualquier idioma que elija utilizar representará con éxito enteros grandes arbitrarios. En otras palabras, asumiremos que cualquier lenguaje / biblioteca que sea capaz de expresarse 3**(3**10)también es capaz de expresarse 3**(3**(3**10))en una máquina lo suficientemente robusta.

Obviamente, dado que es imposible ejecutar su programa, proporcione una explicación de cómo funciona junto con el código

dspyz
fuente
Esto todavía necesita un criterio de puntuación objetivo. Además, probar que el pseudoprograma funciona puede ser realmente desafiante.
Sr. Llama
Dije menos personajes. Es un problema de codegolf.
dspyz
Ese es un procedimiento de puntuación interesante para este problema. "Resuelve la conjetura del primo gemelo en la menor cantidad de caracteres".
PyRulez
hombre, qué buena pregunta
undergroundmonorail

Respuestas:

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

Elegí usar fy gen lugar de h1y h2, según la recompensa; dos líneas adicionales con 10 caracteres en total antes son suficientes para cambiar: f=:h1, g=:h2.

Y la lógica real:

Collatz

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

((-:`>:@*&3)^:(~:&1))^:_es la carne de eso; Es esencialmente un bucle que lo hace while (x != 1) x = collatz(x). Si llamamos a esa oración reduce:

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

reduce&festá destinado a ser un verbo monádico (ver final), donde reduce&f nes cierto iff se reduce(n)detiene. Los otros bits de bucle-y >:^:()^:_, son esencialmente un bucle infinito ( >:es incremental, ^:se puede usar como un condicional y un iterador) que se rompe al encontrar una reducción de Collatz que no se detiene. Finalmente gse llama para ver si el ciclo infinito termina alguna vez.

Goldbach

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

La misma lógica, en su mayor parte, la diferencia obvia es que el cálculo central es ahora +./@1&p:@(-p:@_1&p:) . -p:@_1&p:calcula la diferencia entre un número y todos los primos menores que ese número, 1&p:es una isPrimefunción y +./es OR lógico. Por lo tanto, si la diferencia entre un número y cualquier primo menor que ese número también es primo, entonces se cumple la conjetura de Goldbach y el ciclo infinito continúa. Nuevamente, fse usa en una prueba final de si dicho bucle infinito es realmente infinito.

Primes gemelos

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

Igual que el anterior, excepto (4&p:)^:(2&~:@(-~4&p:)). 4&p:devuelve el siguiente primo más grande después de un número dado.-~4&p:devuelve la diferencia entre un número y el siguiente primo más grande después de él. 2&~:es != 2. Entonces el bucle más interno es análogo a while (nextPrimeAfter(p) - p != 2) p = nextPrimeAfter(p).

Notas

Puede haber errores sintácticos, ya que no he probado con dummy fyg todavía. Además, asumí eso fy gtomaría algún tipo de forma que se puede componer con un verbo a la izquierda y un sustantivo a la derecha, que no estoy completamente seguro de que se adhiera a la gramática J de ninguna manera. Son funciones inherentemente de orden superior, y estoy demasiado cansado para buscar una construcción adecuada como adverbios / conjunciones / lo que sea que tengas en este momento, incluso si existe una construcción tan apropiada.

Realmente no utilicé la concatenación de cadenas adecuada, y en su lugar opté por dejar cadenas individuales en caja. El resultado (suponiendo que todo lo demás sea correcto) sería, por lo tanto, una tabla de 3 columnas, con la columna izquierda como "The Collatz", etc., la columna central es "Conjetura es" y la columna derecha "Verdadero" / "Falso" .

También estoy bastante seguro de que J no convierte enteros a precisión arbitraria por defecto, y la función de utilidad de número primo crucial p:no tiene un dominio arbitrariamente grande. Por otro lado, dado que J admite un tipo de número de precisión arbitrario estándar, no estoy seguro de cuánto esfuerzo se necesitaría para poner este código a la par.

racionalis
fuente
Entonces, ¿admite precisión arbitraria después de todo? Creo que la prueba principal es fácilmente reparable como la respuesta APL.
jimmy23013
Como ya escribí eso en los criterios de recompensa (para CJam), creo que seguiré las reglas y otorgaré la respuesta de Haskell ... Pero de mi parte.
jimmy23013
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]

porque en Haskell las variables pueden contener no solo valores, sino también cálculos (esto se llama pereza). Me permití h1, h2tomar un solo argumento y devolver el clima o no, su evaluación se detendrá.

código un tanto descuidado:

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 poco de explicación:

cuando allse aplica a una lista infinita, se detendrá si uno de los elementos de la lista es False, debido a la pereza (cortocircuito, para todas las personas que no son de Haskell). usamos esto para calcular la conjetura de collatz y la conjetura de primos gemelos.

!empaqueta este truco junto con la impresión. el resultado es Truecuando ftermina en todos los números 4... (esto no importa para la conjetura de collatz o la conjetura de primos gemelos, porque ya sabemos que son verdaderas para números tan pequeños).

el código para la conjetura de collatz es "The Collatz"!c. imprime "La conjetura de Collatz es" y el resultado, que es el clima, ctermina en todos los números 4...

El código para la conjetura de Goldbach es "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]es una función que n, si es una suma de dos primos, devuelve True, pero de lo contrario se repite indefinidamente. por lo tanto, si se detiene porque cada 4..conjetura de goldbach es cierta.

el código para la conjetura de primos gemelos es "The Twin Primes"! \n->or[p$r+2|r<-[n..],p r]. \n->or[p$r+2|r<-[n..],p r]es una función que dada n, si hay primos gemelos mayores que n, devuelve True, pero de lo contrario se repite indefinidamente. así, si se detiene por cada 4..conjetura de primo gemelo, es verdad.

orgulloso Haskeller
fuente
¿Te importaría publicar también una versión no protegida de esto? (con el espacio adecuado y algunas firmas tipo) No sabía que podía poner todas las barras en una línea como lo hizo para c
dspyz el
¿No debería pasar el probador de primalidad desde [2..n-1]? (de lo contrario, todo está compuesto)
dspyz
oh, también, ¿prueba p para primalidad o compostura?
dspyz
Me gusta la extensión natural de haskell: h1 determina si la evaluación de este thunk se detendrá, o mejor aún, h1 devuelve True para todos los cálculos que no son _ | _ donde devuelve False (a menos que el cálculo use h1 en cuyo caso el resultado en sí es _ | _).
dspyz
@dspyz hmm. eso es bueno. pero eso nos permitiría abusar del hecho de que las excepciones son inferiores, y que h1 arroja excepciones cuando se usa incorrectamente ... Me pregunto qué tan útil sería en realidad.
orgulloso Haskeller
3

Python (965 caracteres)

Ya que mi pregunta es no recibir amor. Estoy publicando mi solución (sin código de golf) 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))

Es bastante simple.

numCollatzSteps (n) dice cuántos pasos toma la secuencia de Collatz para un n particular. Se ejecuta infinitamente si dicha secuencia de Collatz no termina.

findNonHaltingN () cuenta hacia arriba comprobando que numCollatzSteps termina para cada n. findNonHaltingN termina si y solo si existe una n para la cual numCollatzSteps no termina.

Entonces podemos verificar si la conjetura de Collatz es verdadera al verificar que findNonHaltingN () no se detiene

isPrime (n) verifica si un número es primo al ver que ningún número entero positivo de 1 a n-1 lo divide

isSumOf2Primes (n) itera sobre todos los enteros positivos entre 2 y n-2 y comprueba que al menos uno es primo junto con su complemento

findNonSum () cuenta números pares hacia arriba desde 4 hasta que alcanza el primer número que no es una suma de 2 primos y luego lo devuelve. Si no existe tal número, entonces continuará infinitamente.

Podemos verificar si la conjetura de Goldbach es cierta al ver que findNonSum no se detiene.

isSmallTwinPrime (n) devuelve verdadero si y solo si n y n + 2 son primos

nextSmallTwinPrime (n) devuelve el siguiente número> = n para el cual isSmallTwinPrime es verdadero

greatestTwinPrimes () cuenta hacia arriba desde 2 comprobando que nextSmallTwinPrime se detiene para todos los n. Si alguna vez nextSmallTwinPrime no se detiene por algún n, entonces se deduce que los primos gemelos más grandes son n-1 yn + 1 y nos detenemos allí

Entonces podemos verificar la validez de la conjetura de primos gemelos comprobando que el más grandeTwinPrimes nunca se detiene.

dspyz
fuente
3

APL (234)

Obviamente no se ha probado, pero la lógica parece sólida. Todos los comandos de impresión están incluidos, la salida son 104caracteres y la lógica real es 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]

Sin 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
fuente
¿Pero APL admite enteros grandes?
jimmy23013
@ user23013: En teoría, el formato de número de APL es un flotante de precisión arbitraria, por lo que, en teoría, puede almacenar cualquier número. Por supuesto, en la práctica, hay un límite, pero depende de la implementación, y la pregunta dice asumir que puede manejar números de tamaño arbitrario.
marinus
La pregunta dice que solo los enteros grandes pueden ser arbitrariamente grandes.
jimmy23013
@ user23013: solo tiene el tipo de un número
marinus
Los enteros grandes generalmente significan enteros de precisión arbitraria. Como se aclaró en la pregunta, debería poder expresarse 3**(3**10)( 3*3*10en APL), lo que da un ERROR DE DOMINIO en tryapl.org.
jimmy23013