Konwolucja Dirichleta

20

Splot dirichleta to specjalny rodzaj splotu , który pojawia się jako bardzo użyteczne narzędzie w teorii liczb. Działa na zbiorze funkcji arytmetycznych .

Wyzwanie

Biorąc pod uwagę dwie funkcje arytmetyczne f,g (tj. Funkcje f,g:NR ), oblicz splot Dirichleta (fg):NR jak zdefiniowano poniżej.

Detale

  • Używamy konwencji 0N={1,2,3,} .
  • Splot Dirichleta fg dwóch funkcji arytmetycznych f,g jest ponownie funkcją arytmetyczną i jest zdefiniowany jako
    (fg)(n)=d|nf(nd)g(d)=ij=nf(i)g(j).
    (Obie sumy są równoważne. Wyrażenied|noznaczadNdzielin zatem sumowanie na naturalnychdzielnikówz n Podobnie można subsitute.i=ndN,j=dNi otrzymujemy drugi równoważny preparat. Jeśli nie jesteś przyzwyczajony do tej notacji, poniżej znajdziesz krok po kroku.) Tylko w celu rozwinięcia (nie ma to bezpośredniego związku z tym wyzwaniem): Definicja pochodzi z obliczenia iloczynuserii Dirichleta:
    (nNf(n)ns)(nNg(n)ns)=nN(fg)(n)ns
  • Dane wejściowe podano jako dwie funkcje czarnej skrzynki . Alternatywnie możesz również użyć nieskończonej listy, generatora, strumienia lub czegoś podobnego, co może wygenerować nieograniczoną liczbę wartości.
  • Istnieją dwie metody wyjściowe: albo funkcja fg jest zwracana, albo alternatywnie możesz wziąć dodatkowe wejście nN i zwrócić bezpośrednio (fg)(n) bezpośrednio.
  • Dla uproszczenia można założyć, że każdy element N może być reprezentowany np. Dodatnim 32-bitowym int.
  • Dla uproszczenia można również założyć, że każdy wpis R może być reprezentowany np. Przez jedną rzeczywistą liczbę zmiennoprzecinkową.

Przykłady

Najpierw zdefiniujmy kilka funkcji. Zauważ, że lista liczb pod każdą definicją reprezentuje kilka pierwszych wartości tej funkcji.

  • tożsamość multiplikatywna ( 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, ...
  • funkcja stałej jednostki ( 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, ...
  • funkcja tożsamości ( A000027 )
    id(n)=nn
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, ...
  • funkcja Möbiusa ( 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, ...
  • funkcja sumy Eulera ( 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, ...
  • funkcja Liouville'a ( A008836 )
    λ(n)=(1)k
    gdziek jest liczbą czynników pierwszychn zliczonych 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, ...
  • funkcja sumy dzielników ( A000203 )
    σ(n)=d|nd
    1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, 24, 31, 18, 39, 20, ...
  • funkcja zliczania dzielników ( 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, ...
  • funkcja charakterystyczna liczb kwadratowych ( 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, ...

Następnie mamy następujące przykłady:

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

Ostatnie są konsekwencją inwersji Möbiusa : dla każdegof,g równanieg=f1 jest równoważnef=gμ .

Przykład krok po kroku

Jest to przykład obliczany krok po kroku dla tych, którzy nie znają notacji stosowanej w definicji. Rozważ funkcje f=μ i g=σ . Ocenimy teraz ich splot μσ przy n=12 . Ich kilka pierwszych terminów wymieniono w poniższej tabeli.

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

Suma iteruje się po wszystkich liczbach naturalnych dN które dzielą n=12 , a zatem d przyjmuje wszystkie naturalne dzielniki n=12=223 . Są to d=1,2,3,4,6,12 . W każdym podsumowaniu oceniamy g=σ punkcie d i mnożymy przez f=μ obliczone w punkciend . Teraz możemy podsumować

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

wada
źródło

Odpowiedzi:

5

Lean , 108 100 95 78 75 bajtów

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

Wypróbuj online!

Więcej przypadków testowych ze wszystkimi funkcjami.

Leaky Nun
źródło
czy lambda jest naprawdę droższa niż cztery bajty fun ?
Mario Carneiro,
lambda to trzy bajty, jak sądzę
Leaky Nun
Myślę, że jest dwa w UTF8 (grecki jest dość niskim unicode)
Mario Carneiro
Masz rację. Grałem również w golfa import
Leaky Nun
Zapisałem też cond5 bajtów
Leaky Nun
4

Haskell , 46 bajtów

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

Wypróbuj online!

Dzięki flawr dla -6 bajtów i wielkim wyzwaniem! I dzięki H.PWiz za kolejne -6!

Mego
źródło
Prostsze jest tutaj krótsze
H.PWiz
@ H.PWiz To całkiem sprytne - nawet nie pomyślałem o zrobieniu tego w ten sposób!
Mego
3

Python 3 , 59 bajtów

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

Wypróbuj online!

Leaky Nun
źródło
Czy //naprawdę jest potrzebny zamiast /?
Pan Xcoder,
/czy produkuje pływaki, prawda?
Leaky Nun
Ponieważ dz ndefinicji jest dzielnikiem , część ułamkowa n/dwynosi zero, więc nie powinno być żadnych problemów z arytmetyką zmiennoprzecinkową. Liczba zmiennoprzecinkowa z ułamkową częścią zerową jest wystarczająco zbliżona do liczb całkowitych dla celów Pythona, a wynikiem działania funkcji jest liczba rzeczywista, więc działanie n/dzamiast n//dpowinno być w porządku.
Mego
3

Wolfram Language (Mathematica), 17 bytes

Oczywiście Mathematica ma wbudowane. Zdarza się również, że zna wiele przykładowych funkcji. Podałem kilka przykładów roboczych.

DirichletConvolve

Wypróbuj online!

Kelly Lowder
źródło
2

Dodaj ++ , 51 bajtów

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

Wypróbuj online!

Bierze dwie predefiniowane funkcje jako argumenty plus ni wyniki (fasol)(n)

Jak to działa

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
Cairney Coheringaahing
źródło
2

R , 58 bajtów

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

Wypróbuj online!

Trwa n, fi g. Na szczęście numberspakiet ma już zaimplementowanych kilka funkcji.

Jeśli dostępne były wersje wektoryzowane, co jest możliwe poprzez zawinięcie każdej z nich Vectorize, możliwa jest następująca 45-bajtowa wersja:

R , 45 bajtów

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

Wypróbuj online!

Giuseppe
źródło
2

APL (Dyalog Classic) , 20 bajtów

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

z ⎕IO←1

Wypróbuj online!

Łatwy do rozwiązania, trudny do przetestowania - generalnie nie jest to mój typ wyzwania. Jednak bardzo mi się podobało!

{ }definiuje dynamiczny operator, którego argumenty ⍺⍺i ⍵⍵dwie funkcje są ze sobą powiązane; jest argumentem liczbowym

∪⍵∨⍳⍵są dzielnikami w porządku rosnącym, tj. niepowtarzalnym ( ) LCM ( ) dla wszystkich liczb naturalnych do niego ( )

⍵⍵¨ zastosować odpowiedni operand do każdego

⍺⍺¨∘⌽ zastosuj lewy operand do każdego w odwrotnej kolejności

+.× produkt wewnętrzny - pomnóż odpowiednie elementy i sumę


To samo w ngn / apl wygląda lepiej dzięki identyfikatorom Unicode, ale zajmuje 2 dodatkowe bajty z powodu 1-indeksowania.

ngn
źródło
Całkiem pewne, że zajmuje 27 dodatkowych bajtów w ngn / apl ...
Erik the Outgolfer
1

Galaretka , 9 bajtów

ÆDṚÇ€ḋÑ€Ʋ

Wypróbuj online!

Linia u góry jest główną linią fa, linia u dołu jest główną linią sol. n jest przekazywany jako argument do tej funkcji.

Erik the Outgolfer
źródło
1

JavaScript (ES6), 47 bajtów

Pobiera dane wejściowe jako (f)(g)(n).

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

Wypróbuj online!

Przykłady

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)))
Arnauld
źródło
1

C (gcc) , 108 bajtów

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

Prosta implementacja, bezwstydnie skradziona z odpowiedzi Pythona Leaky Nun .

Nie golfowany:

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

Wypróbuj online!

joH1
źródło
1

F #, 72 bajty

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

Pobiera dwie funkcje fi gliczbę naturalną n. Odfiltrowuje wartości d, które nie dzielą się w naturalny sposób n. Następnie ocenia f(n/d) i g(d)mnoży je razem i sumuje wyniki.

Ciaran_McCarthy
źródło
0

APL (NARS), 47 znaków, 94 bajty

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

gdzie m i n to funkcja, której należy użyć (ponieważ nie wiem, jak wywołać jedną tablicę funkcji w jednej funkcji w APL). Korzystając z powyższego przykładu, mnożenie funkcji Mobiusa (tutaj jest to 12π) i suma funkcji dzielników (tutaj jest 11π) dla wartości 12, to mnożenie byłoby:

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

jeśli trzeba obliczyć inną wartość:

  {(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 

Można zobaczyć, czy na przykład pierwszym numerem 2000 wynikiem funkcji jest tożsamość

  (⍳2000)≡{(12π⍵[1])×11π⍵[2]}{+/⍺⍺¨{k←⍳⍵⋄(⍵÷b),¨b←k/⍨0=k∣⍵}⍵}¨⍳2000
1
RosLuP
źródło