This is the function i wrote for a program, its supposed to move a value a spot down a list.
def moveCard(deck):
index = deck.index(27)
deck.pop(index)
left = deck[:index+1]
right = deck[index+1:]
left.append(27)
print (left + right)
deck = left + right
however it doesn't properly add the two lists unless i print it within the function it self.
running the funtion using text list cards = [24, 27, 2, 5, 8, 11] prints out the proper list, being [24, 2, 27, 5, 8, 11]. However if i then simply ask for the value of cards after running the method i get
[24, 2, 5, 8, 11]. Any ideas why this is happening?
EDIT
this is my function:
def move_joker_1(deck):
index = deck.index(JOKER1)
deck.pop(index)
left = deck[:index+1]
right = deck[index+1:]
left.append(JOKER1)
deck = left + right
print(left + right)
print(dec
This is what i type into shel/results:
cards = [24, 27, 2, 5, 8, 11]
move_joker_1(cards)
[24, 2, 27, 5, 8, 11]
[24, 2, 27, 5, 8, 11]
print(cards)
[24, 2, 5, 8, 11]
I think your problem is this:
Inside the moveCard function, you've got a parameter named deck. First you do this:
deck.pop(index)
That's modifying the actual list that was passed in, so the caller is going to see that.
Then, later:
deck = left + right
That isn't modifying anything; it's creating a new list, left + right, and changing the local variable deck to be a name for that new list instead of for the old one.
What you probably want to do here is return the new list, so the caller can store it wherever he wants. But in that case, you don't want to mutate the original list with pop.
Alternatively, you could modify the list in-place both times, e.g., by writing deck[:] = left + right.
From your edit: you are not modifying the cards list. You should put a return statement in your function and then call the function as follows: cards = move_joker_1(cards).
Related
Hi I need help to create a program that receives a list and returns a tuple with the following guidelines:
The first value of the tuple is the same of the first in the list.
The second element has to be greater than the first one but with
the shortest distance between them.
Has to be a smaller value
than the second one, but with the maximum distance between them.
For example:
list=[12, 6, 30, 25, 40, 3, 7]
result:
tuple= (12, 25, 3, 6, 7, 30, 40)
There is a function tuple() for the desired outcome
my_list = [1,2]
print(tuple(my_list))
Output: (1, 2)
I have added an answer for the list to tuple conversion. For the algorithm, you can generate the new list and convert it to a tuple with this function.
I think I reached what you want.
The Code I created:
def target(inputs):
output = []
output.append(inputs[0])
inputs = inputs[1:]
# The Second Value
second = [x for x in inputs if x > output[0]]
new = []
for num in second:
new.append(num - output[0])
output.append(second[new.index(min(new))])
inputs.remove(second[new.index(min(new))])
for i in sorted(inputs):
output.append(i)
return tuple(output)
I tested it and it is clear of bugs
I ran it with your list.
inputs=[12, 6, 30, 25, 40, 3, 7]
print(target(inputs))
and this is the output
(12, 25, 3, 6, 7, 30, 40)
I also tested it with this list
inputs=[19, 21, 25, 100, 8, 13]
and the output is
(19, 21, 8, 13, 25, 100)
This question already has answers here:
Strange result when removing item from a list while iterating over it
(8 answers)
Closed 7 years ago.
I'm trying to move the odd numbers in this list to the end without using an external list. When I run the code, it moves half of the odd numbers over, and leaves the other half where they were. The overall output is correct if I run the code twice on the list, but I should only have to run it once, right? What am I doing wrong?
a = [3, 4, 55, 13, 6, 19, 33, 10, 11, 45]
for ind, val in enumerate(a):
if val % 2 != 0:
a.pop(ind)
a.append(val)
print a
Thanks.
This is because, as a general rule, you shouldn't iterate through and modify the same list at the same time. The indices get thrown off!
As you go through and modify the list, not all of the elements actually get cycled through. The a that you are popping is a different list with different indicies after your first change to the list, but you are still using the enumeration of the original version for your loop.
You could use pythons sorting methods (sorted() or someList.sort()) and pass a special key function to it:
>>> sorted(a, key = lambda element: element%2 != 0)
[4, 6, 10, 3, 55, 13, 19, 33, 11, 45]
This is possible because Python sorts are guaranteed to be stable und therefore when multiple records have the same key, their original order is preserved.
Your approach has two problems,
you modify the list on which you iterate
you don't test if the number that slides into the position occupied by an odd number is odd itself
To obviate with 1., you simply can iterate on the indices of your list but to obviate 2., you must start from the end of the list and going towards the beginning, using negative indices.
Executing the following code
a = [3, 4, 55, 13, 6, 19, 33, 10, 11, 45]
for i in range(len(a)):
j = -1-i
if a[j]%2:
a.append(a[j]) ; a.pop(j-1) # j-1 because our list is temporarily longer...
print a
gives you the following output
[4, 6, 10, 45, 11, 33, 19, 13, 55, 3]
I have a list of lists. The lists within these list look like the following:
[0,2,5,8,7,12,16,18], [0,9,18,23,5,8,15,16], [1,3,4,17,19,6,13,23],
[9,22,21,10,11,20,14,15], [2,8,23,0,7,16,9,15], [0,5,8,7,9,11,20,16]
Every small list has 8 values from 0-23 and there are no value repeats within a small list.
What I need now are the three lists which have the values 0-23 stored. It is possible that there are a couple of combinations to accomplish it but I do only need one.
In this particular case the output would be:
[0,2,5,8,7,12,16,18], [1,3,4,17,19,6,13,23], [9,22,21,10,11,20,14,15]
I thought to do something with the order but I'm not a python pro so it is hard for me to handle all the lists within the list (to compare all).
Thanks for your help.
The following appears to work:
from itertools import combinations, chain
lol = [[0,2,5,8,7,12,16,18], [0,9,18,23,5,8,15,16], [1,3,4,17,19,6,13,23], [9,22,21,10,11,20,14,15], [2,8,23,0,7,16,9,15], [0,5,8,7,9,11,20,16]]
for p in combinations(lol, 3):
if len(set((list(chain.from_iterable(p))))) == 24:
print(p)
break # if only one is required
This displays the following:
([0, 2, 5, 8, 7, 12, 16, 18], [1, 3, 4, 17, 19, 6, 13, 23], [9, 22, 21, 10, 11, 20, 14, 15])
If it will always happen that 3 list will form numbers from 0-23, and you only want first list, then this can be done by creating combinations of length 3, and then set intersection:
>>> li = [[0,2,5,8,7,12,16,18], [0,9,18,23,5,8,15,16], [1,3,4,17,19,6,13,23], [9,22,21,10,11,20,14,15], [2,8,23,0,7,16,9,15], [0,5,8,7,9,11,20,16]]
>>> import itertools
>>> for t in itertools.combinations(li, 3):
... if not set(t[0]) & set(t[1]) and not set(t[0]) & set(t[2]) and not set(t[1]) & set(t[2]):
... print t
... break
([0, 2, 5, 8, 7, 12, 16, 18], [1, 3, 4, 17, 19, 6, 13, 23], [9, 22, 21, 10, 11, 20, 14, 15])
Let's do a recursive solution.
We need a list of lists that contain these values:
target_set = set(range(24))
This is a function that recursively tries to find a list of lists that match exactly that set:
def find_covering_lists(target_set, list_of_lists):
if not target_set:
# Done
return []
if not list_of_lists:
# Failed
raise ValueError()
# Two cases -- either the first element works, or it doesn't
try:
first_as_set = set(list_of_lists[0])
if first_as_set <= target_set:
# If it's a subset, call this recursively for the rest
return [list_of_lists[0]] + find_covering_lists(
target_set - first_as_set, list_of_lists[1:])
except ValueError:
pass # The recursive call failed to find a solution
# If we get here, the first element failed.
return find_covering_lists(target_set, list_of_lists[1:])
I'm having a problem where when I pass an array into a function, the original value of the array is changed. My example below should clarify what I mean.
So if I have the falling example:
def swap(array):
while True:
noChange = True
for i in range(len(array) - 1):
if array[i] > array[i + 1]:
array[i], array[i + 1] = array[i + 1], array[i]
noChange = False
if noChange:
return array
def baseline(array):
array = sorted(array)
return array
array = [20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0]
sortedArray = swap(array)
print array # Result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
array = [20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0]
sortedArray = baseline(array)
print array # Result: [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
From above, you can see that for some reason, array has been changed when the function called swap is run but when I run baseline. In the function called swap, I've tried re-naming all instances of array to localArray to see if it made a difference but I'm still having the same problem.
I'm sure this is something very obvious that I've over looked but would somebody be able to explain why this is happening?
When you pass the list array to a function, the argument reference to the same list object, if it's modified inside the function, the original list is modifed as well.
If this is not what you want, copy the list in the beginning of the function:
def swap(array):
array = array[:]
# ...
When you pass a list to a function, you are passing the reference to it, hence if you change the list inside the function it will also get changed, you can send a shallow copy of the list (as the list only contains integers) as the argument, so that it does not get changed.
When calling the function do -
import copy
sortedArray = swap(copy.copy(array))
Another way to do it would be to copy the array inside your function, Example -
import copy
def swap(array):
array = copy.copy(array)
When your list contains references to other mutable objects, you should use copy.deepcopy() function (If you will be making changes inside the objects, but you do not want the same changes to reflect to the objects in the original list).
This is the final product. IF anyone else has any tips to cut it up, please let me know! Thanks a lot for the help!
def triple_cut(deck):
''' (list of int) -> NoneType
Modify deck by finding the first joker and putting all the cards above it
to the bottom of deck, and all the cards below the second joker to the top
of deck.
>>> deck = [2, 7, 3, 27, 11, 23, 28, 1, 6, 9, 13, 4]
>>> triple_cut(deck)
>>> deck
[1, 6, 9, 13, 4, 27, 11, 23, 28, 2, 7, 3]
'''
joker1 = deck.index(JOKER1)
joker2 = deck.index(JOKER2)
first = min(joker1, joker2)
first_cards = []
for cards in range(len(deck[:first])):
cards = 0
pop = deck.pop(cards)
first_cards.append(pop)
joker1 = deck.index(JOKER1)
joker2 = deck.index(JOKER2)
second = max(joker1, joker2)
second_cards = []
for cards in deck[second + 1:]:
pop = deck.pop(deck.index(cards))
second_cards.append(pop)
second_cards.reverse()
for card in second_cards:
deck.insert(0, card)
deck.extend(first_cards)
raah I need to type more because my post is mostly code: please add more details sss ss
A hint:
p = list('abcdefghijkl')
pivot = p.index('g')
q = p[pivot:] + p[:pivot]
List slicing is your friend.
answer to the second revision
when the function is finished, it won't mutate the deck.
The problem is that you didn't give the full code. I'm guessing it looks like this:
def triple_cut(deck)
…
deck = q
And according to your docstring you call it as
deck = […]
triple_cut(deck)
and have gotten confused that the assignment deck = q doesn't propagate out of triple_cut(). You can't modify the formal parameters of a method so the assignment remains local to triple_cut and does not affect the module level variable deck
The proper way to write this is
def triple_cut(cuttable)
…
return cuttable[first:] + cuttable[:first]
deck = […]
deck = triple_cut(deck)
where I changed the name of the argument to cuttable to for purposes of explanation. You could keep the argument name as deck but I wanted to show that when you thought you were assigning to deck you were really assigning to cuttable and that assignment wouldn't carry out of triple_cut().