How to generate a random quadratic function in python - python

I'm attempting to create a random quadratic function to the 2nd degree in python that returns the same result every time.
Something along the lines of:
funk = lambda i : random.randint(0,10)*i**2 + random.randint(0,10)*i + random.randint(0,10)
The problem here is that calling x(5) two different times will have 2 potentially different results. Is it possible to generate a function that has the same result every time, or should I just do something like:
m2 = random.randint(0,9)
m1 = random.randint(0,9)
b = random.randint(0,9)
funk = lambda i : m2*i**2 + m1*i + b
and assign a new random number to globals m2,m1, and b every time I run it?

You need to randomize coefficients only once, then save them somewhere and reuse for the following computations of the same function.
A class instance is ideal for this:
class RandomQuadratic:
def __init__(self):
self.a = random.randint(0,10)
self.b = random.randint(0,10)
self.c = random.randint(0,10)
def __call__(self,x):
return self.a*x**2+self.b*x+self.c
f = RandomQuadratic()
f(5)
f(5)

Do the second approach, but just chuck it into a function. :)
>>> import random
>>> def random_quadratic():
... m2 = random.randint(0,9)
... m1 = random.randint(0,9)
... b = random.randint(0,9)
... funk = lambda i : m2*i**2 + m1*i + b
... return funk
...
>>> foo = random_quadratic()
>>> foo(1)
25
>>> foo(1)
25
>>> foo(1)
25
>>> foo(2)
55
>>> foo(2)
55
>>> foo(2)
55
>>> foo(3)
99
>>> foo(3)
99
>>> foo(3)
99
>>>

Related

How to map or nest Python 2.7 function generators?

If I have a very simple (although possibly very complex) function generator in Python 2.7, like so:
def accumulator():
x = yield 0
while True:
x += yield x
Which can be used, like so:
>>> a = accumulator()
>>> a.send(None)
0
>>> a.send(1)
1
>>> a.send(2)
3
>>> a.send(3)
6
What would be a simple wrapper for another function generator that produces the same result, except multiplied by 2? The above function generator is simple, but please assume it is too complicated to copy-paste. I'm trying something, like:
def doubler():
a = accumulator()
a.send(None)
y = yield 0
while True:
y = 2 * a.send(yield y)
Or, imagining something simpler:
def doubler():
a = accumulator()
a.send = lambda v: 2 * super(self).send(v)
return a
Both of which are horribly broke, so I won't share the syntax errors, but it may illustrate what I'm trying to do.
Ideally, I would like to get something, like:
>>> d = doubler()
>>> d.send(None)
0
>>> d.send(1)
2
>>> d.send(2)
6
>>> d.send(3)
12
The results are the exact same as the original, except doubled.
I'm trying to avoid duplicating a very complicated function generator to create an identical result, except scaled by a known factor.
The second generator will ultimately have a different input stream, so I cannot just use the result from the first generator and double it. I need a second independent generator, wrapping the first.
The input stream is indeterminate, such that it is impossible to generate the entire sequence and then transform.
It seems I want to map or nest these function generators, but I'm not sure of the appropriate jargon, and so I'm getting nowhere in Google.
If you need to have the same interface as a coroutine (i.e. have a send method), then BrenBarn's solution is probably as simple as it gets.*
If you can have a slightly different interface, then a higher-order function is even simpler:
def factor_wrapper(coroutine, factor):
next(coroutine)
return lambda x, c=coroutine, f=factor: f * c.send(x)
You would use it as follows:
>>> a = accumulator()
>>> a2 = factor_wrapper(a, 2)
>>> print a2(1)
2
>>> print a2(2)
6
>>> print a2(3)
12
*Actually you can shave several lines off to make it 4 lines total, though not really reducing complexity much.
def doubler(a):
y = yield next(a)
while True:
y = yield (2 * a.send(y))
or even shorter...
def doubler(a, y=None):
while True:
y = yield 2 * a.send(y)
Either of the above can be used as follows:
>>> a = accumulator()
>>> a2 = doubler(a)
>>> print a2.send(None) # Alternatively next(a2)
0
>>> print a2.send(1)
2
>>> print a2.send(2)
6
>>> print a2.send(3)
12
I didn't tried this, but something along these lines:
class Doubler:
def __init__(self, g):
self.g = g()
def __next__(self):
return self.send(None)
def send(self, val):
return self.g.send(val)*2
Also, after Python 3.5, extending this from collections.abc.Container will eliminate the need of __next__, also will make this a proper generator(It currently doesn't support __throw__ etc., but they're just boilerplate).
Edit: Yes, this works:
In [1]: %paste
def accumulator():
x = yield 0
while True:
x += yield x
## -- End pasted text --
In [2]: %paste
class Doubler:
def __init__(self, g):
self.g = g()
def __next__(self):
return self.send(None)
def send(self, val):
return self.g.send(val)*2
## -- End pasted text --
In [3]: d = Doubler(accumulator)
In [4]: d.send(None)
Out[4]: 0
In [5]: d.send(1)
Out[5]: 2
In [6]: d.send(2)
Out[6]: 6
In [7]: d.send(3)
Out[7]: 12
You just need to move the yield outside the expression that passes y to a:
def doubler():
a = accumulator()
next(a)
y = yield 0
while True:
y = yield (2 * a.send(y))
Then:
>>> a = accumulator()
... d = doubler()
... next(a)
... next(d)
... for i in range(10):
... print(a.send(i), d.send(i))
0 0
1 2
3 6
6 12
10 20
15 30
21 42
28 56
36 72
45 90
I think this is what you want:
def doubler():
a = accumulator()
y = a.send(None)
x = yield 0
while True:
y = a.send(x)
x = yield 2 * y
This completely wraps the accumulator implementation but you could alternatively make that visible and pass it in as a parameter a to doubler.

python - enter the correct number of variables based on function handle

I have a list of variables, and a function object and I would like to assign the correct number of variable depending on the function.
def sum2(x,y):
return x + y
def sum3(x,y,z):
return x + y + z
varList = [1,2,3]
so if f = sum2 , I would like it to call first 2 elements of varList, and if f = sum3 , to call it with 3 elements of the function.
This can be done in a single function, if you are always returning the sum of all the passed arguments.
def sum1(*args):
return sum(args)
This is just utilizing positional arguments, as you don't appear to need to explicitly set individual values. It is also most flexible than the solution provided by ZdaR, as you don't need to know ahead of time the maximum number of arguments you can receive.
Some examples:
>>> print sum1(1, 2, 3)
6
>>> print sum1(1)
1
>>> print sum1(-1, 0, 6, 10)
15
Use the inspect module as follows:
import inspect
n2 = len(inspect.getargspec(sum2)[0])
n3 = len(inspect.getargspec(sum3)[0])
sum2(*varList[0:n2])
sum3(*varList[0:n3])
getargspec returns a 4-tuple of (args, varargs, keywords, defaults). So the above code works if all your args are explicit, i.e. not * or ** args. If you have some of those, change the code accordingly.
You may use default initialization, You should keep in mind the maximum number of variables that could be passed to this function. Then create a function with that number of parameters but initializing them with 0, because a+0 = a(in case some parameters are missing it will replace then with 0 which won't affect the results.)
def sum1(a=0, b=0, c=0, d=0):
return a+b+c+d
print sum1(1)
>>> 1
print sum1(1, 2)
>>> 3
print sum1(1, 2, 3)
>>> 6
print sum1(1, 2, 3, 4)
>>> 10
However, if you call the function with more than 4 arguments, it would raise error statement
Also as suggested by #CoryKramer in the comments you can also pass your varlist = [1, 2, 3, 4] as a parameter :
print sum1(*varlist)
>>> 10
Keeping in mind that the len(varlist) should be less than the number of parameters defined.
A general solution:
To get the number of argument, you can use f.func_code.co_argcount and than pass the correct elements from the list:
def sum2(x,y):
return x + y
def sum3(x,y,z):
return x + y + z
varlist = [2,5,4]
[f(*varlist[:f.func_code.co_argcount]) for f in [sum2,sum3]]
>> [7, 11]
You can check if f is a function with the is keyword
def sum2(x, y):
return x + y
def sum3(x, y, z):
return x + y + z
varList = [1, 2, 3]
f = sum2
if f is sum2:
sum = f(varList[0], varList[1])
print('Sum 2: ' + str(sum))
# Prints: 'Sum 2: 3'
f = sum3
if f is sum3:
sum = f(varList[0], varList[1], varList[2])
print('Sum 3: ' + str(sum))
# Prints: 'Sum 3: 6'
A dict of functions:
def two(l):
return l[0] + l[1]
def three(l):
return l[0] * l[1] + l[2]
funcs = {2:two, 3:three}
l = [1, 2, 3]
print len(l)
print funcs[len(l)](l)

python, how the "x" change its value in the code

a = 100
x = 1000
def myFun(a,b):
x = b-a
return x
a = myFun(a,x)
x = myFun(a,x)
print(x+a)
I know in first function, a = myFun(a,x) is 900, but why is the result of x = myFun(a,x) ,100?
The name x inside the function myFunc() is independent from the global name x. They live in different namespaces.
As such, when you call myFunc(a, x) the first time, the global x value is unchanged; it remains 1000:
>>> a = 100
>>> x = 1000
>>> def myFun(a,b):
... x = b-a
... return x
...
>>> myFun(a,x)
900
>>> x
1000
If you wanted the global x to change when calling myFunc(), you need to tell Python explicitly that x is to be treated as a global in the function:
def myFun(a,b):
global x
x = b-a
return x
Now assigning to x in the function will set the global name x:
>>> a = 100
>>> x = 1000
>>> def myFun(a,b):
... global x
... x = b-a
... return x
...
>>> myFun(a,x)
900
>>> x
900

how to set .__name__ in python?

I am trying to solve this exercise:
Return a function that represents the polynomial with these
coefficients.
For example, if coefs=(10, 20, 30), return the function of x that computes
30 * x**2 + 20 * x + 10. Also store the coefs on the .coefs attribute of
the function, and the str of the formula on the .__name__ attribute.
This is my solution:
def poly(coefs):
#write the string name
l=len(coefs)
coefs=reversed(coefs)
j=0
name=""
for i in coefs:
if j<l-2:
name=name+str(i)+" * x**"+str(l-j-1)+" + "
elif j==l-2:
name=name+str(i)+" * x + "
else:
name=name+str(i)
j=j+1
def calc(x):
name.replace("x",str(x))
calc.__name__=name
return eval(name)
return calc
It does not work very well.
>>> p=poly((1,2,3))
>>> p
<function calc at 0x3b99938> #the name of p is not what I want!!! (*)
>>> y=p(3)
>>> p
<function 3 * x**2 + 2 * x + 1 at 0x3b99938> # now this is right!
>>>
How can I have the right name also in the first call (*) ?
Set the name outside of the function object:
def calc(x):
newname = name.replace("x", str(x))
calc.__name__ = newname
return eval(name)
calc.__name__ = name
return calc
Note that str.replace() does not replace values in strings in-place. It returns the altered string, string values themselves are immutable.
Your initial name will have to use x, since the value of x is not known at the time you call poly(). I'd leave out filling in of x in the name however; the function will not return that exact calculation the next time you call it with a different x. Without replacing x in the name each time you call the function, calc() would simply be:
def calc(x):
return eval(name)
Together with adding name = '' at the top of your poly() function, with the namechange per call in place still, gives:
>>> p = poly((1,2,3))
>>> p
<function 3 * x**2 + 2 * x + 1 at 0x10ecf5488>
>>> p(3)
34
>>> p
<function 3 * 3**2 + 2 * 3 + 1 at 0x10ecf5488>

How to toggle a value?

What is the most efficient way to toggle between 0 and 1?
Solution using NOT
If the values are boolean, the fastest approach is to use the not operator:
>>> x = True
>>> x = not x # toggle
>>> x
False
>>> x = not x # toggle
>>> x
True
>>> x = not x # toggle
>>> x
False
Solution using subtraction
If the values are numerical, then subtraction from the total is a simple and fast way to toggle values:
>>> A = 5
>>> B = 3
>>> total = A + B
>>> x = A
>>> x = total - x # toggle
>>> x
3
>>> x = total - x # toggle
>>> x
5
>>> x = total - x # toggle
>>> x
3
Solution using XOR
If the value toggles between 0 and 1, you can use a bitwise exclusive-or:
>>> x = 1
>>> x ^= 1
>>> x
0
>>> x ^= 1
>>> x
1
The technique generalizes to any pair of integers. The xor-by-one step is replaced with a xor-by-precomputed-constant:
>>> A = 205
>>> B = -117
>>> t = A ^ B # precomputed toggle constant
>>> x = A
>>> x ^= t # toggle
>>> x
-117
>>> x ^= t # toggle
>>> x
205
>>> x ^= t # toggle
>>> x
-117
(This idea was submitted by Nick Coghlan and later generalized by #zxxc.)
Solution using a dictionary
If the values are hashable, you can use a dictionary:
>>> A = 'xyz'
>>> B = 'pdq'
>>> d = {A:B, B:A}
>>> x = A
>>> x = d[x] # toggle
>>> x
'pdq'
>>> x = d[x] # toggle
>>> x
'xyz'
>>> x = d[x] # toggle
>>> x
'pdq'
Solution using a conditional expression
The slowest way is to use a conditional expression:
>>> A = [1,2,3]
>>> B = [4,5,6]
>>> x = A
>>> x = B if x == A else A
>>> x
[4, 5, 6]
>>> x = B if x == A else A
>>> x
[1, 2, 3]
>>> x = B if x == A else A
>>> x
[4, 5, 6]
Solution using itertools
If you have more than two values, the itertools.cycle() function provides a generic fast way to toggle between successive values:
>>> import itertools
>>> toggle = itertools.cycle(['red', 'green', 'blue']).next
>>> toggle()
'red'
>>> toggle()
'green'
>>> toggle()
'blue'
>>> toggle()
'red'
>>> toggle()
'green'
>>> toggle()
'blue'
Note that in Python 3 the next() method was changed to __next__(), so the first line would be now written as toggle = itertools.cycle(['red', 'green', 'blue']).__next__
I always use:
p^=True
If p is a boolean, this switches between true and false.
Here is another non intuitive way. The beauty is you can cycle over multiple values and not just two [0,1]
For Two values (toggling)
>>> x=[1,0]
>>> toggle=x[toggle]
For Multiple Values (say 4)
>>> x=[1,2,3,0]
>>> toggle=x[toggle]
I didn't expect this solution to be almost the fastest too
>>> stmt1="""
toggle=0
for i in xrange(0,100):
toggle = 1 if toggle == 0 else 0
"""
>>> stmt2="""
x=[1,0]
toggle=0
for i in xrange(0,100):
toggle=x[toggle]
"""
>>> t1=timeit.Timer(stmt=stmt1)
>>> t2=timeit.Timer(stmt=stmt2)
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000)
7.07 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000)
6.19 usec/pass
stmt3="""
toggle = False
for i in xrange(0,100):
toggle = (not toggle) & 1
"""
>>> t3=timeit.Timer(stmt=stmt3)
>>> print "%.2f usec/pass" % (1000000 * t3.timeit(number=100000)/100000)
9.84 usec/pass
>>> stmt4="""
x=0
for i in xrange(0,100):
x=x-1
"""
>>> t4=timeit.Timer(stmt=stmt4)
>>> print "%.2f usec/pass" % (1000000 * t4.timeit(number=100000)/100000)
6.32 usec/pass
The not operator negates your variable (converting it into a boolean if it isn't already one). You can probably use 1 and 0 interchangeably with True and False, so just negate it:
toggle = not toggle
But if you are using two arbitrary values, use an inline if:
toggle = 'a' if toggle == 'b' else 'b'
Just between 1 and 0, do this
1-x
x can take 1 or 0
Trigonometric approach, just because sin and cos functions are cool.
>>> import math
>>> def generator01():
... n=0
... while True:
... yield abs( int( math.cos( n * 0.5 * math.pi ) ) )
... n+=1
...
>>> g=generator01()
>>> g.next()
1
>>> g.next()
0
>>> g.next()
1
>>> g.next()
0
Surprisingly nobody mention good old division modulo 2:
In : x = (x + 1) % 2 ; x
Out: 1
In : x = (x + 1) % 2 ; x
Out: 0
In : x = (x + 1) % 2 ; x
Out: 1
In : x = (x + 1) % 2 ; x
Out: 0
Note that it is equivalent to x = x - 1, but the advantage of modulo technique is that the size of the group or length of the interval can be bigger then just 2 elements, thus giving you a similar to round-robin interleaving scheme to loop over.
Now just for 2, toggling can be a bit shorter (using bit-wise operator):
x = x ^ 1
one way to toggle is by using Multiple assignment
>>> a = 5
>>> b = 3
>>> t = a, b = b, a
>>> t[0]
3
>>> t = a, b = b, a
>>> t[0]
5
Using itertools:
In [12]: foo = itertools.cycle([1, 2, 3])
In [13]: next(foo)
Out[13]: 1
In [14]: next(foo)
Out[14]: 2
In [15]: next(foo)
Out[15]: 3
In [16]: next(foo)
Out[16]: 1
In [17]: next(foo)
Out[17]: 2
The easiest way to toggle between 1 and 0 is to subtract from 1.
def toggle(value):
return 1 - value
Using exception handler
>>> def toogle(x):
... try:
... return x/x-x/x
... except ZeroDivisionError:
... return 1
...
>>> x=0
>>> x=toogle(x)
>>> x
1
>>> x=toogle(x)
>>> x
0
>>> x=toogle(x)
>>> x
1
>>> x=toogle(x)
>>> x
0
Ok, I'm the worst:
import math
import sys
d={1:0,0:1}
l=[1,0]
def exception_approach(x):
try:
return x/x-x/x
except ZeroDivisionError:
return 1
def cosinus_approach(x):
return abs( int( math.cos( x * 0.5 * math.pi ) ) )
def module_approach(x):
return (x + 1) % 2
def subs_approach(x):
return x - 1
def if_approach(x):
return 0 if x == 1 else 1
def list_approach(x):
global l
return l[x]
def dict_approach(x):
global d
return d[x]
def xor_approach(x):
return x^1
def not_approach(x):
b=bool(x)
p=not b
return int(p)
funcs=[ exception_approach, cosinus_approach, dict_approach, module_approach, subs_approach, if_approach, list_approach, xor_approach, not_approach ]
f=funcs[int(sys.argv[1])]
print "\n\n\n", f.func_name
x=0
for _ in range(0,100000000):
x=f(x)
How about an imaginary toggle that stores not only the current toggle, but a couple other values associated with it?
toggle = complex.conjugate
Store any + or - value on the left, and any unsigned value on the right:
>>> x = 2 - 3j
>>> toggle(x)
(2+3j)
Zero works, too:
>>> y = -2 - 0j
>>> toggle(y)
(-2+0j)
Easily retrieve the current toggle value (True and False represent + and -), LHS (real) value, or RHS (imaginary) value:
>>> import math
>>> curr = lambda i: math.atan2(i.imag, -abs(i.imag)) > 0
>>> lhs = lambda i: i.real
>>> rhs = lambda i: abs(i.imag)
>>> x = toggle(x)
>>> curr(x)
True
>>> lhs(x)
2.0
>>> rhs(x)
3.0
Easily swap LHS and RHS (but note that the sign of the both values must not be important):
>>> swap = lambda i: i/-1j
>>> swap(2+0j)
2j
>>> swap(3+2j)
(2+3j)
Easily swap LHS and RHS and also toggle at the same time:
>>> swaggle = lambda i: i/1j
>>> swaggle(2+0j)
-2j
>>> swaggle(3+2j)
(2-3j)
Guards against errors:
>>> toggle(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor 'conjugate' requires a 'complex' object but received a 'int'
Perform changes to LHS and RHS:
>>> x += 1+2j
>>> x
(3+5j)
...but be careful manipulating the RHS:
>>> z = 1-1j
>>> z += 2j
>>> z
(1+1j) # whoops! toggled it!
Variables a and b can be ANY two values, like 0 and 1, or 117 and 711, or "heads" and "tails". No math is used, just a quick swap of the values each time a toggle is desired.
a = True
b = False
a,b = b,a # a is now False
a,b = b,a # a is now True
I use abs function, very useful on loops
x = 1
for y in range(0, 3):
x = abs(x - 1)
x will be 0.
Let's do some frame hacking. Toggle a variable by name. Note: This may not work with every Python runtime.
Say you have a variable "x"
>>> import inspect
>>> def toggle(var_name):
>>> frame = inspect.currentframe().f_back
>>> vars = frame.f_locals
>>> vars[var_name] = 0 if vars[var_name] == 1 else 1
>>> x = 0
>>> toggle('x')
>>> x
1
>>> toggle('x')
>>> x
0
If you are dealing with an integer variable, you can increment 1 and limit your set to 0 and 1 (mod)
X = 0 # or X = 1
X = (X + 1)%2
Switching between -1 and +1 can be obtained by inline multiplication; used for calculation of pi the 'Leibniz' way (or similar):
sign = 1
result = 0
for i in range(100000):
result += 1 / (2*i + 1) * sign
sign *= -1
print("pi (estimate): ", result*4)
You can make use of the index of lists.
def toggleValues(values, currentValue):
return values[(values.index(currentValue) + 1) % len(values)]
> toggleValues( [0,1] , 1 )
> 0
> toggleValues( ["one","two","three"] , "one" )
> "two"
> toggleValues( ["one","two","three"] , "three")
> "one"
Pros: No additional libraries, self.explanatory code and working with arbitrary data types.
Cons: not duplicate-save.
toggleValues(["one","two","duped", "three", "duped", "four"], "duped")
will always return "three"

Categories

Resources