Related
I currently have the following, both of which must hold true:
A B C D + A E F = E F G H and
I C J * E = A B C D
Each letter represents a unique digit from 0 to 9 and both equations must hold true.
I need to write a Python solution which outputs the correct answer, here is my code:
import numpy as np
def solve():
for a in range(0,10):
for b in range(0,10):
for c in range(0,10):
for d in range(0,10):
for e in range(0,10):
for f in range(0,10):
for g in range(0,10):
for h in range(0,10):
for i in range(0,10):
for j in range(0,10):
if len(set([a, b, c, d, e, f, g, h, i, j])) == 10:
icj = 100*i + 10*c + j
e = e
abcd = 1000*a + 100*b + 10*c + d
aef = 100*a + 10*e + f
efgh = 1000*e + 100*f + 10*g + h
if icj * e == abcd and abcd + aef == efgh:
print(icj, e, abcd, aef, efgh)
print(solve())
However, when I run this, not only does it take a while to run, it outputs "None". Any ideas as to where I am going wrong?
You should try for x in range(0, 10) instead of for x in range(0,9) because you were looping from 0 to 8
If you want to loop in a more efficient way, you can use permutations:
from itertools import permutations
for a, b, c, d, e, f, g, h, i, j in permutations(range(0, 10), 10):
print(a, b, c, d, e, f, g, h, i, j)
Result :
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 9 8
...
9 8 7 6 5 4 3 2 0 1
9 8 7 6 5 4 3 2 1 0
Here is the final code :
import numpy as np
from itertools import permutations
def solve():
for a, b, c, d, e, f, g, h, i, j in permutations(range(0, 10), 10):
icj = 100*i + 10*c + j
e = e
abcd = 1000*a + 100*b + 10*c + d
aef = 100*a + 10*e + f
efgh = 1000*e + 100*f + 10*g + h
if icj * e == abcd and abcd + aef == efgh:
print(icj, e, abcd, aef, efgh)
print(a, b, c, d, e, f, g, h, i, j)
solve()
Output :
934 7 6538 672 7210
6 5 3 8 7 2 1 0 9 4
Apart from the typos, if you only test in the very inner loop whether all 10 digits are different, this inner loop is executed 1010 = 10,000,000,000 times. If you test at every pass, you "only" need 10! = 3,628,800 passes to this inner loop.
You still can do better changing the order of variables, so the equation abc * d == hibj can be tested without needing the other 3 variables, and only go deeper when it holds. For these 7 digits, you enter 604,800 times in that loop, and only 45 times you need to go deeper to reach the most inner loop only 270 times.
def solve():
for a in range(0, 10):
for b in range(0, 10):
if a != b:
for c in range(0, 10):
if not c in [a, b]:
for d in range(0, 10):
if not d in [a, b, c]:
for h in range(0, 10):
if not h in [a, b, c, d]:
for i in range(0, 10):
if not i in [a, b, c, d, h]:
for j in range(0, 10):
if not j in [a, b, c, d, h, i]:
abc = 100 * a + 10 * b + c
hibj = 1000 * h + 100 * i + 10 * b + j
if abc * d == hibj:
print(abc, '*', d, '=', hibj)
for e in range(0, 10):
if not e in [a, b, c, d, h, i, j]:
for f in range(0, 10):
if not f in [a, b, c, d, h, i, j, e]:
for g in range(0, 10):
if not g in [a, b, c, d, h, i, j, e, f]:
hde = 100 * h + 10 * d + e
defg = 1000 * d + 100 * e + 10 * f + g
if hibj + hde == defg:
print(abc, d, hibj, hde, defg)
solve()
print('done')
Although it now runs fast enough, still more specific optimizations can be thought of:
Change the order to a,b,c and h,i,j then calculate whether hibj is a multiple of abc. Only in case it is, this defines d which should be between 0 and 9, and different from the rest.
Or, the reverse: generate a,b,c,d and then try all the multiples first whether they fit b and then whether the corresponding h,i,j are different from each other and different from a,b,c,d.
h should be smaller than a, otherwise d will be larger than 9. This makes a at least 1.
Usually in this kind of problems, the first digit of every number is supposed to be non-zero, which can further reduce the number of checks.
An alternative approach, is to use an SMT/SAT solver such as Z3. With such a solver, all the conditions are formulated, and via all kind of heuristics a solution is searched for. Example codes: here and here.
This is how the code could look like:
from z3 import Int, And, Or, Distinct, Solver, sat
D = [Int(f'{c}') for c in "abcdefghij"]
a, b, c, d, e, f, g, h, i, j = D
vals_0_to_9 = [And(Di >= 0, Di <= 9) for Di in D]
all_different = [Distinct(D)]
abc = 100 * a + 10 * b + c
hibj = 1000 * h + 100 * i + 10 * b + j
hde = 100 * h + 10 * d + e
defg = 1000 * d + 100 * e + 10 * f + g
equations = [abc * d == hibj, hibj + hde == defg]
s = Solver()
s.add(vals_0_to_9 + all_different + equations)
while s.check() == sat:
m = s.model()
print(", ".join([f'{Di}={m[Di]}' for Di in D]))
s.add(Or([Di != m[Di] for Di in D]))
This prints out a=9, b=3, c=4, d=7, e=2, f=1, g=0, h=6, i=5, j=8 as unique solution.
This question already has an answer here:
How does swapping of members in tuples (a,b)=(b,a) work internally?
(1 answer)
Closed 3 years ago.
a, b, n = 0, 1, 500
while a < n:
print(a)
a, b = b, a+b
and
a, b, n = 0, 1, 500
while a < n:
print(a)
a = b
b = a+b
Both give different output.
What is the difference between a, b = b, a+b and a = b; b = a+b?
The below code is like swapping.
a, b = b, a+b
Its like doing this
temp = a
a = b
b = temp + b
a, b, n = 0, 1, 500
while a < n:
print(a)
a = b
b = a+b
In above line of code - after print(a), code value in b variable will be assigned to a first and hence the value of a is updated and the updated value of a is being used in b = a+b
Lets say, a =0, b =1 . So after print(a), value of a will be 1 first and b will have 1+1 =2.
Whereas,
a, b, n = 0, 1, 500
while a < n:
print(a)
a, b = b, a+b
In the above code, after print(a), a and b values are simultaneously assigned. In this case, whatever value of a is printed in print(a) will be used in assigning value for a in further step.
Lets say, a = 0 and b = 1 ,
after print(a) which will print 0 first, value in a will be 1 and value in b will be 0+1 = 1 because b = a+b will use a =0 and not a =1.
a, b = b, a+b
is equivalent to
tmp = a
a = b
b = tmp+b
This is not comma separated values. You are doing tuple unpacking.
a, b, n = 0, 1, 500
Is the same as:
a, b, n = (0, 1, 500)
The reason they are different is the first line assigns b to a then adds a and b together. It’s essentially the same as:
a = b
b = a+b
This is my first question and I started to learn Python.
Is there a difference between:
a, b = b, a + b
and
a = b
b = a + b
When you write it in below example it shows different results.
def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + b
print()
fib(1000)
and
def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a = b
b = a + b
print()
fib(1000)
In a, b = b, a + b, the expressions on the right hand side are evaluated before being assigned to the left hand side. So it is equivalent to:
c = a + b
a = b
b = c
In the second example, the value of a has already been changed by the time b = a + b is run. Hence, the result is different.
The line:
a, b = b, a + b
is closer to:
temp_a = a
a = b
b = temp_a + b
where b is using the old value of a before a was reassigned to the value of b.
Python first evaluates the right-hand expression and stores the results on the stack, then takes those two values and assigns them to a and b. That means that a + b is calculated before a is changed.
See How does swapping of members in the python tuples (a,b)=(b,a) work internally? for the low-down on how this all works, at the bytecode level.
Let's say we start with a and b like this:
a = 2
b = 3
So, when you do:
a, b = b, a + b
what happens is you create the tuple (b, a + b) or (3, 5) and then unpack it into a and b so a becomes 3 and b becomes 5.
In your second example:
a = b
# a is now 3
b = a + b
# b is 3 + 3, or 6.
Let's grok it.
a, b = b, a + b
It's a tuple assignment, means (a, b) = (b, a + b), just like (a, b) = (b, a)
Start from a quick example:
a, b = 0, 1
#equivalent to
(a, b) = (0, 1)
#implement as
a = 0
b = 1
When comes to (a, b) = (b, a + b)
EAFP, have a try directly
a, b = 0, 1
a = b #a=b=1
b = a + b #b=1+1
#output
In [87]: a
Out[87]: 1
In [88]: b
Out[88]: 2
However,
In [93]: a, b = b, a+b
In [94]: a
Out[94]: 3
In [95]: b
Out[95]: 5
The result is different from the first try.
Tha's because Python firstly evaluates the right-hand a+b
So it equivalent to:
old_a = a
old_b = b
c = old_a + old_b
a = old_b
b = c
In summary, a, b = b, a+b means,
a exchanges to get old_value of b,
b exchanges to get the sum of old value a and old value b,
a, b = b, a + b is similar to a, b = 0, 1 assigning values to both variables a, b at same time. First assign a = b and then b = a + b.
I hope that you haven't been influenced by C language, which the priority of assignment operator = is higher than that of Comma operator ,. Do not think it's (a), (b = b), (a + b). It's a tuple assignment, meaning it's (a, b) = (b, a + b).
There are differences between a,b = b,a+b and a=b b=a+b
let's have a look at the following two examples:
eg1:
a,b = 0,1
while a<10:
print(a)
a,b = b,a+b
#output:
0
1
1
2
3
5
8
eg2:
a,b = 0,1
while a<10:
print(a)
a=b
b=a+b
#output:
0
1
2
4
8
This is because the interpreter always calculates the figures in the right side of the Equals sign first. The calculation results will be assigned to the variables which on the left hand side only if all the calculation has been done on the right hand side.
A = 0
B = 10
C = 20
N = [(A, B, C)]
Avarage = (A + B + C) / sum(1 for i in N if i != 0)
Avarage = 30??
Need Avarage = 15.
Any idea?
You need to remove ( and ) from your list N
a = 0
b = 10
c = 20
n = [a, b, c]
list_avg = sum(n) / sum(1 for i in n if i != 0)
Output:
>>> list_avg
15
N is list containing tupple. So sum(1 for i in N if i != 0) returns 1 as there is only 1 element (a tupple) in list N.
Try:
A = 0
B = 10
C = 20
N = [(A, B, C)]
Avarage = (A + B + C) / sum(1 for i in N[0] if i != 0)
print Avarage
15
OR:
A = 0
B = 10
C = 20
N = [A, B, C]
Avarage = (A + B + C) / sum(1 for i in N if i != 0)
print Avarage
15
As stated by depperm, N is a list of one tuple, so you have in your sum only one element (which is different than 0 because it is a tuple and not an int). Otherwise you can use numpy
import numpy as np
average = np.mean([A, B, C])
Make a new list of values without the zeros, then average that:
non_zero = [v for v in (A, B, C) if v != 0]
avg = sum(non_zero)/len(non_zero)
I have a free text column in a DataFrame, for which I have developed custom handler:
a, b, c, d, e, f = my_transform(text_column)
How do I apply it to DataFrame in order to create 6 new columns a, b, c, d, e, f containing results of transformation?
Without your function it is a bit problematic, but works if return Series:
df = pd.DataFrame({'text_column':['abgdeftk', 'ewerfsfs']})
print (df)
text_column
0 abgdeftk
1 ewerfsfs
def my_transform(x):
#some sample fransformation
a = x[0]
b = x[1]
c = x[2]
d = x[3]
e = x[4]
f = x[5]
return pd.Series([a,b,c,d,e,f])
print (df.text_column.apply(my_transform))
0 1 2 3 4 5
0 a b g d e f
1 e w e r f s