Escribir números racionales como razón de factoriales de primos

19

Nota: este desafío ha sido publicado en el sandbox .

Introducción

Este desafío está inspirado en el Putnam B1 2009 , un problema en una competencia de pregrado en matemáticas. El problema es el siguiente:

Demuestre que cada número racional positivo puede escribirse como un cociente de productos de factoriales de primos (no necesariamente distintos). Por ejemplo,

$ \ frac {10} 9 = \ frac {2! \ cdot 5!} {3! \ cdot 3! \ cdot 3!}. $

Desafío

Su desafío es tomar un par de enteros positivos relativamente primos, que representan el numerador y el denominador de un número racional positivo (o solo el número racional en sí) como entrada, y generar dos listas (o matrices, etc.) de números primos para que el número racional ingresado es igual a la razón del producto de los factoriales de los primos en la primera lista al producto de los factoriales de los primos en la segunda lista.

Notas

  • Puede que no haya primos que contengan tanto en la primera lista como en la segunda lista; sin embargo, una prima puede aparecer tantas veces como se desee en cualquiera de las listas.
  • Se puede suponer que las entradas son (no estrictamente) entre 1 y 65535; sin embargo, no se puede suponer que los factores de los números que necesitará generar estarán en este rango.

Ejemplo de entrada y salida

Aquí hay ejemplos de entradas y salidas legales.

input=>output
10,9 => [2,5],[3,3,3]
2,1 => [2],[]
3,1 => [3],[2]
1,5 => [2,3,2],[5]     (elements of a list may be in any order)
3,2 => [3],[2,2]
6,1 => [3],[]

Las entradas (2,2), (0,3), (3,0), (3,6) y (1,65536) son entradas ilegales (es decir, su programa no necesita comportarse de manera particular en ellas ) Aquí hay algunos ejemplos de resultados ilegales:

1,2 => [2],[2,2] (2 is in both returned lists)
5,2 => [5],[2,4] (4 is not prime)
2,1 => [2],[1] (1 is not prime either)
3,2 => [3],[2] (3!/2! = 3, not 3/2)

Puntuación

Este es el , por lo que gana la puntuación más baja en bytes.

Carl Schildkraut
fuente
¿Se necesita dar algún tipo de racionalidad mínimamente reducida en caso de que haya múltiples formas de expresar la respuesta? Por ejemplo 10/9= [2*5]/[3*3]= [(2!/1!) * (5!/4!)] / [(3!/2!) * (3!/2!)]= [2! * 5! * 2! * 2!] / [3! * 3! * 1! * 4!]= (2! * 2! * 2! *5!) / (3! * 3! * 4!).
Trauma digital
@ Digital Trauma No; sin embargo, 4 no es primo, por lo que el segundo no sería válido. Creo (y puedo escribir una prueba en la pregunta si lo desea) que cualquier representación es única.
Carl Schildkraut
¿Está bien tomar la entrada como la fracción en 10/9lugar de un par de números 10y 9?
Misha Lavrov
@MishaLavrov Claro. Editaré la pregunta para reflejar eso.
Carl Schildkraut
@CarlSchildkraut Gracias, sí, eso ayuda. Pensé que me faltaba algo
Digital Trauma el

Respuestas:

5

05AB1E , 54 53 48 46 40 35 33 32 28 bytes

[D¿÷Z#DÓ€gZD<ØŠQ*DˆR!*]¯øεʒĀ

Pruébalo en línea! Editar: Guardado 2 bytes gracias a @ ASCII-only. Guardado 1 2 3 4 bytes gracias a @Emigna. (¡Solo necesito guardar uno más y tengo la mitad de mi recuento de bytes original!) Explicación:

[       Begin an infinite loop
D¿÷     Reduce to lowest terms
Z#      Exit the loop if the (largest) value is 1
DÓ€g    Find the index of the largest prime factor of each value
Z       Take the maximum
D<ØŠ    Convert index back to prime and save for later
Q       Convert to an pair of which value had the largest prime factor
*       Convert to an pair with that prime factor and zero
Dˆ      Save the pair in the global array for later
R!*     Multiply the other input value by the factorial of the prime
]       End of infinite loop
¯ø      Collect all the saved primes
εʒĀ     Forget all the saved 0s
Neil
fuente
Me encantan los guiones "emocionales" -¦D
RedClover
46 bytes
solo ASCII el
39 bytes
Sr. Xcoder
5

Mathematica, 175 177 169 154 108 bytes

Join@@@Table[x[[1]],{s,{1,-1}},{x,r@#},x[[2]]s]&@*(If[#==1,1,{p,e}=Last@(r=FactorInteger)@#;p^e#0[p!^-e#]]&)

Pruébalo en línea!

Cómo funciona

Esta es la composición de dos funciones. El primero, que se deshace de

If[# == 1,
  1,
  {p,e} = Last[FactorInteger[#]];
  p^e * #0[p!^-e * #]
]&

es una función recursiva para calcular realmente la factorización deseada. Específicamente, dada una entrada racional x, calculamos los primos cuyos factoriales deben estar en el numerador y el denominador, y devolvemos la fracción con todos esos primos multiplicados juntos. (Por ejemplo, en la entrada 10/9 = 2!*5!/(3!*3!*3!), volvemos 10/27 = 2*5/(3*3*3)).

Hacemos esto al tratar con el factor primo más grande en cada paso: si p e ocurre en la factorización de x, ¡nos aseguramos de que p! e ocurre en la factorización factorial, y recurse en x dividido por p! e .

(Anteriormente, tenía una estrategia más inteligente que evita los números grandes mirando el número primo anterior antes de p, ¡pero Mathematica puede manejar números tan grandes como 65521! Fácilmente, por lo que no tiene sentido. La versión anterior que puedes encontrar en la historia es mucho más rápido: en mi computadora, tardé 0.05 segundos en las entradas que esta versión maneja en 1.6 segundos).

La segunda función convierte la salida de la primera función en listas de primos.

Join @@@ 
  Table[x[[1]],
    {s,{1,-1}},
    {x,FactorInteger[#]},
    x[[2]]*s
  ]&

Para s=1(potencias positivas) y s=-1(potencias negativas), y para cada término {prime,exponent}en la factorización r@#, repetimos el número primo prime exponent*smuchas veces.

Versión sin competencia con 109 62 bytes

If[#==1,∇1=1,{p,e}=Last@FactorInteger@#;(∇p)^e#0[p!^-e#]]&

Igual que el anterior, pero en lugar de dar salida como una lista, da salida como una expresión, utilizando el operador ∇ (porque no tiene un significado incorporado) como sustituto de los factoriales. Por lo tanto, una entrada de 10/9da una salida de (∇2*∇5)/(∇3)^3representar (2!*5!)/(3!)^3.

Esto es más corto porque omitimos la segunda parte de la función.


+2 bytes: la tarea f=Firstdebe hacerse en el lugar correcto para evitar que Mathematica se enoje.

-8 bytes: se corrigió un error para las salidas enteras, lo que en realidad acortaba el código.

-15 bytes: FactorIntegerdevuelve una salida ordenada, que podemos aprovechar.

-46 bytes: en realidad no necesitamos ser inteligentes.

Misha Lavrov
fuente
2

Python 2, 220 202 195 183 bytes

g=lambda a,b:a and g(b%a,a)or b;n,d=input();m=c=()
while n+d>2:
 t=n*d;f=p=2
 while t>p:
	if t%p:p+=1;f*=p
	else:t/=p
 if n%p:c+=p,;n*=f
 else:m+=p,;d*=f
 t=g(n,d);n/=t;d/=t
print m,c

Pruébalo en línea! Editar: Guardado 18 25 bytes gracias a @ Mr.Xcoder. Guardado 12 bytes gracias a @JonathanFrech.

Neil
fuente
202 bytes
Sr. Xcoder
Puede acortarlo aún más en Python 2, ya que puede reemplazar múltiples espacios con pestañas en la sangría
Sr. Xcoder
189 bytes .
Jonathan Frech
183 bytes .
Jonathan Frech