Dirichlet-Faltung


19

Die Dirichlet-Faltung ist eine spezielle Art der Faltung , die in der Zahlentheorie als sehr nützliches Werkzeug erscheint. Es arbeitet mit dem Satz von arithmetischen Funktionen .

Herausforderung

Wenn zwei arithmetische Funktionen f,g (dh Funktionen f,g:NR ) gegeben sind, berechnen Sie die Dirichlet-Faltung (fg):NR wie unten definiert.

Einzelheiten

  • Wir verwenden die Konvention 0N={1,2,3,} .
  • Die Dirichlet-Faltung fg zweier arithmetischer Funktionen f,g ist wiederum eine arithmetische Funktion und definiert als
    (fg)(n)=d|nf(nd)g(d)=ij=nf(i)g(j).
    (Beide Summen sind äquivalent. Der Ausdruckd|nbedeutetdNdividiertn, daher ist die Summation über den natürlichenTeilernvon n. Ebenso können wiri=ndN,j=dNund wir erhalten die zweite äquivalente Formulierung. Wenn Sie nicht an diese Notation gewöhnt sind, finden Sie im Folgenden ein schrittweises Beispiel.) Nur zur Erläuterung (dies ist für diese Herausforderung nicht direkt relevant): Die Definition stammt aus der Berechnung des Produkts derDirichlet-Reihe:
    (nNf(n)ns)(nNg(n)ns)=nN(fg)(n)ns
  • Die Eingabe erfolgt als zwei Blackbox-Funktionen . Alternativ können Sie auch eine unendliche Liste, einen Generator, einen Stream oder ähnliches verwenden, um eine unbegrenzte Anzahl von Werten zu erzeugen.
  • Es gibt zwei Ausgabemethoden: Entweder wird eine Funktion fg zurückgegeben, oder Sie können eine zusätzliche Eingabe nN und (fg)(n) direkt zurückgeben.
  • Der Einfachheit halber können Sie davon ausgehen, dass jedes Element von N zB mit einem positiven 32-Bit-Int dargestellt werden kann.
  • Der Einfachheit halber kann man auch davon ausgehen, dass jeder Eintrag R zB durch eine einzige reelle Gleitkommazahl dargestellt werden kann.

Beispiele

Definieren wir zunächst einige Funktionen. Beachten Sie, dass die Liste der Zahlen unter jeder Definition die ersten Werte dieser Funktion darstellt.

  • die multiplikative Identität ( 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, ...
  • die konstante Einheitsfunktion ( 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, ...
  • die Identitätsfunktion ( A000027 )
    id(n)=nn
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, ...
  • die Möbius-Funktion ( 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, ...
  • die Euler-Totientenfunktion ( 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, ...
  • die Liouville-Funktion ( A008836 )
    λ(n)=(1)k
    wobei k die Anzahl der Primfaktoren von n die mit der Multiplizität gezählt werden 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, ...
  • die Divisorsummenfunktion ( A000203 )
    σ(n)=d|nd
    1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, 24, 31, 18, 39, 20, ...
  • die Divisor-Zählfunktion ( 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, ...
  • die charakteristische Funktion von Quadratzahlen ( 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, ...

Dann haben wir folgende Beispiele:

  • ϵ=1μ
  • f=ϵff
  • ϵ=λ|μ|
  • σ=φτ
  • id=σμ undσ=id1
  • sq=λ1 and λ=μsq
  • τ=11 and 1=τμ
  • id=φ1 and φ=idμ

The last for are a consequence of the Möbius inversion: For any f,g the equation g=f1 is equivalent to f=gμ.

Step by Step Example

This is an example that is computed step by step for those not familiar with the notation used in the definition. Consider the functions f=μ and g=σ. We will now evaluate their convolution μσ at n=12. Their first few terms are listed in the table below.

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

The sum iterates over all natural numbers dN that divide n=12, thus d assumes all the natural divisors of n=12=223. These are d=1,2,3,4,6,12. In each summand, we evaluate g=σ at d and multiply it with f=μ evaluated at nd. Now we can conclude

(μσ)(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)

Antworten:



4

Haskell, 46 bytes

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

Try it online!

Thanks to flawr for -6 bytes and a great challenge! And thanks to H.PWiz for another -6!


Simpler is shorter here
H.PWiz

@H.PWiz That's pretty clever - I didn't even think of doing it that way!
Mego

3

Python 3, 59 bytes

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

Try it online!


Is // really needed instead of /?
Mr. Xcoder

/ would produce floats right?
Leaky Nun

Because d is a divisor of n by definition, the fractional part of n/d is zero, so there shouldn't be any issues with floating point arithmetic. Floats with fractional part zero are close enough to ints for Pythonic purposes, and the output of the function is a real number, so doing n/d instead of n//d should be fine.
Mego


2

Add++, 51 bytes

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

Try it online!

Takes two pre-defined functions as arguments, plus n, and outputs (fg)(n)

How it works

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 bytes

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

Try it online!

Takes n, f, and g. Luckily the numbers package has quite a few of the functions implemented already.

If vectorized versions were available, which is possible by wrapping each with Vectorize, then the following 45 byte version is possible:

R, 45 bytes

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

Try it online!




1

JavaScript (ES6), 47 bytes

Takes input as (f)(g)(n).

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

Try it online!

Examples

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

APL (Dyalog Classic), 20 bytes

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

with ⎕IO←1

Try it online!

Easy to solve, hard to test - generally not my type of challenge. Yet, I enjoyed this one very much!

{ } defines a dyadic operator whose operands ⍺⍺ and ⍵⍵ are the two functions being convolved; is the numeric argument

∪⍵∨⍳⍵ are the divisors of in ascending order, i.e. unique () of the LCMs () of with all natural numbers up to it ()

⍵⍵¨ apply the right operand to each

⍺⍺¨∘⌽ apply the left operand to each in reverse

+.× inner product - multiply corresponding elements and sum


The same in ngn/apl looks better because of Unicode identifiers, but takes 2 additional bytes because of 1-indexing.


Pretty sure it takes 27 additional bytes in ngn/apl...
Erik the Outgolfer

1

C (gcc), 108 bytes

#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;}

Straightforward implementation, shamelessly stolen from Leaky Nun's Python answer.

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;
}

Try it online!


1

F#, 72 bytes

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

Takes the two functions f and g and a natural number n. Filters out the values of d that do not naturally divide into n. Then evaluates f(n/d) and g(d), multiples them together, and sums the results.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.