1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
# copyright 2002-2021 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of logilab-constraint.
#
# logilab-constraint is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version.
#
# logilab-constraint is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with logilab-constraint. If not, see <http://www.gnu.org/licenses/>.
"""
Solve a puzzle that got discussed on c.l.p. on october 2002
ABC*DE=FGHIJ with all letters different and in domain [0,9]
"""
from logilab.constraint import fd, Repository, Solver
from logilab.constraint.propagation import BasicConstraint
class DistinctDigits(BasicConstraint):
def __init__(self, variable):
BasicConstraint.__init__(self, variable, None, None)
def narrow(self, domains):
domain = domains[self._variable]
for v in domain.getValues():
s = str(v)
for d in ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"):
if s.count(d) not in (0, 1):
domain.removeValue(v)
break
return 1
def __repr__(self):
return f"<DistinctDigits on variable {self._variable}>"
def menza():
""" """
VARS = "ab"
variables = list(VARS)
domains = {}
constraints = []
domains["a"] = fd.FiniteDomain(range(0, 1000))
domains["b"] = fd.FiniteDomain(range(0, 100))
me = fd.make_expression
for v in variables:
constraints.append(DistinctDigits(v))
dist = ["10000 < a*b "]
for digit in range(10):
dist.append('("%%.3d%%.2d%%.5d" %% (a,b,a*b)).count("%d")==1' % digit)
constraints.append(me(("a", "b"), " and ".join(dist)))
r = Repository(variables, domains, constraints)
return r
if __name__ == "__main__":
import sys
import getopt
opts, args = getopt.getopt(sys.argv[1:], "dv")
verbose = 0
display = 0
create_problem = menza
for o, v in opts:
if o == "-v":
verbose += 1
elif o == "-d":
display = 1
r = create_problem()
print("problem created. let us solve it.")
s = []
for sol in Solver().solve_all(r, verbose):
s.append(sol)
if display:
sol["c"] = sol["a"] * sol["b"]
print(f"{sol['a']} x {sol['b']} = {sol['c']}")
if not display:
print(f"Found {len(s)} solutions")
|