Salta l'array!


19

Facciamo una partita a un giocatore chiamata jump the array . Per giocare, hai solo bisogno di una matrice di numeri interi, diciamo a. Inizi da una certa posizione ie ad ogni turno salti in una nuova posizione. A turno n,

  • se nè pari, salti in posizione assoluta a[i] mod length(a),
  • se nè dispari, si salta nella posizione relativa (i + a[i]) mod length(a).

L'indicizzazione dell'array inizia da zero. Puoi contare il primo salto come turno 0o turno 1, che danno una partita diversa. Dato che lo spazio di stato del gioco è finito (la tua mossa è determinata dalla tua posizione e dalla parità del numero del turno), ovviamente alla fine entrerai in un ciclo di lunghezza pari. Indicato per loop(a, i, b)la lunghezza di questo ciclo, quando il primo salto viene conteggiato come turno b.

Ingresso

Un array non vuoto adi numeri interi con cui giocare.

Produzione

Il numero massimo ptale che, quando si inizia in una posizione ie si considera il primo turno come uno 0o 1, alla fine si immette un ciclo di lunghezza 2 * p. In altre parole, l'output è il numero

max { loop(a, i, b)/2 : i in [0 .. length(a)-1], b in [0,1] }

Regole

Puoi dare una funzione o un programma completo. Vince il conteggio di byte più piccolo e non sono consentite scappatoie standard.

Casi test

[0] -> 1
[-213] -> 1
[1,3,12,-1,7] -> 1
[2,3,5,7,9,11,13,17,19] -> 2
[-2,3,-5,7,-9,11,-13,17,-19,23,-27] -> 3
[0,2,5,4,-9,0,-1,1,-1,1,-6] -> 4

@ kukac67 Sì, è l'ultima opzione, come ha detto Martin.
Zgarb,

Suppongo che modsia definito come sempre positivo ( -1 mod 5 == 4) a differenza di C. È così?
Nutki,

@nutki Sì, uso uno stile Haskell mod, che dà sempre risultati non negativi.
Zgarb,

Se i turni di indicizzazione zero danno un risultato diverso da quello di indicizzazione, dovremmo produrre entrambi i risultati o quale di questi è inferiore?
KSFT,

@ MartinBüttner No, stavo chiedendo di indicizzare le curve , non le matrici.
KSFT,

Risposte:


6

Pyth : 28 caratteri (Python 2: 116 caratteri)

eSmhxtu+G%@Q+eG@QeGlQUQ]ddUQ

Uso:

Provalo qui: Pyth Compiler / Executor

Si aspetta un elenco di numeri interi come input [0,2,5,4,-9,0,-1,1,-1,1,-6]

Spiegazione:

Ho notato un'importante proprietà della funzione loop: per ognuno ic'è un j, quindi quello loop(a,i,0) == loop(a,j,1)e viceversa. Pertanto abbiamo solo bisogno di calcolare i valori loop(a,i,b)per b=0.

Prova: se è un ciclo i -> j -> k -> ... -> z -> icon b = 0, allora esiste il ciclo j -> k -> ... -> z -> i -> jcon b = 1.

Pertanto un semplice script può funzionare nel modo seguente. Iterate su tutto ie provate a raggiungerlo ielaborando iterativamente i = a[(i + a[i]) mod len(a)] mod len(a). Poiché questo calcolo può essere eseguito in un ciclo senza i, annulliamo il calcolo dopo i len(a)passaggi. Quindi stampiamo il ciclo massimo.

Un Python 2 sguardi di implementazione di questo tipo ( 125 carattere }:

a=input();A=len(a);m=[]
for i in range(A):
 j=i
 for c in range(A):
  j=a[(j+a[j])%A]%A
  if i==j:m+=[c+1];break
print max(m)

Per l'implementazione di Pyth ho usato un approccio leggermente diverso. Per ogni icomputo l'elenco delle posizioni e cerco iin questo elenco.

eSmhxtu+G%@Q+eG@QeGlQUQ]ddUQ  
  m                       UQ    for each d in [0, ..., len(input)-1] compute a
      u                ]d         list G (using reduce), 
                                  which is first initialized with G = [d]
                     UQ           for each H in [0, ..., len(input)-1]:
       +G                            append to G the value
         %@Q+eG@QeGlQ                   input[G[-1] +input[G[-1]] % len(input)
                                        (notice that list lookups in pyth work with modular wrapping)
     t                            remove the first value (which is d)
    x                    d        and find the index of d in this shortend list
                                  (it's -1, if d is not in the list)
   h                              add 1
eS                              print the maximum (end of sorted list)  

modifica: Python 2: 116 caratteri

La soluzione di haskeller di @proud era di pochi caratteri più corta della mia soluzione Python, quindi ho dovuto "accorciarlo" un po '.

a=input();A=len(a);l=lambda j,i,c:c<=A and(c*(i==j)or l(a[(j+a[j])%A]%A,i,c+1));print max(l(i,i,0)for i in range(A))

La differenza è che calcolo il numero in modo ricorsivo anziché iterativo.


8

Python - 157

a=input()
z=len(a)
b=[]
for i in range(z):
    s,c,t=[],"",0
    while(c in s[:-1])-1:j=(i*t+a[i])%z;c=`t`+`i`;s+=[c];t^=1
    b+=[len(s)-s.index(c)-1]
print max(b)/2

1
Se inserisci len(a)una variabile e sostituisci tutte le len(a)s con il nome di quella variabile, puoi salvare alcuni caratteri.
Programma FOX il

1
Alcune idee: t+=1;t%=2-> t^=1e if t: j=(j+a[j])%z else: j=a[j]%z->j=(t*j+a[j])%z
Vectorized

1
Usa solo uno spazio per rientrare. Salva 9 caratteri qui.
PurkkaKoodari,

1
Un'altra idea: while c not in s[:-1]:potrebbe essere while(c in s[:-1])-1:.
PurkkaKoodari,

1
E ancora uno. Non è necessario utilizzare j, poiché questo ciclo assegna il contenuto di range(z)a iinvece di incrementarlo. Basta sostituire jcon iper salvare 4 caratteri.
PurkkaKoodari,

5

Haskell, 120 105

f s|t<-l s=maximum[g$drop t$iterate(\i->s!!mod(i+s!!mod i t)t)i|i<-s]
g(x:s)=l$0:fst(span(/=x)o)
l=length

questo genera un elenco infinito per ogni punto di partenza (per motivi di golf si itera su tutti i valori anziché su tutti gli indici, che sono equivalenti). quindi calcola il ciclo di ciascun elenco (la durata del ciclo xsè xs % []).

utilizza le osservazioni di @ jakubes sui cicli. poiché esegue 2 passaggi alla volta, non è necessario dividere per 2 alla fine.

Modifica : ora usa il trucco di @ MthViewMark per eliminare i primi nelementi per garantire un ciclo con il primo elemento. a proposito, sono riuscito a golfare il suo algoritmo sui 112personaggi:

l=length
o(x:y)=1+l(takeWhile(/=x)y)
j a|n<-l a=maximum$map(o.drop n.iterate(\i->mod(a!!mod(i+a!!i)n)n))[0..n-1]

2

Haskell - 139 caratteri

l=length
o(x:y)=1+l(takeWhile(/=x)y)
j a=maximum$map(o.drop n.iterate(b!!))[0..n-1]
 where b=zipWith(\x y->mod(a!!mod(x+y)n)n)a[0..];n=l a

Esempi:

λ: j [0]
1

λ: j [-213]
1

λ: j [1,3,12,-1,7]
1

λ: j [2,3,5,7,9,11,13,17,19]
2

λ: j [-2,3,-5,7,-9,11,-13,17,-19,23,-27]
3

λ: j [0,2,5,4,-9,0,-1,1,-1,1,-6]
4

Questo fa uso dell'osservazione di @Jakube secondo cui è necessario controllare solo la metà dei valori iniziali, mentre si eseguono 2 passaggi per iterazione.


Puoi schiacciare whereil precedente ]. Inoltre, hai provato a utilizzare cycle l!!iinvece di l!!mod n(length l)?
orgoglioso haskeller il

Inoltre, è possibile incorporare be utilizzare una protezione del modello |n<-l aper eliminare where.
orgoglioso haskeller il

2

Python, 160

l=lambda a,b,c,d:(b,c)in d and len(d)-d.index((b,c))or l(a,(a[b]+[0,b][c])%len(a),~c,d+[(b,c)])
j=lambda a:max(l(a,b,c,[])for b in range(len(a))for c in(0,1))/2

La funzione per la risposta è j.
La funzione ricorsiva lrestituisce la lunghezza del loop per un determinato array, start e primo giro e la funzione jtrova il valore max.


Penso che puoi salvare alcuni personaggi definendo j con a lambda.
KSFT,

1

Mathematica, 189 162 161 byte

Se sono consentite funzioni anonime - 161 byte:

Max[l=Length;Table[b={};n=p;i=s-1;e:={i,n~Mod~2};While[b~Count~e<2,b~AppendTo~e;h=#[[i+1]];i=If[EvenQ@n++,h,i+h]~Mod~l@#];l@b-b~Position~e+1,{s,l@#},{p,0,1}]/4]&

Altrimenti - 163 byte:

f=Max[l=Length;Table[b={};n=p;i=s-1;e:={i,n~Mod~2};While[b~Count~e<2,b~AppendTo~e;h=#[[i+1]];i=If[EvenQ@n++,h,i+h]~Mod~l@#];l@b-b~Position~e+1,{s,l@#},{p,0,1}]/4]&

Eseguendo questo su tutti i casi di test:

f /@ {
  {0},
  {-213},
  {1, 3, 12, -1, 7},
  {2, 3, 5, 7, 9, 11, 13, 17, 19},
  {-2, 3, -5, 7, -9, 11, -13, 17, -19, 23, -27},
  {0, 2, 5, 4, -9, 0, -1, 1, -1, 1, -6}
}

Risultati in:

{1, 1, 1, 2, 3, 4}

Python 2, 202 byte

def l(a,n,i):
 b=[]
 while not[i,n]in b:b.append([i,n]);i=(a[i]if n<1 else i+a[i])%len(a);n+=1;n%=2
 return len(b)-b.index([i,n])
def f(a):print max([l(a,n,i) for n in[0,1]for i in range(len(a))])/2

DEMO

Questa è quasi una porta della mia risposta di Mathematica.


Sembra molto simile al mio. Il mio era spento per uno (prima di dividere per due) all'inizio. Non sono ancora sicuro del perché, ma ne ho sottratto uno prima di dividerlo.
KSFT,

Non conosco Mathematica, quindi non posso davvero aiutare di più.
KSFT,

@Zgarb Oh! Bene, questo spiega tutto. Non ci avevo nemmeno pensato. Grazie!
kukac67,

Forcon 3 argomenti è generalmente più breve di While(poiché è possibile salvare un punto e virgola davanti al For).
Martin Ender,

1

Mathematica, 113 112 caratteri

l=Length;m=MapIndexed;f=Max[l/@ConnectedComponents@Graph@m[Tr@#2->#&,Part@@Thread@Mod[#+{Tr@#2,1}&~m~#,l@#,1]]]&

Esempio:

f /@ {
  {0},
  {-213},
  {1, 3, 12, -1, 7},
  {2, 3, 5, 7, 9, 11, 13, 17, 19},
  {-2, 3, -5, 7, -9, 11, -13, 17, -19, 23, -27},
  {0, 2, 5, 4, -9, 0, -1, 1, -1, 1, -6}
}

{1, 1, 1, 2, 3, 4}


1

82 anni

ised '@1{0,2,5,4,-9,0,-1,1,-1,1,-6};@2{1};' '@{4 5}{(@3{:$1_x++x*@2{1-$2}:}2*#$1)::[#$1]};{1+?{:@5{$3::$5}=$4:}@::[2*#$1]_0}/2'

Il primo argomento non conta nella lunghezza (inizializzazione dell'array in $1e binizializzazione in $2- selezionare il "gioco").

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.