#python
#python
Вопрос:
Я новичок в Python и уже несколько дней ломаю голову над проблемой. Я подумывал о том, чтобы оставить его пустым и дождаться ответов профессора, но мы все еще не получили ответы от предыдущего задания (3 месяца назад), и я действительно хочу прогрессировать.
НАСТРОЙКА:
Я создал следующую функцию, которая может сжимать списки в соответствии с повторениями:
def compress(list: List[T]) -> List[Tuple[T, int]] :
"""Returns the compressed list"""
if len(list) == 1 :
return [(list[0], 1)]
result: List[Tuple[T, int]] = []
count: int = 1
i: int
for i in range(1, len(list)) :
if list[i] != list[i-1] :
result.append((list[i-1], count))
count = 1
else :
count = count 1
if i == len(list)-1 :
result.append((list[i], count))
return result
assert compress([3, 3, 3, 3, 1, 1, 2, 3, 3]) == [(3, 4), (1, 2), (2, 1), (3, 2)]
assert compress(['a','a','c','c','c','d','c','c','c','c']) == [('a', 2), ('c', 3), ('d', 1), ('c', 4)]
Я также создал следующую функцию распаковки:
def decompress(code: List[Tuple[T, int]]) -> List[T] :
"""Returns the decompressed list"""
return [value for (value, nb) in code for i in range(nb)]
assert decompress([(3, 4), (1, 2), (2, 1), (3, 2)]) == [3, 3, 3, 3, 1, 1, 2, 3, 3]
assert decompress([('a', 2), ('c', 3), ('d', 1), ('c', 4)]) == ['a', 'a', 'c', 'c', 'c', 'd', 'c', 'c', 'c', 'c']
Затем я создал функцию «перелистывания», которая переворачивает все остальные элементы в списке (я знаю, что это бесполезно, но, эй, в упражнении говорилось, что я должен был так …):
def flipping(liste:List[T]) -> List[T] :
"""Returns the list after flipping every other item"""
length:int = len(liste)
quotient: int = length // 2
i:int
result: List[T] = []
for i in range(quotient) :
resultat = result [liste[2*i 1], liste[2*i]]
if length % 2 == 1 :
result = result [liste[-1]]
return result
assert flipping([1, 2, 3]) == [2, 1, 3]
assert flipping([1, 2, 3, 4]) == [2, 1, 4, 3]
assert flipping(['a', 'a', 'a', 'a', 'c', 'c', 'd', 'c', 'c']) == ['a', 'a', 'a', 'a', 'c', 'c', 'c', 'd', 'c']
ПРОБЛЕМА:
Теперь меня просят создать функцию, которая может переворачивать элементы таким же образом, но из сжатого списка и БЕЗ его распаковки (да, я знаю, не весело).
Единственное, что я знаю наверняка, это то, что это должно выглядеть так:
def flipping_compressed(code:List[Tuple[T, int]]) -> List[Tuple[T, int]] :
#does magic
return result
assert flipping_compressed([('a', 1), ('c', 1), ('d', 1)]) == [('c', 1), ('a', 1), ('d', 1)]
assert flipping_compressed([('a', 1), ('c', 1), ('d', 1), ('a', 1)]) == [('c', 1), ('a', 2), ('d', 1)]
assert flipping_compressed([(3, 4), (1, 2), (2, 1), (3, 2)]) == [(3, 4), (1, 2), (3, 1), (2, 1), (3, 1)]
Я пытался в течение нескольких дней и каждый раз получал огромную функцию, полную вложенных ifs, которые все равно не работают.
Предполагается, что все задание должно быть выполнено менее чем за два часа, поэтому я, очевидно, что-то здесь упустил.
Я был бы признателен за любую помощь от более опытных товарищей, которым нравится хорошая проблема 🙂
Приветствия!
Комментарии:
1. Можете ли вы объяснить, что означает сжатие при переворачивании? Сначала распакуйте (возможно, виртуально) и переверните пары?
2. Подумайте об этом шаг за шагом. Предположим, ваш исходный список начинается с четного номера одного и того же элемента, так что сжатый список начинается с (четное число, символ). Что произойдет с этими символами, когда вы их «перевернете»? Как будет выглядеть сжатый результат? Теперь предположим, что вместо этого он начался с нечетной суммы; что произойдет с последним элементом? Теперь рассмотрим, что происходит со вторым сжатым фрагментом, если там i) есть; ii) нет чего-то, оставшегося от первого фрагмента. Теперь попробуйте обобщить логику.
3. Возможно, вы захотите уточнить описание: вы используете «переключение», не определяя его. Укажите, что это включает в себя замену элементов 2N и 2N 1.
4. @c2ig, это был забавный проект. Я сделал все 4 вещи. Проверьте это
Ответ №1:
Это называется «кодирование длины выполнения»; найдите в теме ресурсы.
Это работает с просто разделенными парами в исходном списке: позиции 0 amp; 1, 2 amp; 3, 4 amp; 5, … Чтобы выполнить замену без распаковки списка, вам необходимо разбить свой список на все точки подкачки. Например, учитывая ваш сжатый список
[(3, 4), (1, 2), (2, 1), (3, 2)]
Вам нужно разбить один элемент в любом месте, где его нужно поменять местами с соседним элементом. В этом примере,
(3, 4) pos 0-3, no need to break
(1, 2) pos 4-5, no need to break
(2, 1) pos 6 .. needs a partner
(3, 2) pos 7-8, needs the first element separated.
Единственный необходимый перерыв дает вам
[(3, 4), (1, 2), (2, 1), (3, 1), (3, 1)]
Обмен внутри группы ничего не делает; единственные необходимые операции — это когда элементы пары имеют разные значения. Это (2, 1), (3, 1) здесь.
[(3, 4), (1, 2), (3, 1), (2, 1), (3, 1)]
Как бы то ни было, это ваш конечный результат.
Давайте рассмотрим другой случай, который вы привели:
[('a', 2), ('c', 3), ('d', 1), ('c', 4)]
При требуемых разрывах четности это становится
[('a', 2), ('c', 2), ('c', 1), ('d', 1), ('c', 4)]
Теперь поменяйте местами соседние пары четно-нечетного индекса:
[('a', 2), ('c', 2), ('d', 1), ('c', 1), ('c', 4)]
Чтобы получить конечный результат, теперь вам нужно пройти по списку, проверяя элементы, которые вы поменяли местами, на предмет «склеивания» с соседними элементами. В этом примере единственным соединением является соло c
, дающее вам
[('a', 2), ('c', 2), ('d', 1), ('c', 5)]
Это желаемый результат.
Я надеюсь, что вы можете разработать некоторый код из этой схемы алгоритма.
Комментарии:
1. Во втором случае самый правый имел
('c', 4)
. Разве это не должно оставаться таким, чтобы результат заканчивался('c', 5)
2. Спасибо за подробное объяснение. Сегодня я узнал кое-что интересное. Сейчас я попытаюсь ответить на вопрос.
3. Что происходит, когда на входе сжатия flip
[(3, 4), (1, 1), (2, 1), (3, 2)]
есть два элемента с одиночными значениями[3,3,3,3,1,2,3,3]
, означает ли это, что мы переключаемся1
2
и оставляем остальные как есть. Я так полагаю. Тогда обратное сжатие будет[3,3,3,3,2,1,3,3]
правильным, я прав? Или у нас будет[3,3,3,1,3,3,2,3]
или[3,3,3,1,3,2,3,3]
?4. Что определяет обмен, так это пары индексов: 0-1, 2-3, 4-5 и т.д. В этом случае мы меняем местами 1 и 2, как вы и подозреваете.
Ответ №2:
import itertools
from typing import Sequence, Tuple, TypeVar, MutableSequence
T = TypeVar('T')
def compress(items: Sequence[T]) -> Sequence[Tuple[T, int]]:
compressed = []
for i in range(len(items)):
last = 0
if i > 0 and items[i] == items[i - 1]:
last = compressed.pop()[1]
compressed.append((items[i], last 1))
return compressed
assert compress([3, 3, 3, 3, 1, 1, 2, 3, 3]) == [(3, 4), (1, 2), (2, 1), (3, 2)]
assert compress(['a','a','c','c','c','d','c','c','c','c']) == [('a', 2), ('c', 3), ('d', 1), ('c', 4)]
def flip(items: Sequence[T]) -> Sequence[T]:
flipped = []
n = len(items)
it = itertools.islice(range(n), 0, None, 2)
for i in it:
if i 1 < n:
flipped.append(items[i 1])
flipped.append(items[i])
return flipped
assert flip([1, 2, 3]) == [2, 1, 3]
assert flip([1, 2, 3, 4]) == [2, 1, 4, 3]
assert flip(['a', 'a', 'a', 'a', 'c', 'c', 'd', 'c', 'c']) == ['a', 'a', 'a', 'a', 'c', 'c', 'c', 'd', 'c']
def flip_compressed(items: MutableSequence[Tuple[T, int]]) -> Sequence[Tuple[T, int]]:
flipped = []
n = len(items)
def append_or_merge(v: T, i: int) -> None:
x = i
if flipped and flipped[-1][0] == v:
x = flipped.pop()[1]
flipped.append((v, x))
for i in range(n):
val, cnt = items[i]
if cnt == 0:
continue
times = cnt // 2
rem = cnt % 2
if times > 0:
append_or_merge(val, times * 2)
if rem == 1:
if i 1 < n:
nxt_val, nxt_cnt = items[i 1]
append_or_merge(nxt_val, 1)
items[i 1] = (nxt_val, nxt_cnt - 1)
append_or_merge(val, 1)
return flipped
assert flip_compressed([('a', 1), ('c', 1), ('d', 1)]) == [('c', 1), ('a', 1), ('d', 1)]
assert flip_compressed([('a', 1), ('c', 1), ('d', 1), ('a', 1)]) == [('c', 1), ('a', 2), ('d', 1)]
assert flip_compressed([(3, 4), (1, 2), (2, 1), (3, 2)]) == [(3, 4), (1, 2), (3, 1), (2, 1), (3, 1)]
Ответ №3:
Это был отличный проект для работы. Спасибо за публикацию вопроса. Я поддержал и добавил в закладки ваш вопрос.
Я правильно понял все 4 процесса. Вот мой код для 4 элементов:
- сжатый список
- распаковать список [понимание списка]
- переворачивал элементы в списке при изменении последовательности
- перевернул сжатый список при изменении последовательности. Очевидно, сделал это без распаковки
Вот код для всех 4 элементов. Я также напечатал значения, чтобы убедиться, что они правильно выполняют сжатие, распаковку и переключение. Выходные данные этой программы также добавляются в нижнюю часть каждого раздела кода.
сжатие списка
def compress(lst):
total = 1
compressed = []
for i in range(1, len(lst)):
if lst[i-1] != lst[i]:
compressed.append((lst[i-1],total))
total = 1
else:
total = 1
if i == len(lst)-1: compressed.append((lst[i],total))
return compressed
assert compress([3, 3, 3, 3, 1, 1, 2, 3, 3]) == [(3, 4), (1, 2), (2, 1), (3, 2)]
assert compress(['a','a','c','c','c','d','c','c','c','c']) == [('a', 2), ('c', 3), ('d', 1), ('c', 4)]
print ('Run Length Encoding : compression :')
print ()
print ("[3, 3, 3, 3, 1, 1, 2, 3, 3]")
print (compress([3, 3, 3, 3, 1, 1, 2, 3, 3]))
print ()
print ("['a','a','c','c','c','d','c','c','c','c']")
print (compress(['a','a','c','c','c','d','c','c','c','c']))
print ()
Вывод для приведенного выше кода:
Run Length Encoding : compression :
[3, 3, 3, 3, 1, 1, 2, 3, 3]
[(3, 4), (1, 2), (2, 1), (3, 2)]
['a','a','c','c','c','d','c','c','c','c']
[('a', 2), ('c', 3), ('d', 1), ('c', 4)]
распаковать список
def decompress(lst):
return [a[0] for a in lst for i in range(a[1])]
assert decompress([(3, 4), (1, 2), (2, 1), (3, 2)]) == [3, 3, 3, 3, 1, 1, 2, 3, 3]
assert decompress([('a', 2), ('c', 3), ('d', 1), ('c', 4)]) == ['a','a','c','c','c','d','c','c','c','c']
print ('Run Length Encoding : decompression :')
print ()
print ("[(3, 4), (1, 2), (2, 1), (3, 2)]")
print (decompress([(3, 4), (1, 2), (2, 1), (3, 2)]))
print ()
print ("[('a', 2), ('c', 3), ('d', 1), ('c', 4)]")
print (decompress([('a', 2), ('c', 3), ('d', 1), ('c', 4)]))
print ()
Вывод для приведенного выше кода:
Run Length Encoding : decompression :
[(3, 4), (1, 2), (2, 1), (3, 2)]
[3, 3, 3, 3, 1, 1, 2, 3, 3]
[('a', 2), ('c', 3), ('d', 1), ('c', 4)]
['a', 'a', 'c', 'c', 'c', 'd', 'c', 'c', 'c', 'c']
переключение значений в списке при изменении значения
def flipping(lst):
i = 0
while i < len(lst)-1:
if lst[i] != lst[i 1]:
lst[i],lst[i 1] = lst[i 1],lst[i]
i =2
return lst
assert flipping([1, 2, 3]) == [2, 1, 3]
assert flipping([1, 2, 3, 4]) == [2, 1, 4, 3]
assert flipping(['a','a','a','a','c', 'c','d','c','c']) == ['a', 'a', 'a', 'a', 'c', 'c', 'c', 'd', 'c']
print ('Run Length Encoding : flipping :')
print ()
print ("[1, 2, 3]")
print (flipping([1, 2, 3]))
print ()
print ("[1, 2, 3, 4]")
print (flipping([1, 2, 3, 4]))
print ()
print ("['a','a','a','a','c', 'c','d','c','c']")
print (flipping(['a','a','a','a','c', 'c','d','c','c']))
print ()
Вывод для приведенного выше кода:
Run Length Encoding : flipping :
[1, 2, 3]
[2, 1, 3]
[1, 2, 3, 4]
[2, 1, 4, 3]
['a','a','a','a','c', 'c','d','c','c']
['a', 'a', 'a', 'a', 'c', 'c', 'c', 'd', 'c']
переворачивайте сжатый список без распаковки
def flip_compressed(lst):
i = 0
j = len(lst)
flst = [[a[0],a[1]] for a in lst] #convert tuples to lists for ease of manipulation
while i < len(flst)-1: #flip based on position. flip only if value is 1
if flst[i][1] == 1:
if flst[i 1][1] > 1:
flst[i 1][1] -=1
flst.insert(i 1,[flst[i 1][0],1])
flst[i][0],flst[i 1][0] = flst[i 1][0],flst[i][0]
i =2
i = 0
while i < len(flst)-1: #check if we need to merge any of the compressed items
if flst[i][0] == flst[i 1][0]:
flst[i][1] = flst[i 1][1]
flst.pop(i 1)
else:
i =1
flst = [(a[0],a[1]) for a in flst] #convert it back to tuples
return flst
assert flip_compressed([('a', 1), ('c', 1), ('d', 1)]) == [('c', 1), ('a', 1), ('d', 1)]
assert flip_compressed([('a', 1), ('c', 1), ('d', 1), ('a', 1)]) == [('c', 1), ('a', 2), ('d', 1)]
assert flip_compressed([(3, 4), (1, 2), (2, 1), (3, 2)]) == [(3, 4), (1, 2), (3, 1), (2, 1), (3, 1)]
print ('Run Length Encoding : flip compressed :')
print ()
print ("[('a', 1), ('c', 1), ('d', 1)]")
print (flip_compressed([('a', 1), ('c', 1), ('d', 1)]))
print ()
print ("[('a', 1), ('c', 1), ('d', 1), ('a', 1)]")
print (flip_compressed([('a', 1), ('c', 1), ('d', 1), ('a', 1)]))
print ()
print ("[(3, 4), (1, 2), (2, 1), (3, 2)]")
print (flip_compressed([(3, 4), (1, 2), (2, 1), (3, 2)]))
print ()
Вывод для приведенного выше кода:
Run Length Encoding : flip compressed :
[('a', 1), ('c', 1), ('d', 1)]
[('c', 1), ('a', 1), ('d', 1)]
[('a', 1), ('c', 1), ('d', 1), ('a', 1)]
[('c', 1), ('a', 2), ('d', 1)]
[(3, 4), (1, 2), (2, 1), (3, 2)]
[(3, 4), (1, 2), (3, 1), (2, 1), (3, 1)]