Expresando la secuencia de suma doble en Raku

13

¿Cómo expresar la secuencia de suma doble doble variable en Perl 6?

Para ver un ejemplo de secuencia de suma doble doble variable , vea esto

imagen

Debe expresarse como es, es decir, sin reducir matemáticamente la suma doble en una sola suma. Gracias.

Lars Malmsteen
fuente

Respuestas:

14

El X(operador cruzado) y el [+](metaoperador de reducción [ ]con operador aditivo +) hacen que esto sea sorprendentemente fácil:

Para representar 1 la suma doble ∑³ x  = 1 ∑⁵ y  = 1 2x + y , puede hacer lo siguiente:

  [+] 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 desea crear un subpara esto, puede escribirlo como los siguientes 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 incluso simplificar las cosas más para

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

Tenga en cuenta que al escribirlo, podemos garantizar que se pasan los rangos, pero al escribirlo en Iterablelugar de Rangepermitir secuencias de suma más interesantes, como, por ejemplo,ΣΣ (1..∞).grep(*.is-prime)[^99], 1..10, { … } eso nos permitiría usar la secuencia de los primeros 100 primos.

De hecho, si realmente quisiéramos, podríamos ir por la borda y permitir un operador arbitrario de suma de profundidad, que se hace más fácil moviendo la función a la izquierda:

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

Al igual que [+]resume todos los valores de nuestra f()función, [X]calcula la cruz iterativamente, por ejemplo, [X] 0..1, 3..4, 5..6primero does 0..1 X 3..4o (0,3),(0,4),(1,3),(1,4), y luego does (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. Lo siento, SO no me deja hacer LaTeX, pero debes tener la idea. 2. Sí, sé que es una letra de subíndice O no un cero, los números de subíndice no son identificadores válidos normalmente, pero puede usar Slang :: Subscripts para habilitarlos.

usuario0721090601
fuente