Salte a matriz!


19

Vamos jogar um jogo para um jogador chamado jump the array . Para jogar, você só precisa de uma matriz de números inteiros, digamos a. Você começa em alguma posição ie, em cada turno, salta para uma nova posição. Por sua vez n,

  • se nfor par, você pula para a posição absoluta a[i] mod length(a),
  • se nfor ímpar, você pula para a posição relativa (i + a[i]) mod length(a).

A indexação da matriz começa em zero. Você pode contar o primeiro salto como turno 0ou turno 1, o que dá um jogo diferente. Como o espaço de estado do jogo é finito (sua jogada é determinada pela sua posição e pela paridade do número do turno), é claro que você finalmente entrará em um loop de comprimento uniforme. Indique pela loop(a, i, b)duração desse loop, quando o primeiro salto é contado como turno b.

Entrada

Uma matriz não vazia ade números inteiros para jogar.

Resultado

O número máximo pque, ao iniciar em alguma posição ie contar o primeiro turno como um 0ou outro 1, você eventualmente insere um loop de comprimento 2 * p. Em outras palavras, sua saída é o número

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

Regras

Você pode atribuir uma função ou um programa completo. A menor contagem de bytes vence e as brechas padrão não são permitidas.

Casos de teste

[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 Sim, é a última opção, como disse Martin.
Zgarb

Presumo que modseja definido como sempre positivo ( -1 mod 5 == 4), diferentemente de C. É esse o caso?
nutki

@nutki Sim, eu uso um estilo Haskell mod, que sempre fornece resultados não negativos.
Zgarb

Se os turnos de indexação zero fornecerem um resultado diferente da indexação com um, devemos gerar um resultado ou qual é o menor?
KSFT

@ MartinBüttner Não, eu estava perguntando sobre indexar as curvas , não as matrizes.
KSFT

Respostas:


6

Pitão : 28 caracteres (caractere Python 2: 116)

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

Uso:

Experimente aqui: Pyth Compiler / Executor

Ele espera uma lista de números inteiros como entrada [0,2,5,4,-9,0,-1,1,-1,1,-6]

Explicação:

Notei uma propriedade importante da função loop: para cada uma iexiste uma j, de modo que loop(a,i,0) == loop(a,j,1)e vice-versa. Portanto, precisamos apenas calcular os valores loop(a,i,b)para b=0.

Prova: se o ciclo é i -> j -> k -> ... -> z -> icom b = 0, então existe o ciclo j -> k -> ... -> z -> i -> jcom b = 1.

Portanto, um script simples pode funcionar da seguinte maneira. Repita sobre todos ie tente alcançá-lo icomputando iterativamente i = a[(i + a[i]) mod len(a)] mod len(a). Como esse cálculo pode ocorrer em um ciclo sem i, cancelamos o cálculo após as len(a)etapas. Em seguida, imprimimos o ciclo máximo.

Uma implementação do Python 2 se parece com isso ( 125 caracteres }:

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)

Para a implementação do pyth, usei uma abordagem um pouco diferente. Para cada ieu calculo a lista de posições e procuro inesta lista.

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)  

editar: Python 2: 116 caracteres

A solução do @proud haskeller era alguns caracteres menor que a minha solução Python, portanto, 'tive' que abreviá-la um pouco.

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

A diferença é que eu calculo o número recursivamente em vez de iterativamente.


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

11
Se você inserir len(a)uma variável e substituir all len(a)s pelo nome dessa variável, poderá salvar alguns caracteres.
ProgramFOX

11
Algumas idéias: t+=1;t%=2-> t^=1and if t: j=(j+a[j])%z else: j=a[j]%z->j=(t*j+a[j])%z
Vectorized

11
Use apenas um espaço para recuar. Salva 9 caracteres aqui.
precisa saber é o seguinte

11
Outra idéia: while c not in s[:-1]:poderia ser while(c in s[:-1])-1:.
PurkkaKoodari

11
E mais um. Você não precisa usar j, pois esse loop atribui o conteúdo de range(z)ao em ivez de incrementá-lo. Basta substituir jpor ipara salvar 4 caracteres.
precisa saber é o seguinte

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

isso gera uma lista infinita para cada ponto de partida (por razões de golfe, iteramos sobre todos os valores, em vez de todos os índices, que são equivalentes). depois calcula o ciclo de cada lista (a duração do ciclo xsé xs % []).

ele usa as observações de @ jakubes sobre ciclos. porque ele dá 2 passos por vez, não precisamos dividir por 2 no final.

Edit : agora usando o truque do @ MthViewMark de eliminar os primeiros nelementos para garantir um ciclo com o primeiro elemento. a propósito, eu consegui jogar seu algoritmo em 112caracteres:

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 caracteres

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

Exemplos:

λ: 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

Isso faz uso da observação de @ jakube de que você só precisa verificar metade dos valores iniciais, enquanto executa 2 etapas por iteração.


Você pode esmagar o wherepara o anterior ]. Além disso, você tentou usar em cycle l!!ivez de l!!mod n(length l)?
haskeller orgulhoso

Além disso, você pode incorporar be usar uma proteção de padrão |n<-l apara eliminar o where.
haskeller orgulhoso

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

A função de resposta é j.
A função recursiva lretorna o comprimento do loop para uma determinada matriz, início e primeiro turno, e a função jencontra o máximo.


Eu acho que você pode salvar alguns caracteres definindo j com a lambda.
KSFT

1

Mathematica, 189 162 161 bytes

Se funções anônimas forem permitidas - 161 bytes:

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]&

Caso contrário - 163 bytes:

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]&

Executando isso em todos os casos de teste:

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

Resulta em:

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

Python 2, 202 bytes

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

Esta é quase uma porta da minha resposta do Mathematica.


Isto parece muito semelhante ao meu. O meu foi desligado por um (antes de dividir por dois) no início. Ainda não sei por que, mas apenas subtraí um antes de dividir.
KSFT

Não conheço o Mathematica, por isso não posso ajudar mais.
KSFT

@Zgarb Oh! Bem, isso explica tudo. Eu nem pensei nisso. Obrigado!
precisa saber é o seguinte

Forcom 3 argumentos geralmente é menor que While(já que você pode economizar um ponto e vírgula na frente do For).
Martin Ender

1

Mathematica, 113 112 caracteres

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

Exemplo:

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

ised 82

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'

O primeiro argumento não conta em tamanho (inicialização de array $1e binicialização em $2- selecione o "jogo").

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.