Как увеличить значения в списке в определенном диапазоне

У меня есть список l =[253, 59, 2, 0, 0, 0, 0, 0], и я хочу установить диапазон (0, 255) для каждого элемента в списке. Я хочу реализовать это на питоне. Я хочу увеличивать элементы один за другим, так что, когда он достигает максимального диапазона, элемент должен сбрасываться на 0, а следующий элемент должен увеличиваться на 1

Вывод должен выглядеть так после каждой итерации:

l =[253, 59, 2, 0, 0, 0, 0, 0]
l =[254, 59, 2, 0, 0, 0, 0, 0]
l =[255, 59, 2, 0, 0, 0, 0, 0]
l =[0, 60, 2, 0, 0, 0, 0, 0]
l =[1, 60, 2, 0, 0, 0, 0, 0]
.
.
.
.
l =[255, 60, 2, 0, 0, 0, 0, 0]
l =[0, 61, 2, 0, 0, 0, 0, 0]

«Я хочу реализовать это на питоне», тогда почему вы отметили это numpy?

mozway 09.12.2022 10:58

Я хочу знать, есть ли способ сделать это с помощью numpy lib. так как с числовыми массивами работать быстрее, чем со списками. @mozway

dvpi 09.12.2022 11:05

поскольку вам нужно будет повторять, я сомневаюсь, что numpy сильно поможет, можете ли вы сообщить нам, должен ли ввод быть произвольным? например если l = [255, 255, 255, 7, 0], то следующая итерация должна быть [0, 0, 0, 8, 0]?

mozway 09.12.2022 11:24

да ввод должен быть произвольным.

dvpi 09.12.2022 15:47
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
123
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Один вариант в чистом питоне:

l = [253, 59, 2, 0, 0, 0, 0, 0]

pos = 0
n_iter = 10
step = 0
for step in range(n_iter):
    for pos in range(len(l)):
        if l[pos] < 255:
            l[pos] += 1
            break
        else:
            l[pos] = 0
    print(f'step {step+1}: {l}')

Вывод:

step 1: [254, 59, 2, 0, 0, 0, 0, 0]
step 2: [255, 59, 2, 0, 0, 0, 0, 0]
step 3: [0, 60, 2, 0, 0, 0, 0, 0]
step 4: [1, 60, 2, 0, 0, 0, 0, 0]
step 5: [2, 60, 2, 0, 0, 0, 0, 0]
step 6: [3, 60, 2, 0, 0, 0, 0, 0]
step 7: [4, 60, 2, 0, 0, 0, 0, 0]
step 8: [5, 60, 2, 0, 0, 0, 0, 0]
step 9: [6, 60, 2, 0, 0, 0, 0, 0]
step 10: [7, 60, 2, 0, 0, 0, 0, 0]

с петлей,

array = [253, 59, 2, 0, 0, 0, 0, 0]
index = 0
while index < len(array):
    while array[index]<256:
        array[index] += 1
        print(array)
    array[index] = 0
    index += 1

Один из способов с циклом:

def inc_list(l):
    for i in range(len(l)):
        l[i] += 1
        if l[i] > 255:
            l[i] = 0
        else:
            return

for _ in range(300):
    print(l)
    inc_list(l)

В качестве альтернативы рекурсивное решение:

def inc_list(l):
    if not l:
        return []
    elif l[0] == 255:
        return [0] + inc_list(l[1:])
    else:
        return [l[0] + 1] + l[1:]

for _ in range(300):
    print(l)
    l = inc_list(l)

tl;dr: однострочник

import struct
list(struct.pack('<Q', struct.unpack('<Q', bytes(start))[0]+1))

1- Счет в 64 бита

Просто чтобы представить другое представление, это то, что вы, кажется, считаете в списке из 8 байтов, представляющих 64-битное целое число с прямым порядком байтов... Почему бы вам просто не сделать это?

def plusOne(l):
   n=0
   b=1
   for dg in l:
       n+=b*dg
       b*=256
   n+=1
   res=[]
   for i in range(len(l)):
       res.append(n%256)
       n//=256
   return res

Как есть, этот ответ не быстрее, чем другие. Я предполагаю, что это даже медленнее (не успел. Но, ну, это явно сложнее).

Но если то, что вы хотите иметь, это просто счетчик, вы можете упростить, сохранив только целое число в качестве значения состояния и сгенерировав список

2- Итератор

def listCounter(start, size):
    while True:
        res=[]
        x=start
        for i in range(size):
            res.append(x%256)
            x//=256
        yield res
        start+=1

myiter=listCounter(254, 8)
print(next(myiter))
print(next(myiter))
for _,l in zip(range(20),listCounter(510,8)):
    print(l)

3- Структура (используя внутреннее представление)

Поскольку именно так 8-байтовое целое число подсчитывается на оборудовании, вы даже можете полагаться на процессор, чтобы сделать это, а не пытаться имитировать его в python.

import struct
l=[254, 255, 0, 0, 1, 0, 0, 0]
nextl=list(struct.pack('<Q', struct.unpack('<Q', bytes(l))[0]+1))

Или в for итератора

import struct
def listCounter(start):
    while True:
        yield start
        start=list(struct.pack('<Q', struct.unpack('<Q', bytes(start))[0]+1))

for _,l in zip(range(10), listCounter([254,255,0,0,1,0,0,0])):
   print(l)
[254, 255, 0, 0, 1, 0, 0, 0]
[255, 255, 0, 0, 1, 0, 0, 0]
[0, 0, 1, 0, 1, 0, 0, 0]
[1, 0, 1, 0, 1, 0, 0, 0]
[2, 0, 1, 0, 1, 0, 0, 0]
[3, 0, 1, 0, 1, 0, 0, 0]
[4, 0, 1, 0, 1, 0, 0, 0]
[5, 0, 1, 0, 1, 0, 0, 0]
[6, 0, 1, 0, 1, 0, 0, 0]
[7, 0, 1, 0, 1, 0, 0, 0]

Объяснение

bytes(l) — это массив байтов, содержащий 8 байтов в l
bytes(l) -> b'\xfe\xff\x00\x00\x01\x00\x00\x00'
Эти 8 байтов представляют собой 64-битное представление числа. Который мы можем извлечь с помощью struct.unpack, указав формат <Q (64-битное целое число, обратный порядок байтов, сначала увеличиваются первые байты)
struct.unpack('<Q', bytes(l)) → (4295032830,)
Это форма кортежа, потому что мы могли запросить последовательность разных чисел. Итак
struct.unpack('<Q', bytes(l))[0] → 4295032830
Мы можем увеличить его
struct.unpack('<Q', bytes(l))[0]+1 → 4295032831
И мы можем получить 64-битное представление массива байтов этого нового целого числа, используя pack
struct.pack('<Q',struct.unpack('<Q', bytes(l))[0]+1) → b'\xff\xff\x00\x00\x01\x00\x00\x00'
Этот массив байтов представляет собой просто числа от 0 до 255, мы можем легко получить их, преобразовав его в список
list(struct.pack('<Q',struct.unpack('<Q', bytes(l))[0]+1)) → [255, 255, 0, 0, 1, 0, 0, 0]

Задача эквивалентна поиску представлений последовательных целых чисел в позиционной системе счисления с основанием 256 (но вы также можете использовать смешанные основания).

numpy распутывать и распутывать

Для меньших списков вы можете найти целое число, имеющее вид l = [253, 59, 2, 0]

value = np.ravel_multi_index(l, [256] * 4, order='F') #sets value to 146429

А затем используйте np.unravel_index, чтобы получить представления первых, скажем, 5 целых чисел:

np.transpose(np.unravel_index(np.arange(value, value+5), [256]*4, order='F'))
>>> array([[253,  59,   2,   0],
           [254,  59,   2,   0],
           [255,  59,   2,   0],
           [  0,  60,   2,   0],
           [  1,  60,   2,   0]], dtype=int64)

Большие случаи

В вашем случае требуется размер = [256] * 8. Это слишком велико, потому что целые числа не могут превышать 2**63 в numpy, а ValueError будет выброшено. В этом случае вы можете реализовать свой собственный способ замены np.ravel_multi_index и np.unravel_index:

shape = np.cumprod([1, 256, 256, 256, 256, 256, 256, 256], dtype=np.int64)
value = np.dot(l, shape) #same 146429

def unravel(values, shape=[256] * 8):
    steps = len(values)
    result_arr = np.empty(shape=(len(shape), steps), dtype=int)
    for j in range(len(shape)):
        result_arr[j] = values % shape[j]
        values =  values // shape[j]
    return np.transpose(result_arr)

unravel(np.arange(value, value+5))
>>> array([[253,  59,   2,   0,   0,   0,   0,   0],
           [254,  59,   2,   0,   0,   0,   0,   0],
           [255,  59,   2,   0,   0,   0,   0,   0],
           [  0,  60,   2,   0,   0,   0,   0,   0],
           [  1,  60,   2,   0,   0,   0,   0,   0]])

Обратите внимание, что во всех случаях требуется только 8 итераций, поэтому он должен быть быстрее, чем только пути Python.

Другие вопросы по теме