Partizionamento reciproco


21

Dato un numero n> 77 , scrivi un programma o una funzione che trova un insieme di interi positivi distinti in modo tale che la somma dell'insieme sia uguale a n , e la somma dei reciproci dell'insieme sia uguale a 1.

Esempio per 80:

80 = 2 + 4 + 10 + 15 + 21 + 28 ⟶ 1/2 + 1/4 + 1/10 + 1/15 + 1/21 + 1/28 = 1

Il tuo programma o funzione deve (teoricamente) funzionare per qualsiasi n <2 32 e non è scusato per errori di arrotondamento in virgola mobile. Si noti che esistono soluzioni per tutti n> 77 .


Vince il codice più breve in byte.

C'è un incentivo bonus: assegnerò un premio alla soluzione più piccola che funziona per qualsiasi registro n e run (n) . Per i piccoli n deve essere veloce (determinato a mia discrezione). Sì, questo è possibile.


3
Tale decomposizione è sempre garantita per esistere? Qualche teorema teorico dei numeri che lo assicura?
Luis Mendo,

Sembra che ci sia per tutti n> 77. (Non ho controllato ogni dettaglio.) Questo avrebbe dovuto essere nella descrizione della tua sfida ...
flawr

1
@flawr, presumo che non abbia incluso quel riferimento perché dà via l' O(log n)algoritmo.
Peter Taylor,

1
Tuttavia avrebbe dovuto menzionare che questo set esiste per il dato n. (E ho trovato quel documento sulla prima pagina quando
ho cercato su Google

1
@flawr, mi ci sono voluti circa 10 minuti per trovarlo. Ci sono arrivato tramite una pagina sulle frazioni egiziane e mi hai fatto ninja di 10 secondi.
Peter Taylor,

Risposte:


3

Mathematica, 54 byte

Select[IntegerPartitions@#,Unequal@@#&&Tr[1/#]==1&,1]&

Circa inefficiente come si arriva, ma si risolve n = 78in circa 9 secondi.

Il risultato viene restituito come un elenco racchiuso in un elenco singleton, ad esempio:

{{45, 12, 9, 5, 4, 3}}

Mi chiedo se funziona per n molto grandi.
njpipeorgan,

@njpipeorgan Data sufficiente memoria e tempo, sì.
Martin Ender,

Ho trovato una stima della lunghezza di IntegerPartition [n], che è all'ordine di exp (sqrt (n)), ~ 10 ^ 10 ^ 4.5 per n = 2 ^ 30. Non credo davvero che la matematica (o anche qualsiasi architettura) sia in grado di contenere l'array.
njpipeorgan,

@njpipeorgan La sfida afferma esplicitamente che l'algoritmo deve funzionare fino a 2 ^ 32 teoricamente , non praticamente (come si presume normalmente per il golf del codice, a meno che la sfida non richieda esplicitamente che il programma finisca effettivamente per tutti gli input in un ragionevole lasso di tempo e memoria ).
Martin Ender,

4

Python 3, 7306 1995 byte

Questa soluzione funziona in complessità log (n) (per quanto ne so).

def i(s,t):
 for n in s[::-1]:t=t.replace(*n)
 return [[]]*78+[list(bytearray.fromhex(a))for a in t.split(",")]
def f(n):
 g,h=lambda c,n:c+[[[2],[3,7,78,91]][n[len(c)]%2]+[i*2for i in c[-1]]],lambda n:[]if n<78 else h((n-[2,179][n%2])//2)+[n]
 v=h(n);c=[i([['g',',03040'],['h',',,0306080'],['i',',020'],['j','b0c1'],['k','21'],['l','60'],['m','30'],['n','141'],['o','k24'],['p',',g'],['q','618'],['r','0c0'],['s','1e'],['t',',0ml'],['u','283c'],['v','e0f1'],['w','2a38'],['x','80'],['y','a0'],['z','01'],['A','50'],['B','24'],['C','i40'],['D','plb1'],['E','gl'],['F','48'],['G','bre1'],['H','28'],['I','6k'],['J','416s'],['K',',040Al'],['L','90'],['M','2a'],['N','54'],['O','k6o'],['P','3c'],['Q','il'],['R','18'],['S','px'],['T','im'],['U','70'],['V','b1'],['W','23'],['X','pj'],['Y','hj'],['Z','0n']],'020lxycHTaRHCyf1517CyfneC91k51cCLdneQU912MCyf0dBiALyf2dClfPEyfneT9s2dELdneEjIgmLydHg5rd14BKLardsE3n8sQ9rd1517Q9rdneplmdRBgUmcRMC5sPEyf102bgA6sPE91z2miAj41IQmc0dRBQUen7spl31z82bT9RFT3wE7neMgmyf0dRBgUmaHMELc1b36EUdBMQLyfs2d,C710M2bgLardRHT3BFQ9rf0dPQ7rdBMQm9Rs2d,0mAl9100d142bE710M2bQmc0fRPtxarfn8sEc1k4sBTfnePExcwtxarf1k8BExcuT3kkT91663C51964,0mAl71k4BMELe12NTcRwQjOT820ltmarf1z8mExeRNCqBFtmyjIHKLa100ds2bQU91bM36garf1k4sBTcRBFgxarfwE91keB2dtUxcn8sME9nbs36gm9rduC5R78,0mAUyf0d14BME91kbB36QLc12AB2dgyjqkHEUeMNT9157eQU9RMFT8s78C8neuixLc1zk4AtUxc1z8Mmt8re0fn8sWhLyc1bH36pl8neu,Kxycsw,iAxc1420l,K8ren8NS9n81bs36hc0vz8WmYzqkmhyv2WBHhyVOHXkJoSjIwSjIuSvz4WASVZIAXZ6skmSj6oFXzOmplvcsW46D61csk46plv8WBFDqoF,tarvk8WBH,tyjkqoHhGqkN,tmvZ8sWmhVZqskmpc0vZ8WAXZqkAplbnImASbn6skwSbn6skuSVOwSVOupGONSbn6soFpyVkJk5aSj6sk78YJkuDkIP5aYOuhvzk4WBAhVzk416oA,tyjkJ265a,,0mxyjk41q53sYzIHmPXkqowXkqouhyVqoHFYz6omFhb0e1zqkmNSyVIP78YJ20klpyVOHwYk620olpc0vz8WBmFXzqomFpG61ckH38PhyjIP78Yz620kmlDkImLDzINUhGIuNDzIA78hb0e1ZIANYkqk366chG6oFNXkJkP5ahVZ6somFSb0e1620kNlhVk41qomADzIFLXkqso78pGqoFNXzkImP5a,tyjk620oHlhG620kNlXzqskm78,tjZqskHmPYqouFD6sku78YzqkNU,tjZqsomF')[v[0]]]
 for o in range(len(v)-1):c=g(c,v)
 return c[-1]

Puoi provare che f(2**32 - 1)viene eseguito quasi istantaneamente

Ho usato questo documento su un metodo per elaborarlo. Con questo metodo c'è un enorme blocco di dati per i valori predeterminati per n da 78 a 334 senza i numeri pari dopo 168. Volevo trasformare questi dati in qualcosa di piccolo e non conoscevo alcun buon algoritmo di compressione quindi fatto mio.

Il modo in cui l'ho compresso era avere un elenco di regole di sostituzione delle stringhe. Ho creato un metodo che ha trovato la regola di sostituzione della stringa che avrebbe ridotto la maggior parte del contenuto, tenendo conto della definizione della regola. Ho quindi applicato questo in modo ricorsivo fino a quando non ho potuto creare più regole (ho usato i caratteri gz e AZ). La stringa che ho creato per sostituire era un elenco separato da virgole dei valori esadecimali per ciascuno dei numeri. In retrospettiva, convertirli nei loro valori esadecimali potrebbe non essere stata la scelta più saggia, probabilmente sarebbe più breve lasciarli in decimali, poiché avere esadecimali salverebbe solo per i numeri a 3 cifre ma aggiungerebbe uno 0 per i numeri a cifra singola.

La riga in cui ho impostato c è possibile visualizzare l'elenco delle regole di sostituzione e il testo su cui viene eseguito. Le regole devono essere applicate anche al contrario perché alcune regole includono caratteri creati da altre regole.

Ci sono anche numerosi posti in questo codice in cui probabilmente potrei ridurre la sintassi, come trasformare l'elenco di elenchi in un unico elenco e quindi utilizzare un metodo diverso per accedere alle regole per sostituire il testo con


1
n=218le uscite [2]sono quelle previste ??
officialaimm,

1
No, vedrò perché succede un po 'più tardi. Mie scuse. Potrebbe essere un errore nei dati compressi inizialmente.
Cameron Aavik il

1

Haskell, 93 byte

import Data.List
import Data.Ratio
p n=[x|x<-subsequences[2..n],sum x==n,1==sum(map(1%)x)]!!0

Orribilmente lento 1 ma funziona in memoria costante. Soluzione fondamentale: controllare tutte le sottosequenze di [2..n]per la somma e la somma dei reciproci.

Restituire tutte le soluzioni anziché una è più corto di 3 byte: basta rimuovere il !!0 (attenzione: il tempo di esecuzione sarà sempre fuori dai grafici).


1 Il tempo di esecuzione dipende dalla prima apparizione del risultato nell'elenco delle sottosequenze. La pigrizia di Haskell interrompe la ricerca se viene trovata la prima corrispondenza. Quando compilato, p 89(risultato [3,4,6,9,18,21,28]:) viene eseguito sul mio laptop (di 4 anni) in 35 secondi. Altri valori, anche più piccoli, possono richiedere ore.


0

Julia, 77 byte

n->collect(filter(i->i==∪(i)&&sum(j->Rational(1,j),i)==1,partitions(n)))[1]

Questa è una funzione lambda inefficiente che accetta un numero intero e restituisce un array di numeri interi. Per chiamarlo, assegnarlo a una variabile.

Otteniamo le partizioni dell'intero usando partitions. Quindi filtriamo l'insieme di partizioni solo per quelli con elementi univoci i cui reciproci sono pari a 1. Per garantire che non si verifichino errori di arrotondamento, usiamo il Rationaltipo di Julia per costruire i reciproci. filterrestituisce un iteratore, quindi dobbiamo collectinserirlo in un array. Questo ci dà una matrice di matrici (con un solo elemento), in modo da poter ottenere il primo utilizzo[1] .

Ora, quando dico inefficiente, lo intendo. L'esecuzione per n = 80 richiede 39.113 secondi sul mio computer e alloca 13.759 GB di memoria.

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.