Get different sets of numbers with repetition - python-3.x

I have a list of numbers:
lst = [1, 2, 3, 1,4]
def permutation(lst):
# If lst is empty then there are no permutations
if len(lst) == 0:
return []
# If there is only one element in lst then, only
# one permuatation is possible
if len(lst) == 1:
return [lst]
# Find the permutations for lst if there are
# more than 1 characters
l = [] # empty list that will store current permutation
# Iterate the input(lst) and calculate the permutation
for i in range(len(lst)):
m = lst[i]
# Extract lst[i] or m from the list. remLst is
# remaining list
remLst = lst[:i] + lst[i + 1:]
# Generating all permutations where m is first
# element
for p in permutation(remLst):
l.append([m] + p)
return l
if __name__ == "__main__":
lst = [1, 2, 3, 1,4]
v_out = permutation(lst)
print(v_out)
I am only getting permutations of 4 length, I want permutatins of all lengths, and only distinct permutations. But within each permutation, repetition is allowed.

This should work... Using the permutations function from itertools and making a set out of everything to prevent duplicates from being added to the overall result
In [20]: from itertools import permutations
In [21]: a = [1, 1, 2, 3]
In [22]: all_results = set()
In [23]: for i in range(1, len(a)):
...: all_results.update(set(permutations(a, i)))
...:
In [24]: all_results
Out[24]:
{(1,),
(1, 1),
(1, 1, 2),
(1, 1, 3),
(1, 2),
(1, 2, 1),
(1, 2, 3),
(1, 3),
(1, 3, 1),
(1, 3, 2),
(2,),
(2, 1),
(2, 1, 1),
(2, 1, 3),
(2, 3),
(2, 3, 1),
(3,),
(3, 1),
(3, 1, 1),
(3, 1, 2),
(3, 2),
(3, 2, 1)}
In [25]:

Related

Finding unique combinations of tuples

Input: 1 2 3 4
Output: (1,2)(3,4)
(1,3)(2,4)
(1,4)(2,3)
I have been able to come up with a solution for the problem but it is efficient. It needs to be optimized.
comb = combinations(Arr,int(n/2))
l = []
for i in comb:
l.append(i)
final_comb = combinations(l,int(n/2))
for i in final_comb:
if is_unique(n,i):
print(i)
def is_unique(n,tup):
k = []
for i in tup:
for j in i:
k.append(j)
if len(set(k)) == n:
return True
return False
The output must be combinations of tuples such that they all have the numbers given as input
Use itertools
from itertools import combinations
list(combinations([1, 2, 3, 4], 2))
>>> [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]

How to assign a random weight to edges in networkx, like weight of edge (a, a) = 0 and weight of edge (a, b) = K, where K is some random number

I am working on weighted graphs and I would like to assign a random weight for the edges of the graph, such that,
weight of edge(a, a) = 0
weight of (a, b) = weight of edge(b, a) = K
where K is some random number. This goes on for all the edges of the graphs.
For that, I am using random.randint() method. I am actually using the logic of sum. If sum of both the edges is same, then assign some random integer.
Here is my code,
nodelist = list(range(1, num_nodes + 1))
edgelist = []
for i in nodelist:
for j in nodelist:
if i == j:
edgelist.append((i, j, 0))
if (i != j and sum((i, j)) == sum((j, i))):
rand = random.randint(5, 25)
edgelist.append((i, j, rand))
print(edgelist)
Actual result,
[(1, 1, 0), (1, 2, 18), (1, 3, 6), (2, 1, 13), (2, 2, 0), (2, 3, 21), (3, 1, 20), (3, 2, 17), (3, 3, 0)]
Expected result,
[(1, 1, 0), (1, 2, K), (1, 3, H), (2, 1, K), (2, 2, 0), (2, 3, P), (3, 1, H), (3, 2, P), (3, 3, 0)]
where, K, H, P are some random integers.
If the ordering of the result is not important following code gives the desired output:
import random
num_nodes = 3
nodelist = list(range(1, num_nodes + 1))
edgelist = []
for i in nodelist:
for j in nodelist:
if j > i:
break
if i == j:
edgelist.append((i, j, 0))
else:
rand = random.randint(5, 25)
edgelist.append((i, j, rand))
edgelist.append((j, i, rand))
print(edgelist)
# [(1, 1, 0), (2, 1, 7), (1, 2, 7), (2, 2, 0), (3, 1, 18), (1, 3, 18), (3, 2, 13), (2, 3, 13), (3, 3, 0)]
In case you need the edges sorted, simply use:
print(sorted(edgelist))
# [(1, 1, 0), (1, 2, 20), (1, 3, 16), (2, 1, 20), (2, 2, 0), (2, 3, 23), (3, 1, 16), (3, 2, 23), (3, 3, 0)]
Just a little change in your code will do the trick.
Here is the solution I found to obtain your expected output
num_nodes = 3
nodelist = list(range(1, num_nodes + 1))
edgelist = []
for i in nodelist:
for j in nodelist:
if i == j:
edgelist.append((i, j, 0))
elif i < j:
rand = random.randint(5, 25)
edgelist.append((i, j, rand))
edgelist.append((j, i, rand))
print(sorted(edgelist))
This code outputs :
[(1, 1, 0), (1, 2, 15), (1, 3, 15), (2, 1, 15), (2, 2, 0), (2, 3, 21), (3, 1, 15), (3, 2, 21), (3, 3, 0)]
So I figured out something interesting. Say below matrix shows edges in a complete graph of 5 nodes,
[1, 1] [1, 2] [1, 3] [1, 4] [1, 5]
[2, 1] [2, 2] [2, 3] [2, 4] [2, 5]
[3, 1] [3, 2] [3, 3] [3, 4] [3, 5]
[4, 1] [4, 2] [4, 3] [4, 4] [4, 5]
[5, 1] [5, 2] [5, 3] [5, 4] [5, 5]
now, moving right side from principal diagonal, we have lists whose first element is less than second element. We just got to target them and append new random weight to it.
Here is my code,
nodelist = list(range(1, num_nodes + 1))
edgelist = []
for i in nodelist:
for j in nodelist:
edgelist.append([i, j])
p = 0
eff_edgelist = []
while p < len(edgelist):
if edgelist[p][0] <= edgelist[p][1]:
eff_edgelist.append(edgelist[p])
p += 1
for i in eff_edgelist:
if i[0] == i[1]:
i.append(0)
else:
i.append(random.randint(5, 50))
eff_edgelist = [tuple(i) for i in eff_edgelist]
for i in list(G.edges(data=True)):
print([i])
and the result,
[(1, 1, {'weight': 0})]
[(1, 2, {'weight': 12})]
[(1, 3, {'weight': 37})]
[(1, 4, {'weight': 38})]
[(1, 5, {'weight': 6})]
[(2, 2, {'weight': 0})]
[(2, 3, {'weight': 12})]
[(2, 4, {'weight': 40})]
[(2, 5, {'weight': 8})]
[(3, 3, {'weight': 0})]
[(3, 4, {'weight': 15})]
[(3, 5, {'weight': 38})]
[(4, 4, {'weight': 0})]
[(4, 5, {'weight': 41})]
[(5, 5, {'weight': 0})]
and if you check, print(G[2][1]), the output will be {'weight': 12},
which means weight of edge(a, b) = weight of edge(b, a).

How to make 3 pairs of sub-lists from a Python list

In Python is there a way to get all 3 pairs or n pairs of a list from a list?
For example list = [1,2,3,4]
result : [[1,2,3],[2,3,4],[1,2,4]]
I want to find all possible n pairs of lists from a Python list. I do not want to import any other functions like itertools.
You can use the module itertools. It comes inside Python by default (you don't need to install it throught third party modules):
>>> import itertools
>>> print(itertools.permutations([1,2,3,4], 3))
[(1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 3, 4), (1, 4, 2), (1, 4, 3), (2, 1, 3), (2, 1, 4), (2, 3, 1), (2, 3, 4), (2, 4, 1), (2, 4, 3), (3, 1, 2), (3, 1, 4), (3, 2, 1), (3, 2, 4), (3, 4, 1), (3, 4, 2), (4, 1, 2), (4, 1, 3), (4, 2, 1), (4, 2, 3), (4, 3, 1), (4, 3, 2)]
This itertools.permutations(iterable, r=None) produces all the possible permutations of a given iterable element (like a list). If r is not specified or is None, then r defaults to the length of the iterable and all possible full-length permutations are generated.
If you are looking only for n pair of permutations instead of all the possible permutations just delete the rest of them:
>>> print(list(itertools.permutations([1,2,3,4], 3))[:3])
[(1, 2, 3), (1, 2, 4), (1, 3, 2)]
As you asked in comments you can do that without importing any module. itertools.permutations is just a function, which you can make by yourself:
def permutations(iterable, r=None):
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
if r > n:
return
indices = list(range(n))
cycles = list(range(n, n-r, -1))
yield tuple(pool[i] for i in indices[:r])
while n:
for i in reversed(range(r)):
cycles[i] -= 1
if cycles[i] == 0:
indices[i:] = indices[i+1:] + indices[i:i+1]
cycles[i] = n - i
else:
j = cycles[i]
indices[i], indices[-j] = indices[-j], indices[i]
yield tuple(pool[i] for i in indices[:r])
break
else:
return
But I strongly advise your importing it. If you don't want to import the whole module, just this function simply do from itertools import permutations.

How to group a list of tuples by nearest values for the n-th element?

I have a list of tuples which looks like this:
d = [(1,1,1),
(2,1,1),
(1,2,1),
(1,12,1),
(13,50,4),
(1,13,32),
(4,48,100),
(0,121,5)
]
And group this list by nearest values for the first element of each tuple, like this:
d_ordered = [
[(1,1,1),(2,1,1),(1,2,1)],
[(1,12,1),(1,13,32)],
[(4,48,100),(13,50,4)],
[(0,121,5)]
]
I found this:https://stackoverflow.com/a/10017017/9071615
which does it for a simple list. I tried to use that as a base but have no idea how to extend the solution to a list of tuples.
Any idea how to have the most efficient sorting for list of tuples?
import numpy as np
from itertools import groupby
n = 1
a = np.array([i[n] for i in d])# or np.array(d)[:,n] if all the elements of d have the same shape
b,c=np.where(np.abs(a-a[:,None]) < 5)# I used a maximum distance of 5, you did not specify exactly the allowable distance
e=set(tuple(k[1] for k in j) for i,j in groupby(zip(b,c),key=lambda x:x[0]))
[[d[j] for j in i] for i in e]
[[(1, 1, 1), (2, 1, 1), (1, 2, 1)],
[(0, 121, 5)],
[(13, 50, 4), (4, 48, 100)],
[(1, 12, 1), (1, 13, 32)]]
Here is a solution using sorted() and lambda:
d = [(1,1,1),
(2,1,1),
(1,2,1),
(1,12,1),
(13,50,4),
(1,13,32),
(4,48,100),
(0,121,5)
]
d_ordered = sorted(d, key = lambda x: (x[1]))
print(d_ordered)
Output:
[(1, 1, 1), (2, 1, 1), (1, 2, 1), (1, 12, 1), (1, 13, 32), (4, 48, 100), (13, 50, 4), (0, 121, 5)]

counting the number of each word in a dictionary

I am trying to fix this code:
def word_counter (input_str):
input_str1 = input_str.lower()
word = 0
input_str2 = dict(enumerate(input_str1.split(), start=1))
if word in input_str2:
input_str2[word] += 1
else:
input_str2[word] = 1
return (input_str2)
word_count_dict = word_counter("This is a sentence")
print(sorted(word_count_dict.items()))
so that instead of the output just being:
[(0, 1), (1, 'this'), (2, 'is'), (3, 'a'), (4, 'sentence')]
it will instead return a count of HOW MANY OF EACH word in input_str as so:
[('a', 1), ('is', 1), ('sentence', 1), ('this', 1)]
any help would be appreciated
You can just use collections.Counter:
>>> from collections import Counter
>>> c = Counter('This is a a a sentence'.split())
>>> c
Counter({'a': 3, 'This': 1, 'is': 1, 'sentence': 1})
>>> c['a']
3
>>> c['This']
1
>>> c.items()
[('This', 1), ('a', 3), ('is', 1), ('sentence', 1)]

Resources