Cálculo de distancias mod N

13

Ha estado recolectando datos de un Advanced Collecting Device Controller ™ durante mucho tiempo. Revisas los registros y, para tu horror, descubres que algo ha salido terriblemente mal: ¡los datos solo contienen los últimos bits de los números!

Afortunadamente, sabes el valor inicial y que el valor nunca cambia rápidamente. Eso significa que puede recuperar el resto simplemente encontrando la distancia desde el principio.

Desafío

Escribirás un programa o una función para calcular la cantidad que ha cambiado un valor, dado un módulo Ny una lista de los módulos de valores intermedios N.

El cambio entre cada par de números siempre es menor queN/2 , por lo que solo habrá una respuesta válida para cada caso de prueba.

Se le dará como entrada un número entero N> 2 y una lista de valores, en el formato que elija. La entrada puede darse a través de STDIN o la línea de comando o argumentos de función.

Producirá un solo entero, la cantidad que ha cambiado el valor original. La salida puede imprimirse en STDOUT o devolverse.

Reglas

  • Su programa debe funcionar para cualquier distancia y módulo menor que 2^20.
  • Puede suponer que:
    • Nes por lo menos 3.
    • La lista tiene al menos 2 valores.
    • Todos los valores en la lista son al menos 0 y menores que N.
    • Todos los cambios en los números son menores que N/2.
  • Cualquier otra cosa es una entrada no válida, y su programa puede hacer lo que quiera.
  • Las lagunas estándar, las bibliotecas no estándar y las funciones integradas para este propósito exacto están prohibidas.
  • Este es el , por lo que gana el programa más corto en bytes.

Ejemplos de casos de prueba

Entrada:

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

Salida:

4

Explicación (con valor de ejemplo):

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

Entrada:

10
5 2 8 9 5

Salida:

-10

Explicación (con valor de ejemplo):

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

Entradas inválidas:

2
0 0 0 0 0

(módulo demasiado pequeño)

6
2 5 4 2

(cambio demasiado grande entre 2 y 5)

PurkkaKoodari
fuente
Un formato de su elección es una pendiente resbaladiza. ¿Puede mi solución GolfScript basarse en una lista de entrada similar :^;[5 2 8 9 5](\ ?
Lynn
3
@Mauris En general, no ... se supone que "un formato de su elección" significa "una representación convencional en su idioma de elección".
Martin Ender
Sin embargo, puede confiar en la lista de entrada como "10 5 2 8 9 5" o "10,5 2 8 9 5" o "10 5,2,8,9,5".
Sparr

Respuestas:

2

TI-BASIC, 15 bytes

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

Toma la lista de Ansy el módulo de 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
lirtosiast
fuente
9

Python 2, 53 bytes

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

Súper respuesta directa. Me pregunto si hay un camino más corto.

Lynn
fuente
Eché de menos esa parte. Gracias.
Lynn
@Jakube Ya lo hice, no sabía .:_2generar pares hasta que vi tu respuesta, estaba usando zip.
orlp
1
@Jakube Lo bajé a 19 :)
orlp
7

Mathematica, 30 bytes

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

Esta es una función anónima que toma dos argumentos. Ejemplo de uso:

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

Esto funciona tomando los Differenceselementos sucesivos, envolviéndolos en el rango -n/2a +n/2con Mody su parámetro de compensación, y luego tomando el total con Tr(trazo de matriz, suma de elementos diagonales).


¡Tenga en cuenta que incluso sin golfizar solo tiene 43 bytes!

f[n_, l_] := Total[Mod[Differences[l], n, -n/2]]
Campeonato 2012
fuente
@es innecesario cuando ya está llamando a la función entre corchetes. Tener ambos es un error de sintaxis.
David Zhang,
@DavidZhang Vaya, no sé lo que estaba pensando. ¡Me parece correcto tratar de responder sin abrir Mathematica!
2012 Arcampion
5

J, 24 bytes

[+/@(]-(>-:)~*[)[|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

Intentaré jugar más al golf y agregaré alguna explicación después de eso.

Pruébelo en línea aquí.

randomra
fuente
1
Claro que es J y no CJam? : P
Optimizer
4

Pyth, 20 19 bytes

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

Robó .:_2de Jakube, idea de Mauris.

orlp
fuente
3

R, 38 bytes

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

Esto crea una función sin nombre que acepta un entero y un vector como entrada y devuelve un solo entero. Para llamarlo, asígnele un nombre, por ejemplo f=function(n,v)....

Ungolfed + explicación:

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

Ejemplos:

> 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
Alex A.
fuente
3

MatLab, 33 bytes

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

Mis disculpas, esta es mi primera respuesta en este sitio web. Al escribir esto en MatLab y luego usar la entrada, ans(modulus_value, [intermediate_values])se devolverá el valor solicitado, donde 'modulus_value' es el valor del módulo y 'intermedio_valores' es una lista de los valores intermedios separados por espacios o comas.

Ejemplo:

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

La función anónima se aprovecha de Matlab mod, diffy sumfunciones para calcular la respuesta. Primero, se calcula la diferencia entre cada uno de los valores intermedios. El resultado se compensa con el módulo dividido por dos, lo que da como resultado un conjunto de valores de diferencia que está unido por [módulo / módulo 2/2]. El resultado se compensa y suma de nuevo.

Creo que esto se puede jugar más, volveré pronto con una actualización. Un agradecimiento especial a @ 2012rcampion por la idea.

Editar: la unwrapfunción de Matlab casi funciona aquí, pero es difícil jugar al golf. El siguiente código devuelve una matriz donde el último valor es la cantidad que ha cambiado el primer valor: @(x,y)unwrap(y/x*2*pi)/2/pi*x-y(1)

Los valores intermedios se escalan al rango de [-pi pi], luego se "desenvuelven" de modo que ningún valor consecutivo esté más separado que pi. Estos valores se vuelven a escalar y desplazar, lo que da como resultado una serie de distancias desde el valor inicial.

Interesante, pero no muy práctico para este desafío: D

Robby
fuente
2

Pyth, 29 bytes

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

Pruébelo en línea: Pyth Compiler / Executor

Jakube
fuente
La entrada está separada por espacios, no por comas; su programa no parece manejar esto.
Lynn
2
@Mauris "una lista de valores, en un formato de su elección"
Jakube
¡Oh mi error! Extrañé totalmente esa parte de la especificación.
Lynn
2

Pip , 39 bytes

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

Requiere la lista de datos como argumentos de línea de comandos y el módulo en STDIN. Si eso es demasiado, tengo una versión que toma dos argumentos de línea de comando para 5 bytes más.

Explicación:

                                         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)

Y solo para demostrar que este puntaje no tan competitivo refleja más mis habilidades de golf que mi idioma, aquí hay un puerto de la solución Python de Mauris en 30 bytes :

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

Gelatina , no competidora

6 bytes Esta respuesta no es competitiva, ya que el desafío es anterior a la creación de Jelly.

Iæ%H}S

Pruébalo en línea!

Cómo funciona

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.
Dennis
fuente