Calcul des distances mod N

13

Vous collectez des données depuis un Advanced Collecting Device Controller ™ depuis longtemps. Vous consultez les journaux, et à votre horreur vous découvrez que quelque chose a terriblement mal tourné: les données ne contiennent que les derniers bits des chiffres!

Heureusement, vous connaissez la valeur de départ et la valeur ne change jamais rapidement. Cela signifie que vous pouvez récupérer le reste en trouvant simplement la distance depuis le début.

Défi

Vous écrirez un programme ou une fonction pour calculer le montant d'une valeur a changé, étant donné un module Net une liste des valeurs intermédiaires modulo N.

Le changement entre chaque paire de nombres est toujours inférieur àN/2 , il n'y aura donc qu'une seule réponse valide pour chaque cas de test.

Vous recevrez en entrée un entier N> 2 et une liste de valeurs, dans un format de votre choix. L'entrée peut être donnée via STDIN ou la ligne de commande ou des arguments de fonction.

Vous afficherez un seul entier, le montant de la valeur d'origine a changé. La sortie peut être imprimée sur STDOUT ou renvoyée.

Règles

  • Votre programme doit fonctionner pour n'importe quelle distance et module inférieur à 2^20.
  • Vous pouvez supposer que:
    • Nest au moins 3.
    • La liste a au moins 2 valeurs.
    • Toutes les valeurs de la liste sont au moins 0 et inférieures à N.
    • Tous les changements dans les nombres sont inférieurs à N/2.
  • Tout le reste est une entrée invalide et votre programme peut faire ce qu'il veut.
  • Les failles standard, toutes les bibliothèques non standard et les fonctions intégrées à cet effet sont interdites.
  • Il s'agit de , donc le programme le plus court en octets l'emporte.

Exemples de cas de test

Contribution:

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

Production:

4

Explication (avec exemple de valeur):

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

Contribution:

10
5 2 8 9 5

Production:

-10

Explication (avec exemple de valeur):

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

Entrées non valides:

2
0 0 0 0 0

(module trop petit)

6
2 5 4 2

(changement trop important entre 2 et 5)

PurkkaKoodari
la source
Un format de votre choix est une pente glissante. Ma solution GolfScript peut-elle s'appuyer sur une liste d'entrées ressemblant :^;[5 2 8 9 5](\ ?
Lynn
3
@Mauris Généralement, non ... "un format de votre choix" est généralement supposé signifier "une représentation conventionnelle dans la langue de votre choix".
Martin Ender
Vous pouvez toutefois vous fier à la liste de saisie qui ressemble à "10 5 2 8 9 5" ou "10,5 2 8 9 5" ou "10 5,2,8,9,5".
Sparr

Réponses:

2

TI-BASIC, 15 octets

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

Prend la liste de Ans et le module 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
la source
9

Python 2, 53 octets

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

Réponse super simple. Je me demande s'il y a un chemin plus court.

Lynn
la source
J'ai raté ce morceau. Merci.
Lynn
@Jakube Je l'ai déjà fait - je n'étais pas au courant de .:_2générer des paires avant d'avoir vu votre réponse - j'utilisais zip.
orlp
1
@Jakube Je suis descendu à 19 :)
orlp
7

Mathematica, 30 octets

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

Il s'agit d'une fonction anonyme qui prend deux arguments. Exemple d'utilisation:

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

Cela fonctionne en prenant les Differenceséléments successifs, en les enveloppant dans la plage -n/2à +n/2avec Modet son paramètre de décalage, puis en prenant le total avec Tr(trace matricielle, somme des éléments diagonaux).


Notez que même non golfé c'est seulement 43 octets!

f[n_, l_] := Total[Mod[Differences[l], n, -n/2]]
2012rcampion
la source
@est inutile lorsque vous appelez déjà la fonction entre crochets. Avoir les deux est une erreur de syntaxe.
David Zhang
@DavidZhang Oups, je ne sais pas à quoi je pensais. Me sert bien pour essayer de répondre sans ouvrir Mathematica!
2012rcampion
5

J, 24 octets

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

Usage:

   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

Je vais essayer de jouer au golf plus et ajouter quelques explications après cela.

Essayez-le en ligne ici.

randomra
la source
1
Bien sûr, son J et non CJam? : P
Optimizer
4

Pyth, 20 19 octets

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

Etole .:_2de Jakube, idée de Mauris.

orlp
la source
3

R, 38 octets

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

Cela crée une fonction sans nom qui accepte un entier et un vecteur en entrée et renvoie un seul entier. Pour l'appeler, donnez-lui un nom, par exemple f=function(n,v)....

Non golfé + explication:

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

Exemples:

> 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.
la source
3

MatLab, 33 octets

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

Mes excuses, c'est ma première réponse sur ce site. Taper ceci dans MatLab puis utiliser l'entrée ans(modulus_value, [intermediate_values])renverra la valeur demandée, où 'module_value' est la valeur du module, et 'intermediaire_values' est une liste des valeurs intermédiaires séparées par des espaces ou des virgules.

Exemple:

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

La fonction anonyme tire parti de MatLab mod,diff et des sumfonctions pour calculer la réponse. Tout d'abord, la différence entre chacune des valeurs intermédiaires est calculée. Le résultat est ensuite compensé par le module divisé par deux, résultant en un ensemble de valeurs de différence qui est lié par [-modulus / 2 module / 2]. Le résultat est ensuite décalé et additionné à nouveau.

Je pense que cela peut être joué plus, je reviendrai bientôt avec une mise à jour. Un merci spécial à @ 2012rcampion pour l'idée.

Edit: Matlab'sunwrap fonction fonctionne presque ici, mais c'est difficile de jouer au golf. Le code suivant retourne un tableau où la dernière valeur est le montant que la première valeur a changé: @(x,y)unwrap(y/x*2*pi)/2/pi*x-y(1)

Les valeurs intermédiaires sont mises à l'échelle dans la plage de [-pi pi], puis "dépliées" de sorte qu'aucune valeur consécutive ne soit à plus de pi. Ces valeurs sont ensuite redimensionnées et décalées, résultant en un tableau de distances par rapport à la valeur de départ.

Intéressant, mais pas très pratique pour ce défi: D

Robby
la source
2

Pyth, 29 octets

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

Essayez-le en ligne: Pyth Compiler / Executor

Jakube
la source
L'entrée est séparée par des espaces, pas par des virgules; votre programme ne semble pas gérer cela.
Lynn
2
@Mauris "une liste de valeurs, dans un format de votre choix"
Jakube
Oh, ma mauvaise! J'ai totalement raté cette partie de la spécification.
Lynn
2

Pip , 39 octets

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

Nécessite la liste des données comme arguments de ligne de commande et le module sur STDIN. Si c'est trop étiré, j'ai une version qui prend deux arguments de ligne de commande pour 5 octets de plus.

Explication:

                                         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)

Et juste pour prouver que ce score moins compétitif reflète mieux mes compétences de golf que ma langue, voici un portage de la solution Python de Mauris en 30 octets :

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

Gelée , non compétitive

6 octets Cette réponse n'est pas concurrente, car le défi est antérieur à la création de Jelly.

Iæ%H}S

Essayez-le en ligne!

Comment ça fonctionne

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
la source