Ausdrücken der doppelten Summationssequenz in Raku

13

Wie kann man die doppelte variable Doppelsummationssequenz in Perl 6 ausdrücken ?

Ein Beispiel für eine doppelte variable Doppelsummationssequenz finden Sie hier

Bild

Es muss so ausgedrückt werden, wie es ist, dh ohne die Doppelsumme mathematisch in eine Einzelsumme zu reduzieren. Vielen Dank.

Lars Malmsteen
quelle

Antworten:

14

Der X( [+]Kreuzoperator ) und der (Reduktionsmetaoperator [ ]mit additivem Operator +) machen dies überraschend einfach:

Um 1 die Doppelsummation ∑³ x  = 1 ∑⁵ y  = 1 2x + y darzustellen , können Sie Folgendes tun:

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

Wenn Sie ein dafür erstellen submöchten, können Sie es wie folgt schreiben: 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 }

Oder vereinfachen Sie die Dinge noch mehr

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

Beachten Sie, dass wir durch die Eingabe sicherstellen können, dass Bereiche übergeben werden, aber durch Eingabe als, Iterableanstatt Rangeinteressantere Summationssequenzen zuzulassen, wie zum Beispiel, ΣΣ (1..∞).grep(*.is-prime)[^99], 1..10, { … }dass wir die Sequenz der ersten 100 Primzahlen verwenden würden.

Wenn wir wirklich wollten, könnten wir sogar über Bord gehen und einen beliebigen Tiefensummierungsoperator zulassen, der am einfachsten gemacht wird, indem die Funktion nach links verschoben wird:

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

Berechnet genau wie [+]alle Werte unserer f()Funktion [X]das Kreuz iterativ, z. B. [X] 0..1, 3..4, 5..6zuerst 0..1 X 3..4oder (0,3),(0,4),(1,3),(1,4)und dann (0,3),(0,4),(1,3),(1,4) X 5..6oder (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. Entschuldigung, SO lässt mich LaTeX nicht machen, aber Sie sollten auf die Idee kommen. 2. Ja, ich weiß, dass dies ein tiefgestellter Buchstabe O ist, keine Null. Indexnummern sind normalerweise keine gültigen Bezeichner, aber Sie können Slang :: Subscripts verwenden , um sie zu aktivieren.

user0721090601
quelle