Meu jogo Diffy está degenerado?

23

Recentemente, postei uma pergunta sobre os jogos Diffy, que ficou sem resposta. Tudo bem, a pergunta é realmente difícil, mas eu gostaria de fazer uma pergunta mais fácil sobre os jogos do Diffy para que possamos fazer a bola rolar.


Como Diffy funciona

Copiado de Find Diffy Games

O jogo Diffy funciona da seguinte maneira: Você começa com uma lista de números inteiros não negativos; neste exemplo, usaremos

3 4 5 8

Então você toma a diferença absoluta entre números adjacentes

 (8)  3   4   5   8
    5   1   1   3

Então você repete. Você repete até perceber que inseriu um loop. E então geralmente o jogo começa do começo novamente.

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

A maioria dos jogos termina com uma série de zeros, o que é considerado um estado de perda, mas alguns jogos raros ficam presos em loops maiores.


Tarefa

Dado o estado inicial de um jogo Diffy, determine se o jogo atinge ou não um estado com todos os zeros. Você deve gerar um valor Truthy ou Falsy para cada um dos dois estados. Qual corresponde ao que não importa.

O objetivo é minimizar o número de bytes em sua fonte.

Assistente de Trigo
fonte
1
A redação da tarefa parece implicar que qualquer jogo que não atinja um estado de todos os zeros é, portanto, periódico. Anteriormente, periódico é definido como incluindo o estado inicial na sequência repetida. Isso significa que qualquer sequência finalmente atinge todos os zeros ou o estado inicial?
Trichoplax
3
Não: adicionar uma constante positiva a qualquer estado periódico diferente de zero resulta em um estado que não retorna a si mesmo nem atinge todos os zeros. Por exemplo, 1 1 0é periódico, assim 42 42 41como esse estado.
9788 Gregory Martin
3
De fato, para a pergunta específica que está sendo feita, nem é preciso ter uma noção de "periódico". "Eventualmente atinge um estado de todos os zeros" é independente e claro.
22817 Greg Greg
2
Eu provei uma caracterização parcial: se o tamanho da lista nfor ímpar, o jogo não será zero, a menos que todos os números sejam iguais. Se o comprimento for uma potência de 2, sempre será zero.
Xnor
3
Um limite do número de etapas para chegar a zero: uma lista com nelementos e o máximo de etapas mna maioria das n * bit_length(m)etapas. Então, n*mtambém é um limite superior. Um limite superior mais forte é t(n) * bit_length(m), onde t(n)está a maior potência de 2 que é um fator de n.
Xnor

Respostas:

27

Pitão, 6 bytes

suaV+e

Suíte de teste

Este programa é muito suave. 0 (falso) significa todos os zeros, qualquer outra coisa (verdade) significa nem todos os zeros.

Como funciona:

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.
isaacg
fonte
6
isso é uma suave solução
Martijn Vissers
14

Mathematica, 52 bytes

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

Função pura tomando uma lista de números inteiros não negativos como entrada e retorno Trueou False.

Abs[#-RotateLeft@#]&é uma função que executa uma rodada do jogo diffy. (Tecnicamente deveria ser RotateRight, mas a resposta final não é afetada e, ei, byte livre.) Portanto, Nest[...,#,R]executa Rrodadas do jogo diffy e, em seguida, 1>Max@detecta se o resultado é todos os zeros.

Como sabemos quantas rodadas de jogo difícil Rfazer? Se mfor o maior valor da entrada, observe que nunca produziremos um número inteiro maior que mnão importa quantas rodadas fizermos. O número total de listas de comprimento lde números inteiros não negativos todos delimitados por mé (m+1)^l. Portanto, se realizarmos as (m+1)^lrodadas do jogo diffy, é garantido que vimos alguma lista duas vezes até então, e assim estaremos na parte periódica do jogo. Em particular, o jogo termina em todos os zeros se e somente se o resultado das (m+1)^lrodadas do jogo for a lista de todos os zeros. Essa expressão é o que Max[1+#]^Tr[1^#]computa.

Greg Martin
fonte
6

Gelatina , 13 bytes

Ṁ‘*L
ṙ1ạ
ÇÑ¡Ṁ

Saídas 0 (falsey) se todo o estado zero for alcançado, caso contrário, um valor verdadeiro (um número inteiro positivo) será retornado.

Experimente online!

Utiliza a observação feita por Greg Martin, segundo a qual os números dentro da matriz nunca podem deixar o domínio [0, m] onde m é o elemento máximo na entrada; portanto, executar (m + 1) l arredonda onde l é o comprimento da entrada. basta.

Quão?

Ṁ‘*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
Jonathan Allan
fonte
Isso poderia ser melhorado com o limite do xnor ?
Assistente de trigo
@ WheatWizard Eu acho que custaria um byte. (Pode ser possível obter um método mais curto, coletando todos os resultados até que eles não sejam exclusivos, mas eu não o encontrei).
23617 Jonathan Allan
2

PHP, 144 bytes

imprima 0 para todo zero e qualquer valor inteiro positivo para 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);

Versão Online

Expandido

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
Jörg Hülsermann
fonte
1
array_push? Mas por que ?
Christoph
1
Além disso, se usar $_GETcomo entrada, você deve assumir que ele contém uma string.
Christoph
1
@Christoph ?0[0]=1&0[1]=1&0[2]=0ou ?0[]=1&0[]=1&0[]=0é uma série de strings, mas isso não importa. Mas você está certo, eu poderia torná-lo mais curto com o ?0=1&1=1&2=0por que não àrray_push`. Tenho certeza de que você ou Titus encontram maneiras melhores de contornar isso.
Jörg Hülsermann
1
array_push($e,$e[$c=0]);é simplesmente exatamente o mesmo $e[]=$e[$c=0];e você ainda usa a sintaxe ( $r[]=$n). Você já usa maxagora, portanto também deve substituir end($r)por, $nporque $né sempre igual a end($r)quando o eco é executado.
Christoph
@Christoph Parece que ontem não era o meu dia. Obrigado. Você me trazer para a minha ideia para uma nova entrada na seção dicas
Jörg Hülsermann
2

R (3.3.1), 87 bytes

Retorna zero para um jogo que termina com todos os zeros e um número positivo caso contrário.

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

aproveita o mesmo fato de Greg Martin e usa o diff embutido para fazer a diferença

Giuseppe
fonte
desde que xnor de ligado é correto (a partir dos comentários), este poderia ser dois bytes mais curto usando max (z) * comprimento (z), mas eu não estou convencido da exatidão
Giuseppe
1

Röda , 80 bytes

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

Experimente online!

Ungolfed:

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
}
fergusq
fonte
1

05AB1E , 13 bytes

Retorna 1 se terminar em zeros e 0 em caso contrário.

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

Experimente online!

Explicação

Usa o limite superior das rodadas: max(input)*len(input)explicado por xnor na seção de comentários.

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
Emigna
fonte
1

J, 22 bytes

Retorna 0(que está efetivamente falseem J) para um jogo degenerado que termina em todos os zeros. Retorna 1( true) se a enésima iteração contiver um número diferente de zero, em que n é igual ao maior número inteiro na sequência original multiplicado pelo comprimento da lista. Veja a resposta de Greg Martin, explicando por que isso é verdade.

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

Tradução:

  • Qual é o sinal *
  • do maior valor >./
  • quando você iterar o seguinte quantas vezes ^:( )
  • o comprimento da lista #multiplicado pelo *maior valor da lista >./:
    • tome o valor absoluto |&de
    • a diferença entre a lista (- )e
    • a lista girada por um 1&|.

Exemplos:

   *>./|&(-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
dinamarquês
fonte
1
Não é isso que afirmam Greg Martin. No entanto, o xnor possui limites melhores nos comentários acima (mas ainda não é apenas o maior número inteiro). O mais simples é multiplicar o maior valor pelo comprimento.
Ørjan Johansen
Boa pegada. Eu não estava prestando atenção suficiente. Eu vou consertar a solução.
Dane
1

JavaScript (ES6), 95 92 90 bytes

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)

Explicação

A função recursiva que se chama contanto que o contador (que começa no valor máximo da lista mais um na potência do comprimento da lista [ = (max + 1)**length]) não seja zero. Em cada chamada, o contador é decrementado e, quando atinge zero, todos os elementos da lista são verificados em relação a zero. Se todos forem iguais a zero, o programa retornará truee, falsecaso contrário.

Luke
fonte
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);

receber entrada via HTTP get, por exemplo, ?3&4&5&8salva alguns bytes.

Imprime 1 se atingir todos os zeros ou nada diferente.


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

pega a lista de argumentos via linha de comando. Eu tenho a sensação de que isso pode ser ainda mais jogado (olhando para @Titus).

Christoph
fonte
1

Python 3.6, 101 bytes

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)

Toma uma tupla de números e retorna False, se terminar em zeros, e True, se repetir.

RootTwo
fonte
0

JavaScript (ES6), 84 83 bytes

Retorna truepara um jogo que termina com todos os zeros, falsecaso contrário.

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)

Teste

Arnauld
fonte