Knight-Path 1.0.D018

/home/archives/knight-path/branch.1/branch.0/delta5682.018/knight-path/solver/brute_force.cc

Go to the documentation of this file.
00001 //
00002 // knight-path - shortest knight path between two squares
00003 // Copyright (C) 2011 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 3 of the License, or (at
00008 // your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License along
00016 // with this program. If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #include <algorithm>
00020 
00021 #include <knight-path/solver/brute_force.h>
00022 
00023 
00024 solver_brute_force::~solver_brute_force()
00025 {
00026 }
00027 
00028 
00029 solver_brute_force::solver_brute_force()
00030 {
00031 }
00032 
00033 
00034 solver::pointer
00035 solver_brute_force::create(void)
00036 {
00037     return pointer(new solver_brute_force());
00038 }
00039 
00040 
00041 solver::list_t
00042 solver_brute_force::solve(const position &from, const position &to)
00043 {
00044     shortest_solution.clear();
00045     list_t path;
00046     // By including the "from" position in the path, we can eliminate
00047     // backtracking to there.
00048     path.push_back(from);
00049     ply(from, to, path);
00050 
00051     // Must be a list of positions through which the Knight passes.
00052     // This must include the ending position, but exclude the starting
00053     // position.
00054     list_t result = shortest_solution;
00055     shortest_solution.clear();
00056     if (result.size() > 1)
00057         result.pop_front();
00058     return result;
00059 }
00060 
00061 
00062 void
00063 solver_brute_force::ply(const position &from, const position &to,
00064     const list_t &progress)
00065 {
00066     // See if we have arrived at the destination.
00067     if (from == to)
00068     {
00069         if
00070         (
00071             shortest_solution.empty()
00072         ||
00073             progress.size() < shortest_solution.size()
00074         )
00075         {
00076             shortest_solution = progress;
00077         }
00078         return;
00079     }
00080 
00081     // The longest possible path is six jumps
00082     // plus one for the start position.
00083     if (progress.size() > 6)
00084         return;
00085 
00086     //
00087     // Ask the position for a list of knight move positions
00088     // that can be reached from there.
00089     //
00090     position::list_t possibilities = from.knight_moves();
00091 
00092     // Try each of those possibilities.
00093     for
00094     (
00095         position::list_t::const_iterator it = possibilities.begin();
00096         it != possibilities.end();
00097         ++it
00098     )
00099     {
00100         // Don't revisit any position.
00101         if (std::find(progress.begin(), progress.end(), *it) == progress.end())
00102         {
00103             list_t one_longer(progress);
00104             one_longer.push_back(*it);
00105             ply(*it, to, one_longer);
00106         }
00107     }
00108 }