Обобщенные коды Грея

13

Входные данные: массив I из k натуральных чисел. Целые числа будут не больше 100 и k ≤ 100 .

Вывод: Ваш код должен вывести все возможные массивы O неотрицательных целых чисел длины k с ограничением 0 ≤ O i ≤ I i . Чтобы перейти от одного массива к другому, вы можете добавить или вычесть 1 к одному значению в массиве. Ваш код не должен выводить один и тот же массив дважды. Если количество выводимых массивов очень велико, ваш код должен продолжать выводить до тех пор, пока он не будет уничтожен.

Примеры

  • Если I - массив из k единиц, то это точно проблема итерации по всем кодам Грея с битовой шириной k , за исключением того, что первый и последний элемент не должны быть достижимы за один шаг.

  • Если I = [2,1]тогда один из возможных порядков выходных массивов(0,0),(0,1),(1,1),(1,0),(2,0),(2,1)

  • Если I = [2,1,3]тогда возможно одно упорядочение выходных массивов (0,0,0),(0,0,1),(0,0,2),(0,0,3),(0,1,3),(0,1,2),(0,1,1),(0,1,0),(1,1,0),(1,1,1),(1,1,2),(1,1,3),(2,1,3),(2,1,2),(2,1,1),(2,1,0),....

Это соревнование по коду для игры в гольф, подача с исходным кодом с самой короткой длиной выигрывает. Не позволяйте коротким ответам на языках игры в гольф отговаривать вас от публикации ответов на других языках. Попробуйте найти самый короткий ответ на любом языке.

Это также проблема с ограниченной сложностью. Каждый новый массив должен быть выведен с O (k) временем, прошедшим с момента предыдущего выведенного массива (или начала программы для первого выведенного массива). Это означает, что время выполнения для каждого нового выходного массива (каждый из которых имеет длину k ) не должно превышать O (k) . То есть это должно занимать время, пропорциональное k, а не, например, k 2 или 2 k . Обратите внимание, что это не среднее время на вывод, а наихудшее время для каждого выводимого массива.

Вы можете предположить, что вся арифметика с 64-разрядными целыми числами может выполняться за постоянное время, а также может считывать и выводить их, а также присваивать, просматривать и изменять значения в массивах.

Одним из следствий ограниченной сложности является то, что решения, которые выводятся только при выходе из программы, неприемлемы.

Ануш
источник
1
(следует «сложить или вычесть 1» по модулю I_i+1? Можете ли вы достичь 0 от I_i?)
user202729
@ user202720 Нет, я не собирался этого делать.
Ануш
Как сложность работает, когда nи kограничены? предполагая, что они идут в бесконечность с битовой шириной, как идти
l4m2
@ l4m2 Для целей анализа сложности предположим, что k стремится к бесконечности.
Ануш
@ Ануш, как же ширина битов?
l4m2

Ответы:

4

Python 3 , 116 байт

def f(a):
 l=len(a);t=[0]*l;d=[1]*l
 while 1:
  i=0;yield t
  while not-1<t[i]+d[i]<=a[i]:d[i]*=-1;i+=1
  t[i]+=d[i]

Попробуйте онлайн!

Спасибо Mnemonic за -1 байт.

Функция генератора. (спасибо Деннису за напоминание, я забыл, что функция существует). Если выходные данные должны быть напечатаны в stdout, тогда используйте print(t,flush=1)для 9 дополнительных байтов, или, если Python вызывается с -u, print(t)достаточно для +1 байта.

Останавливается с ошибкой ( IndexError). Если вы хотите вызвать эту функцию и затем продолжить программу, вы должны ее перехватить.

user202729
источник
Как долго работает внутренний цикл while?
Ануш
@Anush Не более kшагов, потому что на каждом шаге iувеличивается 1и после kшагов i==kи d[i]вызывает ошибку.
user202729
Это очень хорошее решение.
Ануш
Вы можете сохранить байт, заменив not 0<=на not-1<.
1
Не могли бы вы использовать yield tвместо print(t,flush=1)?
Деннис
2

Stax , 22 байта

▒)∙ñ╚▀NK♀F☺S(A#P`░]╪Db

Запустите и отладьте его

Вот большой пример, демонстрирующий асимптотическое поведение. Нажмите run.

Распакованный, размазанный и прокомментированный, это выглядит так.

,           pop from input to main stack
W           run the rest of the program repeatedly until explicitly cancelled
  cJP       copy top of stack and print, delimited by spaces
            get the index to mutate
  i^            iteration index + 1
  x{^|%}I       repeatedly apply divmod using l[k]+1 from input
                get the index of the first value that returns modulus >0
  cU=C      if the result is -1 (no match), then terminate the program
            get the direction to mutate
  s             get the "div" part of the last div operation called "d"
  ^|1           -1 ^ (d+1)
  ~{+}&     increment element in array at the index by the calculated amount

Запустите этот

рекурсивный
источник
1
Измеряя сложность битов, индекс итерации равен O(k)битам, поэтому kвремя деления может занять O(k²)
некоторое
1

JavaScript (Node.js) , 114 байт

a=>{b=a.map(_=>0);c=a.map(_=>1);for(i=0;a[i];b[i]+=c[i]||-1){console.log(b);for(i=0;b[i]==a[i]*c[i];i++)c[i]^=1;}}

Попробуйте онлайн! Ungolfed:

function ggray(maxima) {
    var current = Array(maxima.length).fill(0);
    var flag = Array(maxima.length).fill(1);
    for (;;) {
        console.log(current);
        for (var i = 0; ; i++) {
            if (i == maxima.length) return;
            if (current[i] != maxima[i] * flag[i]) break;
            flag[i] = 1 - flag[i];
        }
        if (flag[i]) current[i]++;
        else current[i]--;
    }
}
Нил
источник
1

Котлин , 181 178 байт

Спасибо: Ануш указал, что я неправильно понял задачу, сэкономив 2 байта. ovs указал на 1-байтовую экономию.

val p={a:List<Int>->var l=a.size
val v=Array(l,{0})
val i=Array(l,{1})
l-=1
o@while(0<1){println(v)
var p=l
while(v[p]+i[p]!in 0..a[p]){i[p]*=-1
p-=1
if(p<0)break@o}
v[p]+=i[p]}}

Попробуйте онлайн!

JohnWells
источник
1
Для примера в вопросе с 2 1 3 ваш код нуждается в 3 2 4 в качестве ввода, как кажется.
Ануш
1
while(true)может бытьwhile(1<2)
ovs