Exprimer la séquence de double sommation dans Raku

13

Comment exprimer la séquence de double sommation double variable en Perl 6?

Pour un exemple de séquence de sommation double variable double , voir ceci

image

Il doit être exprimé tel quel, c'est-à-dire sans réduire mathématiquement la double sommation en une seule sommation. Je vous remercie.

Lars Malmsteen
la source

Réponses:

14

Le X(opérateur croisé) et le [+](méta- [ ]opérateur de réduction avec opérateur additif +) rendent cela étonnamment facile:

Pour représenter 1 la double sommation ∑³ x  = 1 ∑⁵ y  = 1 2x + y , vous pouvez procéder comme suit:

  [+] 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

Si vous souhaitez créer un subpour cela, vous pouvez l'écrire comme suit 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 }

Ou encore simplifier les choses pour

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

Notez qu'en le tapant, nous pouvons nous assurer que les plages sont passées, mais en le tapant comme Iterableplutôt que Rangenous pouvons permettre des séquences de sommation plus intéressantes, comme, disons, ΣΣ (1..∞).grep(*.is-prime)[^99], 1..10, { … }qui nous permettraient d'utiliser la séquence des 100 premiers nombres premiers.

En fait, si nous le voulions vraiment, nous pourrions aller trop loin et autoriser un opérateur de sommation de profondeur arbitraire, ce qui est rendu plus facile en déplaçant la fonction vers la gauche:

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

Tout comme [+]résume toutes les valeurs de notre f()fonction, [X]calcule la croix de manière itérative, par exemple, fait d' [X] 0..1, 3..4, 5..6abord 0..1 X 3..4ou (0,3),(0,4),(1,3),(1,4), puis fait (0,3),(0,4),(1,3),(1,4) X 5..6, ou (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. Désolé, SO ne me laisse pas faire LaTeX, mais vous devriez avoir l'idée. 2. Oui, je sais que c'est une lettre d'indice O et non un zéro, les numéros d'indice ne sont pas des identificateurs valides normalement, mais vous pouvez utiliser Slang :: Subscripts pour les activer.

user0721090601
la source