计算距离mod N


13

很长时间以来,您一直在从Advanced Collecting Device Controller™收集数据。您检查了日志,并惊恐地发现出了什么问题:数据只包含数字的最后几位!

幸运的是,您知道初始值,并且该值永远不会快速变化。这意味着您可以通过查找起点之间的距离来恢复其余部分。

挑战

您将编写一个程序或函数来计算值的变化量,给定一个模数N和一系列中间值modulo N

每对数字之间的变化始终小于N/2,因此每个测试用例只有一个有效答案。

将以N您选择的格式为您提供输入> 2 的整数和值列表作为输入。输入可以通过STDIN或命令行或函数自变量给出。

您将输出一个整数,原始值已更改的数量。输出可以打印到STDOUT或返回。

规则

  • 您的程序必须能以小于的距离和模数工作2^20
  • 您可以假设:
    • N至少是3
    • 该列表至少包含2个值。
    • 列表中的所有值都至少为0且小于N
    • 数字中的所有变化均小于N/2
  • 其他都是无效的输入,您的程序可能会做任何想做的事情。
  • 禁止为此目的而使用标准漏洞,任何非标准库和内置函数。
  • 这是,因此以字节为单位的最短程序获胜。

示例测试用例

输入:

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

输出:

4

说明(带有示例值):

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

输入:

10
5 2 8 9 5

输出:

-10

说明(带有示例值):

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

输入无效:

2
0 0 0 0 0

(模数太小)

6
2 5 4 2

(2到5之间的变化太大)


您选择的格式是滑坡。我的GolfScript解决方案可以依赖看起来像这样的输入列表:^;[5 2 8 9 5](\ 吗?
林恩

3
@Mauris通常,不,...“您选择的格式”通常被认为表示“您选择的语言的常规表示形式”。
马丁·恩德

但是,您可以依赖看起来像“ 10 5 2 8 9 5”或“ 10,5 2 8 9 5”或“ 10 5,2,8,9,5”的输入列表。
Sparr 2015年

Answers:


2

TI-BASIC,15字节

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

从中获取列表,从中获取Ans模数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个字节

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

超级直截了当的答案。我想知道是否有更短的方法。


我错过了。谢谢。
林恩

@Jakube我已经做到了-在.:_2看到您的答案之前,我不知道要生成对-我正在使用zip。
orlp 2015年

1
@Jakube我将其降至19 :)
Orlp

7

Mathematica,30个字节

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

这是一个带有两个参数的匿名函数。用法示例:

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

这是通过取Differences连续元素之间的距离,将它们包装-n/2+n/2with 的范围Mod和其offset参数,然后取总计with Tr(矩阵轨迹,对角元素的总和)来实现的。


请注意,即使是取消高尔夫,它也只有43个字节!

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

@当您已经使用方括号调用该函数时,则没有必要。两者都存在是语法错误。
张大卫

@DavidZhang哎呀,不知道我在想什么。为我提供尝试不打开Mathematica进行回答的权利!
2012rcampion 2015年

5

J,24个字节

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

用法:

   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

以后会尝试打更多的高尔夫球,并添加一些解释。

在这里在线尝试。


1
确定它的J而不是CJam吗?:P
Optimizer 2015年

4

Pyth,20个 19字节

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

.:_2从Jakube 偷走,从Mauris 偷走。


3

R,38个字节

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

这将创建一个未命名函数,该函数接受一个整数和一个向量作为输入并返回一个整数。要给它起个名字,例如f=function(n,v)...

取消+说明:

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

例子:

> 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个字节

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

抱歉,这是我在本网站上的第一个答案。在MatLab中键入此内容,然后使用输入ans(modulus_value, [intermediate_values])将返回请求的值,其中“ modulus_value”是模量值,“ intermediate_values”是中间值列表,中间用空格或逗号分隔。

例:

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

匿名函数利用MATLAB的的moddiffsum功能来计算的答案。首先,计算每个中间值之间的差。然后,将结果除以模量除以2,得到一组由[-模数/ 2模量/ 2]约束的差值。然后将结果偏移并再次求和。

我认为这可以打更多,我会尽快更新。特别感谢@ 2012rcampion的想法。

编辑: Matlab的unwrap功能几乎可以在这里工作,但是打高尔夫球很难。以下代码返回一个数组,其中最后一个值是第一个值已更改的数量: @(x,y)unwrap(y/x*2*pi)/2/pi*x-y(1)

将中间值缩放到π-pipi的范围,然后“解开”,以使连续的值之间相差不超过pi。然后,这些值将重新缩放并移动,从而形成与起始值的距离数组。

有趣,但对这个挑战不是很实用:D


2

Pyth,29个字节

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

在线尝试:Pyth编译器/执行器


输入以空格分隔,不以逗号分隔;您的程序似乎无法处理此问题。
林恩

2
@Mauris“值列表,以您选择的格式”
Jakube 2015年

哦,我不好!我完全错过了规范的那部分。
林恩


2

,39字节

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

需要数据列表作为命令行参数以及STDIN上的模数。如果这太麻烦了,我有一个版本需要两个命令行参数,每个字节5个字节。

说明:

                                         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)

只是为了证明这个不太高的得分比我的语言更能反映我的高尔夫技能,这里有30字节的Mauris Python解决方案:

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

2

果冻,无竞争

6 个字节 这个答案是非竞争性的,因为挑战早于创建Jelly。

Iæ%H}S

在线尝试!

怎么运行的

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.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.