Somma circolare


24

Ispirato da una domanda a StackTranslate.it .

Dato un array non vuoto di numeri interi xe un numero intero positivo n, calcolare la somma di ciascun blocco scorrevole di lunghezza nlungo l'array x, riempiendo circolarmente i valori mancanti a sinistra con i valori da destra come segue:

  • il primo blocco contiene la prima voce di x, preceduta da n-1voci spostate in modo circolare;
  • il secondo blocco ha la prima e la seconda voce di x, precedute da n-2voci spostate in modo circolare; e così via.

L'array di output yha le stesse dimensioni di x. È possibile nsuperare la lunghezza di x, quindi i valori di xvengono riutilizzati circolarmente più volte .

Esempi

Esempio 1 (i valori vengono riutilizzati una sola volta)

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

dare come output

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

dove

  • -2è la somma del blocco [0, -4, 2](i primi due valori provengono dallo spostamento circolare)
  • 2è la somma di [-4, 2, 4](il primo valore deriva dallo spostamento circolare)
  • 3è la somma di [2, 4, -3](non è più necessario lo spostamento circolare)
  • 1 è la somma di [4, -3, 0]
  • -7è la somma di [-3, 0, -4].

Esempio 2 (i valori vengono riutilizzati più volte)

x = [1, 2]
n = 5

dare

y = [7, 8]

dove

  • 7è la somma del blocco [1, 2, 1, 2, 1](i primi quattro valori sono stati riutilizzati in modo circolare)
  • 8è la somma del blocco [2, 1, 2, 1, 2](i primi tre valori sono stati riutilizzati in modo circolare)

Regole aggiuntive

  • L'algoritmo dovrebbe funzionare per matrici di dimensioni arbitrarie e per valori interi arbitrari. È accettabile se il programma è limitato dal tipo di dati o dalle restrizioni di memoria; ma devono essere gestiti valori interi positivi e negativi.
  • L'input / output può essere preso / prodotto con qualsiasi mezzo ragionevole .
  • Programmi o funzioni sono consentiti, in qualsiasi linguaggio di programmazione . Sono vietate le scappatoie standard .
  • Vince il codice più breve in byte.

Casi 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, perché hai dovuto usare le voci precedenti?
Neil,

Risposte:


3

Gelatina , 5 byte

ṙC€}S

Provalo online!

Come funziona

ṙ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 byte

3 byte salvati grazie a @Luis!

:gyn&Z+

Il primo input è la dimensione della finestra e il secondo input è l'array

Provalo su MATL Online

Spiegazione

       % 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 byte

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

O la stessa lunghezza:

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

6

CJam (16 byte)

{_2$*ew1fb\,~)>}

Suite di test online . Questo è un blocco (funzione) anonimo che prende l'array e la lunghezza nello stack e lascia un array nello stack.

Dissezione

{       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 byte

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

Provalo online!

Solo un po 'di ciclo di indice e l'accesso alla lista di input in indici modulo la lunghezza della lista.


3

Haskell , 69 65 64 byte

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

Provalo online! Esempio di utilizzo:[2, 4, -3, 0, -4] # 3 .


L'utilizzo delle voci n successive anziché precedenti potrebbe essere 50 46 byte (eliminando il contrario all'inizio e alla fine):

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

Provalo online!



2

Pyth , 18 16 byte

Salvato 2 byte grazie a @FryAmTheEggman !

JEms<.>*JQ-JhdJl

Provalo qui o Verifica tutti i casi di test.

Risolti tutti i difetti al costo di -6 byte ! Grazie mille a Luis per avermi fatto capire il compito in chat.


Spiegazione (da aggiornare)

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.

Potrebbe essere un modo migliore prima di fare retromarcia, provando presto a giocare a golf.
Mr. Xcoder,

Ottenuto 16 byte, ma sento che dovrebbe esserci ancora qualcosa di più corto.
FryAmTheEggman,

@FryAmTheEggman Grazie. Penso che dovrebbe essere più breve, ma non riesco a capire come
Mr. Xcoder,

2

Java 8, 102 byte

Lambda (al curry) da int[]a lambda da Integera int[]. Assegna a 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;}

Provalo online

Lambda ungolfed

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) % lcalcola un resto non negativo per qualsiasi j. Tratto da qui .



2

Ottava, 53 byte

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

Provalo online!

  • La imfilterfunzione con opzione circularcalcola la convoluzione circolare al centro della finestra, quindi il risultato dovrebbe essere spostato.

2

05AB1E , 10 byte

.׌ùOR¹g£R

Provalo online!

Spiegazione

.×           # 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 byte

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

Provalo online!

La mia prima voce in Perl 6. Probabilmente può essere migliorato.


Si noti che a volte è possibile ridurre la lunghezza utilizzando un blocco appuntito con variabili sigilless anziché un blocco con parametri segnaposto ->\a,\b{[«+»] map {a.rotate(-$_)},^b}Si noti che in questo caso non lo è, ma sarebbe se ci fosse un'altra istanza di $bnel codice.
Brad Gilbert b2gills

2

Kotlin , 141 140 138 byte

Solo un primo tentativo

Presentazione

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

Abbellire

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

Le modifiche

  • Newline rimosso prima dell'ultima parentesi di chiusura

1

Röda , 52 byte

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

Provalo online!

Spiegazione:

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 byte

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 byte salvati grazie a Neil

Uso:

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
Gli ,Nsguardi inutili per me ...
Neil

@Neil Hai ragione, grazie
Bálint,


1

Python 2 , 69 61 byte

- 8 byte Grazie mille @muru

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

Provalo online!

Spiegazione:

Per prima cosa dobbiamo assicurarci che ci siano abbastanza numeri a sinistra dell'elenco originale, questo è raggiunto dal x*n+x parte.

Ad esempio [2,4,-3,0,4],5:

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

Quindi invertiremo l'elenco:

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

Successivamente otteniamo i blocchi corrispondenti per ogni elemento di [len(x)+~i:][:n]. La sezione sarà inversa, ovvero 2 otterrà un blocco: [2,-4,0,-3,4]che è inversa rispetto al previsto [4,-3,0,-4,2], ma dopo tutto abbiamo bisogno della somma. Quindi funziona. :)


Non sei sicuro del motivo per cui devi prima invertire? Non puoi invece modificare le sezioni in seguito nella direzione opposta?
Mr. Xcoder,

@ Mr.Xcoder Penso che ci sia un modo, ma in questo modo era meno noioso, quindi mi sono attaccato a questo ...: D
officialaimm

1
Penso che x[-n+1:]+x*ndovrei darti l'elenco con sufficiente imbottitura su entrambi i lati, senza dover invertire ( lambda x,n:[sum((x[-n+1:]+x*n)[i:i+n])for i in range(len(x))])
muru,

1
@muru L'hai appena modificato? Ora funziona. Molte grazie!
officialaimm,


1

K (oK) , 18 byte

Soluzione:

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

Provalo online!

Esempi:

{+/+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

Spiegazione:

Stavo per pubblicare una soluzione a 31 byte , poi mi sono ricordato che oK ha un built-in per finestre scorrevoli ...

{+/+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

Bonus:

La soluzione a 31 byte che funziona anche in K4 :

q)k){+/+x#y#'|+(:':\|(1-y+x:#x)#x)}[2 4 -3 0 -4;3]
-2 2 3 1 -7
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.