Calcolo delle distanze mod N


13

Raccogli dati da un Advanced Collecting Device Controller ™ da molto tempo. Controlli i registri e con tuo orrore scopri che qualcosa è andato terribilmente storto: i dati contengono solo gli ultimi bit dei numeri!

Fortunatamente, conosci il valore iniziale e che il valore non cambia mai rapidamente. Ciò significa che puoi recuperare il resto semplicemente trovando la distanza dall'inizio.

Sfida

Scriverai un programma o una funzione per calcolare la quantità modificata da un valore, dato un modulo Ne un elenco dei valori intermedi modulo N.

Il cambio tra ogni coppia di numeri è sempre inferiore aN/2 , quindi ci sarà una sola risposta valida per ogni caso di test.

Ti verrà dato come input un numero intero N> 2 e un elenco di valori, in un formato a tua scelta. L'input può essere fornito tramite STDIN o riga di comando o argomenti di funzione.

Verrà emesso un singolo numero intero, la quantità del valore originale è stata modificata. L'output può essere stampato su STDOUT o restituito.

Regole

  • Il programma deve funzionare per qualsiasi distanza e modulo inferiori a 2^20.
  • Puoi presumere che:
    • Nè almeno 3.
    • L'elenco ha almeno 2 valori.
    • Tutti i valori nell'elenco sono almeno 0 e inferiori a N.
    • Tutte le modifiche ai numeri sono inferiori a N/2.
  • Qualsiasi altra cosa è un input non valido e il tuo programma può fare quello che vuole.
  • Sono vietate scappatoie standard, eventuali librerie non standard e funzioni integrate per questo preciso scopo.
  • Questo è , quindi vince il programma più breve in byte.

Esempi di casi di test

Ingresso:

3
0 1 2 2 0 1 0 2 1 2 0 1 2 1 1

Produzione:

4

Spiegazione (con valore di esempio):

Value mod 3: 0 1 2 2 0 1 0 2 1 2 0 1 2 1 1
Value:       0 1 2 2 3 4 3 2 1 2 3 4 5 4 4

Ingresso:

10
5 2 8 9 5

Produzione:

-10

Spiegazione (con valore di esempio):

Value mod 10:  5  2  8  9  5
Value:        15 12  8  9  5

Ingressi non validi:

2
0 0 0 0 0

(modulo troppo piccolo)

6
2 5 4 2

(cambio troppo grande tra 2 e 5)


Un formato a tua scelta è una pendenza scivolosa. La mia soluzione GolfScript può fare affidamento su un elenco di input simile :^;[5 2 8 9 5](\ ?
Lynn,

3
@Mauris Generalmente, no ... "un formato a tua scelta" di solito si presume che significhi "una rappresentazione convenzionale nella tua lingua preferita".
Martin Ender,

Tuttavia, puoi fare affidamento sull'elenco di input simile a "10 5 2 8 9 5" o "10,5 2 8 9 5" o "10 5,2,8,9,5".
Sparr,

Risposte:


2

TI-BASIC, 15 byte

Input N
sum(N/πtan⁻¹(tan(ΔList(πAns/N

Prende l'elenco da Anse il modulo da Input.

                       πAns/N    ; Normalize the list to [0,π)
                 ΔList(          ; Take differences, which are in the range (-π,π)
       tan⁻¹(tan(                ; Modulo, but shorter. Now elements are in (-π/2,π/2)
    N/π                          ; Multiply by N/π. These are displacements at each step.
sum(                             ; Add up all the displacements

9

Python 2, 53 byte

lambda n,l:sum((b-a+n/2)%n-n/2for a,b in zip(l,l[1:]))

Risposta super semplice. Mi chiedo se c'è un modo più breve.


Mi mancava quel poco. Grazie.
Lynn,

@Jakube L'ho già fatto - non ero a conoscenza di .:_2generare coppie finché non ho visto la tua risposta - Stavo usando zip.
orlp,

1
@Jakube Sono arrivato al 19 :)
orlp

7

Mathematica, 30 byte

Tr@Mod[Differences@#2,#,-#/2]&

Questa è una funzione anonima che accetta due argomenti. Esempio di utilizzo:

Tr@Mod[Differences@#2,#,-#/2]&[3, {0, 1, 2, 2, 0, 1, 0, 2, 1, 2, 0, 1, 2, 1, 1}]
(* 4 *)
Tr@Mod[Differences@#2,#,-#/2]&[10, {5, 2, 8, 9, 5}]
(* -10 *)

Questo funziona prendendo il Differencestra elementi successivi, avvolgendoli alla gamma -n/2di +n/2con Moded il suo parametro di offset, quindi portando il totale di Tr(traccia matrice, somma degli elementi diagonali).


Si noti che anche senza licenza è solo 43 byte!

f[n_, l_] := Total[Mod[Differences[l], n, -n/2]]

@non è necessario quando si sta già chiamando la funzione con parentesi quadre. Avere entrambi è un errore di sintassi.
David Zhang,

@DavidZhang Whoops, non so cosa stavo pensando. Mi serve bene per provare a rispondere senza aprire Mathematica!
Campion 2012

5

J, 24 byte

[+/@(]-(>-:)~*[)[|2-~/\]

Uso:

   f=:[+/@(]-(>-:)~*[)[|2-~/\]

   3 f 0 1 2 2 0 1 0 2 1 2 0 1 2 1 1
4

   10 f 5 2 8 9 5
_10

Proverò a giocare di più a golf e aggiungerò qualche spiegazione dopo.

Provalo online qui.


1
Sicuro che sia J e non CJam? : P
Ottimizzatore

4

Pyth, 20 19 byte

sm-J/Q2%+-FdJQ.:vw2

Stola .:_2da Jakube, idea da Mauris.


3

R, 38 byte

function(n,v)sum((diff(v)+n/2)%%n-n/2)

Questo crea una funzione senza nome che accetta un numero intero e un vettore come input e restituisce un singolo numero intero. Per chiamarlo, dagli un nome, ad es f=function(n,v)....

Ungolfed + spiegazione:

f <- function(n, v) {
    # Compute the differences between sequential elements of v
    d <- diff(v)

    # Add n/2 to the differences and get the result modulo n
    m <- (d + n/2) %% n

    # Subtract n/2 then sum the vector
    sum(m - n/2)
}

Esempi:

> f(3, c(0, 1, 2, 2, 0, 1, 0, 2, 1, 2, 0, 1, 2, 1, 1))
[1] 4

> f(10, c(5, 2, 8, 9, 5))
[1] -10

3

MatLab, 33 byte

@(x,y)sum(mod(diff(y)+x/2,x)-x/2)

Mi scuso, questa è la mia prima risposta su questo sito web. Digitando questo in MatLab, quindi usando l'input ans(modulus_value, [intermediate_values])si restituirà il valore richiesto, dove 'modulo_valore' è il valore del modulo e 'intermedio_valori' è un elenco dei valori intermedi separati da spazi o virgole.

Esempio:

ans(3, [0 1 2 2 0 1 0 2 1 2 0 1 2 1 1])

La funzione anonima sfrutta MatLab di mod, diffe sumfunzioni per calcolare la risposta. Innanzitutto, viene calcolata la differenza tra ciascuno dei valori intermedi. Il risultato viene quindi compensato dal modulo diviso per due, risultando in un insieme di valori di differenza che è vincolato da [-modulus / 2 modulo / 2]. Il risultato viene quindi sfalsato e nuovamente sommato.

Penso che si possa giocare di più, tornerò presto con un aggiornamento. Un ringraziamento speciale a @ 2012rcampion per l'idea.

Modifica: la unwrapfunzione di Matlab funziona quasi qui, ma è difficile da golf. Il codice seguente restituisce un array in cui l'ultimo valore è la quantità modificata dal primo valore: @(x,y)unwrap(y/x*2*pi)/2/pi*x-y(1)

I valori intermedi vengono ridimensionati nell'intervallo di [-pi pi], quindi "non imballati" in modo tale che nessun valore consecutivo sia superiore a pi. Questi valori vengono quindi ridimensionati e spostati, risultando in una matrice di distanze dal valore iniziale.

Interessante, ma non molto pratico per questa sfida: D


2

Pyth, 29 byte

+sm**._K-Fdvz>y.aKvz.:Q2-eQhQ

Provalo online: Pyth Compiler / Executor


L'input è separato da spazio, non separato da virgola; il tuo programma non sembra gestirlo.
Lynn,

2
@Mauris "un elenco di valori, in un formato a tua scelta"
Jakube

Oh mio Dio! Mi mancava totalmente quella parte delle specifiche.
Lynn,


2

Pip , 39 byte

Qn$+({a>n/2?a-na<-n/2?a+na}Mg@>1-g@<-1)

Richiede l'elenco di dati come argomenti della riga di comando e il modulo su STDIN. Se è troppo lungo, ho una versione che richiede due argomenti della riga di comando per altri 5 byte.

Spiegazione:

                                         g is list of cmdline args (implicit)
Qn                                       Read n from stdin
                            g@>1         All but the first of the cmdline args
                                -g@<-1   ...minus all but the last of the cmdline args
                                         (i.e. a list of the differences of adjacent items)
     {                    }M             ...to which, map the following function:
      a>n/2?a-n                            If diff is too big, subtract n;
               a<-n/2?a+n                  else if too small, add n;
                         a                 else return unchanged
  $+(                                 )  Sum; print (implicit)

E solo per dimostrare che questo punteggio non così competitivo è più riflettente sulle mie capacità di golf rispetto alla mia lingua, ecco un port della soluzione Python di Mauris in 30 byte :

Qn$+({(n/2-$-a)%n-n/2}MgZg@>1)

2

Gelatina , non competitiva

6 byte Questa risposta non è competitiva, poiché la sfida precede la creazione di Jelly.

Iæ%H}S

Provalo online!

Come funziona

Iæ%H}S    Main link. Left input: A (list). Right input: N (integer).

I         Compute the increments (deltas of consecutive elements) of A.
   H}     Halve the right input (N).
 æ%       Mod the increments into (-N/2, N/2].
     S    Take the sum of all results.
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.