Assign a repeated sequence to an index in python - python

I am very new to python and I wanted to know, how can I assign an integer incrementally to every 3 values in a series. Might be better to explain with an example:
The result should contain the following pattern :
(1,1),(2,1),(3,1),(4,2),(5,2),(6,2),(7,3).......

Alternatively, just using a simple for loop and two variables:
val1 = 1
val2 = 1
for a in range(10): # this number is arbitrarily large
for b in range(3): # this number is not arbitrary
print( (val1, val2) )
val1 += 1
val2 += 1

You can use the floor division operator with a list comprehension:
n = range(1, 10)
res = [(i, idx//3 + 1) for idx, i in enumerate(n)]
print(res)
[(1, 1), (2, 1), (3, 1),
(4, 2), (5, 2), (6, 2),
(7, 3), (8, 3), (9, 3)]

If you want this to be infinite, I'd suggest looking into the utilities in itertools
from itertools import count
def integers_rep(n):
for i in count(1):
for _ in range(n):
yield i
def gen_sequence():
return zip(count(1), integers_rep(3))
count(n) is an iterable which will yield the sequence n, n+1, n+2, ... ad infinitum starting at it's first argument (which defaults to 0 if nothing is passed).
gen_sequence which would create your sequence, uses zip which takes N-iterables and produces a sequence of N-tuples (two sequences => pairs, three => triples, etc.). By taking count and the other sequence, you will be able to then get their pairs.
By using these tools, you would be able to define everything at a high level (which can be useful for mathematical sequences).

Related

I'm not able to understand this code in tuple

init_tuple = [(0, 1), (1, 2), (2, 3)]
result = sum(n for _, n in init_tuple)
print(result)
The output for this code is 6. Could someone explain how it worked?
Your code extracts each tuple and sums all values in the second position (i.e. [1]).
If you rewrite it in loops, it may be easier to understand:
init_tuple = [(0, 1), (1, 2), (2, 3)]
result = 0
for (val1, val2) in init_tuple:
result = result + val2
print(result)
The expression (n for _, n in init_tuple) is a generator expression. You can iterate on such an expression to get all the values it generates. In that case it reads as: generate the second component of each tuple of init_tuple.
(Note on _: The _ here stands for the first component of the tuple. It is common in python to use this name when you don't care about the variable it refers to (i.e., if you don't plan to use it) as it is the case here. Another way to write your generator would then be (tup[1] for tup in init_tuple))
You can iterate over a generator expression using for loop. For example:
>>> for x in (n for _, n in init_tuple):
>>> print(x)
1
2
3
And of course, since you can iterate on a generator expression, you can sum it as you have done in your code.
To get better understanding first look at this.
init_tuple = [(0, 1), (1, 2), (2, 3)]
sum = 0
for x,y in init_tuple:
sum = sum + y
print(sum)
Now, you can see that what above code does is that it calculate sum of second elements of tuple, its equivalent to your code as both does same job.
for x,y in init_tuple:
x hold first value of tuple and y hold second of tuple, in first iteration:
x = 0, y = 1,
then in second iteration:
x = 1, y = 2 and so on.
In your case you don't need first element of tuple so you just use _ instead of using variable.

How to get all permutations of a list taken k things at at a time using a user defined recursive function(Python)

I'd like to make a recursive algorithm generating all permutations of a list of integers taken k things at a time.
To be specific, what I want to do is create a recursive function Perm(list, k) from scratch returning a output satisfying the following condition.
from itertools import permutations
li = [1,2,3,4]
set(permutations(li, 2)) == set(Perm(li, 2))
I tried it by referring to the Shailaja's codes (Perm(lst,n)) from this link: Recursive Algorithm to generate all permutations of length k of a list in Python
Since the function returns a nested list, I've tried to convert the nested list to a set of tuples. However, I was unable to find any solutions because the function is a recursive algorithm. Could anyone help me out to change the Perm function to get the following format of outputs? Thanks a lot.
# the output of set(Perm(li, 2))
{(1, 2),
(1, 3),
(1, 4),
(2, 1),
(2, 3),
(2, 4),
(3, 1),
(3, 2),
(3, 4),
(4, 1),
(4, 2),
(4, 3)}
Since the function returns a nested list, I've tried to convert the nested list to a set of tuples.
Yes, that is indeed what is needed. So Perm should yield tuples.
Here is a possible recursive implementation for Perm:
def Perm(lst, size):
if size <= 0:
yield () # empty tuple
else:
for i, val in enumerate(lst):
for p in Perm(lst[:i] + lst[i+1:], size-1):
yield (val, *p)
This passes the test given in the question.

Generating 3-tuples from a set of 2-tuples

In an earlier question:
Generating maximum number of 3-tuples from a list of 2-tuples
I got an answer from #AChampion that seems to work if the number of 2-tuples is divisible by 3. However, the solution fails if we, for example, have 10 2-tuples. After fumbling with it for a while I'm under the impression that it is impossible to find a perfect solution for say:
(1,2)(1,3),(1,4),(2,3),(2,4),(3,4)
So I'm interested in finding one solution that minimizes the number of remainder tuples. In the example above the result could be:
(1,2,3) # derived from (1,2), (1,3), (2,3)
(1,4),(2,4),(3,4) # remainder tuples
The rule for generating 3-tuple from 3 2-tuple is:
(a,b), (b,c), (c,a) -> (a, b, c)
i.e. the 2-tuples is a cycle with length 3. The order of the elements in a 3-tuple is not important, i.e:
(a,b,c) == (c,a,b)
I'm actually interested in the case where we have a number n:
for x in range(1,n+1):
for y in range(1,n+1):
if x!=y:
a.append((x,y))
# a = [ (1,2),...,(1,n), (2,1),(2,3),...,(2,n),...(n,1),...,(n,n-1) ]
From a, minimize the number of 2-tuples that is left when producing 3-tuples. Each 2-tuple can only be used once.
I wrapped my brain around this for several hours but I can't seem to come up with an elegant solution (well, neither have I found an ugly one:-) for the general case. Any thoughts?
For this you need to create number of combinations that will use for replacement. Then loop over you data for 3 item that contains any of above combinations and replace them.
I have done thi in several steps.
from itertools import combinations
# create replacements elements
number_combinations_raw = list(combinations(range(1, 5), 3))
# create proper number combinations
number_combinations = []
for item in number_combinations_raw:
if (item[0] + 1 == item[1]) and (item[1] + 1 == item[2]):
number_combinations.append(item)
# create test data
data = [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4)]
# reduce data
reduce_data = []
for number_set in number_combinations:
count = 0
merged_data = []
for item in data:
if (number_set[0] in item and number_set[1] in item) or (number_set[1] in item and number_set[2] in item) \
or (number_set[0] in item and number_set[2] in item):
merged_data.append(item)
count += 1
if count == 3:
reduce_data.append((number_set, merged_data))
# delete merged elements from data list and add replacement
for item in data:
for reduce_item in reduce_data:
for element in reduce_item[1]:
if element in data:
data.remove(element)
data = [reduce_item[0]] + data
# remove duplicated replaced elements
final_list = list(dict.fromkeys(data))
Output:
[(1, 2, 3), (1, 4), (2, 4)]

Out of range index

I am trying to make a program that will count the numbers in the list number, and would search for a sum of 10 in sequence_len numbers.
In the minute it gets a 10, it should stop.
1. With this code I have an error. what should I do?
total=total+(list_n[i+n])
IndexError: list index out of range
2.I want the first for to be stop if Im finding a sum of then. Is it write to "break" at the end as I did or should I write i=len(list_n)?
number = 1234
sequence_len = 2
list_n=[]
total=0
b="false"
list_t=[]
for j in str(number):
list_n.append(int(j))
c=len(list_n)
for i in list_n:
n=0
while n<sequence_len:
total=total+(list_n[i+n])
n=n+1
if total==10:
b=true
seq=0
while seq>sequence_len:
list_t.append(list_t[i+seq])
seq=seq+1
break
else:
total=0
if b=="true":
break
if b=="false":
print "Didn’t find any sequence of size", sequence_len
else:
print "Found a sequence of size", sequence_len ,":", list_t
You have a couple of errors. First with the basic:
b=true
This needs to the True, otherwise, python will look for the true variable.
Secondly, i actually contains the value of the variable for that iteration (loop). For example:
>>> l = ['a', 'b', 'c']
>>> for i in l: print i
a
b
c
Because of this, you cannot use it as an index, as indexes have to be integers. So, what you need to do is use enumerate, this will generate a tuple of both the index and the value, so something like:
for i, var in enumerate(list_n):
n = 0
An example of enumerate in action:
>>> var = enumerate([1,6,5,32,1])
>>> for x in var: print x
(0, 1)
(1, 6)
(2, 5)
(3, 32)
(4, 1)
And this statement should has logical problems I believe:
total = total + (list_n[i + n - 1])
If you want to get a sum of 10 from a list of numbers, you can use this brute-force technique:
>>> list_of_n = [1,0,5,4,2,1,2,3,4,5,6,8,2,7]
>>> from itertools import combinations
>>> [var for var in combinations(list_of_n, 2) if sum(var) == 10]
[(5, 5), (4, 6), (2, 8), (2, 8), (3, 7), (4, 6), (8, 2)]
So, if you want a 10 from 3 numbers in the list, you would put combinations(list_of_n, 3) instead of combinations(list_of_n, 2).
When you say
for i in list_n:
i will not refer to the indices, but to the list elements themselves. If you want just the indices,
for i in range(len(list_n)):
len(list_n) will give you the size of the list and range(len(list_n)) will give you a range of numbers starting from 0 and ending with len(list_n) - 1

making list in python

When i executed the following python script
list= (1,2,3,4,1,2,7,8)
for number in list:
item1= number
item2= list[list.index(item1)+2]
couple= item1, item2
print couple
the goal is to link each number with the second following
I obtain this result
(1, 3)
(2, 4)
(3, 1)
(4, 2)
(1, 3)
(2, 4)
(and then the index gets out of range but this is not the problem)
My question is why the number 1 in the fifth line is still coupled to the number 3 and how can i make that it is coupled to the number 7; idem for the number 2 in the sixth line that should be coupled to the number 8.
additional question
what do I do if i only want to make a list of the couples that start with 1: [(1,3), (1,7)]
list.index returns the offset of the first occurrence of the value in the list - thus if you do [1,1,1].index(1), the answer will always be 0, even though 1 and 2 are also valid answers.
Instead, try:
from itertools import islice, izip, ifilter
mylist = [1,2,3,4,1,2,7,8]
for pair in ifilter(lambda x: x[0]==1, izip(mylist, islice(mylist, 2, None))):
print pair
results in
(1, 3)
(1, 7)
xs.index(x) gives you the index of the first occurence of x in xs. So when you get to the second 1, .index gives you the index of the first 1.
If you need the index alongside the value, use enumerate: for i, number in enumerate(numbers): print number, numbers[i+2].
Note that I deliberately didn't use the name list. It's the name of a built-in, you shouldn't overwrite it. Also note that (..., ...) is a tuple (and therefore can't be changed), not a list (which is defined in square brackets [..., ...] and can be changed).
You have duplicates in the list so index always returns the first index.
Start your program with for index in range(len(list) - 1)
You are using .index which returns the first occurrence of number.
consider:
for number in range(len(list)):
item1= list[number]
item2= list[number+2]
couple= item1, item2
print couple
>>> zip(lst, lst[2:])
[(1, 3), (2, 4), (3, 1), (4, 2), (1, 7), (2, 8)]
To get only pairs (1, X):
>>> [(a, b) for (a, b) in zip(lst, lst[2:]) if a == 1]
[(1, 3), (1, 7)]
Recommended reading:
http://docs.python.org/tutorial/datastructures.html
http://docs.python.org/howto/functional.html

Categories

Resources