Scrivere numeri razionali come rapporto tra fattoriali di numeri primi


19

Nota: questa sfida è stata pubblicata sulla sandbox .

introduzione

Questa sfida è ispirata a Putnam B1 del 2009 , un problema in una competizione di matematica universitaria. Il problema è il seguente:

Mostra che ogni numero razionale positivo può essere scritto come un quoziente di prodotti di fattoriali di numeri primi (non necessariamente distinti). Per esempio,

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

Sfida

La tua sfida è quella di prendere una coppia di numeri interi relativamente primi positivi, che rappresentano il numeratore e il denominatore di un numero razionale positivo (o solo il numero razionale stesso) come input e produrre due elenchi (o array, ecc.) Di numeri primi in modo che il numero razionale immesso è uguale al rapporto tra il prodotto dei fattoriali dei numeri primi nella prima lista e il prodotto dei fattoriali dei numeri primi nella seconda lista.

Appunti

  • Non ci possono essere numeri primi che contenessero sia nel primo elenco che nel secondo elenco; tuttavia, un numero primo può apparire quante volte si desidera in entrambi gli elenchi.
  • Si può presumere che gli ingressi siano (non rigorosamente) tra 1 e 65535; tuttavia, non si può presumere che i fattoriali dei numeri che sarà necessario produrre siano compresi in questo intervallo.

Esempio di input e output

Ecco alcuni esempi di input e output legali.

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

Gli input (2,2), (0,3), (3,0), (3,6) e (1.65536) sono input illegali (cioè il tuo programma non deve comportarsi in alcun modo su di essi ). Ecco alcuni esempi di output illegali:

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)

punteggio

Questo è , quindi vince il punteggio più basso in byte!


È necessario fornire una sorta di razionale minimamente ridotta nel caso in cui vi siano molteplici modi per esprimere la risposta? Ad esempio 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 digitale

@DigitalTrauma No; tuttavia, 4 non è un numero primo, quindi il secondo non sarebbe valido. Credo (e posso scrivere una prova nella domanda se vuoi) che ogni rappresentazione è unica.
Carl Schildkraut,

Va bene prendere input come la frazione 10/9piuttosto che una coppia di numeri 10e 9?
Misha Lavrov,

@MishaLavrov Certo. Modificherò la domanda per riflettere ciò.
Carl Schildkraut,

@CarlSchildkraut Grazie - sì, aiuta - pensavo mi mancasse qualcosa
Digital Trauma,

Risposte:


5

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

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

Provalo online! Modifica: salvato 2 byte grazie solo a @ ASCII. Salvato 1 2 3 4 byte grazie a @Emigna. (Ho solo bisogno di salvarne un altro e sono fino alla metà del mio conteggio byte originale!) Spiegazione:

[       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

Adoro gli script "emotivi" -¦D
RedClover,



5

Mathematica, 175 177 169 154 108 byte

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

Provalo online!

Come funziona

Questa è la composizione di due funzioni. Il primo, che ungolfs a

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

è una funzione ricorsiva per calcolare effettivamente la fattorizzazione desiderata. In particolare, dato un input razionale x, calcoliamo i numeri primi i cui fattoriali dovrebbero essere nel numeratore e denominatore e restituiamo la frazione con tutti quei numeri primi moltiplicati insieme. (Ad esempio, sull'input 10/9 = 2!*5!/(3!*3!*3!), torniamo 10/27 = 2*5/(3*3*3).)

Facciamo questo trattare con il più grande fattore primo ad ogni passo: se p e si verifica nella fattorizzazione di x, ci assicuriamo p! si verifica nella fattorizzazione fattoriale e si basa su x diviso per p! e .

(In precedenza, avevo una strategia più intelligente che evita grandi numeri guardando il numero primo precedente prima di p, ma Mathematica può gestire numeri grandi come 65521! Facilmente, quindi non ha senso. La vecchia versione che puoi trovare nella storia è molto più veloce: sul mio computer, ci sono voluti 0,05 secondi sugli input che questa versione gestisce in 1,6 secondi.)

La seconda funzione trasforma l'output della prima funzione in elenchi di numeri primi.

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

Per s=1(poteri positivi) e s=-1(poteri negativi), e per ogni termine {prime,exponent}della fattorizzazione r@#, ripetiamo il numero primo prime exponent*smolte volte.

Versione non competitiva con 109 62 byte

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

Come sopra, ma invece di fornire l'output come elenco, fornisce l'output come espressione, usando l'operatore ∇ (perché non ha un significato incorporato) come sostituto dei fattoriali. Pertanto, un input di 10/9fornisce un output di (∇2*∇5)/(∇3)^3da rappresentare (2!*5!)/(3!)^3.

Questo è più breve perché saltiamo la seconda parte della funzione.


+2 byte: l'assegnazione f=Firstdeve essere eseguita nel posto giusto per evitare che Mathematica si arrabbi.

-8 byte: risolto un bug per gli output interi, che in realtà rendeva il codice più breve.

-15 byte: FactorIntegerrestituisce un output ordinato, di cui possiamo trarre vantaggio.

-46 byte: in realtà non abbiamo bisogno di essere intelligenti.


2

Python 2, 220 202 195 183 byte

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

Provalo online! Modifica: salvato 18 25 byte grazie a @ Mr.Xcoder. Risparmiato 12 byte grazie a @JonathanFrech.



Puoi accorciarlo ancora di più in Python 2, poiché puoi sostituire più spazi con le schede nella rientranza
Mr. Xcoder


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.