Map -1, 0, 1 to 1000, 1500, 2000 - python

This is my first time making an algorithm for any of my projects.
I have an Xbox controller I will be using in a Python script using Pygame to read the output from the controller. Pygame outputs 0 when centered, -1 when full left, and 1 when full right.
For my application I need to translate this to values between 1000 and 2000 where 1000 is -1, 1500 is 0, and 2000 is 1.
Not asking necessarily for an answer, just some help with how to go about making an algorithm for myself.

If these are the only values possible, then you can create a dict to map Pygame outputs to your values.
positionMap = {-1:1000,0:1500,1:2000}
newVal = positionMap[oldVal]
But, if intermediate values are also possible then use this equation:
newVal = oldVal*500 + 1500

Your function can be of the form f(x) = ax^2 + bx + c. Put your transformations in a system and solve it:
a(-1)^2 + b(-1) + c = 1000
a*0^2 + b*0 + c = 1500
a*1^2 + b*1 + c = 2000
a - b + c = 1000
c = 1500
a + b + c = 2000
a - b = -500
a + b = 500
=> 2a = 0 => a = 0
=> b = 500
So you can use the function f(x) = 500x + 1500.
f(-1) = 1000
f(0) = 1500
f(1) = 2000
f(0.3) = 1650

There are many ways to do what you're asking. The simplest way is a linear mapping using the two point form of a line. You probably learned this in algebra but you might have forgotten it so here's a refresher: http://www.mathsisfun.com/algebra/line-equation-2points.html.
In your case, the x values are what you're given (-1 .. 1) and the y values are what you want (1000..2000).
Of course if you'd like to change the feel of the controller, you might choose not to use a linear function. You might want something that slows down as you approach the limits of the controller for example.

def mapInput(value):
minInput = -1
maxInput = 1
minOutput = 1000
maxOutput = 2000
return (value - minInput)*(maxOutput-minOutput)/(maxInput-minInput) + minOutput
If those values are never going to change, then you could save a few processor cycles and just do:
def mapInput(value):
return value * 500 + 1500

If you are new to Python too, then might like to use an if/elif/else statement as that might be more readable for you:
if in_value == -1:
out_value = 1000
elif in_value == 0:
out_value = 1500
else:
out_value = 2000
The code could be wrapped in a function or used in-line.

Related

Fibonacci sequence calculator seems correct but can't find similar code online. Is there something wrong?

I made a simple Fibonacci sequence calculator for the first 22 terms:
i=1
n=0
while i<=20000:
i = i + n
n = i - n
print(i)
Looks like the result is correct
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
but I can't seem to find similar code anywhere online. I think that's a big red flag. Can someone tell me what is wrong here? Is this inefficient code?
No, that code is fine. The probable reason you can't find similar code online is that it's unusual to use the subtraction operator in Fibonacci, which is a purely additive function, tn = tn-2 + tn-1.
It works, of course, since addition/subtraction is both commutative and associative, meaning that order and grouping of terms is unimportant:
i = i + n # iNew = iOld + nOld
n = i - n # nNew = (iNew) - nOld
# = (iOld + nOld) - nOld
# = iOld + (nOld - nOld)
# = iOld + (0)
# = iOld
Use of subtraction allows you to bypass needing a third variable, which would be something like this in a lesser language than Python:
nextN = i + n
i = n
n = nextN
In Python, you don't actually need that since you can use tuple assignment such as:
(n, i) = (i, n + i)
With that, everything on the right of the = is evaluated before any assignments to the left.
It's an unusual way to do it, but it's correct. Your lines:
i = i + n
n = i - n
are the same as doing:
new_i = i + n
n = i
i = new_i
or,
i, n = i + n, i
which would be the usual way in Python.

Need to reduce run time on creating a list of numbers based on a formula and a number n

Need a better way to create a list of numbers, so that the run time is less. Or probably figure out a better approach to my problem.
I'm running a code to create a series of numbers based on 2 formulas. Starting from 1, the formulas create the following numbers. The idea is to return the number n from the list that is created at the end. Even tough the formulas create the same number in some cases, only unique values remain, and the list is sorted to match. I use a while loop to create the list, and I believe that reducing the number of repetitions can help with my problem, but I can't figure out a way to effectively reduce it, without ruining the purpose of my code.
def dbl_linear(n):
x = 1
y = 0
z = 0
i = 0
u = []
u.append(x)
while i <= n:
x = (u)[i]
y = 2 * x + 1
u.append(y)
z = 3 * x + 1
u.append(z)
i = i + 1
u.sort()
uFix = set(u)
uFix = list(uFix)
uFix.sort()
return uFix[n]
print(dbl_linear(50))
These are the expected results. Which I get, but it takes too long.
dbl_linear(10), 22)
dbl_linear(20), 57)
dbl_linear(30), 91)
dbl_linear(50), 175)
Your function can be considerably simplified to:
Code:
def dbl_linear(n):
u = [1]
for i in range(n):
x = u[i]
u.extend((2 * x + 1, 3 * x + 1))
return sorted(set(u))[n]
Test Code:
assert dbl_linear(10) == 22
assert dbl_linear(20) == 57
assert dbl_linear(30) == 91
assert dbl_linear(50) == 175

How to enter a Googol in Python?

I've heard that Python does not have any upper limit with integers. So I wanted to give a try:
a = 1e100
b = 1
c = a + b + a
c - 2 * a
> 0.0
Unfortunately I realized that writing 1e2 returns a float while 100 returns an int.
I've then tested with long('1' + '0' * 100) which works.
a = long('1' + '0' * 100)
b = 1
c = a + b + a
c - 2 * a
> 1L
Is this solution the only way to affect a Googol to a variable?
Subsequent question:
How to avoid confusion between floating point and fixed point during computations?
You can get a Googol like so:
10**100
I dont really understand your question but i think you are asking is there only this way to manipulate googol variable .
i just tried this on my python idle and got this
>>> a = 10 ** 100
>>> b = 1
>>> c = a + b + a
>>> c - 2 *a
1
>>>
You could use the power operator:
base**times
so 123 googols would be 123*10**100

Optimising iterative loop

I'm gradually moving from Matlab to Python and would like to get some advice on optimising an iterative loop.
This is how I am currently running the loop, and for info I've included the code that defines the variables.
nh = 2000
h = np.array(range(nh))
nt = 10000
wmin = 1
wmax = 10
hw = np.array(wmin + (wmax-wmin)*invlogit(randn(1,nh)));
sl = np.array(zeros((nh,1))+radians(40))
fa = np.array(zeros((nh,1))+radians(35))
c = np.array(zeros((nh,1))+4.4)
y = np.array(zeros((nh,1))+17.6)
yw = np.array(zeros((nh,1))+9.81)
ir = 0.028
m = np.array(zeros((nh,nt)));
m[:,49] = 0.1
z = np.array(zeros((nh,nt)))
z[:,0] = 0+(3.0773-0)*rand(nh,1).T
reset = np.array(zeros((nh,nt)))
fs = np.array(zeros((nh,nt)))
for t in xrange(0, nt-1):
fs[:,t] = (c.T+(y.T-m[:,t]*yw.T)*z[:,t]*(np.cos(sl.T)**2)*np.tan(fa.T))/(y.T*z[:,t]*np.sin(sl.T)*np.cos(sl.T))
reset[fs[:,t]<=1,t+1] = 1;
z[fs[:,t]<=1,t+1] = 0;
z[fs[:,t]>1,t+1] = z[fs[:,t]>1,t]+(ir/hw[0,fs[:,t]>1]).T
This is how I would optimise the code in Matlab, however it runs fairly slowly in python. I suspect there is a more pythonic way of doing this and would really appreciate a nudge in the right direction.
Many thanks!
Not specifically about the loop, you're doing a ton of extra work in calls that look like:
np.array(zeros((nh,nt)))
Just use:
np.zeros((nh,nt))
in its place. Additionally, you could replace:
h = np.array(range(nh))
with:
h = np.arange(nh)
Other comments:
You're calling np.sin(sl.T)*np.cos(sl.T) in every loop although, sl does not appear to be changing at all. Just calculate it once and assign it to a variable that you use in the loop. You do this in a bunch of your trig calls.
The expression
(c.T+(y.T-m[:,t]*yw.T)*z[:,t]*(np.cos(sl.T)**2)*np.tan(fa.T))/(y.T*z[:,t]*np.sin(sl.T)*np.cos(sl.T))
uses c, y, m, yw, sl, fa that do not change inside the loop. You could compute several subexpressions before the loop.
Also, most of those arrays contain one repeated value. You could compute with scalars instead:
sl = radians(40)
fa = radians(35)
c = 4.4
y = 17.6
yw = 9.81
Then, with precomputed subexpressions:
A = cos(sl)**2 * tan(fa) * (y - m*yw)
B = y*sin(sl)*cos(sl)
for t in xrange(0, nt-1):
fs[:,t] = (c + A[:,t]*z[:,t]) / (B*z[:,t])
less = fs[:,t]<=1
more = np.logical_not(less)
reset[less,t+1] = 1
z[less,t+1] = 0
z[more,t+1] = z[more,t]+(ir/hw[0,more]).T

Solving Puzzle in Python

I got one puzzle and I want to solve it using Python.
Puzzle:
A merchant has a 40 kg weight which he used in his shop. Once, it fell
from his hands and was broken into 4 pieces. But surprisingly, now he
can weigh any weight between 1 kg to 40 kg with the combination of
these 4 pieces.
So question is, what are weights of those 4 pieces?
Now I wanted to solve this in Python.
The only constraint i got from the puzzle is that sum of 4 pieces is 40. With that I could filter all the set of 4 values whose sum is 40.
import itertools as it
weight = 40
full = range(1,41)
comb = [x for x in it.combinations(full,4) if sum(x)==40]
length of comb = 297
Now I need to check each set of values in comb and try all the combination of operations.
Eg if (a,b,c,d) is the first set of values in comb, I need to check a,b,c,d,a+b,a-b, .................a+b+c-d,a-b+c+d........ and so on.
I tried a lot, but i am stuck at this stage, ie how to check all these combination of calculations to each set of 4 values.
Question :
1) I think i need to get a list all possible combination of [a,b,c,d] and [+,-].
2) does anyone have a better idea and tell me how to go forward from here?
Also, I want to do it completely without help of any external libraries, need to use only standard libraries of python.
EDIT : Sorry for the late info. Its answer is (1,3,9,27), which I found a few years back. I have checked and verified the answer.
EDIT : At present, fraxel's answer works perfect with time = 0.16 ms. A better and faster approach is always welcome.
Regards
ARK
Earlier walk-through anwswer:
We know a*A + b*B + c*C + d*D = x for all x between 0 and 40, and a, b, c, d are confined to -1, 0, 1. Clearly A + B + C + D = 40. The next case is x = 39, so clearly the smallest move is to remove an element (it is the only possible move that could result in successfully balancing against 39):
A + B + C = 39, so D = 1, by neccessity.
next:
A + B + C - D = 38
next:
A + B + D = 37, so C = 3
then:
A + B = 36
then:
A + B - D = 35
A + B - C + D = 34
A + B - C = 33
A + B - C - D = 32
A + C + D = 31, so A = 9
Therefore B = 27
So the weights are 1, 3, 9, 27
Really this can be deduced immediately from the fact that they must all be multiples of 3.
Interesting Update:
So here is some python code to find a minimum set of weights for any dropped weight that will span the space:
def find_weights(W):
weights = []
i = 0
while sum(weights) < W:
weights.append(3 ** i)
i += 1
weights.pop()
weights.append(W - sum(weights))
return weights
print find_weights(40)
#output:
[1, 3, 9, 27]
To further illustrate this explaination, one can consider the problem as the minimum number of weights to span the number space [0, 40]. It is evident that the number of things you can do with each weight is trinary /ternary (add weight, remove weight, put weight on other side). So if we write our (unknown) weights (A, B, C, D) in descending order, our moves can be summarised as:
ABCD: Ternary:
40: ++++ 0000
39: +++0 0001
38: +++- 0002
37: ++0+ 0010
36: ++00 0011
35: ++0- 0012
34: ++-+ 0020
33: ++-0 0021
32: ++-- 0022
31: +0++ 0100
etc.
I have put ternary counting from 0 to 9 alongside, to illustrate that we are effectively in a trinary number system (base 3). Our solution can always be written as:
3**0 + 3**1 +3**2 +...+ 3**N >= Weight
For the minimum N that this holds true. The minimum solution will ALWAYS be of this form.
Furthermore, we can easily solve the problem for large weights and find the minimum number of pieces to span the space:
A man drops a known weight W, it breaks into pieces. His new weights allow him to weigh any weight up to W. How many weights are there, and what are they?
#what if the dropped weight was a million Kg:
print find_weights(1000000)
#output:
[1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 202839]
Try using permutations for a large weight and unknown number of pieces!!
Here is a brute-force itertools solution:
import itertools as it
def merchant_puzzle(weight, pieces):
full = range(1, weight+1)
all_nums = set(full)
comb = [x for x in it.combinations(full, pieces) if sum(x)==weight]
funcs = (lambda x: 0, lambda x: x, lambda x: -x)
for c in comb:
sums = set()
for fmap in it.product(funcs, repeat=pieces):
s = sum(f(x) for x, f in zip(c, fmap))
if s > 0:
sums.add(s)
if sums == all_nums:
return c
>>> merchant_puzzle(40, 4)
(1, 3, 9, 27)
For an explanation of how it works, check out the answer Avaris gave, this is an implementation of the same algorithm.
You are close, very close :).
Since this is a puzzle you want to solve, I'll just give pointers. For this part:
Eg if (a,b,c,d) is the first set of values in comb, i need to check
a,b,c,d,a+b,a-b, .................a+b+c-d,a-b+c+d........ and so on.
Consider this: Each weight can be put to one scale, the other or neither. So for the case of a, this can be represented as [a, -a, 0]. Same with the other three. Now you need all possible pairings with these 3 possibilities for each weight (hint: itertools.product). Then, a possible measuring of a pairing (lets say: (a, -b, c, 0)) is merely the sum of these (a-b+c+0).
All that is left is just checking if you could 'measure' all the required weights. set might come handy here.
PS: As it was stated in the comments, for the general case, it might not be necessary that these divided weights should be distinct (for this problem it is). You might reconsider itertools.combinations.
I brute forced the hell out of the second part.
Do not click this if you don't want to see the answer. Obviously, if I was better at permutations, this would have required a lot less cut/paste search/replace:
http://pastebin.com/4y2bHCVr
I don't know Python syntax, but maybe you can decode this Scala code; start with the 2nd for-loop:
def setTo40 (a: Int, b: Int, c: Int, d: Int) = {
val vec = for (
fa <- List (0, 1, -1);
fb <- List (0, 1, -1);
fc <- List (0, 1, -1);
fd <- List (0, 1, -1);
prod = fa * a + fb * b + fc * c + fd * d;
if (prod > 0)
) yield (prod)
vec.toSet
}
for (a <- (1 to 9);
b <- (a to 14);
c <- (b to 20);
d = 40-(a+b+c)
if (d > 0)) {
if (setTo40 (a, b, c, d).size > 39)
println (a + " " + b + " " + c + " " + d)
}
With weights [2, 5, 15, 18] you can also measure all objects between 1 and 40kg, although some of them will need to be measured indirectly. For example, to measure an object weighting 39kg, you would first compare it with 40kg and the balance would pend to the 40kg side (because 39 < 40), but then if you remove the 2kg weight it would pend to the other side (because 39 > 38) and thus you can conclude the object weights 39kg.
More interestingly, with weights [2, 5, 15, 45] you can measure all objects up to 67kg.
If anyone doesn't want to import a library to import combos/perms, this will generate all possible 4-move strategies...
# generates permutations of repeated values
def permutationsWithRepeats(n, v):
perms = []
value = [0] * n
N = n - 1
i = n - 1
while i > -1:
perms.append(list(value))
if value[N] < v:
value[N] += 1
else:
while (i > -1) and (value[i] == v):
value[i] = 0
i -= 1
if i > -1:
value[i] += 1
i = N
return perms
# generates the all possible permutations of 4 ternary moves
def strategy():
move = ['-', '0', '+']
perms = permutationsWithRepeats(4, 2)
for i in range(len(perms)):
s = ''
for j in range(4):
s += move[perms[i][j]]
print s
# execute
strategy()
My solution as follows:
#!/usr/bin/env python3
weight = 40
parts = 4
part=[0] * parts
def test_solution(p, weight,show_result=False):
cv=[0,0,0,0]
for check_weight in range(1,weight+1):
sum_ok = False
for parts_used in range(2 ** parts):
for options in range(2 ** parts):
for pos in range(parts):
pos_neg = int('{0:0{1}b}'.format(options,parts)[pos]) * 2 - 1
use = int('{0:0{1}b}'.format(parts_used,parts)[pos])
cv[pos] = p[pos] * pos_neg * use
if sum(cv) == check_weight:
if show_result:
print("{} = sum of:{}".format(check_weight, cv))
sum_ok = True
break
if sum_ok:
continue
else:
return False
return True
for part[0] in range(1,weight-parts):
for part[1] in range(part[0]+1, weight - part[0]):
for part[2] in range( part[1] + 1 , weight - sum(part[0:2])):
part[3] = weight - sum(part[0:3])
if test_solution(part,weight):
print(part)
test_solution(part,weight,True)
exit()
It gives you all the solutions for the given weights
More dynamic than my previous answer, so it also works with other numbers. But breaking up into 5 peaces takes some time:
#!/usr/bin/env python3
weight = 121
nr_of_parts = 5
# weight = 40
# nr_of_parts = 4
weight = 13
nr_of_parts = 3
part=[0] * nr_of_parts
def test_solution(p, weight,show_result=False):
cv=[0] * nr_of_parts
for check_weight in range(1,weight+1):
sum_ok = False
for nr_of_parts_used in range(2 ** nr_of_parts):
for options in range(2 ** nr_of_parts):
for pos in range(nr_of_parts):
pos_neg = int('{0:0{1}b}'.format(options,nr_of_parts)[pos]) * 2 - 1
use = int('{0:0{1}b}'.format(nr_of_parts_used,nr_of_parts)[pos])
cv[pos] = p[pos] * pos_neg * use
if sum(cv) == check_weight:
if show_result:
print("{} = sum of:{}".format(check_weight, cv))
sum_ok = True
break
if sum_ok:
continue
else:
return False
return True
def set_parts(part,position, nr_of_parts, weight):
if position == 0:
part[position] = 1
part, valid = set_parts(part,position+1,nr_of_parts,weight)
return part, valid
if position == nr_of_parts - 1:
part[position] = weight - sum(part)
if part[position -1] >= part[position]:
return part, False
return part, True
part[position]=max(part[position-1]+1,part[position])
part, valid = set_parts(part, position + 1, nr_of_parts, weight)
if not valid:
part[position]=max(part[position-1]+1,part[position]+1)
part=part[0:position+1] + [0] * (nr_of_parts - position - 1)
part, valid = set_parts(part, position + 1, nr_of_parts, weight)
return part, valid
while True:
part, valid = set_parts(part, 0, nr_of_parts, weight)
if not valid:
print(part)
print ('No solution posible')
exit()
if test_solution(part,weight):
print(part,' ')
test_solution(part,weight,True)
exit()
else:
print(part,' ', end='\r')

Categories

Resources