Il mio gioco Diffy è degenerato?


23

Di recente ho pubblicato una domanda sui giochi Diffy che è rimasta senza risposta. Va bene, la domanda è davvero difficile, ma vorrei fare una domanda più semplice sui giochi Diffy in modo che possiamo far rotolare la palla.


Come funziona Diffy

Copiato da Trova giochi diffusi

Il gioco Diffy funziona nel modo seguente: Inizi con un elenco di numeri interi non negativi, in questo esempio useremo

3 4 5 8

Quindi prendi la differenza assoluta tra i numeri adiacenti

 (8)  3   4   5   8
    5   1   1   3

Quindi ripeti. Ripeti finché non ti accorgi di essere entrato in un ciclo. E poi generalmente il gioco ricomincia dall'inizio.

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

La maggior parte dei giochi termina in una serie di zeri, che è considerato uno stato perdente, ma alcuni rari giochi rimangono bloccati in loop più grandi.


Compito

Dato lo stato iniziale di un gioco Diffy, determinare se il gioco alla fine raggiunge uno stato di tutti zeri. Dovresti produrre un valore di Verità o Falsia per ciascuno dei due stati. Che corrisponde a cui non importa.

L'obiettivo è ridurre al minimo il numero di byte nella sorgente.


1
La formulazione del compito sembra implicare che qualsiasi gioco che non raggiunge uno stato di tutti gli zeri è quindi periodico. In precedenza, periodico è definito come includendo lo stato iniziale nella sequenza ripetuta. Questo significa che ogni sequenza alla fine raggiunge o tutti gli zero o lo stato iniziale?
trichoplax,

3
No: l'aggiunta di una costante positiva a qualsiasi stato periodico diverso da zero determina uno stato che non ritorna a se stesso né va a tutti gli zeri. Ad esempio, 1 1 0è periodico, così 42 42 41è un tale stato.
Greg Martin,

3
In effetti, per la domanda specifica che viene posta, non è nemmeno necessaria una nozione di "periodico". "Alla fine raggiunge uno stato di tutti zeri" è autonomo e chiaro.
Greg Martin,

2
Ho dimostrato una caratterizzazione parziale: se la lunghezza dell'elenco nè dispari, il gioco non va a zero a meno che tutti i numeri siano uguali. Se la lunghezza è una potenza di 2, va sempre a zero.
xnor

3
Un limite del numero di passaggi per raggiungere lo zero: un elenco con nelementi e numero massimo mdi n * bit_length(m)passaggi nella maggior parte dei passaggi. Quindi, n*mè anche un limite superiore. Un limite superiore più forte è t(n) * bit_length(m), dov'è t(n)il potere maggiore di 2 che è un fattore di n.
xnor

Risposte:


27

Pyth, 6 byte

suaV+e

Suite di test

Questo programma è molto soave. 0 (falsa) significa tutti gli zeri, qualsiasi altra cosa (verità) significa non tutti gli zero.

Come funziona:

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
questa è una soluzione delicata
Martijn Vissers,

14

Mathematica, 52 byte

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

Funzione pura che prende un elenco di numeri interi non negativi come input e return Trueo False.

Abs[#-RotateLeft@#]&è una funzione che esegue un round del gioco diffy. (Tecnicamente dovrebbe essere RotateRight, ma la risposta definitiva non è interessata, e hey, byte libero.) Quindi Nest[...,#,R]esegue i Rround del gioco diffy, e quindi 1>Max@rileva se il risultato è tutto zero.

Come facciamo a sapere quanti round di gioco diffy Rdevono fare? Se mè il valore più grande nell'input, nota che non produrremo mai un numero intero maggiore di mqualsiasi numero di round facciamo. Il numero totale di elenchi di lunghezza ldi numeri interi non negativi tutti delimitati mè (m+1)^l. Quindi, se eseguiamo i (m+1)^lround del gioco diffy, ci sarà garantito di aver già visto un paio di liste due volte, e quindi saremo nella parte periodica del gioco. In particolare, il gioco termina in tutti gli zeri se e solo se il risultato di (m+1)^lround del gioco è l'elenco di tutti zeri. Quell'espressione è ciò che Max[1+#]^Tr[1^#]calcola.


6

Gelatina , 13 byte

Ṁ‘*L
ṙ1ạ
ÇÑ¡Ṁ

Emette 0 (falso) se verrà raggiunto lo stato tutto zero, altrimenti viene restituito un valore di verità (un numero intero positivo).

Provalo online!

Utilizza l'osservazione fatta per la prima volta da Greg Martin che i numeri all'interno dell'array potrebbero non lasciare mai il dominio [0, m] dove m è l'elemento massimo nell'input, quindi eseguendo (m + 1) l arrotondamenti dove l è la lunghezza dell'input sufficiente.

Come?

Ṁ‘*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

Questo potrebbe essere migliorato con il limite di xnor ?
Wheat Wizard

@WheatWizard Penso che costerebbe un byte. (Potrebbe essere possibile ottenere un metodo più breve raccogliendo tutti i risultati fino a quando non sono univoci, ma non l'ho trovato).
Jonathan Allan,

2

PHP, 144 byte

stampa 0 per tutto zero e qualsiasi valore intero positivo per vero

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

Versione online

allargato

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? Ma perché ?
Christoph,

1
anche se usando $_GETcome input dovresti assumere che contenga una stringa.
Christoph,

1
@Christoph ?0[0]=1&0[1]=1&0[2]=0o ?0[]=1&0[]=1&0[]=0è un array di stringhe ma questo non ha importanza. Ma hai ragione, potrei accorciarlo con il ?0=1&1=1&2=0motivo per cui non àrray_push` Sono sicuro che tu o Titus trovate modi migliori per accorciarlo.
Jörg Hülsermann,

1
array_push($e,$e[$c=0]);è semplicemente lo stesso di $e[]=$e[$c=0];e già usi la sintassi ( $r[]=$n). maxAdesso lo usi già, quindi dovresti anche sostituirlo end($r)con $nperché $nè sempre uguale a end($r)quando viene eseguita l'eco.
Christoph,

@Christoph Sembra che ieri non sia stata la mia giornata. Grazie. Mi hai portato alla mia idea per una nuova voce nella sezione suggerimenti
Jörg Hülsermann

2

R (3.3.1), 87 byte

Restituisce zero per una partita che termina in tutti zeri e un numero positivo in caso contrario.

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

sfrutta lo stesso fatto di Greg Martin e usa il diff incorporato per fare il diffing


purché il limite di xnor sia corretto (dai commenti), questo potrebbe essere più breve di due byte usando max (z) * lunghezza (z) ma non sono convinto della correttezza
Giuseppe

1

Röda , 80 byte

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

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

1

05AB1E , 13 byte

Restituisce 1 se termina con zero e 0 altrimenti.

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

Provalo online!

Spiegazione

Usa il limite superiore dei round: max(input)*len(input)spiegato da xnor nella sezione commenti.

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 byte

Restituisce 0(che è effettivamente falsein J) per un gioco degenerato che termina in tutti gli zeri. Restituisce 1( true) se l'ennesima iterazione contiene un numero diverso da zero, dove n è uguale al numero intero più grande nella sequenza originale moltiplicato per la lunghezza dell'elenco. Vedi la risposta di Greg Martin che spiega perché questo è vero.

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

Traduzione:

  • Qual è il segno *
  • del massimo valore >./
  • quando ripetete quanto segue quante volte ^:( )
  • la lunghezza dell'elenco #moltiplicata per *il valore più grande dell'elenco >./:
    • prendere il valore assoluto |&di
    • la differenza tra l'elenco (- )e
    • l'elenco ruotato di uno 1&|.

Esempi:

   *>./|&(-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
Non è questa la tesi di Greg Martin. Tuttavia, xnor ha limiti migliori nei commenti sopra (ma non è solo il numero intero più grande). Il più semplice è moltiplicare il valore più grande per la lunghezza.
Ørjan Johansen,

Buona pesca. Non stavo prestando abbastanza attenzione. Riparerò la soluzione.
Dane,

1

JavaScript (ES6), 95 92 90 byte

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)

Spiegazione

La funzione ricorsiva che si chiama finché il contatore (che inizia con il valore massimo nell'elenco più uno alla potenza della lunghezza dell'elenco [ = (max + 1)**length]) non è zero. Ad ogni chiamata, il contatore viene decrementato e quando raggiunge lo zero, tutti gli elementi nell'elenco vengono controllati rispetto allo zero. Se sono tutti uguali a zero, il programma ritorna truee in caso falsecontrario.


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

prendendo input via HTTP get ad esempio ?3&4&5&8salva pochi byte.

Stampa 1 se raggiunge tutti gli zeri o nient'altro.


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

prende l'elenco degli argomenti dalla riga di comando. Ho la sensazione che questo possa essere ulteriormente migliorato (guardando @Titus).


1

Python 3.6, 101 byte

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)

Prende una tupla di numeri e restituisce False se termina in zeri e True se passa in loop.


0

JavaScript (ES6), 84 83 byte

Ritorna trueper una partita che termina con tutti zeri, falsealtrimenti.

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)

Test

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.