How could I shuffle a list to this rule? - python

I am trying to make an algorithm to shuffle a list and then make a new list of all the combinations according to this rule:
You are only allowed to swap one pair. For example:
array = [1, 2, 3]
[3, 2, 1] #number at index 0 switched with number at index 2
Any thoughts on how to write it?
Edit:
Saschas code worked well. I wrote this code before asking the question:
sols = []
for i in range(len(a)):
for j in range(len(a)):
a[i] = a[j]
a[j] = a[i]
sols_perm.append(a)
I was aware that I would get some identical elements in the list because of unordered pairs but it just created a list full of identical elements. Any thoughts why?

sols = []
for i in range(len(array)):
for j in range(i+1, len(array)): # symmetry-reduction -> ordered pairs
sol = array[:] # copy list
sol[i], sol[j] = sol[j], sol[i] # swap
sols.append(sol)

Try the function below:
def swap(inlist):
n = len(inlist)
res = [x for x in inlist]
for i in range(n):
for j in range(i+1, n):
tmp = res[i]
res[i] = res[j]
res[j] = tmp
return res

Related

how to solve this problem sum of the element of list in triangle format

I was attempting the sum of elements of the list. where I have to add the adjacent elements of the list and create a new list and repeat the process until I have the last element which will be the answer. I am able to solve the list of lengths less than 5 but I am not able to generalize the solution for any given list. Help me to solve this problem. below is my starting code:
here is the example;
general example of the problem
lst=[]
n=int(input())
for i in range(0,n):
num = int(input())
lst.append(num)
print(lst)
sum1=[]
for i in range(1,len(lst)):
sum=i+i+1
sum1.append(sum)
print(sum1)
The following seems reasonably simple:
n = int(input())
lst = [int(input()) for _ in range(n)]
while len(lst) > 1:
lst[:] = map(sum, zip(lst, lst[1:])) # all sums of neighbours
print(lst)
# Output for 1 2 3 4
# [3, 5, 7]
# [8, 12]
# [20]
Some docs:
zip
map
sum
A simple understandable function:
def solve(seq):
while len(seq) > 1:
res = []
for i in range(len(seq) - 1):
res.append(seq[i] + seq[i+1])
print(res)
seq = res
return res[0]
solve([1,2,3,4])
The idea is to find adjacent sums and store in a new list. Keep doing till length becomes 1.
Some higher order function magic can be added to this if the logic becomes clear to someone.
Given 2 lists of equal length you could do this:
M = [1,2,3]
N = [5,6,7]
print(*map(sum, zip(M,N)))

Can't figure out why I keep getting a "list index out of range" error. Can someone assist me?

I keep getting a "list index out of range" error, but don't know why. Can someone help?
arr = []
if __name__ == '__main__':
x = int(input())
y = int(input())
z = int(input())
n = int(input())
for x in range (x+1):
for y in range(y+1):
for z in range(z+1):
arr.append([x,y,z])
for i in range(len(arr)):
if (arr[i][0] + arr[i][1] + arr[i][2] == n):
del arr[i]
print(arr)
This is happening because you're mutating your list as you traverse through it. In your specific example, you would actually be better off creating a new list from the old list. In this example:
arr = [x for x in arr if (x[0] + x[1] + x[2] != n)]
EDIT: In addition to the comment about the scope of this activity relative to main.
It's better to build a list like this as a comprehension, where you can filter the elements as you build the list rather than having to go back and try to extract them after the fact:
x, y, z, n = (int(input()) for _ in range(4))
arr = [
[i, j, k]
for i in range(x+1)
for j in range(y+1)
for k in range(z+1)
if i + j + k != n
]
That is because you iterate over the len of an array, but that len is computed and stored at the beginning, it isn't update. Let's say the array if of len 5, the loop generates 0,1,2,3,4 but if you delete an item during the loop, when doing arr[4] it'll fail
The best solution is to keep interesting items, not delete the others, whether with another array, or a list comprehension. Also you can iterate of the values of an array, not on indices
# new array
new_vals = []
for v in arr:
if sum(v) != n:
new_vals.append(v)
# list comprehension
arr = [v for v in arr if sum(v) != n]

Printing all subsets with only a given length in python

I have the task to print all subsets of given length, I have created the functions to print out the all the subsets. Everything works fine the subsets are generated, but the output is wrong for each call. For example if I call print(get_subsets([1,2,3],2)) the output is [1,2] [1,3] [2,3] and [3]. Of course 3 is not supposed to be there and I can't figure out why. Any help will be appreciated and feedback of course.
def get_subsets(nums, k):
all_subsets = []
_gen_subsets(nums =nums,curr_idx =0,curr_subset=[],
all_subsets=all_subsets)
for curr_subset in all_subsets:
if len(curr_subset) > k or len(curr_subset) < k:
all_subsets.remove(curr_subset)
return all_subsets
def _gen_subsets(nums,curr_idx, curr_subset, all_subsets):
if curr_idx >= len(nums):
all_subsets.append(curr_subset)
else:
itr_subset = curr_subset.copy()
itr_subset.append(nums[curr_idx])
_gen_subsets(nums=nums,
curr_idx=curr_idx+1,
curr_subset=itr_subset,
all_subsets=all_subsets)
_gen_subsets(nums=nums,
curr_idx=curr_idx+1,
curr_subset=curr_subset,
all_subsets=all_subsets)
You are trying to iterate through a list from which you are also removing elements. This messed up the position and index of the list of subsets and gave you the wrong output.
Change the function get_subsets to this:
def get_subsets(nums, k):
all_subsets = []
_gen_subsets(nums =nums,curr_idx =0,curr_subset=[],
all_subsets=all_subsets)
final_subset = all_subsets.copy()
for n in all_subsets:
if len(n) != k:
final_subset.remove(n)
return final_subset
Or this:
def get_subsets(nums, k):
all_subsets = []
_gen_subsets(nums =nums,curr_idx =0,curr_subset=[],
all_subsets=all_subsets)
all_subsets = [n for n in all_subsets if len(n) == k]
return all_subsets
Your problem is caused by this:
for curr_subset in all_subsets:
if len(curr_subset) > k or len(curr_subset) < k:
all_subsets.remove(curr_subset)
You are removing array elements while iterating. That leads to the following scenario: Initially you have array [X1, X2, X3].
In the first iteration, you remove the first element X1. Then the second element X2 becomes the first element and therefore, on the second iteration, the third element X3 (which has become the second element) is traversed and X2 is skipped. That is why [3] is not removed from your array.
To solve this, you can change get_subsets function as below:
def get_subsets(nums, k):
all_subsets = []
_gen_subsets(nums =nums,curr_idx =0,curr_subset=[],
all_subsets=all_subsets)
all_subsets = [subset for subset in all_subsets if len(subset) == k]
return all_subsets
maybe thes two will help you?
def Combinations(l, d):
if (d <= 1) or (len(l) <= 1):
return [[i] for i in l]
else:
result = []
for i in range(len(l)):
c = l[i]
lx = l[:i]+l[i+1:]
for cmb in Combinations(lx, d-1):
result.append([c]+cmb)
return result
print(*Combinations([1, 2, 3, 4, 5, 6], 2), sep='\n')
def Allocations(l, d):
if (d <= 1) or (len(l) <= 1):
return [[i] for i in l]
else:
result = []
for i in range(len(l)+1-d):
c = l[i]
lx = l[i+1:]
for cmb in Allocations(lx, d-1):
result.append([c]+cmb)
return result
print(*Allocations([1, 2, 3, 4, 5, 6], 3), sep='\n')

Making Matrices without a library / Inserting nested lists without anything being in a list

I am trying to input and then print a matrix in Python without a library.
Code:
a = []
n = int(input('Length of the row'))
m = int(input('Length of the column'))
for j in range(0, m):
a[j].append([])
for i in range(0, n):
for j in range(0, m):
a[i][j] = int(input())
for i in range(0, n):
print()
for j in range(0, m):
print(a[i][j], end=" ")
Working:
When I put my list to be let's say:
a = [[1,1,1],[1,1,1],[1,1,1]]
And put both m and n to be 3, It works exactly as it should.
Error:
But having only an empty list, as in the code example, I always get an error that list index is out of range.
a[j].append([]) IndexError: list index out of range
Problem:
I don't know how to input nested lists inside a list, and integers inside those nested lists, with a loop, or with anything for that matter.
It is bound to fail:
a = []
# ...
for j in range(0, m):
a[j].append([]) # a is empty, so a[j] must fail!
Try instead:
a = []
n = int(input('Length of the row'))
m = int(input('Length of the column'))
for i in range(m): # m is len of outer list: number of rows == len of column
a.append([])
for j in range(n): # n is len of inner list (those are the rows)
a[i].append(int(input()))
# append as well, as indexes to fill do not exist yet
# the loop could be written as a comprehension:
a = [[int(input()) for _ in range(n)] for _ in range(m)]
for i in range(m):
print()
for j in range(n):
print(a[i][j], end=" ")
Remove the first loop and then make the input loop look something like this:
a = [None] * n
for i in range(n):
a[i] = []
for j in range(m):
a[i].append(int(input()))
append will add elements to a list. a is empty at firsts so a[i] is an error. See my sample that does what you want.
a = []
n = int(input('Enter row count: '))
m = int(input('Enter column count: '))
for i in range(0, n):
a.append([])
for i in range(0, n):
for j in range(0, m):
a[i].append(int(input()))
for i in range(0, n):
print()
for j in range(0, m):
print(a[i][j], end=" ")
print()
Sample run:
Enter row count: 2
Enter column count: 3
1
2
3
4
5
6
1 2 3
4 5 6
When you create a it is empty so you cannot not index anything in it.
>>> a = []
>>> len(a)
0
>>> a[0]
Traceback (most recent call last):
File "<pyshell#126>", line 1, in <module>
a[0]
IndexError: list index out of range
>>>
Just append the empty lists:
>>> a.append([])
>>> a
[[]]
>>> len(a)
1
>>> a[0]
[]
>>>
You have a similar problem when adding to the inner loops. It could be done like this
>>> i = 0
>>> a[i].append(int(input()))
4
>>> a
[[4]]
>>>
You have two mistakes:
You are not being consistent on what are rows and what columns
You are addressing an array/list content that hasn't been allocated any memory
Furthermore, you don't need that third for loop.
n=2
m=3
a=[]
for i in range(0, n):
a.append([])
for j in range(0, m):
a[i].append( int(input()) )
print(a)
which, for input 1-6, gives you
1
2
3
4
5
6
[[1, 2, 3], [4, 5, 6]]

Find/extract a sequence of integers within a list in python

I want to find a sequence of n consecutive integers within a sorted list and return that sequence. This is the best I can figure out (for n = 4), and it doesn't allow the user to specify an n.
my_list = [2,3,4,5,7,9]
for i in range(len(my_list)):
if my_list[i+1] == my_list[i]+1 and my_list[i+2] == my_list[i]+2 and my_list[i+3] == my_list[i]+3:
my_sequence = list(range(my_list[i],my_list[i]+4))
my_sequence = [2,3,4,5]
I just realized this code doesn't work and returns an "index out of range" error, so I'll have to mess with the range of the for loop.
Here's a straight-forward solution. It's not as efficient as it might be, but it will be fine unless you have very long lists:
myarray = [2,5,1,7,3,8,1,2,3,4,5,7,4,9,1,2,3,5]
for idx, a in enumerate(myarray):
if myarray[idx:idx+4] == [a,a+1,a+2,a+3]:
print([a, a+1,a+2,a+3])
break
Create a nested master result list, then go through my_sorted_list and add each item to either the last list in the master (if discontinuous) or to a new list in the master (if continuous):
>>> my_sorted_list = [0,2,5,7,8,9]
>>> my_sequences = []
>>> for idx,item in enumerate(my_sorted_list):
... if not idx or item-1 != my_sequences[-1][-1]:
... my_sequences.append([item])
... else:
... my_sequences[-1].append(item)
...
>>> max(my_sequences, key=len)
[7, 8, 9]
A short and concise way is to fill an array with numbers every time you find the next integer is the current integer plus 1 (until you already have N consecutive numbers in array), and for anything else, we can empty the array:
arr = [4,3,1,2,3,4,5,7,5,3,2,4]
N = 4
newarr = []
for i in range(len(arr)-1):
if(arr[i]+1 == arr[i+1]):
newarr += [arr[i]]
if(len(newarr) == N):
break
else:
newarr = []
When the code is run, newarr will be:
[1, 2, 3, 4]
#size = length of sequence
#span = the span of neighbour integers
#the time complexity is O(n)
def extractSeq(lst,size,span=1):
lst_size = len(lst)
if lst_size < size:
return []
for i in range(lst_size - size + 1):
for j in range(size - 1):
if lst[i + j] + span == lst[i + j + 1]:
continue
else:
i += j
break
else:
return lst[i:i+size]
return []
mylist = [2,3,4,5,7,9]
for j in range(len(mylist)):
m=mylist[j]
idx=j
c=j
for i in range(j,len(mylist)):
if mylist[i]<m:
m=mylist[i]
idx=c
c+=1
tmp=mylist[j]
mylist[j]=m
mylist[idx]=tmp
print(mylist)

Categories