从列表中删除相邻数字的三元组



问题在这里。输入是一个整数列表。如果三个相邻的数字相邻出现,它们应该被删除,并再次进行操作。Iphone应用程序,有相同颜色的球。输出应该是将被销毁的球的计数。

的例子:

input = [3,3,4,4,4,3,4]

1日迭代

output: [3,3,3,4]
最终输出:

6   

第一次迭代时4,4,4,所以有三个球。第二个是3 3 3。六。

我的代码如下。它将删除4,4,4,但之后会失败,因为列表索引将很快超出范围。

def balls(a):

curr_index = 0
removed_count = 0
while len(a) > 2:
if (a[curr_index] == a[curr_index+1]) and (a[curr_index] == a[curr_index+2]):
a.remove(a[curr_index])
a.remove(a[curr_index+1])
a.remove(a[curr_index+2])
curr_index += 1
removed_count += 3
return removed_count
a = [3, 3, 4, 4, 4, 3, 4]

print(balls(a)) # should print 6

任何想法?

input_values = [3,3,4,4,4,3,4]

values = input_values
while len(values) >= 3:
for x in range(0,len(values)-2):    

# if we find 3 values in ar row
if values[x] == values[x+1] and values[x] == values[x+2]:

# update values by cutting out the series
values = values[:x] + values[x+3:]

# break this for loop
break
else:
# for loops can have an else statement
# this means that we came at the end of the for loop
# this if we didn't break the loop (and didn't found a valid triple)
# then we brea
break

#result  - amount of removed balls     
values, len(input_values) - len(values)

一个更通用的方法,你可以定义N

(它将找到精确的N个值)


input_values = [3,3,4,4,4,4,3,3,4]
# amount of neighbours
N = 4
values = input_values
# keep looping as long as we've N values
while len(values) >= N:

# we need this if we break the inner loop
stop = False

# loop over values from left to right
# 3 -> 3 -> 4 -> 4 -> ... until  -N + 1
# because that is the last spot that we've N values left 
for x in range(0, len(values) - N + 1):    


# scout for the next numbers (x+1 x+2 x+3 ....)
# this goes from, x+1 until the end of the serie
# also start counting from 2 - because
# if we've a single match, 2 numbers are equal
for e, y in enumerate(range(x+1, len(values)), start=2):

# if x and y are different, the stop this scouting
# remember y = x+1   x+2  x+3 ....
if values[x] != values[y]:
break

# if we reached this stage, we know that 
# x and x+1     x+2   ... are equal
# but also check if we've enough matches
if e == N:
# update values by cutting out the series
values = values[:x] + values[y+1:]
stop = True
break

if stop:
break


else:
# for loops can have an else statement
# this means that we came at the end of the for loop
# this if we didn't break the loop (and didn't found a valid triple)
# then we brea
break

values, len(input_values) - len(values)

有一种方法:

your_list=[3, 3, 4, 4, 4, 3, 4]
def remove_one(l):
if len(l)>2:
for i in range(len(l)-2):
if l[i]==l[i+1]==l[i+2]:
res.extend(l[i:i+3])
l=l[:i]+l[i+3:]
return l
return []
res=[]
while len(your_list)>2:
your_list=remove_one(your_list)
print(len(res))

输出:

6

具有最小阈值的方法

input_values = [3,3,4,4,4,4,4,3,3,4]
# threshold
N = 3
values = input_values
while len(values) >= N:

# we need this if we break the inner loop
stop = False

# loop over values
for x in range(0, len(values) - N + 1):    

# scout for the next numbers (x+1 x+2 x+3 ....)
for e, y in enumerate(range(x+1, len(values)), start=2):
# check if the values of x and  x+1   (x+2  x+3 ...) are different
if values[x] != values[y]:

# if so, check if we've reached our threshold of N
if e >= N:

# if this is the case update values by cutting out the series
values = values[:x] + values[y:]
stop = True
break

# if x+n  != x then we break this scouting loop
break
# stop is True, this means, that we found N neibouring numbers
# thus we can break this loop, and start over with a new* value
if stop:
break


else:
# for loops can have an else statement
# this means that we came at the end of the for loop
# thus if we didn't break the loop (and didn't found a valid triple)
# then we break
break

values, len(input_values) - len(values)

你的代码有几个问题。

第一个是你试图在列表上迭代一次,但这对你的例子不起作用。

第二种情况是你假设列表总是减少到小于3,如果你有更多的数字,情况就不会是这样了。

还有一些地方可以简化语法,例如:

if (a[curr_index] == a[curr_index+1]) and (a[curr_index] == a[curr_index+2]):

等价于:

if a[curr_index] == a[curr_index + 1] == a[curr_index + 2]:

a.remove(a[curr_index])
a.remove(a[curr_index+1])
a.remove(a[curr_index+2])

等价于:

del a[curr_index: curr_index + 3]

这里有一种方法可以做到这一点,尽管有更有效的方法。

def balls(a):
removed = 0
complete = False
# Run until complete is set or the list is too short for a match
while not complete and len(a) >= 3:
for idx, val in enumerate(a):
if val == a[idx + 1] == a[idx + 2]:
del a[idx: idx + 3]
removed += 3
break  # Restart every time we find a match
# If it's the last possible match, set complete
if idx == len(a) - 3:
complete = True
break
return removed

我有点晚了,但我的想法是一次完成处理。这个想法是,当你删除一个三元组时,返回两个位置来重新检查是否通过该更改创建了一个新的三元组。

的例子:

3 3 4 4 4 3
^--- tripple found here, remove it
3 3 3
^--- move the cursor 2 positions left and continue checking

代码:

def drop3(lst):
# drop3 destroys the lst, make a copy if you want to keep it
dropped = 0 
cursor = 0 
limit = len(lst) - 2 
while cursor < limit:
if lst[cursor] == lst[cursor+1] == lst[cursor+2]:
del lst[cursor:cursor+3]
cursor = max(0, cursor-2)
limit -= 3
dropped += 3
else:
cursor += 1
return dropped

线性时间解:

def balls(a):
b = []
for x in a:
b.append(x)
if b[-3:] == [x] * 3:
del b[-3:]
return len(a) - len(b)

最新更新