Моя гра Diffy вироджена?


23

Нещодавно я відправив на питання про Diffy іграх, залишилися без відповіді. Це добре, питання справді важке, але я хотів би зробити простіше питання про ігри Diffy, щоб ми могли отримати м'яч кочення.


Як працює Діффі

Скопійовано з Find Diffy Games

Гра Diffy працює так: Ви починаєте зі списку невід'ємних цілих чисел, у цьому прикладі ми будемо використовувати

3 4 5 8

Тоді ви берете абсолютну різницю між суміжними числами

 (8)  3   4   5   8
    5   1   1   3

Потім ти повториш. Ви повторюєте, поки не зрозумієте, що ввели цикл. І тоді взагалі гра починається з початку заново.

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

Більшість ігор закінчуються рядком з усіх нулів, що вважається втраченим станом, але рідкісна кількість ігор застряє у великих петлях.


Завдання

З огляду на початковий стан гри Diffy, визначте, чи гра в підсумку досягне стану всіх нулів. Ви повинні вивести значення Truthy або Falsy для кожного з двох станів. Що відповідає, що не має значення.

Мета - мінімізувати кількість байтів у вашому джерелі.


1
Формулювання завдання, мабуть, означає, що будь-яка гра, яка не досягає стану всіх нулів, є періодичною. Раніше періодичний визначається як включення початкового стану в повторювану послідовність. Чи означає це, що будь-яка послідовність зрештою досягає або всіх нулів, або початкового стану?
трихоплакс

3
Ні: додавання позитивної константи до будь-якого ненульового періодичного стану призводить до стану, який ні повертається до себе, ні переходить на всі нулі. Наприклад, 1 1 0є періодичним, таким 42 42 41є і такий стан.
Грег Мартін

3
Дійсно, для конкретного питання, яке задається, навіть не потрібно поняття "періодичний". "Врешті-решт досягає стану всіх нулів" є самодостатнім і зрозумілим.
Грег Мартін

2
Я довів часткову характеристику: Якщо довжина списку nнепарна, гра не перейде до нуля, якщо всі числа не рівні. Якщо довжина - потужність 2, вона завжди йде до нуля.
xnor

3
Обмеження кількості кроків до досягнення нуля: Список з nелементами та максимумом mзаймає не більше n * bit_length(m)кроків. Отже, n*mтакож є верхньою межею. Більш сильна верхня межа - t(n) * bit_length(m)де t(n)найбільша потужність 2, що є фактором n.
xnor

Відповіді:


27

Pyth, 6 байт

suaV+e

Тестовий набір

Ця програма дуже влучна. 0 (хибний) означає всі нулі, що-небудь інше (truthy) означає не всі нулі.

Як це працює:

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
ось вирішальне рішення
Martijn Vissers

14

Математика, 52 байти

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

Чистий функція приймає список невід'ємних цілих чисел в якості вхідних даних і повернення Trueабо False.

Abs[#-RotateLeft@#]&- це функція, яка виконує один раунд гри "складний". (Технічно це повинно бути RotateRight, але остаточна відповідь не зачіпається. Ей, вільний байт.) Так Nest[...,#,R]виконується Rраунд гри складності, а потім 1>Max@виявляється, чи є результат усіма нулями.

Як ми можемо знати, скільки раундів Rдля різних ігор зробити? Якщо mце найбільше значення вхідних даних, зауважте, що ми ніколи не будемо створювати ціле число, більше, ніж mнезалежно від того, скільки раундів ми зробимо. Загальна кількість списків довжини lневід’ємних цілих чисел, на які всі обмежені, mстановить (m+1)^l. Отже, якщо ми проводимо (m+1)^lраунди складної гри, ми гарантовано побачимо деякий список до цього часу, і таким чином будемо в періодичній частині гри. Зокрема, гра закінчується на всіх нулях тоді і лише тоді, коли результатом (m+1)^lраундів гри є список нулів. Цей вираз - це те, що Max[1+#]^Tr[1^#]обчислюється.


6

Желе , 13 байт

Ṁ‘*L
ṙ1ạ
ÇÑ¡Ṁ

Виводить 0 (фальси), якщо буде досягнуто всі нульовий стан, інакше повернеться триєдне значення (додатне ціле число).

Спробуйте в Інтернеті!

Використовує спостереження, вперше зроблене Грегом Мартіном, про те, що числа в масиві ніколи не можуть залишати область [0, m], де m - максимальний елемент на вході, тому виконання (m + 1) l кругів, де l - довжина входу, достатньо

Як?

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


@WheatWizard Я думаю, що це обійдеться в байт. (Можливо, можна отримати коротший метод, зібравши всі результати, поки вони не будуть унікальними, але я не знайшов його).
Джонатан Аллан

2

PHP, 144 байт

надрукуйте 0 для всіх нуля і будь-яке додатне ціле значення для істинного

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

Інтернет-версія

Розширено

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? Але чому ?
Крістоф

1
також якщо ви використовуєте $_GETяк вхід, слід припустити, що він містить рядок.
Крістоф

1
@Christoph ?0[0]=1&0[1]=1&0[2]=0або ?0[]=1&0[]=1&0[]=0це масив рядків, але це не має значення. Але ти маєш рацію, я міг би скоротити її, ?0=1&1=1&2=0чому б не àrray_push` Я впевнений, що ти чи Тит знайдемо кращі способи усунути це.
Йорг Гюльсерманн

1
array_push($e,$e[$c=0]);просто так само, як $e[]=$e[$c=0];і ви навіть використовуєте синтаксис вже ( $r[]=$n). Ви вже використовуєте в maxданий час , так що ви повинні також замінити end($r)з , $nтому що $nзавжди однаково , end($r)коли відлуння виконується.
Крістоф

@Christoph Схоже, що вчора не було мого дня. Дякую. Ви
підвели

2

R (3.3.1), 87 байт

Повертає нуль для гри, що закінчується всіма нулями, а додатне число - інакше.

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

використовує той самий факт, як Грег Мартін, і використовує вбудований розділ, щоб зробити складне


за умови, що обмеження xnor правильне (з коментарів), це може бути на два байти коротше, використовуючи max (z) * length (z), але я не переконаний у правильності
Giuseppe

1

Roda , 80 байт

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

Спробуйте в Інтернеті!

Безголівки:

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 байт

Повертає 1, якщо він закінчується нулями, а 0 - інакше.

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

Спробуйте в Інтернеті!

Пояснення

Використовує верхню межу раундів: max(input)*len(input)пояснено xnor у розділі коментарів.

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 байти

Повертається 0(що ефективно falseв J) для виродженої гри, що закінчується на всіх нулях. Повертає 1( true), якщо n-та ітерація містить ненульове число, де n дорівнює найбільшому цілому числу в початковій послідовності, помноженому на довжину списку. Дивіться відповідь Грега Мартіна, що пояснює, чому це правда.

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

Переклад:

  • Який знак *
  • найбільшої цінності >./
  • коли ви повторюєте наступне стільки разів ^:( )
  • довжина списку, #помножена *на найбільше значення у списку >./:
    • приймати абсолютне значення |&в
    • різниця між списком (- )та
    • список обертається одним 1&|.

Приклади:

   *>./|&(-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
Це не вимога Грега Мартіна. Однак, xnor має кращі межі у коментарях вище (але все ж не просто найбільше ціле число). Найпростіше - помножити найбільше значення на довжину.
Ørjan Johansen

Хороший улов. Я не приділяв достатньої уваги. Я виправлю рішення.
Дейн

1

JavaScript (ES6), 95 92 90 байт

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)

Пояснення

Рекурсивна функція, яка викликає себе до тих пір, поки лічильник (який починається з максимального значення в списку плюс один до потужності довжини списку [ = (max + 1)**length]) не дорівнює нулю. При кожному виклику лічильник зменшується, і коли він досягає нуля, всі елементи списку перевіряються на нуль. Якщо всі вони дорівнюють нулю, то повертається програмі true, і в falseіншому випадку.


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

приймаючи вхід через HTTP get, наприклад, ?3&4&5&8економить кілька байт.

Друкує 1, якщо він досягає всіх нулів або нічого іншого.


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

приймає список аргументів за допомогою командного рядка. У мене є відчуття, що це можна пограти ще більше (дивлячись на @Titus).


1

Python 3.6, 101 байт

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)

Бере кортеж чисел і повертає False, якщо він закінчується нулями, і True, якщо він циклічно.


0

JavaScript (ES6), 84 83 байт

Повертається trueдо гри, що закінчується всіма нулями, falseінакше.

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)

Тест

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