Somma del divisore derivante dalla fattorizzazione in potenza primaria


11

Il compito è calcolare la somma divisore di un numero data la sua scomposizione in fattori primi.

Ingresso

Due array (o qualcosa di equivalente) di lunghezza n , uno contenente il fattore primo e l'altro contenente l'esponente corrispondente.

Produzione

La somma di tutti i divisori (incluso il numero stesso).

Esempio

Il numero 240 ha 2, 3 e 5 come fattori primi con 4, 1 e 1 come rispettivi esponenti. L'output previsto sarebbe quindi 744.

Input: [2,3,5] [4,1,1]
Output: 744

punteggio

Vince il codice più corto in byte!

Se la complessità del tempo di esecuzione della soluzione è O (somma degli esponenti) anziché O (prodotto degli esponenti), il punteggio può essere moltiplicato per 0,8.


Una domanda simile è stata pubblicata qui, ma non è stata una sfida. Penso che il problema sia abbastanza interessante da essere giocato a golf.

Il vincitore sarà scelto questo fine settimana


L'array a fattore primo deve sempre essere il primo e l'array esponente in secondo luogo o possiamo supporre che gli array siano immessi al contrario?
Sp3000,

Puoi assumere qualsiasi formato di input simile a quello proposto
Moartem

Non riesco a trovarlo in questo momento, ma penso che questo o qualcosa di simile sia su projecteuler.net
flawr

Risposte:


3

Pyth, 13 byte * 0,8 = 10,4

*Fms^LhdhedCQ

Dimostrazione.

Questa risposta funziona in modo leggermente diverso da quelli sopra. Per calcolare la somma dei fattori delle potenze primi del numero, invece di usare una formula aritmetica, i fattori vengono esplicitamente costruiti e sommati.

Per esempio, sulla coppia [primo, esponente] [2, 4], mappiamo 2 ^ xsopra 0, 1, 2, 3, 4, dando [1, 2, 4, 8, 16], che viene poi sintetizzato a 31.

I risultati vengono quindi moltiplicati insieme e stampati.

Se l'espiazione è implementata correttamente o se è presente una cache dei risultati intermedia, ciò avverrà O(sum of exponents).


Indipendentemente dall'implementazione, non credo sia possibile calcolare la prima n potenza di a in O (n) tempo, a meno che non si presuma che la moltiplicazione sia O (1).
Dennis,

@Dennis Bene, i termini di ordine superiore dominano, quindi probabilmente avrebbe il tempo di esecuzione della moltiplicazione di ordine più alto, il che è O(n)se possiamo supporre che la base sia una costante.
isaacg,

9

CJam, 15 byte * 0,8 = 12

q~.{_@)#(\(/}:*

Provalo online . L'ordine di input è prima l'elenco degli esponenti, quindi l'elenco dei numeri primi (-3 byte grazie a @Dennis) .

(p, e)Trova per ogni coppia esponente primo

(p^(e+1) - 1)/(p - 1)

quindi trova il prodotto di tutti questi. Ad esempio, per 240 questo sarebbe

(1 + 2 + 4 + 8 + 16)(1 + 3)(1 + 5) = 31 * 4 * 6 = 744

A seconda di come viene implementata l'espiazione, questo può essere migliore di O(sum of exponents).


6

APL, 18 13 byte * 0,8 = 10,4

×/(1-⊣×*)÷1-⊣

Questo crea un treno di funzioni diadico che prende la matrice di fattori a sinistra e gli esponenti a destra.

×/             ⍝ Vector product of
  (1-⊣×*)      ⍝ each factor^(exponent+1)-1
         ÷1-⊣  ⍝ divided by factor-1

Provalo online . Si noti che questo è lo stesso approccio della risposta CJam incredibilmente intelligente di Sp3000 .

5 byte salvati grazie a Dennis!


2

TI-BASIC, 17 byte * 0,8 = 13,6

Utilizza anche il metodo Sp3000, anche se l'ho trovato in modo indipendente. Prende un elenco da Input e uno dalla schermata principale.

Input E
prod(AnsAns^∟E-1)/prod(Ans-1

Usando prod (due volte è più piccolo perché ci permette di usare la parentesi aperta gratuitamente. Nota che questa risposta non supporta array vuoti, perché non ci sono array vuoti in TI-BASIC.


2

Haskell, 38 * 0,8 = 30,4

product$zipWith(\p e->(p*p^e-1)/(p-1))

Uso:

product$zipWith(\p e->(p*p^e-1)/(p-1)) [2,3,5] [4,1,1]
744.0

La funzione anonima prende (p,e)la somma divisore per somma di p^eserie geometrica. Comprimere le due liste con questo come unire e prendere il prodotto dà il risultato.

Non sono riuscito a trovare qualcosa di più corto dell'espressione aritmetica

(p*p^e-1)/(p-1)
sum$map(p^)[0..e]

Forse c'è un modo per sbarazzarsi di (\p e->_).

La definizione della funzione Infix fornisce la stessa lunghezza (38):

p%e=(p*p^e-1)/(p-1)
product$zipWith(%)

2

C ++, 111 80 77 byte * 0,8 = 61,6

int g(int*p,int*e,int n){return n?g(p+1,e+1,n-1)*(pow(*p,*e-1)-1)/(*p-1):1;}

Questo calcola (p ^ (e + 1) -1) / (p-1) e moltiplica ricorsivamente tutti i fattori. L'ho scoperto un anno fa.

Grazie per l'aiuto, completamente dimenticato dell'uso booleano in stile c ++.


1
n==0semplifica !n- o potresti invertire i risultati e semplicemente usaren
Toby Speight il

2

Matlab, 53

function t=f(x,y)
s=1:prod(x.^y);t=s*~mod(s(end),s)';

Esempio:

>> f([2 3 5], [4 1 1])
ans =
   744

Sembra che tu possa aggiungere il bonus di 0,8
Moartem il

@Moartem Grazie! Ma non ne sono sicuro. Calcolo il numero se quindi collaudo tutti i possibili divisori da 1a s. Quindi è (almeno) O (s), che è probabilmente tra O (somma degli esponenti) e O (prodotto degli esponenti)
Luis Mendo,

Sì, esatto, è persino più grande di O (prodotto degli esponenti)
Moartem

1

Python 2.156

from itertools import*
from operator import*
i=input()
print sum(reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]])))

Ingresso

[[2,3,5],[4,1,1]]

Produzione

744

Spiegazione

Questo programma riceve un elenco di 2 elenchi: fattori ed esponenti.

i=input() # Receive list of 2 lists: i[0] for factors i[1] for exponents

Quindi crea l'elenco di tutte le possibili combinazioni dell'elenco esponente.

[x+1 for x in i[1]] # [4,1,1]->[5,2,2] (to include last element)
map(range,[x+1 for x in i[1]]) # [[0, 1, 2, 3, 4], [0, 1], [0, 1]]
product(*map(range,[x+1 for x in i[1]])) # [(0, 0, 0), (0, 0, 1), ..., (4, 1, 1)]

e comprimilo con i fattori:

zip(i[0],p) for p in product(*map(range,[x+1 for x in i[1]])) # [[(2, 0), (3, 0), (5, 0)], ..., [(2, 4), (3, 1), (5, 1)]]

Calcola i fattori in base alla potenza degli esponenti:

 [a**b for a,b in zip(i[0],p)]for p in product(*map(range,[x+1 for x in i[1]])) # [[1, 1, 1], ..., [16, 3, 5]]

e moltiplica ogni lista (questo ci dà tutti i divisori):

reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]])) # [1, 5, 3, 15, ..., 240]

Infine, sommare tutti gli elenchi e stampare:

print sum(reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]]))) # 744

Potresti spiegare brevemente cosa fa il tuo codice (dato che non ho familiarità con Python), così posso giudicare la complessità del tuo codice?
Moartem,

È un approccio intelligente, ma la complessità è il prodotto degli esponenti
Moartem,

@Moartem Sì, non ho trascorso molto tempo a ridurre la complessità
TheCrypt

1

Python 3, 134 120 117

Input: due matrici separate da virgola separate da virgola.

Esempio:

(2,3,7,11),(4,2,3,2)
21439600
from functools import*
a=eval(input())
print(reduce(int.__mul__,(sum(x**j for j in range(y+1))for x,y in zip(*a)),1))

Con NumPy può essere ridotto a 100 byte:

import numpy
a=eval(input())
print(numpy.product([sum(x**j for j in range(y+1))for x,y in zip(*a)]))

1
Per il primo esempio, solo per sapere, invece di importare operatorper l'utilizzo muluna volta, è possibile utilizzare float.__mul__per salvare un mucchio di byte.
Kade,

1

Gelatina, non competitiva

Questa risposta non è competitiva, poiché la sfida precede la creazione di Jelly.

5 byte (nessun bonus)

*PÆDS

Provalo online!

Come funziona

*PÆDS    Main link. Left input: p (prime factors). Right input: e (exponents).

*        Elevate the prime factors to the corresponding exponents.
 P       Take the product of all powers.
  ÆD     Find all divisors of the product.
    S    Compute the sum of the divisors.

7 byte (5,6 byte dopo il bonus)

*‘}’:’{P

Come funziona

×*’:’{P  Main link. Left input: p (prime factors). Right input: e (exponents).

 *       Elevate the prime factors to the corresponding exponents.
         This yields p ** e.
×        Multiply the prime factors with the corresponding powers.
         This yields p ** (e + 1).
  ’      Decrement the resulting products.
         This yields p ** (e + 1) - 1.
    ’{   Decrement the prime factors.
         This yields p - 1.
   :     Divide the left result by the right one.
         This yields (p ** (e + 1) - 1) / (p - 1).
      P  Take the product of all quotients.

Provalo online!


1

APL, 12 byte * 0,8 = 9,6

×/1++/¨⎕*⍳¨⎕

Questo legge due elenchi dalla tastiera, gli esponenti prima, cioè:

      ×/1++/¨⎕*⍳¨⎕
⎕:
      4 1 1
⎕:
      2 3 5
744

Spiegazione:

  • : leggi un elenco dalla tastiera (gli esponenti)
  • ⍳¨: per ogni numero nell'elenco, genera un elenco [1..n].
  • ⎕*: leggi un altro elenco dalla tastiera (i numeri primi) e aumenta ogni primo a ciascuno degli esponenti negli elenchi corrispondenti
  • +/¨: somma ogni elenco
  • 1+: aggiungi uno a ciascun risultato, per compensare la mancanza x^0in ciascuna delle liste
  • ×/: prendere il prodotto dei risultati

1

Racchetta (schema), 65 * 0,8 = 52 byte

Stessa aritmetica di tutti gli altri

(λ(x y)(foldl(λ(m n o)(*(/(-(expt m(+ n 1))1)(- m 1))o))1 x y))

Spiegazione:

(λ (x y)    ;defines anonymous function with two inputs
    (foldl    ;recursively applies the following function to all elements of the lists given to an argument given (foldl function argument lists lists lists...)
        (λ (m n o) (* (/ (- (expt m (+ n 1)) 1) (- m 1)) o))    ;an anonymous function representing the same arithmetic used in the CJam answer, then multiplying it with our incrementor
        1 x y))    ;the incrementor argument is 1, and the input lists are the ones provided into the original function

0

Python 2, 80 byte * 0,8 = 64

Ciò presuppone che l'input arrivi uno dopo l'altro. Segue la stessa formula descritta nella risposta CJam di Sp3000.

print(reduce(float.__mul__,[~-(x**-~y)/~-x for x,y in zip(input(),input())],1)) 

Se ciò non è consentito, lo userò come soluzione, che ottiene un punteggio di 84 byte * 0,8 = 67,2. L'input deve essere separato da una virgola, ad es [2,3,5],[4,1,1].

k=input()
print(reduce(float.__mul__,[~-(x**-~y)/~-x for x,y in zip(k[0],k[1])],1))

Psst. Hey! Questa è una possibile soluzione in Symbolic, qualcosa su cui sto lavorando:Ƥ(П([~-(x**-~y)/~-xϝx,yϊʐ(Ί,Ί)],1))


0

Mathematica, 40 byte

Total[Outer@@{*}~Join~(#^0~Range~#2),3]&

Senza usare nessuno degli inbuilt che si occupano di divisori, per differenziarsi dall'altra soluzione matematica nel thread.

L'input è (usando l'esempio) [{2, 3, 5}, {4, 1, 1}]


0

Perl 5, 96 byte

Ovviamente questo non è vincente, ma ho deciso di scriverlo per divertimento.

È una subroutine:

{($b,$e)=@_;$s=1;map$s*=$b->[$_]**$e->[$_],0..@$b-1;$_=1x$s;for$j(1..$s){$i+=$j*/^(.{$j})*$/}$i}

Guardalo in azione così:

perl -e'print sub{...}->([2,3,5],[4,1,1])'

Come funziona:

  • ($b,$e)=@_legge gli array di input $b(basi) e $e(esponenti) di input .
  • $s=1 inizializza il prodotto.
  • map$s*=$b->[$_]**$e->[$_],0..@$b-1si moltiplica $sper i successivi poteri esponente di base. Ora $sè il numero composto.
  • $_=1x$simposta $_uguale a una stringa di quelli, $slunga. $iè inizializzato su 0.
  • for$j(1..$s){$i+=$j*/^(.{$j})*$/}cerca, per ogni numero $jtra 1 e $s, di rompersi $_mentre i $jcaratteri si ripetono un numero qualsiasi di volte. Se può, allora $jdivide $s, ed /^(.{$j})*$/è 1 (altrimenti è 0), ed $iè aumentato di $j. Pertanto, aggiungiamo al $inumero di partizioni in una partizione uguale di $_. Come sottolinea Omar E. Pol , $iè il numero che stiamo cercando.
  • $ialla fine ritorna $i.

0

J, 14 byte * 0,8 = 11,2

[:*/(^>:)%&<:[

uso

   f =: [:*/(^>:)%&<:[
   2 3 5 f 4 1 1
744
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.