I have this function here:
def swap_cards(deck, index_deck):
swap_deck = []
after_index = []
bandf_index = []
if index_deck >= len(deck):
for i in range(0, len(deck) + 1):
if deck[i] == index_deck:
after_index += [deck[0]]
else:
bandf_index += [deck[i]]
swap_deck += [deck[index_deck]] + bandf_index[1:index_deck - 1] + after_index
Every time I try to input an index that is greater than or equal to the deck length I get the error 'list index out of range'
Example:
swap_cards([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9)
I expect [9, 1, 2, 3, 4, 5, 6, 7, 8, 0] but am instead getting 'list index out of range'.
Switching the last and the first number, I don't know what I am doing wrong.
You have a problem with len(). Assuming your index_deck is 9 as in the example above:
if index_deck >= len(deck):
for i in range(0, len(deck) + 1):
This range will yield [0,1,2,3,4,5,6,7,8,9,10,11]
if deck[i] == index_deck:
after_index += [deck[0]]
Since array indexes are zero-based, the above line will generate the error. deck[10] and deck[11] don't exist.
else:
bandf_index += [deck[i]]
Fixing the above len() statement will fix this as well (again, you may try to access deck[10] if the if statement is false.
swap_deck += [deck[index_deck]] + bandf_index[1:index_deck - 1] + after_index
Final thing: you verify that if index_deck >= len(deck):. This will break the above line at deck[index_check] since here you will always access an index which does not exist.
Related
Write a function that accepts a list. The function should change the element of a list with a max value on its right side. The last element of a list should be changed to -1.
Input: [17, 18, 5, 4, 6, 1]
Output: [18, 6, 6, 6, 1,−1]
I was able to do the first part but I can't seem to change the value of the last element to -1.
def list_change(lista):
for i in range(0, len(lista)):
if i == (len(lista) - 1):
x = 0 - 1
lista[i] = lista[x]
else:
tmax = -100000000
for j in range(i + 1, len(lista)):
if lista[j] > tmax:
lista[i] = lista[j]
tmax = lista[j]
print(lista)
list_change([17, 18, 5, 4, 6, 1])
It is easy, change the last element using its index -
def list_change(lista):
for i in range(0, len(lista)):
if i == (len(lista) - 1):
x = 0 - 1
lista[i] = lista[x]
else:
tmax = -100000000
for j in range(i + 1, len(lista)):
if lista[j] > tmax:
lista[i] = lista[j]
tmax = lista[j]
lista[-1] = -1 # Get the last element and change it.
print(lista)
list_change([17, 18, 5, 4, 6, 1])
To get the last element of the list, use the list[-1] syntax. The list[-n] syntax gets the nth-to-last element. So list[-1] gets the last element, list[-2] gets the second to last.
list[-1] = -1
Edit: first of all, don't use list as a variable, list is used to create a new list as list(...) as an alternative to [...]. Secondly, check the list is not empty before making the aforementioned call.
So if variable x is referencing a list object
if not x:
x.append(elem)
else:
x[-1] = elem
Here's the problem. The input is a list of integers. If more than three adjacent numbers appear next to each other they should be dropped and the operation goes again. Kind of similar to the Iphone game, where player needs to pop lines of three or more balls of the same colors. The output should be the count of the balls that will be removed.
The algorithm is as follows. Starting with a sample list of say [3,3,4,4,4,4,3,2].
First iteration should remove the 4,4,4,4 - so the list would become [3,3,3,2], and the intermediary output of removed numbers will be 4.
Second iteration should remove 3,3,3 - so the final list would be [2] and final count of removed numbers - 7.
The first implementation for three consecutive items came from another stackoverflow thread - Remove triplets of adjacent numbers from the list
Here's the working function implementation for exactly 3 consecutive numbers:
def balls(l):
values = l
while len(values) >= 3:
print(values) #for demonstrative purposes of this question
for x in range(0,len(values)-2):
if values[x] == values[x+1] and values[x] == values[x+2]:
values = values[:x] + values[x+3:]
break
else:
break
print(values) #for demonstrative purposes of this question
return len(l) - len(values)
balls([3, 3, 4, 4, 4, 3, 4])
Output:
[3, 3, 4, 4, 4, 3, 4]
[3, 3, 3, 4]
[4]
6
How could I update the implementation to include the more general solution of removing 3+ consecutive numbers. I am thinking about tracking the start and end index of the consecutive duplicates, then subsetting the list. However, not sure how to implement that. Here are the tests that should work.
if __name__ == "__main__":
test1 = [3, 3, 4, 4, 4, 3, 4]
print(balls(test1))
#Output should be 6
test2 = [5, 5, 5, 5, 5, 5, 5, 5]
print(balls(test2))
#Output should be 8
test3 = [5, 7, 8, 3]
print(balls(test3))
#Output should be 0
def remove_consecutive(l, length):
amount = len(l)
count = 1
start = 0
current = l[0]
i = 1
while i < len(l):
if l[i] == current:
count += 1
else:
if count >= length:
for i in range(count):
l.pop(start)
start = 0
i = 0
current = l[0]
else:
start = i
current = l[i]
count = 1
i+=1
if count >= length:
for i in range(count):
l.pop(start)
return amount - len(l)
Wuff, i got it. My brain is kinda stinky lately so it took so long.
Here is my code, it works well. But I think there may be better ways to achieve higher efficiency.
def remove_consecutive(lst):
len_init = len(lst)
contain_tuplets = True
while contain_tuplets:
for i in range(len(lst)-2):
indices_to_pop = []
if lst[i]==lst[i+1]==lst[i+2]:
indices_to_pop.extend([i, i+1, i+2])
for j in range(i+3,len(lst)):
if lst[j] == lst[i]:
indices_to_pop.append(j)
else:
break
[lst.pop(i) for _ in indices_to_pop]
contain_tuplets = True
break
else:
contain_tuplets = False
count_removed_numbers = len_init - len(lst)
return count_removed_numbers, lst
test case1:
lst = [3,3,4,4,4,4,3,2]
remove_consecutive(lst)
output
(7, [2])
test case 2:
lst = [2, 2, 1, 1, 1, 2, 1]
remove_consecutive(lst)
output:
(6, [1])
def remove_consecutive(l, length):
amount = 0
count = 1
current = l[0]
for i in range(1, len(l)):
if l[i] == current:
count += 1
if count > length:
amount += 1
elif count == length:
amount += length
else:
current = l[i]
count = 1
return amount
I am trying to find consecutive values from an unsorted list. Experimental code below:
num = [8, 9, 4, 1, 2, 3]
#(num[0+1]) next value
for i in range(len(num)-1): # not using -1 will cause index error
if num[i]+1==num[i+1]:
print('Con',num[i])
Problem: I am unable to get the last value with this current code. My output excludes the last value. Here is what I get (no 9 or no 3):
Con 8
Con 1
Con 2
I have seen a few complex solutions which were a little difficult for me to understand. Is it possible to tweak the for loop part a little and get the entire sequence? Thanks a lot.
You can use the function groupby:
from itertools import groupby
num = [8, 9, 4, 1, 2, 3]
# Enumerate and get differences between counter—integer pairs
# Group by differences (consecutive integers have equal differences)
gb = groupby(enumerate(num), key=lambda x: x[0] - x[1])
# Repack elements from each group into list
all_groups = ([i[1] for i in g] for _, g in gb)
# Filter out one element lists
list(filter(lambda x: len(x) > 1, all_groups))
# [[8, 9], [1, 2, 3]]
This is because you only check the next number. When you want the second number (like 9 or 3), you have to include a check for the previous number too. This will make the if a bit longer, but it'll work.
num=[8,9,4,1,2,3]
for i in range(len(num)):
if (
( # check for the next number
i + 1 != len (num) and # don't check the end of the list
num[i]+1==num[i+1]
) or ( # check for the previous number
i != 0 and # don't check before the list
num [i-1] == num [i] - 1
)
): print('Con',num[i])
Also, I had to remove the -1 in your range, because I already do a manual check, and as pointed out, this prvented 3 from being shown.
Your code only tests in one direction (being followed by a consecutive number).
For the full sequence you have to test in both direction.
num=[8,9,4,1,2,3]
assert(len(num) > 1)
for i, n in enumerate(num):
if i != 0:
if n == num[i-1] + 1:
print("Con", n)
continue
if i != len(num) - 1:
if n == num[i+1] - 1:
print("Con", n)
One way would be to print both numbers when you found them to be consecutive, but also check that the one at index i-1 was not in the consecutive list as well so that the number at index i is not printed twice:
num = [8, 9, 4, 1, 2, 3]
for i in range(len(num)-1): # not using -1 will cause index error
if num[i] + 1 == num[i + 1]:
if i == 0 or (i - 1 >= 0 and num[i - 1] != num[i] - 1):
print('Con', num[i])
print('Con', num[i + 1])
Could try with a more complex list as well:
num = [8, 9, 4, 1, 2, 3, 4, 4, 8, 9, 1, 2, 3, 0, 1, 5, 6, 1]
for i in range(len(num)-1): # not using -1 will cause index error
if num[i] + 1 == num[i + 1]:
if i == 0 or (i - 1 >= 0 and num[i - 1] != num[i] - 1):
print('Con', num[i])
print('Con', num[i + 1])
num = [8, 9, 4, 1, 2, 3]
def con(rng, pos=0):
if pos < len(rng):
if (pos > 0 and rng[pos]-1 == rng[pos-1]) or (pos < len(rng) -1 and rng[pos]+1 == rng[pos+1]):
print("con", rng[pos])
con(rng, pos+1)
con(num)
edit:
this is solution is based on concurrent function, and needs only the list as argument. As long as they are within lower-/upperbound of list, the function will check if (previous number)-1 or (next number)+1 are equal (this number)
output will be:
con 8
con 9
con 1
con 2
con 3
I wrote this code for a simple linear search:
def floor(array, target):
i = 0
while i < len(array):
if array[i] == target:
print("The target value can be found at index: " + str(array[i]))
break
else:
i = i + 1
floor([1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14], 5)
The problem I'm having is that it's not returning the values I want. For some reason it doesn't start counting at 0, so when I make the target 1 it tells me the index is 1. Likewise, if I make the target 4 it will give me the second value of 4 at index 4 rather than the one at index 3. Even when the target is a higher number, it only seems to count the value of 4 once. I'm not sure what I'm doing wrong, can anyone offer some advice?
You're printing out the value at the index ie array[i] instead of i.
You're printing the value of the array at the index instead of the index itself. This fixes it. Also consider a return instead of a print statement.
def floor(array, target):
i = 0
while i < len(array):
if array[i] == target:
print("The target value can be found at index: " + str(i))
return i
else:
i = i + 1
four_ind = floor([1, 2, 3, 4, 4, 5, 6, 7, 8, 9], 4) # returns 3
try this:
def floor(array, target):
for i, value in enumerate(array):
if value == target:
print('target is in:', i)
floor([1,2,3,4,5, 4, 4,6], 4)
**I need to make a quicksort algorithm but so that it uses only one list and does swaps inside of it. I managed to make it "sort" or position the first element but now i don't know how to implement the recursion. The biggest problem I'm having is how to recursively work on a part of the list instead of making the new one. Here is my code:
-------------------------------------------------------------------------------**
New code, same problem.
Here is my code. It does the job but gets stuck in the loop.
def qsort(n,l,g):
if l is None:
l=0
if g is None:
g=len(n)
if g-l<=1:
return n
print g-l
p=n[l]
i=1+l
j=1+l
for x in n[l+1:g]:
if x<p:
n[i],n[j]=n[j],n[i]
i+=1
j+=1
n[l],n[i-1]=n[i-1],n[l]
ls=0
le=i-1
gs=i
ge=j
print n
qsort(n,ls,le)
qsort(n,gs,ge)
Can someone give me any suggestions, I'm lost. Can't find whats wrong or how to fix it.
Know its messy but cant do better atm :D
Write it like this:
def qsort(li, lo=None, hi=None):
if lo is None:
lo = 0
if hi is None:
hi = len(li) - 1
...
...
if hi - lo > 1:
qsort(## left half ##)
qsort(## right half ##)
lo and hi are the smallest and largest indexes you should look at in li, respectively.
Swap version of quicksort.
quicksort([10, 0, 9, 1, 8, 2, 7, 3, 6, 4, 5]) >> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
quicksort([0, 4, 2, 3, 6]) >> [0, 2, 3, 4, 6]
def quicksort(seq):
if len(seq) <= 1:
return seq
pivot_index = len(seq)-1
i = 0
while i < pivot_index:
if seq[i] > seq[pivot_index] and pivot_index-1 == i:
seq[i], seq[pivot_index] = seq[pivot_index], seq[i]
pivot_index -= 1
i = 0
elif seq[i] > seq[pivot_index] and pivot_index > 1:
seq[pivot_index-1], seq[pivot_index] = seq[pivot_index], seq[pivot_index-1]
seq[i], seq[pivot_index] = seq[pivot_index], seq[i]
pivot_index -= 1
i = 0
else:
i += 1
return quicksort(seq[:pivot_index]) + [seq[pivot_index]] + quicksort(seq[pivot_index+1:])