moving elements in a list of Python - python

I have a list of integers; it contains the integer 27, but we don't know its index.
We have to find the index and then swap it with the item following it. If the index of 27 is the last element (list[-1]) than we swap 27 with the first element.
my_list = [1, 2, 3, 4, 27] # original
my_list = [27, 2, 3, 4, 1] # result
I know how to swap 27 when it is not the last element, but I don't know how to swap 27 with the first element like in the example I showed.

Once the number you are looking for always exists in the list just index and swap using modulo:
my_list = [1, 2, 3, 4, 27]
def swap(l,n):
ln = len(l)
ind = my_list.index(n)
l[ind], l[(ind + 1)% ln] = l[(ind + 1) % ln], l[ind]
Using % ln just mean we wrap around so when ind = 5 as per your example (4 + 1) % 5 will be 0
Output:
In [45]: my_list = [1, 2, 3, 4, 27]
In [46]: swap(my_list, 27)
In [47]: my_list
Out[47]: [27, 2, 3, 4, 1]
In [48]: swap(my_list, 4)
In [49]: my_list
Out[49]: [27, 2, 3, 1, 4]
You might want to handle the case where n does not exist:
def swap(l,n):
ln = len(l)
try:
ind = my_list.index(n)
l[ind], l[(ind + 1)% ln] = l[(ind + 1) % ln], l[ind]
except IndexError:
pass
What you do in the except is up to you.

Related

Swapping opposite elements of a List of Integers if either is Odd

Write a program with the definition of a function named Array_Swap() that will accept an integer list & its size as arguments and the function will swap elements in such a way that the first element is swapped with the last element, the second element is swapped with the second last element and so on, only if anyone or both the elements are odd and display the result.
If initially, a list of seven elements is: [5, 16, 4, 7, 19, 8, 2], the contents of the list after the execution should be:
[2, 16, 19, 7, 4, 8, 5].
def Array_Swap(List,Size):
for i in range (Size//2):
List[i]=List[Size//2-i]
print(List)
L=[]
n=int(input("Enter number of elements"))
for i in range(n):
x=int(input("Enter element"))
L.append(x)
Array_Swap(L,len(L))
The size/length of the list is not relevant because it can be obtained by len(list). And even then it's not required to conditionally swap items in the list. I suggest that the Size parameter be removed, but considering it's an assignment, it can be given a default of None so that it can be ignored by the caller if desired.
The following algorithm zips the input list with its reverse to form pairs relative to their index from the front and end of the list respectively, i.e. the first and last items are paired, the second and second last are paired, etc. Once the items are paired it is simply a matter of iterating over the list and emitting the second number of the pair if either number is odd, or the first number if neither is odd - effectively swapping the pairs as required.
This is done in-place (that's what the List[:] does) with a list comprehension.
def ArraySwap(List, Size=None):
List[:] = [b if (a % 2 or b % 2) else a
for a, b in zip(List, reversed(List))]
print(List)
>>> l = [5, 16, 4, 7, 19, 8, 2]
>>> ArraySwap(l)
[2, 16, 19, 7, 4, 8, 5]
>>> l
[2, 16, 19, 7, 4, 8, 5]
>>> l = list(range(1,30))
>>> ArraySwap(l)
[29, 2, 27, 4, 25, 6, 23, 8, 21, 10, 19, 12, 17, 14, 15, 16, 13, 18, 11, 20, 9, 22, 7, 24, 5, 26, 3, 28, 1]
>>> ArraySwap([1])
[1]
>>> ArraySwap([])
[]
To swap two elements in the list, use the pattern a, b = b, a.
If i is the index of a list item, it's opposite/mirror element is -(i+1), or - i - 1.
so for the 0th element (first one), the mirror is -(0+1), = -1
using that as the indexer for the element, swap the two list elements IF
check that at least one of them is odd before swapping:
def Array_Swap(List,Size):
for i in range (Size // 2):
if List[i] % 2 == 1 or List[-(i+1)] % 2 == 1:
List[i], List[-(i+1)] = List[-(i+1)], List[i]
print(List)
L = [5, 16, 4, 7, 19, 8, 2] # use your input blocks as before, this is an example
Array_Swap(L,len(L))
Output: [2, 16, 19, 7, 4, 8, 5]
(And if L = [5, 16, 4, 7, 19, 8, 1, 2], output is [2, 1, 4, 19, 7, 8, 16, 5].)
Btw, you don't need to pass in the size of the list as a parameter.
You could do just: for i in range(len(List) // 2)
Another solution:
def Array_Swap(List, Size=None):
if Size is None:
Size = len(List)
for (i, j) in zip(range(Size // 2), range(Size - 1, Size // 2, -1)):
if List[i] % 2 or List[j] % 2:
List[i], List[j] = List[j], List[i]
print(List)
Alternatively:
Size parameter is redundant since python's list instance knows its own size
Use bitwise operatos & | >>... possibly cheaper than modulus % and divide / operations.
def Array_Swap(List):
for i in range(len(List) >> 1):
if (List[i] | List[-i-1]) & 1:
List[i], List[-i-1] = List[-i-1], List[i]
print(List)
The standard way to swap two variables in Python is:
a, b = b, a
In this case, you would do:
lst[i], lst[size - i - 1] = lst[size - i - 1], lst[i]
which swaps the ith element with the element that is at index size - i - 1 (i.e. the ith index from the end).
The other issue with your code is that it doesn't check whether either of the elements being swapped are odd, which you can resolve by adding the condition:
if lst[i] % 2 or lst[size - i - 1] % 2:
before doing the swap. This uses the modulo operator (%) to check the parity of the elements. Taking a number modulo 2 will return 1 if the number is odd. If either are odd (1 has a truth value of True), the condition would succeed and the swap will be performed.
Finally, your function was printing the list, rather than returning it. Its usually best to return a result and print the returned result.
The full working version, with the above three changes is as follows:
def list_swap(lst, size):
for i in range(size // 2):
if lst[i] % 2 or lst[size - i - 1] % 2:
lst[i], lst[size - i - 1] = lst[size - i - 1], lst[i]
return lst
l = []
n = int(input("Enter number of elements: "))
for _ in range(n):
x = int(input("Enter element: "))
l.append(x)
result = list_swap(l, len(l))
print(result)
Also note, I've changed all the variables to be lowercase, which is standard in Python.
With your shown example:
Enter number of elements: 7
Enter element: 5
Enter element: 16
Enter element: 4
Enter element: 7
Enter element: 19
Enter element: 8
Enter element: 2
[2, 16, 19, 7, 4, 8, 5]

Python adding a list to a slice of another list

Here's basic problem:
>>> listb = [ 1, 2, 3, 4, 5, 6, 7 ]
>>> slicea = slice(2,5)
>>> listb[slicea]
[3, 4, 5]
>>> lista = listb[slicea]
>>> lista
[3, 4, 5]
>>> listb[slicea] += lista
>>> listb
[1, 2, 3, 4, 5, 3, 4, 5, 6, 7]
listb should be
[1, 2, 6, 8, 10, 6, 7]
But 3, 4, 5 was inserted after 3, 4, 5 not added to it.
tl;dr
I have this code that's not working:
self.lib_tree.item(song)['values'][select_values] = adj_list
self.lib_tree.item(album)['values'][select_values] += adj_list
self.lib_tree.item(artist)['values'][select_values] += adj_list
The full code is this:
def toggle_select(self, song, album, artist):
# 'values' 0=Access, 1=Size, 2=Selected Size, 3=StatTime, 4=StatSize,
# 5=Count, 6=Seconds, 7=SelSize, 8=SelCount, 9=SelSeconds
# Set slice to StatSize, Count, Seconds
total_values = slice(4, 7) # start at index, stop before index
select_values = slice(7, 10) # start at index, stop before index
tags = self.lib_tree.item(song)['tags']
if "songsel" in tags:
# We will toggle off and subtract from selected parent totals
tags.remove("songsel")
self.lib_tree.item(song, tags=(tags))
# Get StatSize, Count and Seconds
adj_list = [element * -1 for element in \
self.lib_tree.item(song)['values'][total_values]]
else:
tags.append("songsel")
self.lib_tree.item(song, tags=(tags))
# Get StatSize, Count and Seconds
adj_list = self.lib_tree.item(song)['values'][total_values] # 1 past
self.lib_tree.item(song)['values'][select_values] = adj_list
self.lib_tree.item(album)['values'][select_values] += adj_list
self.lib_tree.item(artist)['values'][select_values] += adj_list
if self.debug_toggle < 10:
self.debug_toggle += 1
print('artist,album,song:',self.lib_tree.item(artist, 'text'), \
self.lib_tree.item(album, 'text'), \
self.lib_tree.item(song, 'text'))
print('adj_list:',adj_list)
The adj_list has the correct values showing up in debug.
How do I add a list of values to the slice of a list?
The behavior you want is not a feature of any Python built-in type; + with built-in sequences means concatenation, not element-wise addition. But numpy arrays will do what you want, so I'd suggest looking into numpy. Simple example:
>>> import numpy as np
>>> a = np.array([2,3,4], dtype=np.int64)
>>> b = np.array([5,6,7], dtype=np.int64)
>>> a += b
>>> a
array([ 7, 9, 11])
>>> print(a)
[ 7 9 11]
>>> print(a.tolist())
[7, 9, 11]
Note that the output (both repr and str forms) looks a little different from Python lists, but you can convert back to a plain Python list if needed.

constructing arithmetic progressions from loop

I am trying to work out a program that would calculate the diagonal coefficients of pascal's triangle.
For those who are not familiar with it, the general terms of sequences are written below.
1st row = 1 1 1 1 1....
2nd row = N0(natural number) // 1 = 1 2 3 4 5 ....
3rd row = N0(N0+1) // 2 = 1 3 6 10 15 ...
4th row = N0(N0+1)(N0+2) // 6 = 1 4 10 20 35 ...
the subsequent sequences for each row follows a specific pattern and it is my goal to output those sequences in a for loop with number of units as input.
def figurate_numbers(units):
row_1 = str(1) * units
row_1_list = list(row_1)
for i in range(1, units):
sequences are
row_2 = n // i
row_3 = (n(n+1)) // (i(i+1))
row_4 = (n(n+1)(n+2)) // (i(i+1)(i+2))
>>> def figurate_numbers(4): # coefficients for 4 rows and 4 columns
[1, 1, 1, 1]
[1, 2, 3, 4]
[1, 3, 6, 10]
[1, 4, 10, 20] # desired output
How can I iterate for both n and i in one loop such that each sequence of corresponding row would output coefficients?
You can use map or a list comprehension to hide a loop.
def f(x, i):
return lambda x: ...
row = [ [1] * k ]
for i in range(k):
row[i + 1] = map( f(i), row[i])
where f is function that descpribe the dependency on previous element of row.
Other possibility adapt a recursive Fibbonachi to rows. Numpy library allows for array arifmetics so even do not need map. Also python has predefined libraries for number of combinations etc, perhaps can be used.
To compute efficiently, without nested loops, use Rational Number based solution from
https://medium.com/#duhroach/fast-fun-with-pascals-triangle-6030e15dced0 .
from fractions import Fraction
def pascalIndexInRowFast(row,index):
lastVal=1
halfRow = (row>>1)
#early out, is index < half? if so, compute to that instead
if index > halfRow:
index = halfRow - (halfRow - index)
for i in range(0, index):
lastVal = lastVal * (row - i) / (i + 1)
return lastVal
def pascDiagFast(row,length):
#compute the fractions of this diag
fracs=[1]*(length)
for i in range(length-1):
num = i+1
denom = row+1+i
fracs[i] = Fraction(num,denom)
#now let's compute the values
vals=[0]*length
#first figure out the leftmost tail of this diag
lowRow = row + (length-1)
lowRowCol = row
tail = pascalIndexInRowFast(lowRow,lowRowCol)
vals[-1] = tail
#walk backwards!
for i in reversed(range(length-1)):
vals[i] = int(fracs[i]*vals[i+1])
return vals
Don't reinvent the triangle:
>>> from scipy.linalg import pascal
>>> pascal(4)
array([[ 1, 1, 1, 1],
[ 1, 2, 3, 4],
[ 1, 3, 6, 10],
[ 1, 4, 10, 20]], dtype=uint64)
>>> pascal(4).tolist()
[[1, 1, 1, 1], [1, 2, 3, 4], [1, 3, 6, 10], [1, 4, 10, 20]]

Retaining information through recursion under strict conditions (Python)

My partner and I are working on a problem in which we need to reduce an array and run operations on the pieces (in this case, of 2), we are reducing with recursion and sending the left-right hand sides of the array back into function.
We have all this working fine, and for example, using the array [2, 3, 4, 5, 6, 7, 8, 9] we get all the pieces we need.
The problem is, we need each of these pieces to then run the math operation on the next piece we get.
So, for example we recur down to [2, 3] and transform that into [5, -1]. Then we recur down to [4, 5] and change that into [9, -1] and combine them into [14, -2, -4, 0]. This is the left hand side of our array. And this works great. And then it does the right hand side, and it gets the answer we want. This works great.
The problem, is we now need both parts together (can't use global variables). And we have been stuck here for several hours. We can only pass the simplified array through the recursion, and if we initialize an array to hold both parts it will get reset when the right-hand side starts.
Thanks
EDIT: Code: The H is starting matrix that is given, but it doesn't matter, it as no relevance its just there so the unit test goes through (We could use it, but we don't really know how)
The imput for x is [2,3,4,5,6,7,8,9]
def hadmatmult(H, x):
d = 0
n = len(x)
first = 0
last = len(x)
a = [0] * math.floor(n/2)
b = [0] * math.floor(n/2)
if n == 2:
temp1 = x[0]
x[0] = temp1 + x[1]
x[1] = temp1 - x[1]
else:
mid = math.floor((first+last)/2)
for i in range(first, mid):
a[i] = x[i]
hadmatmult(H, a)
for j in range(mid, last):
b[d] = x[j]
d = d + 1
hadmatmult(H, b)
if(len(a) == 2:
adds = [0] * len(a)
subs = [0] * len(a)
for t in range(0, len(a)):
adds[t] = a[t] + b[t]
subs[t] = a[t] - b[t]
#alladds = alladds + adds
#allsubs = allsubs + subs
print(adds)
print(subs)
Output: This outputs the parts, [14, -2, -4, 0] and [30, -2, -4, 0]
If you must recurse, do so in a simpler way. Strip off the elements you need and recurse through the rest.
x = [2,3,4,5,6,7,8,9]
def recurse_and_stuff(x):
if len(x) == 0:
# base case
return []
a, b, = x[:2], x[2:4]
m,n,o,p = [a[0]+a[1], a[0]-a[1], b[0]+b[1], b[0]-b[1]]
result = [[m+o, n+p, m-o, n-p]] + recurse_and_stuff(x[4:])
return result
>>> x = [2,3,4,5,6,7,8,9]
>>> recurse_and_stuff(x)
[[14, -2, -4, 0], [30, -2, -4, 0]]
>>> x = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
>>> recurse_and_stuff(x)
[[14, -2, -4, 0], [30, -2, -4, 0], [46, -2, -4, 0], [62, -2, -4, 0]]
# works for longer inputs as long as len(x) % 4 == 0
To recurse all the way down:
import itertools
def do_the_needful(a,b):
try:
zipped = zip(a,b)
except TypeError:
# a and b are ints, not lists of ints
zipped = [(a,b)]
return itertools.chain.from_iterable(zip(*[[aa+bb, aa-bb] for aa,bb in zipped]))
def recurse_and_stuff(x):
if len(x) == 1:
return list(x[0])
# if you only have to iterate through this, there's no
# need to call `list(...)` here.
return recurse_and_stuff([do_the_needful(x[i], x[i+1]) for i in range(0, len(x), 2)])

Iterate through each value of list in order, starting at random value

Given the following code:
length = 10
numbers = [x for x in range(length)]
start_index = randint(0,length-1)
# now output each value in order from start to start-1 (or end)
# ex. if start = 3 --> output = 3,4,5,6,7,8,9,0,1,2
# ex if start = 9 ---> output = 9,0,1,2,3,4,5,6,7,8
What is the best / simplest / most pythonic / coolest way to iterate over the list and print each value sequentially, beginning at start and wrapping to start-1 or the end if the random value were 0.
Ex. start = 3 then output = 3,4,5,6,7,8,9,1,2
I can think of some ugly ways (try, except IndexError for example) but looking for something better. Thanks!
EDIT: made it clearer that start is the index value to start at
You should use the % (modulo) operator.
length = 10
numbers = [x for x in range(length)]
start = randint(0, length)
for i in range(length):
n = numbers[(i + start) % length]
print(n)
>>> start = randint(0, len(numbers))
>>> start
1
You can use list slicing then iterate over that
>>> numbers[start:] + numbers[:start]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
You can also use the modulus % operator in a list comprehension
>>> [numbers[i%len(numbers)] for i in range(start, start + len(numbers))]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
What is the best / simplest / most pythonic / coolest way ...
You can use collections.deque and its rotate function, like this
>>> from collections import deque
>>> d = deque(numbers)
>>> d.rotate(-9)
>>> d
deque([9, 0, 1, 2, 3, 4, 5, 6, 7, 8])
>>>
>>> d = deque(numbers)
>>> d.rotate(-2)
>>> d
deque([2, 3, 4, 5, 6, 7, 8, 9, 0, 1])
You can try to iterate over the list with simple conditional loops
i = start
while(True):
print i,
if i==numbers[-1]: # If it's the last number
i=numbers[0]
else:
i += 1
if i==start: # One iteration is over
break
This will print 3 4 5 6 7 8 9 0 1 2

Categories