我的Diffy游戏退化了吗?


23

最近,我发布了一个有关Diffy游戏问题,但尚未得到解答。很好,这个问题确实很困难,但是我想对Diffy游戏提出一个更简单的问题,以便我们能够解决问题。


Diffy如何运作

复制自Find Diffy Games

Diffy游戏的工作方式如下:从一个非负整数列表开始,在本示例中,我们将使用

3 4 5 8

然后取相邻数字之间的绝对差

 (8)  3   4   5   8
    5   1   1   3

然后重复。重复直到您意识到自己已经进入循环。通常,游戏会从头开始。

3 4 5 8
5 1 1 3
2 4 0 2
0 2 4 2
2 2 2 2
0 0 0 0
0 0 0 0

大多数游戏都以全零的字符串结尾,这被认为是失败状态,但是很少有游戏陷入较大的循环。


任务

给定Diffy游戏的开始状态,确定游戏是否最终达到全零状态。您应该为两个状态中的每个状态输出一个Truthy或Falsy值。哪个对应哪个都没有关系。

目标是最大程度地减少源中的字节数。


1
任务用语似乎暗示着任何未达到全零状态的游戏都是周期性的。之前,周期性定义为在重复序列中包括初始状态。这是否意味着任何序列最终都会达到全零或初始状态?
trichoplax

3
否:向任何非零周期状态添加正常数会导致既不返回自身也不返回全零的状态。例如,1 1 0是周期性的,42 42 41这样的状态也是如此。
格雷格·马丁

3
确实,对于所提出的具体问题,甚至不需要“周期性”的概念。“最终达到全零的状态”是自成体系的,并且很清楚。
格雷格·马丁

2
我已经证明了部分特征:如果列表长度n为奇数,除非所有数字均相等,否则游戏不会为零。如果长度是2的幂,则它始终为零。
xnor

3
要达到零的步数范围的界线:包含n元素和最大值的列表最多m需要n * bit_length(m)步数。因此,n*m也是一个上限。较高的上限是t(n) * bit_length(m),其中t(n)2的最大乘方是的因子n
xnor

Answers:


27

Pyth,6个字节

suaV+e

测试套件

这个程序很和ave。0(虚假)表示全零,其他(真)表示并非全零。

怎么运行的:

suaV+e
suaV+eGGGQ    Variable introduction.
 u       Q    Apply the following function repeatedly to its previous result,
              starting with the input. Stop when a value occurs which has
              occurred before.
  aV          Take the absolute differences between elements at the same indices of
        G     The previous list and
    +eGG      The previous list with its last element prepended.
s             The repeated value is returned. Sum its entries. This is zero (falsy)
              if and only if the entries are all zero.

6
多数民众赞成在一个温和的解决方案
Martijn Vissers'Apr

14

Mathematica,52个字节

1>Max@Nest[Abs[#-RotateLeft@#]&,#,Max[1+#]^Tr[1^#]]&

将非负整数列表作为输入并返回Trueor的纯函数False

Abs[#-RotateLeft@#]&是执行一轮难度游戏的功能。(从技术上讲应该是RotateRight,但最终答案不会受到影响,嘿,自由字节。)因此Nest[...,#,R]执行R一轮diffy游戏,然后1>Max@检测结果是否全为零。

我们如何知道R要进行几轮困难游戏?如果m是输入中的最大值,请注意,m无论我们进行多少回合,我们都不会产生大于的整数。全部为l的非负整数长度的列表总数m(m+1)^l。因此,如果我们进行(m+1)^l困难游戏的回合,那么到那时我们肯定会看到两次列表,因此将进入游戏的周期部分。特别是,当且仅当(m+1)^l游戏回合的结果是全零列表时,游戏才以全零结束。该表达式是Max[1+#]^Tr[1^#]计算的结果。


6

果冻,13 个字节

Ṁ‘*L
ṙ1ạ
ÇÑ¡Ṁ

如果将到达全零状态,则输出0(假),否则返回真值(正整数)。

在线尝试!

使用格雷格·马丁(Greg Martin)首先观察到的结果,数组中的数字可能永远不会离开域[0,m],其中m是输入中的最大元素,因此执行(m + 1)l个舍入,其中l是输入的长度将满足。

怎么样?

Ṁ‘*L - Link 1, number of rounds to perform: list a
Ṁ    - maximum of a
 ‘   - incremented
   L - length of a
  *  - exponentiate

ṙ1ạ - Link 2, perform a round: list x
ṙ1  - rotate x left by 1
  ạ - absolute difference (vectorises) with x

ÇÑ¡Ṁ - Main link: list a
  ¡  - repeat:
Ç    -     the last link (2) as a monad
 Ñ   -     the next link (1) as a monad times
   Ṁ - return the maximum of the resulting list

可以用xnor's bound改善它吗?
小麦巫师

@WheatWizard我认为这将花费一个字节。(通过收集所有结果直到它们不是唯一的,但我还没有找到它,可能有一种更短的方法)。
乔纳森·艾伦

2

PHP,144字节

打印0表示全零,任何正整数表示true

<?for($r[]=$_GET[0];!$t;){$e=end($r);$e[]=$e[$c=0];for($n=[];++$c<count($e);)$n[]=abs($e[$c-1]-$e[$c]);$t=in_array($n,$r);$r[]=$n;}echo max($n);

在线版本

展开式

for($r[]=$_GET;!$t;){
    $e=end($r);  # copy last array
    $e[]=$e[$c=0]; # add the first item as last item
    for($n=[];++$c<count($e);)$n[]=abs($e[$c-1]-$e[$c]); # make new array
    $t=in_array($n,$r); # is new array in result array
    $r[]=$n; # add the new array
}
echo max($n); # Output max of last array

1
array_push?但为什么 ?
Christoph'Apr

1
另外,如果$_GET用作输入,则应假定它包含一个字符串。
Christoph'Apr

1
@Christoph ?0[0]=1&0[1]=1&0[2]=0或是?0[]=1&0[]=1&0[]=0字符串数组,但这无关紧要。但是您是正确的,我可以通过?0=1&1=1&2=0不使用àrray_push` 来缩短它的长度,我相信您或Titus会找到更好的方法来缩短它。
—JörgHülsermann'17

1
array_push($e,$e[$c=0]);与完全相同,$e[]=$e[$c=0];甚至您已经在使用语法($r[]=$n)。max现在您已经使用过,因此也应该替换为end($r)$n因为$n它总是等于end($r)执行回显时的时间。
Christoph'Apr

@Christoph看来昨天不是我的日子。谢谢。你已经把我带到我的想法在尖端部分的新条目
约尔格Hülsermann

2

R(3.3.1),87字节

对于以全零结尾的游戏,返回零,否则返回正数。

z=scan();sum(Reduce(function(x,y)abs(diff(c(x,x[1]))),rep(list(z),max(z+1)^length(z))))

利用了格雷格·马丁(Greg Martin)的相同事实,并使用内置的差异进行差异化


如果xnor的边界是正确的(根据评论),则可以使用max(z)* length(z)缩短两个字节,但我不相信这种正确性
Giuseppe

1

Röda,80个字节

f l...{x=[{peek a;[_];[a]}()|slide 2|abs _-_];[sum(x)=0]if[x in l]else{x|f*l+x}}

在线尝试!

取消高尔夫:

function f(l...) { /* function f, variadic arguments */
    x := [ /* x is a list of */
        { /* duplicate the first element of the stream to the last position */
            peek a /* read the first element of the stream */
            [_]    /* pull all values and push them */
            [a]    /* push a */
        }() |
        slide(2) | /* duplicate every element except first and last */
        abs(_-_)   /* calculate the difference of every pair */
    ]
    /* If we have already encountered x */
    if [ x in l ] do
        return sum(x) = 0 /* Check if x contains only zeroes */
    else
        x | f(*l+x) /* Call f again, with x appended to l */
    done
}

1

05AB1E,13个字节

如果以零结尾则返回1,否则返回0

Z¹g*F¤¸ì¥Ä}_P

在线尝试!

说明

使用回合的上限:xnor在注释部分中进行了max(input)*len(input)解释。

Z              # get max(input)
 ¹g            # get length of input
   *           # multiply
    F          # that many times do:
     ¤         # get the last value of the current list (originally input)
      ¸        # wrap it
       ì       # prepend to the list
        ¥      # calculate deltas
         Ä     # calculate absolute values
          }    # end loop
           _   # negate each (turns 0 into 1 and everything else to 0)
            P  # calculate product

1

J,22个字节

返回以全零结尾的退化游戏的返回值0false在J中有效)。如果第n次迭代包含一个非零数字,则返回1true),其中n等于原始序列中最大的整数乘以列表的长度。请参阅格雷格·马丁(Greg Martin)的答案,以解释为何如此。

*>./|&(-1&|.)^:(#*>./)

翻译:

  • 什么标志 *
  • 最大的价值 >./
  • 当您多次迭代以下内容时 ^:( )
  • 清单的长度 #乘以*的最大值>./
    • 取绝对值|&
    • 列表(- )和之间的区别
    • 列表旋转一个 1&|.

例子:

   *>./|&(-1&|.)^:(#*>./) 1 1 0
1
   *>./|&(-1&|.)^:(#*>./) 42 42 41
1
   *>./|&(-1&|.)^:(#*>./) 3 4 5 8
0
   *>./|&(-1&|.)^:(#*>./) 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1
0

1
那不是格雷格·马丁的主张。但是,xnor在上面的注释中有更好的界限(但不仅限于最大整数)。最简单的是将最大值乘以长度。
与Orjan约翰森

接得好。我没有引起足够的重视。我将解决问题。
Dane

1

JavaScript(ES6),95 92 90字节

f=(a,b=(Math.max(...a)+1)**(c=a.length))=>b?f(a.map((v,i)=>v-a[++i%c]),b-1):a.every(v=>!v)

说明

只要计数器(从列表中的最大值开始,再加上列表[ = (max + 1)**length] 的长度的乘方)开始,递归函数就不为零。在每次调用时,计数器都会递减,当计数器为零时,将检查列表中的所有元素是否为零。如果它们都等于零,则程序返回truefalse否则返回。


1

PHP 123 115

for($a=$_GET,$b=[];!in_array($a,$b);){$b[]=$c=$a;$c[]=$c[0];foreach($a as$d=>&$e)$e=abs($e-$c[$d+1]);}echo!max($a);

通过HTTP获取输入获取例如 ?3&4&5&8节省了一些字节。

如果它达到全零,则输出1,否则输出1。


for($e=$argv,$r=[];!in_array($e,$r);$q=$e[0]){$e[0]=end($e);$r[]=$e;foreach($e as$k=>&$q)$q=abs($q-$e[$k+1]);}echo!max($e);

通过命令行获取参数列表。我觉得这可以打得更远(@Titus)。


1

Python 3.6,101个字节

def f(t):
 x={}
 while x.get(t,1):x[t]=0;t=(*(abs(a-b)for a,b in zip(t,t[1:]+t[:1])),)
 return any(t)

接受一个数字元组,如果以零结尾则返回False,如果循环则返回True。


0

JavaScript(ES6), 84 83字节

返回true以全零结尾的游戏,false否则返回。

f=(a,k=a)=>k[b=a.map((n,i)=>Math.abs(n-a[(i||a.length)-1]))]?!+b.join``:f(k[b]=b,k)

测试

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.