Esprimendo la doppia sequenza di sommatoria in Raku


13

Come esprimere la doppia somma doppia sequenza di sommatoria in Perl 6?

Per un esempio di sequenza doppia somma doppia variabile vedere questo

Immagine

Deve essere espresso così com'è, cioè senza ridurre matematicamente la doppia sommazione in un'unica sommazione. Grazie.

Risposte:


14

Il X(operatore incrociato) e il [+](metaoperatore di riduzione [ ]con operatore additivo +) lo rendono sorprendentemente facile:

Per rappresentare 1 la doppia somma ∑³ x  = 1 ∑⁵ y  = 1 2x + y , puoi fare quanto segue:

  [+] do for 1..3 X 1..5 -> ($x, $y) { 2 * $x + $y }
#        for 1..3 X 1..5                             # loop cross values
#                        -> ($x, $y)                 # plug into x/y
#                                    { 2 * $x + $y } # calculate each iteration
#     do                                             # collect loop return vals 
# [+]                                                # sum them all

Se si desidera creare un subper questo, è possibile scrivere come segue 2

sub ΣΣ (
    Int $aₒ, Int $aₙ,     # to / from for the outer
    Int $bₒ, Int $bₙ,     # to / from for the inner
    &f where .arity = 2   # 'where' clause guarantees only two params
) {
  [+] do for $aₒ..$aₙ X $bₒ..$bₙ -> ($a, $b) { &f(a,b) }
}

say ΣΣ 1,3, 1,5, { 2 * $^x + $^y }

O anche semplificare di più le cose

sub ΣΣ (
    Iterable \a,            # outer values
    Iterable \b,            # inner values
    &f where .arity = 2) {  # ensure only two parameters
  [+] do f(|$_) for a X b
}

# All of the following are equivalent
say ΣΣ 1..3, 1..5, -> $x, $y { 2 * $x  + $y  }; # Anonymous block
say ΣΣ 1..3, 1..5,           { 2 * $^x + $^y }; # Alphabetic args
say ΣΣ 1..3, 1..5,             2 *  *  +  *   ; # Overkill, but Whatever ;-) 

Si noti che digitandolo, possiamo garantire che gli intervalli vengano passati, ma digitandolo come Iterablepiuttosto che Rangepossiamo consentire sequenze di sommatoria più interessanti, come, diciamo, ΣΣ (1..∞).grep(*.is-prime)[^99], 1..10, { … }che ci permetterebbero di usare la sequenza dei primi 100 numeri primi.

In effetti, se lo volessimo davvero, potremmo esagerare e consentire un operatore sommario di profondità arbitrario, che è reso più semplice spostando la funzione a sinistra:

sub ΣΣ (
    &function, 
    **@ranges where                # slurp in the ranges
        .all   ~~ Iterable &&      # make sure they're Iterables 
        .elems == &function.arity  # one per argument in the function
) {
  [+] do function(|$_) for [X] @ranges;
};

Proprio come [+]riassume tutti i valori della nostra f()funzione, [X]calcola la croce in modo iterativo, ad esempio [X] 0..1, 3..4, 5..6prima fa 0..1 X 3..4o (0,3),(0,4),(1,3),(1,4), e poi fa (0,3),(0,4),(1,3),(1,4) X 5..6, o (0,3,5),(0,4,5),(1,3,5),(1,4,5),(0,3,6),(0,4,6),(1,3,6),(1,4,6).


1. Mi dispiace, SO non mi lascia fare LaTeX, ma dovresti avere l'idea. 2. Sì, lo so che è una lettera di pedice O non zero, i numeri di pedice normalmente non sono identificatori validi, ma puoi usare Slang :: Subscripts per abilitarli.

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.