Convoluzione di Dirichlet


20

La convoluzione di Dirichlet è un tipo speciale di convoluzione che appare come uno strumento molto utile nella teoria dei numeri. Funziona sul set di funzioni aritmetiche .

Sfida

Date due funzioni aritmetiche f,g (ovvero funzioni ) calcola la convoluzione di Dirichlet come definito di seguito.f,g:NR ( f g ) : NR (fg):NR

Dettagli

  • Usiamo la convenzione .0N={1,2,3,}
  • La convoluzione di Dirichlet di due funzioni aritmetiche è di nuovo una funzione aritmetica ed è definita come(Entrambe le somme sono equivalenti. L'espressione significa divide , quindi la somma è sopra i divisori naturali di n . Allo stesso modo possiamo sostituire i = \ frac {n} {d} \ in \ mathbb N, j = d \ in \ mathbb Nfgf,g
    (fg)(n)=d|nf(nd)g(d)=ij=nf(i)g(j).
    d|ndNnni=ndN,j=dNe otteniamo la seconda formulazione equivalente. Se non sei abituato a questa notazione, c'è un esempio passo dopo passo in basso.) Solo per elaborare (questo non è direttamente rilevante per questa sfida): La definizione viene dal calcolo del prodotto della serie Dirichlet :
    (nNf(n)ns)(nNg(n)ns)=nN(fg)(n)ns
  • L'input è dato come due funzioni della scatola nera . In alternativa, potresti anche utilizzare un elenco infinito, un generatore, un flusso o qualcosa di simile che potrebbe produrre un numero illimitato di valori.
  • Esistono due metodi di output: viene restituita una funzione fg , oppure in alternativa è possibile prendere un input aggiuntivo nN e restituire direttamente (fg)(n) .
  • Per semplicità puoi supporre che ogni elemento di N possa essere rappresentato con ad esempio un int positivo a 32 bit.
  • Per semplicità puoi anche supporre che ogni voce R possa essere rappresentata, ad esempio, da un singolo numero in virgola mobile reale.

Esempi

Definiamo prima alcune funzioni. Si noti che l'elenco di numeri sotto ogni definizione rappresenta i primi valori di quella funzione.

  • l'identità moltiplicativa ( A000007 )
    ϵ(n)={1n=10n>1
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
  • la funzione unità costante ( A000012 )
    1(n)=1n
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
  • la funzione identità ( A000027 )
    id(n)=nn
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, ...
  • la funzione Möbius ( A008683 )
    μ(n)={(1)k if n is squarefree and k is the number of Primefactors of n0 otherwise 
    1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, ...
  • la funzione totient di Eulero ( A000010 )
    φ(n)=np|n(11p)
    1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8, ...
  • la funzione di Liouville ( A008836 ) dove è il numero di fattori primi di conteggiato con molteplicità
    λ(n)=(1)k
    kn1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, ...
  • la funzione di somma divisore ( A000203 )
    σ(n)=d|nd
    1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, 24, 31, 18, 39, 20, ...
  • la funzione di conteggio dei divisori ( A000005 )
    τ(n)=d|n1
    1, 2, 2, 3, 2, 4, 2, 4, 3, 4, 2, 6, 2, 4, 4, 5, 2, 6, 2, 6, 4, 4, 2, 8, ...
  • la funzione caratteristica dei numeri quadrati ( A010052 )
    sq(n)={1 if n is a square number0otherwise
    1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, ...

Quindi abbiamo i seguenti esempi:

  • ϵ=1μ
  • f=ϵff
  • ϵ=λ|μ|
  • σ=φτ
  • id=σμ eσ=id1
  • sq=λ1 eλ=μsq
  • τ=11 e1=τμ
  • id=φ1 φ = i d μ eφ=idμ

Gli ultimi per sono una conseguenza dell'inversione di Möbius : per ogni l'equazione è equivalente a .f,gg=f1f=gμ

Esempio passo dopo passo

Questo è un esempio che viene calcolato passo dopo passo per coloro che non hanno familiarità con la notazione utilizzata nella definizione. Considera le funzioni e . Valuteremo ora la loro convoluzione a . I loro primi termini sono elencati nella tabella seguente.f=μg=σμσn=12

ff(1)f(2)f(3)f(4)f(5)f(6)f(7)f(8)f(9)f(10)f(11)f(12)μ111011100110σ134761281513181228

La somma scorre su tutti i numeri naturali che dividono , quindi assume tutti i divisori naturali di . Questi sono . In ogni addendo, valutiamo a e moltiplicarlo con valutata a . Ora possiamo concluderedNn=12dn=12=223d=1,2,3,4,6,12g=σdf=μnd

(μσ)(12)=μ(12)σ(1)+μ(6)σ(2)+μ(4)σ(3)+μ(3)σ(4)+μ(2)σ(6)+μ(1)σ(12)=01+13+04+(1)7+(1)12+128=0+310712+28=12=id(12)

Risposte:


4

Lean , 108 100 95 78 75 byte

def d(f g:_->int)(n):=(list.iota n).foldr(λd s,ite(n%d=0)(s+f d*g(n/d))s)0

Provalo online!

Più testcase con tutte le funzioni.


Lambda è davvero più costoso di quattro byte per fun ?
Mario Carneiro,

lambda è di tre byte, suppongo
Leaky Nun

Penso che siano due in UTF8 (il greco è piuttosto basso unicode)
Mario Carneiro

Hai ragione. Ho anche giocato a golf sull'importazione
Leaky Nun il

Ho anche usato condper salvare 5 byte
Leaky Nun

4

Haskell , 46 byte

(f!g)n=sum[f i*g(div n i)|i<-[1..n],mod n i<1]

Provalo online!

Grazie a flawr per -6 byte e una grande sfida! E grazie a H.PWiz per un altro -6!


Più

@ H.PWiz È abbastanza intelligente - non avevo nemmeno pensato di farlo in quel modo!
Mego

3

Python 3 , 59 byte

lambda f,g,n:sum(f(d)*g(n//d)for d in range(1,n+1)if 1>n%d)

Provalo online!


È //davvero necessario invece di /?
Mr. Xcoder,

/produrrebbe galleggianti giusto?
Leaky Nun,

Poiché dè un divisore nper definizione, la parte frazionaria n/dè zero, quindi non dovrebbero esserci problemi con l'aritmetica in virgola mobile. I float con zero parziale frazionario sono abbastanza vicini agli ints per scopi Pythonic e l'output della funzione è un numero reale, quindi fare n/dinvece di n//ddovrebbe andare bene.
Mego


2

Aggiungi ++ , 51 byte

D,g,@~,$z€¦~¦*
D,f,@@@,@b[VdF#B]dbRzGb]$dbL$@*z€g¦+

Provalo online!

Accetta due funzioni predefinite come argomenti, più n , e output (fg)(n)

Come funziona

D,g,		; Define a helper function, $g
	@~,	; $g takes a single argument, an array, and splats that array to the stack
		; $g takes the argument e.g. [[τ(x) φ(x)] [3 4]]
		; STACK : 			[[τ(x) φ(x)] [3 4]]
	$z	; Swap and zip:			[[3 τ(x)] [4 φ(x)]]
	€¦~	; Reduce each by execution:	[[τ(3) φ(4)]]
	¦*	; Take the product and return:	τ(3)⋅φ(4) = 4

D,f,		; Define the main function, $f
	@@@,	; $f takes three arguments: φ(x), τ(x) and n (Let n = 12)
		; STACK:			[φ(x) τ(x) 12]
	@	; Reverse the stack:		[12 τ(x) φ(x)]
	b[V	; Pair and save:		[12]			Saved: [τ(x) φ(x)]
	dF#B]	; List of factors:		[[1 2 3 4 6 12]]
	dbR	; Copy and reverse:		[[1 2 3 4 6 12] [12 6 4 3 2 1]]
	z	; Zip together:			[[[1 12] [2 6] [3 4] [4 3] [6 2] [12 1]]]
	Gb]	; Push Saved:			[[[1 12] [2 6] [3 4] [4 3] [6 2] [12 1]] [[τ(x) φ(x)]]]
	$dbL	; Number of dividors:		[[[τ(x) φ(x)]] [[1 12] [2 6] [3 4] [4 3] [6 2] [12 1]] 6]
	$@*	; Repeat:			[[[1 12] [2 6] [3 4] [4 3] [6 2] [12 1]] [[τ(x) φ(x)] [τ(x) φ(x)] [τ(x) φ(x)] [τ(x) φ(x)] [τ(x) φ(x)] [τ(x) φ(x)]]]
	z	; Zip:				[[[τ(x) φ(x)] [1 12]] [[τ(x) φ(x)] [2 6]] [[τ(x) φ(x)] [3 4]] [[τ(x) φ(x)] [4 3]] [[τ(x) φ(x)] [6 2]] [[τ(x) φ(x)] [12 1]]]
	€g	; Run $g over each subarray:	[[4 4 4 6 4 6]]
	¦+	; Take the sum and return:	28

2

R , 58 byte

function(n,f,g){for(i in (1:n)[!n%%1:n])F=F+f(i)*g(n/i)
F}

Provalo online!

Prende n, fe g. Fortunatamente il numberspacchetto ha già alcune delle funzioni implementate.

Se erano disponibili versioni vettorializzate, che è possibile racchiudendole ognuna con Vectorize, è possibile la seguente versione a 45 byte:

R , 45 byte

function(n,f,g,x=1:n,i=x[!n%%x])f(i)%*%g(n/i)

Provalo online!


2

APL (Dyalog Classic) , 20 byte

{(⍺⍺¨∘⌽+.×⍵⍵¨)∪⍵∨⍳⍵}

con ⎕IO←1

Provalo online!

Facile da risolvere, difficile da testare, generalmente non è il mio tipo di sfida. Tuttavia, mi è piaciuto molto questo!

{ }definisce un operatore diadico i cui operandi ⍺⍺e ⍵⍵le due funzioni sono contorte; è l'argomento numerico

∪⍵∨⍳⍵sono i divisori di in ordine crescente, cioè unici ( ) dei LCM ( ) di con tutti i numeri naturali fino ad esso ( )

⍵⍵¨ applica l'operando giusto a ciascuno

⍺⍺¨∘⌽ applica l'operando di sinistra a ciascuno al contrario

+.× prodotto interno: moltiplica gli elementi e la somma corrispondenti


Lo stesso in ngn / apl sembra migliore a causa degli identificatori Unicode, ma richiede 2 byte aggiuntivi a causa dell'indicizzazione 1.


Abbastanza sicuro ci vogliono 27 byte aggiuntivi in ​​ngn / apl ...
Erik the Outgolfer



1

JavaScript (ES6), 47 byte

Accetta input come (f)(g)(n).

f=>g=>h=(n,d=n)=>d&&!(n%d)*f(n/d)*g(d)+h(n,d-1)

Provalo online!

Esempi

liouville =
n => (-1) ** (D = (n, k = 2) => k > n ? 0 : (n % k ? D(n, k + 1) : 1 + D(n / k, k)))(n)

mobius =
n => (M = (n, k = 1) => n % ++k ? k > n || M(n, k) : n / k % k && -M(n / k, k))(n)

sq =
n => +!((n ** 0.5) % 1)

identity =
n => 1

// sq = liouville * identity
console.log([...Array(25)].map((_, n) => F(liouville)(identity)(n + 1)))

// liouville = mobius * sq
console.log([...Array(20)].map((_, n) => F(mobius)(sq)(n + 1)))

1

C (gcc) , 108 byte

#define F float
F c(F(*f)(int),F(*g)(int),int n){F s=0;for(int d=0;d++<n;)if(n%d<1)s+=f(n/d)*g(d);return s;}

Implementazione diretta, rubata senza vergogna dalla risposta Python di Leaky Nun .

Ungolfed:

float c(float (*f)(int), float (*g)(int), int n) {
    float s = 0;
    for(int d = 1; d <= n;++d) {
        if(n % d == 0) {
            s += f(n / d) * g(d);
        }
    }
    return s;
}

Provalo online!


1

F #, 72 byte

let x f g n=Seq.filter(fun d->n%d=0){1..n}|>Seq.sumBy(fun d->f(n/d)*g d)

Prende le due funzioni fe ged un numero naturale n. Filtra i valori dche non si dividono naturalmente in n. Quindi valuta f(n/d) e g(d), li moltiplica insieme e somma i risultati.



0

APL (NARS), 47 caratteri, 94 byte

{(m⍵[1])×n⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}

dove m e n sono la funzione che si deve usare (questo perché non so come chiamare un array di funzioni in una funzione in APL). Usando l'esempio sopra la moltiplicazione della funzione Mobius (qui è 12π) e la somma della funzione divisori (qui è 11π) per il valore 12 tale moltiplicazione sarebbe:

  {(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}12
12

se si deve calcolare qualche altro valore:

  {(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}1002
1002
  {(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}1001
1001
  {(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}20000x
20000 

Si può vedere se ad esempio il primo numero 2000 il risultato della funzione è l'identità

  (⍳2000)≡{(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}¨⍳2000
1
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.