Why Python don't accept 03 as a number?

Avi Gross avigross at verizon.net
Sat Dec 8 12:40:06 EST 2018


Jach,

Just for fun, I looked at the  puzzle you asked about and solved it several
ways without running into your 03 problem at all. There are more efficient
solutions than total brute force.

Anyone not interested, stop here, please. After my explanations, I show a
python program then the output it produces.

The comments in the python program (below) explain the solution classes but
let me suggest a little algebra simplifies the problem so fewer brute force
iterations are needed.

The simplistic algorithm can be written as a single list comprehension with
(in this case) 5 "for" clauses and one "if" clause.

You are solving for: ab + aa + cd == ce

So 
for all digits possible for a
for all remaining digits possible for b each iteration
for all remaining digits possible for c each iteration
for all remaining digits possible for d each iteration
for all remaining digits possible for e each iteration
if the condition applies.

Clearly the above is deeply nested with 10!/5! Iterations or 30,240.

But a little algebra simplifies the solution so c drops out of the equation
as shown below in the comments.
The test becomes:  21*a + b + d - e == 0

You can apply that as the condition using four loops. You get 32 solutions
and for each you can let c be any of 10 possibilities for 320 total
solutions, if I did it right. The number of iterations is now only 5,040 and
you are evaluating fewer terms with c gone. The full test would have been
(10*a +b )+ (10*a + a) + (10*c + d) == (10*c + e)

BUT a tad more analysis shows that all solutions require "a" to be zero. If
a >=1 then 21*a must be >= 21.
But b and c cannot be more than 9+8 which is 17 and subtracting e makes it
no larger. So "a" MUST be zero.

So the solution can be done with only three loops for b, d, and e. 720
iterations.

The commented code is below. It can be done in as little as two lines of
code if the list comprehension is done in one line but why make it hard to
read.

If there is a flaw in my reasoning or the program below, please point it
out. You said there were 192 solutions. I found 320.
And, there are more efficient solutions possible but overkill for this
application.

Avi

################### START CODE ##############
# GOAL: find all solutions of a puzzle
# ab + aa + cd == ce
# Where each of the letters a through e
# are UNIQUE values ranging from 0 to 9

# Make the equation simpler
# expand ab to 10*a + b
# expand aa to 10*a + a
# expand cd to 10*c + d
# add to get 21*a + b + 10*c + d
# expand ce to 10*c + e
# simplify 21*a + b + 10*c + d = 10*c + e
# the 10*c on both sides cancel.
# RESULT: 21*a + b + d - e = 0
# the value of c is not relevant and
# you can solve without e and then add back
# all ten possibilities later.

# Method:
# Use a set of digits.
# Use a list comprehension with four loops.
# Each loop chooses all available values
# for a,b,d,e by subtracting the set
# of digits already in use at the time from all digits.

digits = set(range(10))

matches = [ (a, b, d, e)
            for a in digits
            for b in (digits - {a})
            for d in (digits -{a,b})
            for e in (digits -{a,b,d})
            if ( 21*a + b + d - e == 0)
            ]

print("SOLVING FOR: 21*a + b + d - e == 0")
print(f"matches found in batches of 10: {len(matches)}")

for (a,b,d,e) in matches:
    solution =  {'a' : a,
                    'b' : b,
                    'c' : 'any digit',
                    'd' : d,
                    'e' : e
                 }
    print(solution)

# Note the result shows all solutions have 'a' being zero.
# That was obvious from the equation as there were 21 of them
# and if a was 1 in 21*a + b + d - e = 0
# then clearly band d cannot be more than 9+8 so no solution
# unless a == 0.
# So you can solve this easier using the above techique by just
# solving b + d - e = 0

matches = [ (b, d, e)
            for b in digits
            for d in (digits -{b})
            for e in (digits -{b,d})
            if ( b + d == e)
            ]

print("\nSOLVING FOR: b + d == e")
print(f"matches found in batches of 10: {len(matches)}")

for (b,d,e) in matches:
    solution =  {'a' : '0',
                    'b' : b,
                    'c' : 'any digit',
                    'd' : d,
                    'e' : e
                 }
    print(solution)

################### END CODE ##############
################### BEGIN OUTPUT ##############
SOLVING FOR: 21*a + b + d - e == 0
matches found in batches of 10: 32
{'a': 0, 'b': 1, 'c': 'any digit', 'd': 2, 'e': 3}
{'a': 0, 'b': 1, 'c': 'any digit', 'd': 3, 'e': 4}
{'a': 0, 'b': 1, 'c': 'any digit', 'd': 4, 'e': 5}
{'a': 0, 'b': 1, 'c': 'any digit', 'd': 5, 'e': 6}
{'a': 0, 'b': 1, 'c': 'any digit', 'd': 6, 'e': 7}
{'a': 0, 'b': 1, 'c': 'any digit', 'd': 7, 'e': 8}
{'a': 0, 'b': 1, 'c': 'any digit', 'd': 8, 'e': 9}
{'a': 0, 'b': 2, 'c': 'any digit', 'd': 1, 'e': 3}
{'a': 0, 'b': 2, 'c': 'any digit', 'd': 3, 'e': 5}
{'a': 0, 'b': 2, 'c': 'any digit', 'd': 4, 'e': 6}
{'a': 0, 'b': 2, 'c': 'any digit', 'd': 5, 'e': 7}
{'a': 0, 'b': 2, 'c': 'any digit', 'd': 6, 'e': 8}
{'a': 0, 'b': 2, 'c': 'any digit', 'd': 7, 'e': 9}
{'a': 0, 'b': 3, 'c': 'any digit', 'd': 1, 'e': 4}
{'a': 0, 'b': 3, 'c': 'any digit', 'd': 2, 'e': 5}
{'a': 0, 'b': 3, 'c': 'any digit', 'd': 4, 'e': 7}
{'a': 0, 'b': 3, 'c': 'any digit', 'd': 5, 'e': 8}
{'a': 0, 'b': 3, 'c': 'any digit', 'd': 6, 'e': 9}
{'a': 0, 'b': 4, 'c': 'any digit', 'd': 1, 'e': 5}
{'a': 0, 'b': 4, 'c': 'any digit', 'd': 2, 'e': 6}
{'a': 0, 'b': 4, 'c': 'any digit', 'd': 3, 'e': 7}
{'a': 0, 'b': 4, 'c': 'any digit', 'd': 5, 'e': 9}
{'a': 0, 'b': 5, 'c': 'any digit', 'd': 1, 'e': 6}
{'a': 0, 'b': 5, 'c': 'any digit', 'd': 2, 'e': 7}
{'a': 0, 'b': 5, 'c': 'any digit', 'd': 3, 'e': 8}
{'a': 0, 'b': 5, 'c': 'any digit', 'd': 4, 'e': 9}
{'a': 0, 'b': 6, 'c': 'any digit', 'd': 1, 'e': 7}
{'a': 0, 'b': 6, 'c': 'any digit', 'd': 2, 'e': 8}
{'a': 0, 'b': 6, 'c': 'any digit', 'd': 3, 'e': 9}
{'a': 0, 'b': 7, 'c': 'any digit', 'd': 1, 'e': 8}
{'a': 0, 'b': 7, 'c': 'any digit', 'd': 2, 'e': 9}
{'a': 0, 'b': 8, 'c': 'any digit', 'd': 1, 'e': 9}

SOLVING FOR: b + d == e
matches found in batches of 10: 32
{'a': '0', 'b': 1, 'c': 'any digit', 'd': 2, 'e': 3}
{'a': '0', 'b': 1, 'c': 'any digit', 'd': 3, 'e': 4}
{'a': '0', 'b': 1, 'c': 'any digit', 'd': 4, 'e': 5}
{'a': '0', 'b': 1, 'c': 'any digit', 'd': 5, 'e': 6}
{'a': '0', 'b': 1, 'c': 'any digit', 'd': 6, 'e': 7}
{'a': '0', 'b': 1, 'c': 'any digit', 'd': 7, 'e': 8}
{'a': '0', 'b': 1, 'c': 'any digit', 'd': 8, 'e': 9}
{'a': '0', 'b': 2, 'c': 'any digit', 'd': 1, 'e': 3}
{'a': '0', 'b': 2, 'c': 'any digit', 'd': 3, 'e': 5}
{'a': '0', 'b': 2, 'c': 'any digit', 'd': 4, 'e': 6}
{'a': '0', 'b': 2, 'c': 'any digit', 'd': 5, 'e': 7}
{'a': '0', 'b': 2, 'c': 'any digit', 'd': 6, 'e': 8}
{'a': '0', 'b': 2, 'c': 'any digit', 'd': 7, 'e': 9}
{'a': '0', 'b': 3, 'c': 'any digit', 'd': 1, 'e': 4}
{'a': '0', 'b': 3, 'c': 'any digit', 'd': 2, 'e': 5}
{'a': '0', 'b': 3, 'c': 'any digit', 'd': 4, 'e': 7}
{'a': '0', 'b': 3, 'c': 'any digit', 'd': 5, 'e': 8}
{'a': '0', 'b': 3, 'c': 'any digit', 'd': 6, 'e': 9}
{'a': '0', 'b': 4, 'c': 'any digit', 'd': 1, 'e': 5}
{'a': '0', 'b': 4, 'c': 'any digit', 'd': 2, 'e': 6}
{'a': '0', 'b': 4, 'c': 'any digit', 'd': 3, 'e': 7}
{'a': '0', 'b': 4, 'c': 'any digit', 'd': 5, 'e': 9}
{'a': '0', 'b': 5, 'c': 'any digit', 'd': 1, 'e': 6}
{'a': '0', 'b': 5, 'c': 'any digit', 'd': 2, 'e': 7}
{'a': '0', 'b': 5, 'c': 'any digit', 'd': 3, 'e': 8}
{'a': '0', 'b': 5, 'c': 'any digit', 'd': 4, 'e': 9}
{'a': '0', 'b': 6, 'c': 'any digit', 'd': 1, 'e': 7}
{'a': '0', 'b': 6, 'c': 'any digit', 'd': 2, 'e': 8}
{'a': '0', 'b': 6, 'c': 'any digit', 'd': 3, 'e': 9}
{'a': '0', 'b': 7, 'c': 'any digit', 'd': 1, 'e': 8}
{'a': '0', 'b': 7, 'c': 'any digit', 'd': 2, 'e': 9}
{'a': '0', 'b': 8, 'c': 'any digit', 'd': 1, 'e': 9}
################### END OUTPUT ##############

-----Original Message-----
From: Python-list <python-list-bounces+avigross=verizon.net at python.org> On
Behalf Of jfong at ms4.hinet.net
Sent: Saturday, December 8, 2018 4:26 AM
To: python-list at python.org
Subject: Re: Why Python don't accept 03 as a number?

Avi Gross at 2018/12/8 UTC+8 PM2:09:20 wrote:
> [[READERS DIGEST CONDENSED ANSWER: use int("string") ]]
> 
> Since we all agree python will not make notations like "05" work 
> indefinitely, and the need expressed is how to solve a symbolic puzzle 
> (see message below) then it makes sense to look at alternate
representations.
> 
> I have a question first. How are you solving your puzzles? 
> 
>     ab + aa + cd == ce

Try all the combinations:-)

The only way I can think of is try-error. It takes no more 10 lines to go
from "ab + aa + cd == ce" to yield one correct answer, such as "03 + 00 + 15
== 18", using itertools' permutations(), string's translate() and re.

> Why does 05 ever even appear in your solution?

I don't know. There is total 192 answers for this puzzle anyway.

> Are you generating all possible answers by setting each variable to 
> one of 0 to 9 then the second to any of the remaining nine choices 
> then the third to the remaining 8 and so on? For any method like that, 
> you can presumably make each component like
> 
> ab = 10*a + b
> 
> in the loop.
> 
> Similarly for aa and cd and ce. If the equality above is true, you 
> found the solution and break out. If there can be multiple solutions, 
> note the solution and keep going. But note for the 5 variables above, 
> you are testing
> 10*9*8*7*6 combinations.
> 
> Another idea is to use strings like "05" as bizarrely, the function 
> int() seems to be an ex eption that does NOT care about leading 
> whitespace or
> zeroes:
> 
> >>> int("05")
> 5
> >>> int("  0005")
> 5
> 
> And even handles all zeroes:
> 
> >>> int("000000")
> 0
> 
> You can also use lstrip() with an argument to remove zeros:
> 
> >>> a = eval("05".lstrip("0"))
> 	     
> >>> a
> 	     
> 5
> 
> If you are in a situation where you only want to remove leading zeroes 
> if the following character is a digit and not "o" or "b" or "x", use 
> regular expressions or other techniques.

As far as the leading zero problem was concerned, the simplest way is using
re.sub()

> I will just toss in the possible use of the SymPy module to do actual 
> symbolic computations to solve some of these. Perhaps a tad advanced.

I don't know SymPy and if it can shorten the execution time. But I am very
curious about if there is other algorithm which can apply to this problem:-)

--Jach
--
https://mail.python.org/mailman/listinfo/python-list




More information about the Python-list mailing list