Berechnung der Entfernungen mod N

13

Sie haben lange Zeit Daten von einem Advanced Collecting Device Controller ™ gesammelt . Sie überprüfen die Protokolle und stellen zu Ihrem Entsetzen fest, dass etwas furchtbar schief gelaufen ist: Die Daten enthalten nur die letzten Bits der Zahlen!

Zum Glück kennen Sie den Startwert und wissen, dass sich der Wert nie schnell ändert. Das heißt, Sie können den Rest wiederherstellen, indem Sie nur die Entfernung vom Start finden.

Herausforderung

Sie schreiben ein Programm oder eine Funktion, um den Betrag zu berechnen, um den sich ein Wert geändert hat, wenn ein Modul Nund eine Liste der Zwischenwerte modulo gegeben sind N.

Der Wechsel zwischen jedem Zahlenpaar ist immer kleiner alsN/2 , sodass es für jeden Testfall nur eine gültige Antwort gibt.

Als Eingabe erhalten Sie eine Ganzzahl N> 2 und eine Werteliste in einem Format Ihrer Wahl. Die Eingabe kann über STDIN oder Befehlszeilen- oder Funktionsargumente erfolgen.

Sie geben eine einzelne Ganzzahl aus, den Betrag, um den sich der ursprüngliche Wert geändert hat. Die Ausgabe kann auf STDOUT gedruckt oder zurückgesendet werden.

Regeln

  • Ihr Programm muss für alle Entfernungen und Module arbeiten, die kleiner als 2^20.
  • Sie können davon ausgehen, dass:
    • Nist zumindest 3.
    • Die Liste hat mindestens 2 Werte.
    • Alle Werte in der Liste sind mindestens 0 und kleiner als N.
    • Alle Änderungen in den Zahlen sind kleiner als N/2.
  • Alles andere ist eine ungültige Eingabe, und Ihr Programm kann tun, was es will.
  • Standardlücken, nicht standardisierte Bibliotheken und integrierte Funktionen für diesen Zweck sind verboten.
  • Das ist , also gewinnt das kürzeste Programm in Bytes.

Beispiel Testfälle

Eingang:

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

Ausgabe:

4

Erklärung (mit Beispielwert):

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

Eingang:

10
5 2 8 9 5

Ausgabe:

-10

Erklärung (mit Beispielwert):

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

Ungültige Eingaben:

2
0 0 0 0 0

(zu kleiner Modul)

6
2 5 4 2

(zu großer Wechsel zwischen 2 und 5)

PurkkaKoodari
quelle
Ein Format Ihrer Wahl ist eine rutschige Steigung. Kann sich meine GolfScript-Lösung auf eine Eingabeliste verlassen, die so aussieht :^;[5 2 8 9 5](\ ?
Lynn
3
@ Mauris Im Allgemeinen bedeutet "ein Format Ihrer Wahl" nicht "eine konventionelle Darstellung in der Sprache Ihrer Wahl".
Martin Ender
Sie können sich jedoch darauf verlassen, dass die Eingabeliste wie folgt aussieht: "10 5 2 8 9 5" oder "10,5 2 8 9 5" oder "10 5,2,8,9,5".
Sparr

Antworten:

2

TI-BASIC, 15 Byte

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

Nimmt die Liste ab Ansund den Modul ab 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
quelle
9

Python 2, 53 Bytes

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

Super direkte Antwort. Ich frage mich, ob es einen kürzeren Weg gibt.

Lynn
quelle
Ich habe das ein bisschen verpasst. Vielen Dank.
Lynn
@Jakube Ich habe es bereits getan - ich wusste nicht, dass .:_2ich Paare generieren sollte, bis ich Ihre Antwort sah - ich habe zip verwendet.
Orlp
1
@ Jakube Ich habe es auf 19 :)
Orlp
7

Mathematica, 30 Bytes

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

Dies ist eine anonyme Funktion, die zwei Argumente akzeptiert. Beispielverwendung:

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

Dies funktioniert, indem die Differencesaufeinanderfolgenden Elemente in den Bereich -n/2bis +n/2mit Modund den dazugehörigen Offset-Parameter eingeschlossen und dann die Summe mit Tr(Matrix-Kurve, Summe der diagonalen Elemente) genommen werden.


Beachten Sie, dass es selbst ungolfed nur 43 Bytes sind!

f[n_, l_] := Total[Mod[Differences[l], n, -n/2]]
2012rcampion
quelle
@ist unnötig, wenn Sie die Funktion bereits mit eckigen Klammern aufrufen. Beides ist ein Syntaxfehler.
David Zhang
@ DavidZhang Whoops, weiß nicht, was ich gedacht habe. Es tut mir gut, wenn ich versuche zu antworten, ohne Mathematica zu öffnen!
2012rcampion
5

J, 24 Bytes

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

Verwendung:

   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

Ich werde versuchen mehr Golf zu spielen und danach eine Erklärung hinzufügen.

Probieren Sie es hier online aus.

randomra
quelle
1
Sicher es ist J und nicht CJam? : P
Optimizer
4

Pyth, 20 bis 19 Bytes

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

Stola .:_2aus Jakube, Idee von Mauris.

orlp
quelle
3

R, 38 Bytes

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

Dadurch wird eine unbenannte Funktion erstellt, die eine Ganzzahl und einen Vektor als Eingabe akzeptiert und eine einzelne Ganzzahl zurückgibt. Um es zu nennen, geben Sie ihm einen Namen, z f=function(n,v)....

Ungolfed + Erklärung:

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

Beispiele:

> 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.
quelle
3

MatLab, 33 Bytes

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

Entschuldigung, dies ist meine erste Antwort auf dieser Website. Wenn Sie dies in MatLab eingeben und dann die Eingabe verwenden, ans(modulus_value, [intermediate_values])wird der angeforderte Wert zurückgegeben, wobei 'modulus_value' der Modulwert ist und 'intermediate_values' eine Liste der durch Leerzeichen oder Kommas getrennten Zwischenwerte ist.

Beispiel:

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

Die anonyme Funktion nutzt Matlab mod, diffund sumFunktionen , die Antwort zu berechnen. Zunächst wird die Differenz zwischen den einzelnen Zwischenwerten berechnet. Das Ergebnis wird dann durch den durch zwei geteilten Modul versetzt, was zu einer Menge von Differenzwerten führt, die durch [- Modul / 2 Modul / 2] begrenzt ist. Das Ergebnis wird dann versetzt und erneut aufsummiert.

Ich denke, das kann man mehr Golf spielen, ich werde bald mit einem Update zurück sein. Besonderer Dank geht an @ 2012rcampion für die Idee.

Edit: Matlabs unwrapFunktion funktioniert hier fast, aber es ist schwierig, Golf zu spielen. Der folgende Code gibt ein Array zurück, in dem der letzte Wert dem Betrag entspricht, um den sich der erste Wert geändert hat: @(x,y)unwrap(y/x*2*pi)/2/pi*x-y(1)

Die Zwischenwerte werden auf den Bereich von [-pi pi] skaliert und dann "abgewickelt", so dass kein aufeinanderfolgender Wert mehr als pi voneinander entfernt ist. Diese Werte werden dann neu skaliert und verschoben, was zu einer Reihe von Abständen vom Startwert führt.

Interessant, aber nicht sehr praktisch für diese Herausforderung: D

Robby
quelle
2

Pyth, 29 Bytes

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

Probieren Sie es online aus: Pyth Compiler / Executor

Jakube
quelle
Die Eingabe ist durch Leerzeichen und nicht durch Kommas getrennt. Ihr Programm scheint damit nicht fertig zu werden.
Lynn
2
@ Mauris "eine Liste von Werten in einem Format Ihrer Wahl"
Jakube
Oh mein Schlimmes! Ich habe diesen Teil der Spezifikation total verpasst.
Lynn
2

Pip , 39 Bytes

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

Erfordert die Liste der Daten als Befehlszeilenargumente und den Modul für STDIN. Wenn das zu viel ist, habe ich eine Version, die zwei Befehlszeilenargumente für weitere 5 Byte benötigt.

Erläuterung:

                                         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)

Und nur um zu beweisen, dass diese nicht so wettbewerbsfähige Punktzahl meine Golffähigkeiten besser widerspiegelt als meine Sprache, hier eine Portierung von Mauris 'Python-Lösung in 30 Bytes :

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

Gelee , nicht konkurrierend

6 bytes Diese Antwort ist nicht konkurrierend, da die Herausforderung vor der Erstellung von Jelly liegt.

Iæ%H}S

Probieren Sie es online!

Wie es funktioniert

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
quelle