creating a non-literal python tuple programmatically - python

I want to create a tuple of length m, with a 1 in each position except for one n in position k.
e.g.: m=5, n=7, k=3 should yield (1,1,1,7,1) (length 5 with a 7 in position 3)
How can I do this?

>>> m, n, k = 5, 7, 3
>>> tuple(n if i == k else 1 for i in range(m))
(1, 1, 1, 7, 1)

First construct a list, then turn it into a tuple if you really need to:
def make_tuple(m, n, k):
a = [1] * m
a[k] = n
return tuple(a)
Example:
>>> make_tuple(m=5, n=7, k=3)
(1, 1, 1, 7, 1)

(1,) * k + (n,) + (1,) * (m-k-1)

Related

how do I multiply integers in a set?

You are given a sequence of positive ints where every element appears three times, except one that appears only once (let's call it x) and one that appears only twice (let's call it y).
Your task is to find x * x * y.
e.g.
arr = [1,1,1,2,2,2,3,3,4] -> 4 x 4 x 3
I have written some code below. I have a question regarding the final part of the code- so after the completion of the loop, there should be one integer left in seen_once and one integer left in seen_twice, but how do I then multiply these numbers, as they are now sitting in a set()?
def Missing_Values(arr):
seen_once = set()
seen_twice = set()
seen_thrice = set()
for i in arr:
if i not in seen_once or seen_twice or seen_thrice:
seen_once.add(i)
elif i in seen_once:
seen_twice.add(i)
seen_once.remove(i)
elif i in seen_twice:
seen_thrice.add(i)
seen_twice.remove(i)
return seen_once*seen_once*seen_twice
Missing_Values(arr)
One way would be to pop the values.
x = seen_once.pop()
y = seen_twice.pop()
return x * x * y
You can use counter from collections for better performance that also improves readability.
Following is the code:
from collections import Counter
arr = [1, 1, 1, 2, 2, 2, 3, 3, 4]
d = Counter(arr)
ans = 1
for x, cnt in d.items():
if cnt == 2:
ans *= x
elif cnt == 1:
ans *= (x * x)
print(ans)
You can also use list comprehension as a generator as follows:
from collections import Counter
arr = [1, 1, 1, 2, 4, 4, 3, 3, 4]
d = Counter(arr)
x, y = (x**(3 - cnt) for x, cnt in d.items() if(cnt <= 2))
print(x*y)
Counter Explanation:
Counter returns a dictionary where array item as a Key and item frequency as a value. For example, if array arr = [1, 1, 1, 2, 2, 2, 3, 3, 4] then counter provide following dictionary:
d = {
1: 3,
2: 3,
3: 2,
4: 1
}
You have a bug in your code, this is a working piece:
def Missing_Values(arr):
seen_once = set()
seen_twice = set()
seen_thrice = set()
for i in arr:
if i not in seen_once and i not in seen_twice and i not in seen_thrice: # Note this line!
seen_once.add(i)
elif i in seen_once:
seen_twice.add(i)
seen_once.remove(i)
elif i in seen_twice:
seen_thrice.add(i)
seen_twice.remove(i)
return next(iter(seen_once))*next(iter(seen_once))*next(iter(seen_twice))
arr = [1,1,1,2,2,2,3,3,4]
print(Missing_Values(arr))

How to correctly substitude indexed variable in sympy?

I try to use IndexBase for summation, but dont understand, how to do substitution of sequences:
A = sympy.IndexedBase('A')
i = sympy.Symbol('i', integer=True)
N = sympy.Symbol('N', integer=True)
S = sympy.Sum(A[i], (i, 0, N))
Trace = sympy.Sum(A[i, i], (i, 0, N))
S.subs([(A, range(3)), (N, 2)]).doit() # python3 range
# result: 3
S.subs([(A, [8, 16, 32]), (N, 2)]).doit()
# result: A[0] + A[1] + A[2]
S.subs([(A, numpy.arange(3)), (N, 2)]).doit()
# result: A[0] + A[1] + A[2]
Trace.subs([(A, numpy.diag([2, 4, 8])), (N, 2)]).doit()
# result: A[0, 0] + A[1, 1] + A[2, 2]
The only case which works is substitution of range. Could you explain, how to substitude it in general case?
Usually one substitutes for Indexed objects A[i] rather than for IndexedBase A. This works if the sum is written out explicitly by doit prior to substitution.
S.subs(N, 2).doit().subs([(A[i], i**2) for i in range(3)]) # 5
or
values = [8, 16, 32]
S.subs(N, 2).doit().subs([(A[i], values[i]) for i in range(3)]) # 56
Similarly, Trace.subs(N, 2).doit().subs([(A[i, i], values[i]) for i in range(3)]) returns 56.
The substitution by Python range works because it's sympified by subs into SymPy's Range object, which is something that can be a part of a SymPy expression.
>>> S.subs([(A, range(3)), (N, 2)])
Sum(Range(0, 3, 1)[i], (i, 0, 2))
It looks like one should be able to similarly substitute with SymPy's SeqFormula objects:
>>> n = sympy.symbols('n')
>>> S.subs([(A, sympy.sequence(n**2, (n, 0, 3))), (N, 3)])
Sum(SeqFormula(n**2, (n, 0, 3))[i], (i, 0, 3))
But subsequent doit fails here with SympifyError: None which looks like a bug.

Get n in exact k parts. Recursion and partition algorithm. p(n,k)

I'm looking to enumerate all the partitions of n in k parts.
So for p(5,3) i'd get 2 partitions of k = 3 => (3,1,1), (2,2,1).
Here's what I found from searching and looking through stackoverflow :
def p(n,k):
lst = []
if n < k:
return lst
elif k == 1:
return lst
elif k == n:
return lst
else:
p(n-1, k-1)
p(n-k, k)
return lst
^^^^ This is the form i want,
As it is, finding the sum of k parts is easy, you return p(n-1, k-1) + p(n-k,k). As for me, I need to list each element like so [(3,1,1), (2,2,1)].
My main problem is to "build" those partitions recursively. How would you tackle this?
Edit
If you get base case k = 1, add + 1, k-1 times. (4,1) then (4,1,1)
If you get base case k = n, split up and remove one to each part.
Like so : (3,3) then (3,3,3) then (2,2,2)
If you get base case k < n, nothing
Basically, my problem is to "stack" up the ones from base case to top and get a complete list p(6,3) = [(2,2,2), (4,1,1), (3,2,1)]
I would add to the recursive function a third parameter m which is the maximum value an element can have in the partition. Then I would define the function like this:
def p(n, k, m=None):
if m is None:
m = n - k + 1 # maximum can be n - k + 1 since minimum is 1
if k == 0:
if n == 0:
yield ()
return
for i in xrange(1, m + 1): # first could be from 1 to the maximum
# the rest of the sum will be n - i among k - 1 elements with
# maximum i
for t in p(n - i, k - 1, i):
yield (i, ) + t
Examples:
>>> list(p(10, 3))
[(4, 3, 3), (4, 4, 2), (5, 3, 2), (5, 4, 1), (6, 2, 2), (6, 3, 1), (7, 2, 1), (8 , 1, 1)]
>>> list(p(6, 2))
[(3, 3), (4, 2), (5, 1)]

Create list [(1,1),(1,2), .. ,(1,n)], for any given n. Use this list then to create all fractions 1.0/k k from 1 to n

completely new to python tried doing this but did not work.
>>> list (range (1, 9))
[1, 2, 3, 4, 5, 6, 7, 8]
>>> args = [1,9]
>>> list (range (args))
Any help will be appreciated
create first list:
[(1, x) for x in range(1, n + 1)]
create second list:
[1.0 / x for x in range(1, n + 1)]
First, the list of (1,i) pairs:
pairs = [(1, x) for x in range(1, n + 1)]
Next, the list of ratios:
divs = [num/denom for num, denom in pairs]
(you may also need from __future__ import division if you're using python 2.x)

counting up and then down a range in python

I am trying to program a standard snake draft, where team A pick, team B, team C, team C, team B, team A, ad nauseum.
If pick number 13 (or pick number x) just happened how can I figure which team picks next for n number of teams.
I have something like:
def slot(n,x):
direction = 'down' if (int(x/n) & 1) else 'up'
spot = (x % n) + 1
slot = spot if direction == 'up' else ((n+1) - spot)
return slot
I have feeling there is a simpler, more pythonic what than this solution. Anyone care to take a hack at it?
So I played around a little more. I am looking for the return of a single value, rather than the best way to count over a looped list. The most literal answer might be:
def slot(n, x): # 0.15757 sec for 100,000x
number_range = range(1, n+1) + range(n,0, -1)
index = x % (n*2)
return number_range[index]
This creates a list [1,2,3,4,4,3,2,1], figures out the index (e.g. 13 % (4*2) = 5), and then returns the index value from the list (e.g. 4). The longer the list, the slower the function.
We can use some logic to cut the list making in half. If we are counting up (i.e. (int(x/n) & 1) returns False), we get the obvious index value (x % n), else we subtract that value from n+1:
def slot(n, x): # 0.11982 sec for 100,000x
number_range = range(1, n+1) + range(n,0, -1)
index = ((n-1) - (x % n)) if (int(x/n) & 1) else (x % n)
return number_range[index]
Still avoiding a list altogether is fastest:
def slot(n, x): # 0.07275 sec for 100,000x
spot = (x % n) + 1
slot = ((n+1) - spot) if (int(x/n) & 1) else spot
return slot
And if I hold the list as variable rather than spawning one:
number_list = [1,2,3,4,5,6,7,8,9,10,11,12,12,11,10,9,8,7,6,5,4,3,2,1]
def slot(n, x): # 0.03638 sec for 100,000x
return number_list[x % (n*2)]
Why not use itertools cycle function:
from itertools import cycle
li = range(1, n+1) + range(n, 0, -1) # e.g. [1, 2, 3, 4, 4, 3, 2, 1]
it = cycle(li)
[next(it) for _ in xrange(10)] # [1, 2, 3, 4, 4, 3, 2, 1, 1, 2]
Note: previously I had answered how to run up and down, as follows:
it = cycle(range(1, n+1) + range(n, 0, -1)) #e.g. [1, 2, 3, 4, 3, 2, 1, 2, 3, ...]
Here's a generator that will fulfill what you want.
def draft(n):
while True:
for i in xrange(1,n+1):
yield i
for i in xrange(n,0,-1):
yield i
>>> d = draft(3)
>>> [d.next() for _ in xrange(12)]
[1, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 1]
from itertools import chain, cycle
def cycle_up_and_down(first, last):
up = xrange(first, last+1, 1)
down = xrange(last, first-1, -1)
return cycle(chain(up, down))
turns = cycle_up_and_down(1, 4)
print [next(turns) for n in xrange(10)] # [1, 2, 3, 4, 4, 3, 2, 1, 1, 2]
Here is a list of numbers that counts up, then down:
>>> [ -abs(5-i)+5 for i in range(0,10) ]
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]
Written out:
count_up_to = 5
for i in range( 0, count_up_to*2 ):
the_number_you_care_about = -abs(count_up_to-i) + count_up_to
# do stuff with the_number_you_care_about
Easier to read:
>>> list( range(0,5) ) + list( range( 5, 0, -1 ) )
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]
Written out:
count_up_to = 5
for i in list( range(0,5) ) + list( range(5, 0, -1) ):
# i is the number you care about
Another way:
from itertools import chain
for i in chain( range(0,5), range(5,0,-1) ):
# i is the number you care about

Categories