While Loop to produce Mathematical Sequences? - python

I've been asked to do the following:
Using a while loop, you will write a program which will produce the following mathematical sequence:
1 * 9 + 2 = 11(you will compute this number)
12 * 9 + 3 = 111
123 * 9 + 4 = 1111
Then your program should run as far as the results contain only "1"s. You can build your numbers as string, then convert to ints before calculation. Then you can convert the result back to a string to see if it contains all "1"s.
Sample Output:
1 * 9 + 2 = 11
12 * 9 + 3 = 111
123 * 9 + 4 = 1111
1234 * 9 + 5 = 11111
Here is my code:
def main():
Current = 1
Next = 2
Addition = 2
output = funcCalculation(Current, Addition)
while (verifyAllOnes(output) == True):
print(output)
#string concat to get new current number
Current = int(str(Current) + str(Next))
Addition += 1
Next += 1
output = funcCalculation(Current, Next)
def funcCalculation(a,b):
return (a * 9 + b)
def verifyAllOnes(val):
Num_str = str(val)
for ch in Num_str:
if(str(ch)!= "1"):
return False
return True
main()
The bug is that the formula isn't printing next to the series of ones on each line. What am I doing wrong?

Pseudo-code:
a = 1
b = 2
result = a * 9 + b
while string representation of result contains only 1s:
a = concat a with the old value of b, as a number
b = b + 1
result = a * 9 + b
This can be literally converted into Python code.

Testing all ones
Well, for starters, here is one easy way to check that the value is all ones:
def only_ones(n):
n_str = str(n)
return set(n_str) == set(['1'])
You could do something more "mathy", but I'm not sure that it would be any faster. It would much more easily
generalize to other bases (than 10) if that's something you were interested in though
def only_ones(n):
return (n % 10 == 1) and (n == 1 or only_ones2(n / 10))
Uncertainty about how to generate the specific recurrence relation...
As for actually solving the problem though, it's actually not clear what the sequence should be.
What comes next?
123456
1234567
12345678
123456789
?
Is it 1234567890? Or 12345678910? Or 1234567900?
Without answering this, it's not possible to solve the problem in any general way (unless in fact the 111..s
terminate before you get to this issue).
I'm going to go with the most mathematically appealing assumption, which is that the value in question is the
sum of all the 11111... values before it (note that 12 = 11 + 1, 123 = 111 + 11 + 1, 1234 = 1111 + 111 + 11 + 1, etc...).
A solution
In this case, you could do something along these lines:
def sequence_gen():
a = 1
b = 1
i = 2
while only_ones(b):
yield b
b = a*9 + i
a += b
i += 1
Notice that I've put this in a generator in order to make it easier to only grab as many results from this
sequence as you actually want. It's entirely possible that this is an infinite sequence, so actually running
the while code by itself might take a while ;-)
s = sequence_gen()
s.next() #=> 1
s.next() #=> 11
A generator gives you a lot of flexibility for things like this. For instance, you could grab the first 10 values of the sequence using the itertools.islice
function:
import itertools as it
s = sequence_gen()
xs = [x for x in it.islice(s, 10)]
print xs

Related

recursive function multiply and sum

Hope to find some help here with a new excercise.
I luckily understand how to use recursive functions, but this one is killing me, im probably just thinking too much outside of the box.
We're given a string:
c = "3+4*5+6+1*3"
And now we have to code a function, which recursivly gives us the result of that calculation.
Now i know the recursive end should be the length of the string, which should be 1.
Our professor did give us another example which we should use for this function.
int(number)
string.split(symbol, 1)
we have following code given:
c = "3+4*5+6+1*3"
print(c)
print()
sub1, sub2 = c.split("+", 1)
print("Result with '+':")
print("sub1=" + sub1)
print("sub2=" + sub2)
print()
sub1, sub2 = c.split("*", 1)
print("Result with '*':")
print("sub1=" + sub1)
print("sub2=" + sub2)
print()
My thoughts were to split the strings to a minimum, so i can turn them into integers and than sum them together. But im absolutly lost there how the code should look like, im a real beginner so im really sorry. I dont even know it the beginning i was thinking of is right. Still hoping, someone can help!
what i had:
def calc(string):
if len(string) == 1:
return string
Thanks for all of you!
Greets
Chrissi
I created a function that solves equations like these. However, the only characters possible are numbers, and operators add (+) and mult (*). If you try to use any other characters such as spaces, there's going to be errors.
# Solves a mathematical equation containing digits [0-9], and operators
# such as add + or multiply *
def solve(equation, operators, oindex=0):
# If an operator is available, use the operator
if (oindex < len(operators)):
# Get the current operator and pair: a op b
op = operators[oindex]
pair = equation.split(op, 1)
# If the pair is a pair (has 2 elements)
if (len(pair) == 2):
# Solve left side
a = solve(pair[0], operators)
# Solve right side
b = solve(pair[1], operators)
# If current operator is multiply: multiply a and b
if (op == '*'):
print(a, '*', b, '=', a*b)
return a * b
# If current operator is add: add a and b
elif (op == '+'):
print(a, '+', b, '=', a+b)
return a + b
# If it's not a pair, try using another operator
else:
return solve(equation, operators, oindex+1)
else:
# If no operators are available, then equation is
# just a number.
return int(equation)
if __name__ == '__main__':
equation = "3+4*5+6+1*3"
# If mult (*) takes precedence, operator order is "+*"
# > 3+4*5+6+1*3 = ((3)+((4*5)+((6)+(1*3))))
# = ((3)+((20)+((6)+(3))))
# = ((3)+(20+(9)))
# = ((3)+(29))
# = (32)
print("MULT, then ADD -> ",equation + " = ", solve(equation, "+*"))
# If add (+) takes precedence, operator order is "*+"
# > 3+4*5+6+1*3 = ((3+4)*(((5)+(6+1))*(3)))
# = ((7)*((5+7)*(3)))
# = ((7)*(12*3))
# = (7*36)
# = (252)
print("ADD, then MULT -> ",equation + " = ", solve(equation, "*+"))
To set the operators, you can use the paramter operators, which is a string that takes all supported operators. In this case: +*.
The order of these characters matter, changing the precedence of each operator inside the equation.
Here's the output:
4 * 5 = 20
1 * 3 = 3
6 + 3 = 9
20 + 9 = 29
3 + 29 = 32
MULT, then ADD -> 3+4*5+6+1*3 = 32
3 + 4 = 7
6 + 1 = 7
5 + 7 = 12
12 * 3 = 36
7 * 36 = 252
ADD, then MULT -> 3+4*5+6+1*3 = 252

Pandas Convert object values used in Passive Components to float

I have a dataframe of part numbers stored as object with a string containing 3 digits of values of following format:
Either 1R2, where the R is the decimal separator
Or only numbers where the first 2 are significant and the 3rd is the number of 0 following:
101 = 100
010 = 1
223 = 22000
476 = 47000000
My dataframe (important are positions 5~7):
MATNR
0 xx01B101KO3XYZC
1 xx03C010CA3GN5T
2 xx02L1R2CA3ANNR
Below code works fine for the 1R2 case and converts object to float64.
But I am stuck with getting the 2 significant numbers together with the number of 0s.
value_pos1 = 5
value_pos2 = 6
value_pos3 = 7
df['Value'] = pd.to_numeric(np.where(df['MATNR'].str.get(value_pos2)=='R',
df['MATNR'].str.get(value_pos1) + '.' + df['MATNR'].str.get(value_pos3),
df['MATNR'].str.slice(start=value_pos1, stop=value_pos3) + df['MATNR'].str.get(value_pos3)))
Result
MATNR object
Cap pF float64
dtype: object
Index(['MATNR', 'Value'], dtype='object')
MATNR Value
0 xx01B101KO3XYZC 101.0
1 xx03C010CA3GN5T 10.0
2 xx02L1R2CA3ANNR 1.2
It should be
MATNR Value
0 xx01B101KO3XYZC 100.0
1 xx03C010CA3GN5T 1.0
2 xx02L1R2CA3ANNR 1.2
Following I tried with errors and on top there is a wrong value for 0 # pos3 being 1 instead 0.
df['Value'] = pd.to_numeric(np.where(df['MATNR'].str.get(value_pos2)=='R',
df['MATNR'].str.get(Value_pos1) + '.' + df['MATNR'].str.get(value_pos3),
df['MATNR'].str.slice(start=value_pos1, stop=value_pos3) + str(pow(10, pd.to_numeric(df['MATNR'].str.get(value_pos3))))))
Do you have an idea?
If I have understood your problem correctly, defining a method and applying it to all the values of the column seems most intuitive. The method takes a str input and returns a float number.
Here is a snippet of what the simple method will entaik.
def get_number(strrep):
if not strrep or len(strrep) < 8:
return 0.0
useful_str = strrep[5:8]
if useful_str[1] == 'R':
return float(useful_str[0] + '.' + useful_str[2])
else:
zeros = '0' * int(useful_str[2])
return float(useful_str[0:2] + zeros)
Then you could simply create a new column with the numeric conversion of the strings. The easiest way possible is using list comprehension:
df['Value'] = [get_number(x) for x in df['MATNR']]
Not sure where the bug in your code is, but another option that I tend to use when creating a new column based on other columns is pandas' apply function:
def create_value_col(row):
if row['MATNR'][value_pos2] == 'R':
val = row['MATNR'][value_pos1] + '.' + row['MATNR'][value_pos3]
else:
val = (int(row['MATNR'][value_pos1]) * 10 +
int(row['MATNR'][value_pos2])) * 10 ** int(row['MATNR'][value_pos3])
return val
df['Value'] = df.apply(lambda row: create_value_col(row), axis='columns')
This way, you can create a function that processes the data however you want and then apply it to every row and add the resulting series to your dataframe.

Long multiplication of two numbers given as strings

I am trying to solve a problem of multiplication. I know that Python supports very large numbers and it can be done but what I want to do is
Enter 2 numbers as strings.
Multiply those two numbers in the same manner as we used to do in school.
Basic idea is to convert the code given in the link below to Python code but I am not very good at C++/Java. What I want to do is to understand the code given in the link below and apply it for Python.
https://www.geeksforgeeks.org/multiply-large-numbers-represented-as-strings/
I am stuck at the addition point.
I want to do it it like in the image given below
So I have made a list which stores the values of ith digit of first number to jth digit of second. Please help me to solve the addition part.
def mul(upper_no,lower_no):
upper_len=len(upper_no)
lower_len=len(lower_no)
list_to_add=[] #saves numbers in queue to add in the end
for lower_digit in range(lower_len-1,-1,-1):
q='' #A queue to store step by step multiplication of numbers
carry=0
for upper_digit in range(upper_len-1,-1,-1):
num2=int(lower_no[lower_digit])
num1=int(upper_no[upper_digit])
print(num2,num1)
x=(num2*num1)+carry
if upper_digit==0:
q=str(x)+q
else:
if x>9:
q=str(x%10)+q
carry=x//10
else:
q=str(x%10)+q
carry=0
num=x%10
print(q)
list_to_add.append(int(''.join(q)))
print(list_to_add)
mul('234','567')
I have [1638,1404,1170] as a result for the function call mul('234','567') I am supposed to add these numbers but stuck because these numbers have to be shifted for each list. for example 1638 is supposed to be added as 16380 + 1404 with 6 aligning with 4, 3 with 0 and 8 with 4 and so on. Like:
1638
1404x
1170xx
--------
132678
--------
I think this might help. I've added a place variable to keep track of what power of 10 each intermediate value should be multiplied by, and used the itertools.accumulate function to produce the intermediate accumulated sums that doing so produces (and you want to show).
Note I have also reformatted your code so it closely follows PEP 8 - Style Guide for Python Code in an effort to make it more readable.
from itertools import accumulate
import operator
def mul(upper_no, lower_no):
upper_len = len(upper_no)
lower_len = len(lower_no)
list_to_add = [] # Saves numbers in queue to add in the end
place = 0
for lower_digit in range(lower_len-1, -1, -1):
q = '' # A queue to store step by step multiplication of numbers
carry = 0
for upper_digit in range(upper_len-1, -1, -1):
num2 = int(lower_no[lower_digit])
num1 = int(upper_no[upper_digit])
print(num2, num1)
x = (num2*num1) + carry
if upper_digit == 0:
q = str(x) + q
else:
if x>9:
q = str(x%10) + q
carry = x//10
else:
q = str(x%10) + q
carry = 0
num = x%10
print(q)
list_to_add.append(int(''.join(q)) * (10**place))
place += 1
print(list_to_add)
print(list(accumulate(list_to_add, operator.add)))
mul('234', '567')
Output:
7 4
7 3
7 2
1638
6 4
6 3
6 2
1404
5 4
5 3
5 2
1170
[1638, 14040, 117000]
[1638, 15678, 132678]

Solving multivariate equation for a subset of variables

I am using sympy to solve some equations and I am running into a problem. I have this issue with many equations but I will illustrate with an example. I have an equation with multiple variables and I want to solve this equation in terms of all variables but one is excluded. For instance the equation 0 = 2^n*(2-a) - b + 1. Here there are three variables a, b and n. I want to get the values for a and b not in terms of n so the a and b may not contain n.
2^n*(2-a) - b + 1 = 0
# Since we don't want to solve in terms of n we know that (2 - a)
# has to be zero and -b + 1 has to be zero.
2 - a = 0
a = 2
-b + 1 = 0
b = 1
I want sympy to do this. Maybe I'm just not looking at the right documentation but I have found no way to do this. When I use solve and instruct it to solve for symbols a and b sympy returns to me a single solution where a is defined in terms of n and b. I assume this means I am free to choose b and n, However I don't want to fix n to a specific value I want n to still be a variable.
Code:
import sympy
n = sympy.var("n", integer = True)
a = sympy.var("a")
b = sympy.var("b")
f = 2**n*(2-a) - b + 1
solutions = sympy.solve(f, [a,b], dict = True)
# this will return: "[{a: 2**(-n)*(2**(n + 1) - b + 1)}]".
# A single solution where b and n are free variables.
# However this means I have to choose an n I don't want
# to that I want it to hold for any n.
I really hope someone can help me. I have been searching google for hours now...
Ok, here's what I came up with. This seems to solve the type of equations you're looking for. I've provided some tests as well. Of course, this code is rough and can be easily caused to fail, so i'd take it more as a starting point than a complete solution
import sympy
n = sympy.Symbol('n')
a = sympy.Symbol('a')
b = sympy.Symbol('b')
c = sympy.Symbol('c')
d = sympy.Symbol('d')
e = sympy.Symbol('e')
f = sympy.sympify(2**n*(2-a) - b + 1)
g = sympy.sympify(2**n*(2-a) -2**(n-1)*(c+5) - b + 1)
h = sympy.sympify(2**n*(2-a) -2**(n-1)*(e-1) +(c-3)*9**n - b + 1)
i = sympy.sympify(2**n*(2-a) -2**(n-1)*(e+4) +(c-3)*9**n - b + 1 + (d+2)*9**(n+2))
def rewrite(expr):
if expr.is_Add:
return sympy.Add(*[rewrite(f) for f in expr.args])
if expr.is_Mul:
return sympy.Mul(*[rewrite(f) for f in expr.args])
if expr.is_Pow:
if expr.args[0].is_Number:
if expr.args[1].is_Symbol:
return expr
elif expr.args[1].is_Add:
base = expr.args[0]
power = sympy.solve(expr.args[1])
sym = expr.args[1].free_symbols.pop()
return sympy.Mul(sympy.Pow(base,-power[0]), sympy.Pow(base,sym))
else:
return expr
else:
return expr
else:
return expr
def my_solve(expr):
if not expr.is_Add:
return None
consts_list = []
equations_list = []
for arg in expr.args:
if not sympy.Symbol('n') in arg.free_symbols:
consts_list.append(arg)
elif arg.is_Mul:
coeff_list = []
for nested_arg in arg.args:
if not sympy.Symbol('n') in nested_arg.free_symbols:
coeff_list.append(nested_arg)
equations_list.append(sympy.Mul(*coeff_list))
equations_list.append(sympy.Add(*consts_list))
results = {}
for eq in equations_list:
var_name = eq.free_symbols.pop()
val = sympy.solve(eq)[0]
results[var_name] = val
return results
print(my_solve(rewrite(f)))
print(my_solve(rewrite(g)))
print(my_solve(rewrite(h)))
print(my_solve(rewrite(i)))

How to toggle between two values?

I want to toggle between two values in Python, that is, between 0 and 1.
For example, when I run a function the first time, it yields the number 0. Next time, it yields 1. Third time it's back to zero, and so on.
Sorry if this doesn't make sense, but does anyone know a way to do this?
Use itertools.cycle():
from itertools import cycle
myIterator = cycle(range(2))
myIterator.next() # or next(myIterator) which works in Python 3.x. Yields 0
myIterator.next() # or next(myIterator) which works in Python 3.x. Yields 1
# etc.
Note that if you need a more complicated cycle than [0, 1], this solution becomes much more attractive than the other ones posted here...
from itertools import cycle
mySmallSquareIterator = cycle(i*i for i in range(10))
# Will yield 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 0, 1, 4, ...
You can accomplish that with a generator like this:
>>> def alternate():
... while True:
... yield 0
... yield 1
...
>>>
>>> alternator = alternate()
>>>
>>> alternator.next()
0
>>> alternator.next()
1
>>> alternator.next()
0
You can use the mod (%) operator.
count = 0 # initialize count once
then
count = (count + 1) % 2
will toggle the value of count between 0 and 1 each time this statement is executed. The advantage of this approach is that you can cycle through a sequence of values (if needed) from 0 - (n-1) where n is the value you use with your % operator. And this technique does not depend on any Python specific features/libraries.
e.g.
count = 0
for i in range(5):
count = (count + 1) % 2
print(count)
gives:
1
0
1
0
1
You may find it useful to create a function alias like so:
import itertools
myfunc = itertools.cycle([0,1]).next
then
myfunc() # -> returns 0
myfunc() # -> returns 1
myfunc() # -> returns 0
myfunc() # -> returns 1
In python, True and False are integers (1 and 0 respectively). You could use a boolean (True or False) and the not operator:
var = not var
Of course, if you want to iterate between other numbers than 0 and 1, this trick becomes a little more difficult.
To pack this into an admittedly ugly function:
def alternate():
alternate.x=not alternate.x
return alternate.x
alternate.x=True #The first call to alternate will return False (0)
mylist=[5,3]
print(mylist[alternate()]) #5
print(mylist[alternate()]) #3
print(mylist[alternate()]) #5
from itertools import cycle
alternator = cycle((0,1))
next(alternator) # yields 0
next(alternator) # yields 1
next(alternator) # yields 0
next(alternator) # yields 1
#... forever
var = 1
var = 1 - var
That's the official tricky way of doing it ;)
Using xor works, and is a good visual way to toggle between two values.
count = 1
count = count ^ 1 # count is now 0
count = count ^ 1 # count is now 1
To toggle variable x between two arbitrary (integer) values,
e.g. a and b, use:
# start with either x == a or x == b
x = (a + b) - x
# case x == a:
# x = (a + b) - a ==> x becomes b
# case x == b:
# x = (a + b) - b ==> x becomes a
Example:
Toggle between 3 and 5
x = 3
x = 8 - x (now x == 5)
x = 8 - x (now x == 3)
x = 8 - x (now x == 5)
This works even with strings (sort of).
YesNo = 'YesNo'
answer = 'Yes'
answer = YesNo.replace(answer,'') (now answer == 'No')
answer = YesNo.replace(answer,'') (now answer == 'Yes')
answer = YesNo.replace(answer,'') (now answer == 'No')
Using the tuple subscript trick:
value = (1, 0)[value]
Using tuple subscripts is one good way to toggle between two values:
toggle_val = 1
toggle_val = (1,0)[toggle_val]
If you wrapped a function around this, you would have a nice alternating switch.
If a variable is previously defined and you want it to toggle between two values, you may use the
a if b else c form:
variable = 'value1'
variable = 'value2' if variable=='value1' else 'value1'
In addition, it works on Python 2.5+ and 3.x
See Expressions in the Python 3 documentation.
Simple and general solution without using any built-in. Just keep the track of current element and print/return the other one then change the current element status.
a, b = map(int, raw_input("Enter both number: ").split())
flag = input("Enter the first value: ")
length = input("Enter Number of iterations: ")
for i in range(length):
print flag
if flag == a:
flag = b;
else:
flag = a
Input:
3 835Output:38383
Means numbers to be toggled are 3 and 8
Second input, is the first value by which you want to start the sequence
And last input indicates the number of times you want to generate
One cool way you can do in any language:
variable = 0
variable = abs(variable - 1) // 1
variable = abs(variable - 1) // 0

Categories