Somme en mouvement circulaire


24

Inspiré d' une question à Stack Overflow .

Étant donné un tableau d'entiers non vide xet un entier positif n, calculez la somme de chaque bloc glissant de longueur le nlong du tableau x, en remplissant de manière circulaire les valeurs manquantes à gauche avec des valeurs à droite comme suit:

  • le premier bloc contient la première entrée de x, précédée par n-1des entrées décalées circulairement;
  • le deuxième bloc a les première et deuxième entrées de x, précédées par n-2des entrées décalées circulairement; etc.

Le tableau de sortie ya la même taille que x. Il est possible nde dépasser la longueur de x, puis les valeurs de xsont réutilisées plusieurs fois de manière circulaire .

Exemples

Exemple 1 (les valeurs ne sont réutilisées qu'une seule fois)

x = [2, 4, -3, 0, -4]
n = 3

donner en sortie

y = [-2, 2, 3, 1, -7]

  • -2est la somme du bloc [0, -4, 2](les deux premières valeurs proviennent du décalage circulaire)
  • 2est la somme de [-4, 2, 4](la première valeur provient du décalage circulaire)
  • 3est la somme de [2, 4, -3](aucun décalage circulaire n'est plus nécessaire)
  • 1 est la somme de [4, -3, 0]
  • -7est la somme de [-3, 0, -4].

Exemple 2 (les valeurs sont réutilisées plusieurs fois)

x = [1, 2]
n = 5

donner

y = [7, 8]

  • 7est la somme du bloc [1, 2, 1, 2, 1](les quatre premières valeurs ont été réutilisées circulairement)
  • 8est la somme du bloc [2, 1, 2, 1, 2](les trois premières valeurs ont été réutilisées circulairement)

Règles supplémentaires

  • L'algorithme devrait fonctionner pour les tableaux de taille arbitraire et pour les valeurs entières arbitraires. Il est acceptable si le programme est limité par le type de données ou les restrictions de mémoire; mais les valeurs entières positives et négatives doivent être gérées.
  • Les entrées / sorties peuvent être prises / produites par tout moyen raisonnable .
  • Les programmes ou fonctions sont autorisés, dans n'importe quel langage de programmation . Les failles standard sont interdites.
  • Le code le plus court en octets gagne.

Cas de test

x, n, -> y

[2, 4, -3, 0, -4], 3          ->  [-2, 2, 3, 1, -7]
[1, 2], 5                     ->  [7, 8]
[2], 7                        ->  [14]
[-5, 4, 0, 1, 0, -10, -4], 4  ->  [-19, -15, -5, 0, 5, -9, -13]
[-5, 4, 0, 1, 0, -10, -4], 1  ->  [-5, 4, 0, 1, 0, -10, -4]
[-2, -1, 0, 1, 2, 3], 5       ->  [4, 3, 2, 1, 0, 5]
[-10, 0, 10], 4               ->  [-10, 0, 10]

6
Bah, pourquoi avez-vous dû utiliser les entrées précédentes?
Neil

Réponses:


3

Gelée , 5 octets

ṙC€}S

Essayez-le en ligne!

Comment ça marche

ṙC€}S  Main link. Arguments: A (array), n (positive integer)

   }   Apply the link to the left to the right argument (n).
 C€      Complement each; map (z -> 1-z) over [1, ..., n], yielding [0, ..., 1-n].
ṙ      Rotate A 0, ..., 1-n units to the left (i.e., 0, ..., n-1 units to the
       right), yielding a 2D array.
    S  Take the sum of the rows.

7

MATL, 11 10 9 7 octets

3 octets économisés grâce à @Luis!

:gyn&Z+

La première entrée est la taille de la fenêtre et la deuxième entrée est le tableau

Essayez-le sur MATL Online

Explication

       % Implicitly grab the first input (n)
       %     STACK: { 3 }
:      % Create the array [1...n]
       %     STACK: { [1, 2, 3] }
g      % Convert it to a logical array, yielding an array of 1's of length n
       %     STACK: { [1, 1, 1] }
y      % Implicitly grab the second input and duplicate it
       %     STACK: { [2, 4, -3, 0, -4], [1, 1, 1], [2, 4, -3, 0, -4]}
n      % Determine the length of the array
       %     STACK: { [2, 4, -3, 0, -4], [1, 1, 1], 5}
&Z+    % Perform circular convolution
       %     STACK: { [-2, 2, 3, 1, -7] }
       % Implicitly display the result

6

Mathematica, 29 octets

RotateLeft[#,1-n]~Sum~{n,#2}&

Ou la même longueur:

ListConvolve[1~Table~#2,#,1]&

6

CJam (16 octets)

{_2$*ew1fb\,~)>}

Suite de tests en ligne . Il s'agit d'un bloc (fonction) anonyme qui prend le tableau et la longueur sur la pile et laisse un tableau sur la pile.

Dissection

{       e# Declare a block
  _2$*  e#   Repeat the array n times: this guarantees having enough windows even
        e#   if x is only a single element
  ew    e#   Take each window of n elements
  1fb   e#   Sum each of the windows
  \,~)  e#   Compute -n
  >     e#   Take the last n elements of the array of sums
}

4

Haskell, 57 octets

a#n|l<-length a=[sum[a!!mod j l|j<-[i-n..i-1]]|i<-[1..l]]

Essayez-le en ligne!

Juste quelques boucles d'index et l'accès à la liste d'entrée aux index modulent la longueur de la liste.


3

Haskell , 69 65 64 octets

r=reverse
s#n=r$init[sum$take n$x++cycle(r s)|x<-scanr(:)[]$r s]

Essayez-le en ligne! Exemple d' utilisation: [2, 4, -3, 0, -4] # 3.


Utiliser les entrées n réussies au lieu des entrées précédentes pourrait représenter 50 à 46 octets (se débarrasser de l'inverse au début et à la fin):

s#n=init[sum$take n$x++cycle s|x<-scanr(:)[]s]

Essayez-le en ligne!



2

Pyth , 18 16 octets

Sauvegardé 2 octets grâce à @FryAmTheEggman !

JEms<.>*JQ-JhdJl

Essayez-le ici ou vérifiez tous les cas de test.

Correction de tous les défauts au coût de -6 octets ! Merci beaucoup à Luis de m'avoir fait comprendre la tâche dans le chat.


Explication (à mettre à jour)

KEms<>_*QhK-lQhdKU - Full program.

KE                 - Assign the second input to a variable K.
  m              U - Map over the range [0...len(first input)).
       *QhK        - First input * (Second input + 1).
      _            - Reverse.
     >     -lQhd   - All the elements of the above after len(x)-current element-1
    <          K   - Up until the second input.
   s               - Sum.

Cela pourrait être un meilleur moyen avant de reculer, en essayant de jouer au golf bientôt.
M. Xcoder

J'ai 16 octets, mais je pense qu'il devrait toujours y avoir quelque chose de plus court.
FryAmTheEggman

@FryAmTheEggman Merci. Je pense que cela devrait être plus court mais je ne sais pas comment
M. Xcoder

2

Java 8, 102 octets

Lambda (au curry) de int[]à lambda de Integerà int[]. Attribuer à Function<int[], Function<Integer, int[]>>.

a->n->{int l=a.length,o[]=new int[l],i=0,j;for(;i<l;i++)for(j=i-n;j++<i;)o[i]+=a[(j%l+l)%l];return o;}

Essayez-le en ligne

Lambda non golfé

a ->
    n -> {
        int
            l = a.length,
            o[] = new int[l],
            i = 0,
            j
        ;
        for (; i < l; i++)
            for (j = i - n; j++ < i; )
                o[i] += a[(j % l + l) % l];
        return o;
    }

(j % l + l) % lcalcule un reste non négatif pour tout j. Pris d' ici .



2

Octave, 53 octets

@(x,n)shift(imfilter(x,+!!(1:n),'circular'),fix(n/2))

Essayez-le en ligne!

  • La imfilterfonction avec option circularcalcule la convolution circulaire au centre de la fenêtre donc le résultat doit être décalé.

2

05AB1E , 10 octets

.׌ùOR¹g£R

Essayez-le en ligne!

Explication

.×           # repeat input_1 input_2 times
  Ν         # push all sublists of size input_2
    O        # sum each
     R       # reverse the list
      ¹g£    # take the first len(input_1) items
         R   # reverse the list

2

Perl 6 , 42 39 octets

{@^a;[«+»] map {@a.rotate(-$_)},^$^b}

Essayez-le en ligne!

Ma première entrée en Perl 6. Peut probablement être amélioré.


Notez que vous pouvez parfois réduire la longueur en utilisant un bloc pointu avec des variables sigilless plutôt qu'un bloc avec des paramètres d'espace réservé ->\a,\b{[«+»] map {a.rotate(-$_)},^b}Notez que ce n'est pas le cas dans ce cas, mais ce serait le cas s'il y avait une autre instance de $bdans le code.
Brad Gilbert b2gills

2

Kotlin , 141 140 138 octets

Juste un premier coup

Soumission

fun c(a:List<Int>,n:Int):List<Int>{
return (0..(a.size-1)).map{var t=0
for (o in 0..(n-1)){var i=it-o
while(i<0) {i+=a.size};t+=a[i]}
t}}

Embellie

fun c(a: List<Int>, n: Int): List<Int> {
    return (0..(a.size - 1)).map {    // Iterate over the items
        var t = 0                     // Start the total at 0
        for (o in 0..(n - 1)) {       // Start at the item, go over the window backwards
            var i = it - o            // -------------------------
            while (i < 0) {           //  Make the index in range
                i += a.size           //
            }                         // -------------------------
            t += a[i]                 // Add the item to the total
        }
        t                             // Return the total
    }
}

TryItOnline

Modifications

  • Suppression de la nouvelle ligne avant la dernière fermeture du support

1

Röda , 52 octets

f a,n{(a*n)|slide n|tail#a*n|{head n|sum}while open}

Essayez-le en ligne!

Explication:

f a,n{
  (a*n)|    /* Push the items in a n times to the stream */
  slide n|  /* Create a sliding block of length n */
  tail#a*n| /* Push the last n*len(a) values in the stream to the stream */
  {         /* While there are elements in the stream (stream is open): */
    head n| /*   Pull n values from the stream */
    sum     /*   Sum them and push the sum to the stream */
  } while open
}

1

JavaScript ES6 80 78 octets

x=>n=>x.map((_,i)=>eval('for(L=x.length,N=0,j=++i-n;j<i;j++)N+=x[(j%L+L)%L]'))

2 octets économisés grâce à Neil

Usage:

f=x=>n=>x.map((_,i)=>eval('for(L=x.length,N=0,j=++i-n;j<i;j++)N+=x[(j%L+L)%L]'))

f([2, 4, -3, 0, -4])(3)

1
Les ,Nregards inutiles pour moi ...
Neil

@Neil Vous avez raison, merci
Bálint


1

Python 2 , 69 61 octets

- 8 octets Merci beaucoup @muru

lambda x,n:[sum((x[-n+1:]+x*n)[i:i+n])for i in range(len(x))]

Essayez-le en ligne!

Explication:

Nous devons d'abord nous assurer qu'il y a suffisamment de chiffres à gauche de la liste d'origine, ceci est obtenu par le x*n+x partie.

Par exemple [2,4,-3,0,4],5:

                   ,2,4,-3,0,-4
 ....-4,2,4,-3,0,-4,2,4,-3,0,-4

Ensuite, nous inverserons la liste:

 <original->
 -4,0,-3,4,2, -4,0,-3, 4........
           <-2's block->     

Ensuite, nous obtenons des blocs correspondants pour chaque élément par [len(x)+~i:][:n]. La tranche sera inversée, c'est-à-dire que 2 gagnera un bloc: [2,-4,0,-3,4]qui est inverse de l'attendu [4,-3,0,-4,2], mais nous avons besoin de la somme après tout. Donc ça marche. :)


Vous ne savez pas pourquoi vous devez inverser en premier? Ne pouvez-vous pas modifier les tranches plus tard dans le sens inverse à la place?
M. Xcoder

@ Mr.Xcoder Je pense qu'il existe un moyen, mais ce moyen était moins fastidieux, donc je suis resté avec ça ...: D
officialaimm

1
Je pense que x[-n+1:]+x*ndevrait vous donner la liste avec un rembourrage suffisant de chaque côté, sans avoir à inverser ( lambda x,n:[sum((x[-n+1:]+x*n)[i:i+n])for i in range(len(x))])
muru

1
@muru Vous venez de l'éditer? Maintenant ça marche. Merci beaucoup!
officialaimm


1

K (oK) , 18 octets

Solution:

{+/+y':(1-y+#x)#x}

Essayez-le en ligne!

Exemples:

{+/+y':(1-y+#x)#x}[1 2;5]
7 8
{+/+y':(1-y+#x)#x}[-5 4 0 1 0 -10 -4;4]
-19 -15 -5 0 5 -9 -13
{+/+y':(1-y+#x)#x}[-10 0 10;4]
-10 0 10

Explication:

Était sur le point de publier une solution de 31 octets , alors je me suis souvenu que oK avait une fonction intégrée pour les fenêtres coulissantes ...

{+/+y':(1-y+#x)#x} / the solution
{                } / lambda with implicit x and y parameters
               #x  / take (#) from list x
       (    #x)    / length of x
          y+       / add y (window size)
        1-         / subtract from 1 to give a negative
    y':            / sliding window of size y
   +               / flip
 +/                / sum

Prime:

La solution de 31 octets qui fonctionne également en K4 :

q)k){+/+x#y#'|+(:':\|(1-y+x:#x)#x)}[2 4 -3 0 -4;3]
-2 2 3 1 -7
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.