2017-10-17 13:08:10 +02:00
|
|
|
// Copyright 2010-2017 Google
|
2010-09-15 12:42:33 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
2014-07-09 15:18:27 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
//
|
|
|
|
|
// Cryptoarithmetics problem
|
|
|
|
|
//
|
|
|
|
|
// Solves equation SEND + MORE = MONEY among numbers
|
|
|
|
|
// where each digit is represented by a letter.
|
|
|
|
|
//
|
|
|
|
|
// Solution:
|
|
|
|
|
// S=9; M=1; O=0; E=5; N=6; D=7; R=8; Y=2.
|
|
|
|
|
|
2017-04-26 17:30:25 +02:00
|
|
|
#include "ortools/base/commandlineflags.h"
|
|
|
|
|
#include "ortools/base/logging.h"
|
|
|
|
|
#include "ortools/constraint_solver/constraint_solver.h"
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
namespace operations_research {
|
|
|
|
|
|
|
|
|
|
void Cryptoarithmetics() {
|
2010-10-06 16:04:31 +00:00
|
|
|
Solver solver("cryptarithm");
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
// model with carry
|
2010-10-06 16:04:31 +00:00
|
|
|
IntVar* s = solver.MakeIntVar(1, 9, "s");
|
|
|
|
|
IntVar* m = solver.MakeIntVar(1, 9, "m");
|
|
|
|
|
IntVar* o = solver.MakeIntVar(0, 9, "o");
|
|
|
|
|
IntVar* e = solver.MakeIntVar(0, 9, "e");
|
|
|
|
|
IntVar* n = solver.MakeIntVar(0, 9, "n");
|
|
|
|
|
IntVar* d = solver.MakeIntVar(0, 9, "d");
|
|
|
|
|
IntVar* r = solver.MakeIntVar(0, 9, "r");
|
|
|
|
|
IntVar* y = solver.MakeIntVar(0, 9, "y");
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2011-05-17 20:38:55 +00:00
|
|
|
std::vector<IntVar*> letters;
|
2010-09-15 12:42:33 +00:00
|
|
|
letters.push_back(s);
|
|
|
|
|
letters.push_back(m);
|
|
|
|
|
letters.push_back(o);
|
|
|
|
|
letters.push_back(e);
|
|
|
|
|
letters.push_back(n);
|
|
|
|
|
letters.push_back(d);
|
|
|
|
|
letters.push_back(r);
|
|
|
|
|
letters.push_back(y);
|
|
|
|
|
|
2012-01-16 11:03:56 +00:00
|
|
|
solver.AddConstraint(solver.MakeAllDifferent(letters));
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
// carry variables
|
2010-10-06 16:04:31 +00:00
|
|
|
IntVar* c1 = solver.MakeIntVar(0, 1, "c1");
|
|
|
|
|
IntVar* c2 = solver.MakeIntVar(0, 1, "c2");
|
|
|
|
|
IntVar* c3 = solver.MakeIntVar(0, 1, "c3");
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
// initial constraint is separated into four small constraints
|
2010-10-06 16:04:31 +00:00
|
|
|
IntVar* v1 = solver.MakeSum(e, d)->Var();
|
|
|
|
|
IntVar* v2 = solver.MakeSum(y, solver.MakeProd(c1, 10))->Var();
|
|
|
|
|
solver.AddConstraint(solver.MakeEquality(v1, v2));
|
|
|
|
|
|
|
|
|
|
v1 = solver.MakeSum(solver.MakeSum(c1, n), r)->Var();
|
|
|
|
|
v2 = solver.MakeSum(e, solver.MakeProd(c2, 10))->Var();
|
|
|
|
|
solver.AddConstraint(solver.MakeEquality(v1, v2));
|
|
|
|
|
|
|
|
|
|
v1 = solver.MakeSum(solver.MakeSum(c2, e), o)->Var();
|
|
|
|
|
v2 = solver.MakeSum(n, solver.MakeProd(c3, 10))->Var();
|
|
|
|
|
solver.AddConstraint(solver.MakeEquality(v1, v2));
|
|
|
|
|
|
|
|
|
|
v1 = solver.MakeSum(solver.MakeSum(c3, s), m)->Var();
|
|
|
|
|
v2 = solver.MakeSum(o, solver.MakeProd(m, 10))->Var();
|
|
|
|
|
solver.AddConstraint(solver.MakeEquality(v1, v2));
|
|
|
|
|
|
2014-01-08 12:01:58 +00:00
|
|
|
DecisionBuilder* const db = solver.MakePhase(
|
|
|
|
|
letters, Solver::CHOOSE_FIRST_UNBOUND, Solver::ASSIGN_MIN_VALUE);
|
2010-10-06 16:04:31 +00:00
|
|
|
solver.NewSearch(db);
|
|
|
|
|
if (solver.NextSolution()) {
|
2010-09-15 12:42:33 +00:00
|
|
|
CHECK_EQ(s->Value(), 9);
|
|
|
|
|
CHECK_EQ(m->Value(), 1);
|
|
|
|
|
CHECK_EQ(o->Value(), 0);
|
|
|
|
|
CHECK_EQ(e->Value(), 5);
|
|
|
|
|
CHECK_EQ(n->Value(), 6);
|
|
|
|
|
CHECK_EQ(d->Value(), 7);
|
|
|
|
|
CHECK_EQ(r->Value(), 8);
|
|
|
|
|
CHECK_EQ(y->Value(), 2);
|
|
|
|
|
|
2013-06-11 14:51:23 +00:00
|
|
|
LOG(INFO) << "S=" << s->Value();
|
|
|
|
|
LOG(INFO) << "M=" << m->Value();
|
|
|
|
|
LOG(INFO) << "O=" << o->Value();
|
|
|
|
|
LOG(INFO) << "E=" << e->Value();
|
|
|
|
|
LOG(INFO) << "N=" << n->Value();
|
|
|
|
|
LOG(INFO) << "D=" << d->Value();
|
|
|
|
|
LOG(INFO) << "R=" << r->Value();
|
|
|
|
|
LOG(INFO) << "Y=" << y->Value();
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
2013-06-11 14:51:23 +00:00
|
|
|
LOG(INFO) << "Cannot solve problem: number of failures "
|
|
|
|
|
<< solver.failures();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2010-10-06 16:04:31 +00:00
|
|
|
solver.EndSearch();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2014-01-08 12:01:58 +00:00
|
|
|
} // namespace operations_research
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2014-01-08 12:01:58 +00:00
|
|
|
int main(int argc, char** argv) {
|
2018-06-08 16:40:43 +02:00
|
|
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
2010-09-15 12:42:33 +00:00
|
|
|
operations_research::Cryptoarithmetics();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|