Перейти масив!


19

Давайте пограємо в гру для одного гравця, яку називають стрибком масиву . Для відтворення, скажімо, потрібен лише масив цілих чисел a. Ви починаєте з якоїсь позиції i, і на кожному повороті ви переходите до нової позиції. У свою чергу n,

  • якщо nце рівно, ви переходите до абсолютного положення a[i] mod length(a),
  • якщо nце не дивно, ви стрибаєте у відносне положення (i + a[i]) mod length(a).

Індексація масиву починається з нуля. Ви можете рахувати перший стрибок як поворот 0або поворот 1, які дають іншу гру. Оскільки простір стану гри є обмеженим (ваш хід визначається вашою позицією та паритетом числа повороту), ви, звичайно, введете цикл рівної довжини. Позначається loop(a, i, b)довжиною цієї петлі, коли перший стрибок рахується як поворот b.

Вхідні дані

Непорожній масив aцілих чисел для гри в гру.

Вихідні дані

Максимальна кількість pтаких, що, починаючи з якоїсь позиції iі рахуючи перший виток як 0або 1, ви, врешті, вводите цикл довжини 2 * p. Іншими словами, ваш вихід - це число

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

Правила

Ви можете надати функцію або повну програму. Найменший байт виграє, а стандартні лазівки заборонені.

Тестові справи

[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 Так, останній варіант, як сказав Мартін.
Згарб

Я припускаю, що modце визначається як завжди позитивний ( -1 mod 5 == 4) на відміну від C. Це так?
nutki

@nutki Так, я використовую стиль Haskell mod, який завжди дає негативні результати.
Згарб

Якщо обертання нульової індексації дає результат, відмінний від одноіндексування, чи слід виводити результат, чи той, який менший?
KSFT

@ MartinBüttner Ні, я питав про індексацію поворотів , а не для масивів.
KSFT

Відповіді:


6

Pyth : 28 символів (Python 2: 116 символів)

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

Використання:

Спробуйте тут: компілятор / виконавець Pyth

Він очікує список цілих чисел як вхід [0,2,5,4,-9,0,-1,1,-1,1,-6]

Пояснення:

Я помітив одну важливу властивість функції loop: Для кожного iє a j, так що loop(a,i,0) == loop(a,j,1)і навпаки. Тому нам потрібно лише обчислити значення loop(a,i,b)для b=0.

Доведення: Якщо це цикл i -> j -> k -> ... -> z -> iз b = 0, тоді існує цикл j -> k -> ... -> z -> i -> jз b = 1.

Тому простий сценарій може працювати наступним чином. Перебрати все iі спробувати досягти iшляхом ітеративного обчислення i = a[(i + a[i]) mod len(a)] mod len(a). Оскільки це обчислення може запуститись у цикл без i, ми скасовуємо обчислення після len(a)кроків. Потім друкуємо максимальний цикл.

Реалізація Python 2 виглядає приблизно так ( 125 символів }:

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)

Для реалізації pyth я використав трохи інший підхід. Для кожного iя обчислюю список позицій і шукаю iв цьому списку.

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)  

редагувати: Python 2: 116 символів

Рішення @proud haskeller було на кілька символів коротшим, ніж моє рішення Python, тому мені довелося трохи скоротити його.

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

Різниця полягає в тому, що я обчислюю число рекурсивно замість ітераційного.


8

Пітон - 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
Якщо ви введете len(a)змінну і заміните всі len(a)s на ім'я цієї змінної, ви можете зберегти деякі символи.
ProgramFOX

1
Деякі ідеї: t+=1;t%=2-> t^=1та if t: j=(j+a[j])%z else: j=a[j]%z->j=(t*j+a[j])%z
Векторизований

1
Використовуйте лише один пробіл для відступу. Тут зберігається 9 символів.
PurkkaKoodari

1
Інша ідея: while c not in s[:-1]:могла б бути while(c in s[:-1])-1:.
PurkkaKoodari

1
І ще один. Ви не повинні використовувати j, оскільки цей цикл привласнює вміст range(z)для iзамість збільшення його. Просто замініть jна, iщоб зберегти 4 символи.
PurkkaKoodari

5

Хаскелл, 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

це генерує нескінченний список для кожної відправної точки (з причин гольфу ми повторюємо всі значення замість усіх індексів, які є еквівалентними). потім він обчислює цикл кожного списку (тривалість циклу xsстановить xs % []).

він використовує спостереження @ jakubes щодо циклів. оскільки це кроки 2 кроки одночасно, нам не потрібно ділити на кінець на 2.

Редагувати : тепер використовуючи хитрість @ MthViewMark відкидати перші nелементи, щоб гарантувати цикл із першим елементом. до речі, мені вдалося розіграти його алгоритм для 112персонажів:

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 символів

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

Приклади:

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

Це використовує спостереження @ jakube, що вам потрібно перевірити лише половину вихідних значень, виконуючи 2 кроки за ітерацію.


Ви можете скосити whereпопередній ]. Також ви намагалися використовувати cycle l!!iзамість l!!mod n(length l)?
гордий haskeller

Крім того, ви можете вбудовувати bі використовувати захисну схему |n<-l aдля усунення where.
гордий haskeller

2

Пітон, 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

Функція відповіді така j.
Рекурсивна функція lповертає довжину циклу для заданого масиву, початку та першого повороту, і функція jзнаходить макс.


Я думаю, що ви можете зберегти деякі символи, визначивши j з a lambda.
КСФТ

1

Математика, 189 162 161 байт

Якщо дозволені анонімні функції - 161 байт:

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

В іншому випадку - 163 байти:

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

Запуск цього на всіх тестових випадках:

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}

Пітон 2, 202 байти

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

Це майже порт моєї відповіді Mathematica.


Це дуже схоже на моє. Спочатку шахта була вимкнена однією (перш ніж розділитись на дві). Я досі не впевнений, чому, але я просто відняв одну, перш ніж розділити.
КСФТ

Я не знаю Mathematica, тому я не можу реально допомогти більше.
KSFT

@Zgarb О! Добре, що все пояснює. Я навіть про це не думав. Спасибі!
kukac67

Forз 3 аргументами зазвичай коротше While(оскільки ви можете заощадити на крапці з комою перед значком For).
Мартін Ендер

1

Математика, 113 112 символів

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

Приклад:

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

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'

Перший аргумент до уваги береться в довжину (ініціалізацію масиву в $1і bініціалізацію в $2- виберіть «гри»).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.