Question

15 puzzle and A-Star

Asked by: jiminika

I heard that A-Star can be used to solve 15 Puzzle. Can anyone show me how to do this in details!?

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2001-07-14 at 00:45:27ID20150586
Tags

puzzle

,

15

,

star

Topic

Physics & Artificial Intelligence in Game Programming

Participating Experts
4
Points
200
Comments
13

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. Unable to use energy star functions
    Hello, Here is my unsolved problem: I have just changed my monitor and my display card. My new monitor is energy star compliant.(Hitachi CM630ET) (more precisely it meets the EPA Energy Star VESA DPMS standar and NUTEK specification) The display Card is a number 9 3D revolu...
  2. STAR Queries
    We have a multidimensional database but Oracle never seems to use the STAR query method. I always have to put the hint in. I analyzed all the tables. Is there some way I can steer the optimizer in choosing the STAR query method? We use third party tools to run the queries tha...
  3. Most elegant solution for creating a star
    I'm sure lots of people have been required to write the "star" program (i.e. you give it a number, and it creates a star whose width is <number> , like this: star 3 * * * * * * * * * (of course, the stars won't line up in a proportional font - copy th...
  4. solving tetravex puzzle
    I need program/algorithm/article to solve tetravex puzzle fast. the tetravex dimension is about 15x15. I'm thinking of using A* but, I cannot find good heuristic function for it...
  5. Cube Puzzle solver
    I have a cube puzzle, where there are 8 wooden blocks, each with a coloured ring on each face, making up a large cube, inside an open-topped clear plastic container. The puzzle is solved by getting all of the same colour on every side of the large cube. There are 6 colours, o...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: fl0ydPosted on 2001-10-04 at 12:55:10ID: 6528639

Hi jiminika,

this question is surely worth the 200 points. To answer your question right away: A* *CAN* be used to solve the 15 puzzle. However it might not be the best approach; I'll get to that in a minute.

As this is going to become a bit lengthy let me offer you a table of contents so you don't get lost:
1. Breaking down the problem
2. Dijkstra's algorithm
3. Dijkstra + knowledge -> A*
4. Can you picture this?

All code priveded is optimized for readablity only.


1. Breaking down the problem:

As with all problems you'd like to present to a computer you will have to transform it, so that a machine can 'understand' it. Thus transformation usually means abstraction of the nature of the problem.
Let's go back to the 15 puzzle. There are 4 pieces of information to describe the entire problem. A set of states (S), a set of transitions (T) to move from one state to another, a start state (start), and a goal state (goal).
Set of states (S): this is a machine-readable description of all possible constellations of the puzzle. I'd suggest using a 4x4 array
char tile[16];
to describe the layout, where tile[0] is the top left corner, tile[3] the top right corner, tile[15] the bottom right corner. Fill this array with the respective number of the tile and mark the empty spot with a '0'. This way you have just created the start state (start). Your goal state (goal) is {1, 2, 3, ..., 14, 15, 0}.
Set of transitions (T): this refers to sliding pieces on the board to get from one layout to another. For any state of the puzzle this can be 2, 3, or 4 legal moves (2 at corners, 3 on edges, and 4 on the interior). We'll use
char dir;
for transitions and declare the directions as follows:
right: 00000001b (1)
top: 00000010b (2)
left: 00000100b (4)
bottom: 00001000b (8)
Information on which tile is to be moved can be gathered from the direction code (d) and the current state (cs). Let's say d == 4 (left) and cs = { 0, .... } then the 2nd tile (tile[1]) is to be moved.
Let's take a step back and see what we have so far: We know WHAT the puzzle looks like (start), we know WHERE we are headed (goal), and we know HOW to walk (set of transitions T). Still with me? Good!

2. Dijkstra's algorithm

With all the WHAT, WHERE, and HOW we still don't know WHICH step at any give puzzle state will get us closer to our goal. There aren't many means to choose from when there is nothing to decide upon, so let's face it: a situation like this calls for brute force. Beginnig with the start state we do the following:
a.) set cs = start
b.) if( cs == goal ) return GOAL_REACHED;
c.) for each legal direction set cs = transform( cs, dir ) and goto b.)
[transform( const char[16]& state, const char dir ) returns new puzzle state after sliding the appropriate tile into the specified direction]
Simplified - and not quite accurate, I admit - this is Dijkstra's algorithm: Check for ALL possibilities until we reach the goal. Cool! We've reached the goal then? Technically speaking, yes, cs == goal. From a human perspective, though, the interest is more towards 'can you tell me how?'. Damn, we forgot the housekeeping. We need some structure to hold information on where we came from.
struct node {
    char tile_state[16];
    char dir_parent;
};
And we need some means to 'remember' where a possible parent of a parent came from. What about some sort of long term memory that stores all puzzle states we've examined so far? Let's just call it closed (as in 'closed for examination'):
#include <list>
std::list<node> closed;
Let's refine the algorithm above:
a.) node n = {start, 0};
b.) if( n.tile_state == goal ) return solution;
c.) for each legal dir { open.push_back( n ); n.tile_state = transform( n.tile_state, dir ); n.dir_parent = rev_dir( dir ); goto b.); }
Now we have all the information to construct a solution. Starting at goal, we check for equality with start. If not, we retrieve node n from closed, where n.tile_state == cs, and append n.dir_parent to our solution list, ... The list is still doubly inverted. All we have to do is to change the order from back to front and reverse each direction. Voila - here it is.
Well, possibly, but not necessarily. We did not take any precautions to avoid ending up in an endless loop (i.e. moving a tile to the left and moving it to the right again, then left, right, left, right, ...) And possibly we could use the little information we have gathered on our way to speed up calculation. Let's redesign our node structure:
class node {
    char tile_state[16];
    char dir_parent;
    int move_count;
};
move_count is set to 0 for the start node and increased by 1 for each expansion. We'll also be using a short term memory list that holds all nodes open for examination and call it open. Before expanding a node the open list is sorted in ascending order, so we'll expand all nodes whose tile_state can be reached with one move, then those, that can be reached in two moves, and so on.
To finish this section, here is the more complete algorithm in pseudo-code:
a.) node n = { s, 0, 0 }; open.push_back( n );
b.) if( 0 == open.size() ) return FAILED;  // no solution!
c.) open.sort( ASCENDING ); n = open.front(); open.pop_front();
d.) if( n.tile_state == goal ) return solution;
e.) closed.push_back( n );
f.) for( char d = 1; d <=8; d << 1 ) {
        if( legal_move( n.tile_state, d ) ) {
            node n_new = transform( n.tile_state, d );
            if( !closed.find( n_new ) && !open.find( n_new ) ) {
                open.push_back( n_new );
            }
        }
    }
g.) goto b.)

Enough for today, my girlfriend needs attention...
The rest will follow tomorrow.

regards,
.:fl0yd:.

 

by: fl0ydPosted on 2001-10-05 at 15:27:41ID: 6531994

What a night...

Anyway, let's go over what we have so far. With Dijkstra's algorithm we have a - computationally expensive - method to solve problems given a search space (S, T), a start state (start), and the goal state (goal). Btw. this algorithm can be applied to any problem that can be abstracted to search space, start, and goal. Now why is this approach so computationally expensive? Because the algorithm applied is basically dumb, i.e. it doesn't use any means to decide, which transition seems to be the most promising one to take at any given puzzle state.

3. Dijkstra + knowledge -> A*:

To reduce the effort necessary to find a solution we will have to find some means to favor one transition over another at a given state. For the 15 puzzle there is no actual information to gain from looking at the layout, as far as I can see. So we will have to guess which one of any two given states is closer to our goal. Let's call additional information on a problem 'heuristic' (h). One thing we can be sure about the 15 puzzle is, that if
h = number of tiles at wrong locations
we will need at least h moves (at least 1 move for each incorrect tile) to reach the goal. How can we use this information to reduce the amount of searching necessary to find a solution? Let's go back to Dijkstra's algorithm. Instead of sorting our open list with respect to the number of moves taken so far, let's take our estimate on the 'distance' from the goal into account. While Dijkstra's sorting predicate is
f = g (g = costs so far)
we'll use costs + estimate
f = g + h
and call this 'new' algorithm A*. So the difference between Dijkstra's algorithm and A* is, that Dijkstra is searching indifferent in all possible directions whereas A* is searching in favor of those directions, that are presumably closer to the goal. Bare in mind though that our presumtions are based on guessing only.

3.1. Small guess-ology:

It appears to be logical that A* will find a solution faster than Dijkstra if our presumtions are all correct. But what happens if not? What if only some of them are wrong? Let's discover the different degrees of, hmm, wrongness? wrongity? anyone? If our estimated distance is wrong it can be either too large or too small. Overestimating is dangerous in that we may be skipping potential solutions. Understimating is not only harmless, but essential to ensure that the returned solution requires the least number of transitions to be reached.

3.2. It's all in the heuristics:

Let's check the heuristic above against this. It is obvious that if n tiles are in wrong locations it takes n moves at best to reach the solution. Since A* uses the heuristic as a decisive means to cut down computational effort, the heuristic's quality is the key component to success. If it comes close to the actual effort it unleashes A*'s power. In fact, if every guess is correct, i.e. we have a perfect heuristic, A*'s very first try at the puzzle will return the best possible solution. However, our heuristic only returns values in the range of [0..15] and becomes somwhat void after about 100 moves. In the introduction I said that 'it might not be the best approach'. There is some computational overhead involved in calculating the heuristic. In our case this might not really matter, however, if our chosen heuristic is very poor, A* can become even more timeconsuming than Dijkstra! In other words: While Dijkstra will find the best solution, A*'s heuristic is in charge of the time spent to discover it.

So what do we have now? In section 1 we found a way to present the problem in a machine-readable form. Section 2 introduced a method to blindly search for a solution. In section 3 we discovered a possibility to bring orientation into the darkness. 'Yeah, I know, but this is all theoretical. Don't you have a more specific explanation, a more visual one?' I hear you ask.

4. Can you picture this?:

Well, no. The 1-dimensionality of the 15 puzzle seems to be ungraspable for my mind. If you don't mind, let's leave this problem behind and look at something different. Pretend we're implementing pathfinding strategies for a tile-based RTS-game. The search space is defined by our grid consisting of w * h tiles. In this case the open list can be depicted as the outer border of all tiles that have been examined in search of a solution. The closed list contains all tiles 'inside' the open list. When applying Dijkstra's algorithm to find the shortest path from A to B, the search radius will extend in a circular fashion around A (if we allow diagonal moves, otherwise it would be a square) until the border touches B. Thus the open list forms a circle, and closed contains everything inside forming a disc. A*'s search pattern is more irregular and extends more towards the presumably best path. If we have a perfect heuristic the closed list will be nothing but a single line containing the path with the open list surrounding it. In a worst case scenario though, after an A*-search has completed, the closed list can contain all positions, but the goal B, which would be the last one in the open list. I hope this can help to clarify why an A* equipped with a bad - even though correctly underestimating - heuristic can perform worse than Dijkstra.

This is it. For now. Give me a day and I'll come up with some code. If anyone cares about, let me know and I'll mail it to you. I'd like to post it here, but without a fixed-font (and possibly syntax highlighting) it doesn't really turn out readable. If you have questions, insults, comments, ... let me know.

regards,
.:fl0yd:.



------------------------------------------------------------------------------------
errata (guess noone is perfect, oh well...):

c.) for each legal dir { open.push_back( n ); n.tile_state = transform( n.tile_state, dir ); n.dir_parent
= rev_dir( dir ); goto b.); }

should be:

c.) closed.push_back( n );
    ++n.move_count;
    for each legal dir {
        n.tile_state = transform( n.tile_state, dir );
        if( !closed.find( n ) ) {        // == if not already visited
            n.dir_parent = rev_dir( dir );
            goto b.)
        }
    }
    return FAILED;        // no solution


f.) for( char d = 1; d <=8; d << 1 ) {
       if( legal_move( n.tile_state, d ) ) {
           node n_new = transform( n.tile_state, d );
           if( !closed.find( n_new ) && !open.find( n_new ) ) {
               open.push_back( n_new );
           }
       }
   }

should be:

f.) ++n.move_count;
    for( char d = 1; d <= 8; d << 1 ) {
        if( legal_move( n.tile_state, d ) ) {
            node node_new( transform( n.tile_state, d ), rev_dir( d ), n.move_count );
            if( !closed.find( n_new ) )        // not visited yet
                if( !open.find( n_new ) )        // and not already in examination queue
                    open.push_back( n_new );
                else        // if already in examination queue
                    if( *open.find( n_new ).move_count > n_new.move_count )
                        *open.find( n_new ) = n_new;    // if faster to reach replace it
        }
    }



disclaimer: no animals were harmed during the course this production

 

by: fl0ydPosted on 2001-10-07 at 08:37:23ID: 6534328

Not quite done benchmarking yet. However for the special case of start_state =
[[  0,  1,  2,  3]
 [  6,  7,  8,  4]
 [  5,  9, 10, 11]
 [ 13, 14, 15, 12]]
Dijkstra's algorithm will find the 12-move solution in about 8 minutes, while A* will do it in less than a second!!!

Just in case: The solution is: left, left, left, up, right, right, right, up, left, left, left, up.

.:fl0yd:.

p.s.: updates will follow, as soon as i implemented the rest of the benchmarking stuff.

 

by: yairyPosted on 2001-10-14 at 23:12:33ID: 6540228

Here is the code I wrote when I was a 1'st degree student
in AI course, It implements A* on 8-puzzle...
The puzzle is represented by a LONG type 9 digits number.

As the code is self documented,
Ask me please any question.

Compiles welll on VC6...


#include <math.h>
#include <iostream.h>
#define MaxSize 10000
#define NumberOfPuzzles 100

long InitialStates[NumberOfPuzzles]={
       396842751      ,241867539      ,139674825      ,194785263      ,657438291
      ,697234518      ,178943562      ,642513879      ,319267548      ,197485236
      ,398642157      ,261753489      ,632174859      ,236759814      ,891527463
      ,463827519      ,853172649      ,283916547      ,538726491      ,756219834
      ,798562314      ,138476925      ,692384175      ,189276354      ,793148256
      ,861327954      ,287359461      ,426583197      ,231596478      ,652871349
      ,253476198      ,724368591      ,394615872      ,592138674      ,218753649
      ,784691235      ,964712358      ,854639271      ,957841623      ,431782659
      ,987246513      ,985741623      ,916845237      ,295176384      ,741962538
      ,954361827      ,236148957      ,675491238      ,397651248      ,873145269
      ,197634825      ,178345296      ,672594138      ,378294561      ,934867512
      ,593468217      ,147623985      ,394865721      ,534897621      ,928173456
      ,657482139      ,256794138      ,324981756      ,274169583      ,761928543
      ,271693485      ,276958431      ,251837694      ,857296341      ,642193785
      ,945278631      ,674529381      ,156347829      ,584291763      ,356872149
      ,851372649      ,392185467      ,342859176      ,586429713      ,597463281
      ,296437185      ,239518647      ,263518479      ,642318957      ,127435986
      ,941823567      ,124369875      ,147586329      ,938264175      ,735689241
      ,431675892      ,213698475      ,625187439      ,978124563      ,648293175
      ,379265841      ,359487261      ,973182546      ,584327169      ,793256418
};


class node
{
public:
      long puzzle;
      int val;
      bool WasOpened;
      int TreeLevel;
};


class puzzle
{
      int WhereIsDigitInNum(int,long);
      node list[MaxSize];
      int ListIndex, CurrentTreeLevel;
      long original, goal;
      int MDistance(long,long);
      void ReturnSons(long,long&,long&,long&,long&);
      long swap(long, int, int);
      void SolvePuzzle();
      void InsertToList(long,long,long,long);
      long FindBest();
      //int LinerConflict(long);
public:
      puzzle();
};


puzzle::puzzle()
{
      int i;
      float AvPath=0, AvListIndex=0;
      
      goal=123456789;

      for (i=0; i<NumberOfPuzzles; i++)
      {
            ListIndex=0;
            CurrentTreeLevel=-1;                        // first level is zero...

            original=InitialStates[i];
            cout << "Puzzle: " << i+1 << '\t';
            SolvePuzzle();

            AvPath+=CurrentTreeLevel;
            AvListIndex+=ListIndex;
      }

      AvPath/=NumberOfPuzzles;
      AvListIndex/=NumberOfPuzzles;

      cout << endl << "Average path: " << AvPath << endl;
      cout << "Average Num of Nodes: " << AvListIndex << endl;
}


void puzzle::SolvePuzzle()
{
      long CurrentNum,s1,s2,s3,s4;
      CurrentNum=original;

      InsertToList(CurrentNum,0,0,0);

      while (CurrentNum!=goal && ListIndex<MaxSize-4)
      {
            CurrentNum=FindBest();
            ReturnSons(CurrentNum, s1, s2, s3, s4);
            InsertToList(s1, s2, s3, s4);
      }

      if (CurrentNum!=goal)
            cout << "Fail" << endl;
      else
            cout << "Success" << '\t';

      cout << ListIndex << '\t';
      cout << CurrentTreeLevel << endl;
}


long puzzle::FindBest()
{
      int min, i, j, mini;
      bool found=false;
      // set the first minimal value
      for (i=0; i<ListIndex && !found; i++)
            if (list[i].WasOpened==false)
            {
                  found=true;
                  min=list[i].val;
                  mini=i;
            }
      
      // search the most minimal value
      for (j=i; j<ListIndex; j++)
            if ((list[j].val<=min) && (list[j].WasOpened==false))
            {
                  min=list[j].val;
                  mini=j;
            }

      list[mini].WasOpened=true;
      CurrentTreeLevel=list[mini].TreeLevel;
      
      return list[mini].puzzle;
}


void puzzle::InsertToList(long a,long b,long c,long d)
{
      long arr[4];
      int index=0, i;
      bool found;

      if (a)
      {
            arr[index]=a;
            index++;
      }
      if (b)
      {
            arr[index]=b;
            index++;
      }
      if (c)
      {
            arr[index]=c;
            index++;
      }
      if (d)
      {
            arr[index]=d;
            index++;
      }

      index--;
      while (index>=0)
      {
            found=false;
            for (i=0; i<ListIndex && !found; i++)
                  if (arr[index]==list[i].puzzle)
                        found=true;

            // if not found OR found with better Mdistance.
            if ((found && CurrentTreeLevel+1+MDistance(arr[index],goal)<list[i-1].val) || (!found))
            {
                  list[ListIndex].puzzle=arr[index];
                  list[ListIndex].WasOpened=false;
                  list[ListIndex].TreeLevel=CurrentTreeLevel+1;
                  list[ListIndex].val=list[ListIndex].TreeLevel+MDistance(arr[index],goal);
                  ListIndex++;
            }
            index--;
      }
}


long puzzle::swap(long num,int a, int b)
{
      long v[10];
      int i, temp;

      for (i=9; i>=1; i--)
      {
            v[i]=num%10;
            num/=10;
      }

      temp=v[a];
      v[a]=v[b];
      v[b]=temp;

      num=0;
      for (i=1; i<=9; i++)
      {
            num*=10;
            num+=v[i];
      }

      return num;
}


int puzzle::WhereIsDigitInNum(int digit,long num)
{
      bool found=false;
      int DigitFromNum, pos=9;

      while (!found && num)
      {
            DigitFromNum=num%10;
            if (digit==DigitFromNum)
                  found=true;
            else
            {
                  pos--;
                  num/=10;
            }
      }

      return pos;
}


void puzzle::ReturnSons(long num,long& sr,long& sl,long& su,long& sd)
{
      int SpacePos;
      SpacePos=WhereIsDigitInNum(1,num);

      // shift with right
      if (SpacePos%3==0)
            sr=0;
      else
            sr=swap(num,SpacePos,SpacePos+1);

      // shift with left
      if (SpacePos%3==1)
            sl=0;
      else
            sl=swap(num,SpacePos,SpacePos-1);

      // shift with upper
      if (SpacePos<4)
            su=0;
      else
            su=swap(num,SpacePos,SpacePos-3);

      // shift with lower
      if (SpacePos>6)
            sd=0;
      else
            sd=swap(num,SpacePos,SpacePos+3);
}


int puzzle::MDistance(long org, long tar)
{
      int i,MSum=0,OrgPos,TarPos,OrgRow,TarRow,OrgLine,TarLine;
      for (i=2; i<=9; i++)
      {
            OrgPos=WhereIsDigitInNum(i,org);
            TarPos=WhereIsDigitInNum(i,tar);
            OrgLine=(OrgPos-1)/3;
            TarLine=(TarPos-1)/3;

            OrgRow=OrgPos%3;
            if (OrgRow==0)
                  OrgRow=3;

            TarRow=TarPos%3;
            if (TarRow==0)
                  TarRow=3;

            MSum+=abs(OrgLine-TarLine)+abs(OrgRow-TarRow);
      }

      //MSum+=LinerConflict(org);
      return MSum;
}

/*
int puzzle::LinerConflict(long puzzle)
{
      int OrgPos,NextPos,OrgRow,NextRow,OrgLine,NextLine,DownPos,DownLine, DownRow,i,r=0;
      for (i=2; i<=8; i++)
      {
            OrgPos=WhereIsDigitInNum(i,puzzle);
            NextPos=WhereIsDigitInNum(i+1,puzzle);
            OrgLine=(OrgPos-1)/3;
            NextLine=(NextPos-1)/3;

            OrgRow=OrgPos%3;
            if (OrgRow==0)
                  OrgRow=3;

            NextRow=NextPos%3;
            if (NextRow==0)
                  NextRow=3;

            if ((OrgLine==NextLine) && (OrgRow-NextRow==1))
                  r+=2;

            if (i<=6)
            {
                  DownPos=WhereIsDigitInNum(i+3,puzzle);
                  DownLine=(DownPos-1)/3;
                  
                  DownRow=DownPos%3;
                  if (DownRow==0)
                        DownRow=3;

                  if ((OrgRow==DownRow) && (OrgLine-DownLine==1))
                        r+=2;
            }

            
      }
      return r;
}
*/

void main()
{
      puzzle p;
}







 

by: fl0ydPosted on 2001-10-16 at 00:50:23ID: 6541992

Thanks a heap for NOT responding to my post at all. Since there was no feedback whatsoever I won't post any results nor will I share my src -- btw, it's way more structured and speed optimized than yairy's "1'st degree student in AI course"-implementation, with tons of information I gathered when working in the gaming industry. Too bad...
Yairy, you don't talk about your heuristic - the heart and soul of any A*-implementation. Looks like you're using the sum of all tile-distances to their respective goal-positions. However, this will only speed up the last portion of the search and MAY significantly slow down search in more complex situations.

somewhat disappointed,
.:fl0yd:.

ps: I don't believe that posting src-code without any explanation is helpful. It certainly doesn't do justice to "Can anyone show me how to do this in details".

 

by: yairyPosted on 2001-10-23 at 05:25:02ID: 6564914

dear fl0yd,

Don't be mad at me.
I am only tring to help.
I read your answer and agree with most of it.

I think you expanded the subject far too long.

I didn't attached a document cause I wanted to filter
fox that just know to cut and paste.

I still think is a good program.
I used Manhatten-distance (total sum of distnces) to evalute f().
It a good heuristic, not perfect.
but it apply the rules and very fast to calculate.
Maybe it can be even updated instead of re-calculating from father to sons.

I'll be very interested to hear how you "speed optimized"
the algorithm.

I'll give you half the points too.

Yair

 

by: fl0ydPosted on 2001-10-31 at 04:29:26ID: 6604034

 

by: fl0ydPosted on 2001-11-04 at 11:46:37ID: 6617424

ahhhh, crappy internet connections at our university pool, didn't mean to say nothing :(

yairy,
sorry, I got a little carried away. I hope I didn't insult you, I just felt that posting uncommented src isn't too helpful. I'll have to stick to my principles though and won't post any of my own src. However, I can point you in the right direction. First of all, using long's might seem reasonable at first sight, however, I used a char[16] instead. Could have packed 2 tiles into one byte and used char[8] with a bit of overhead for access. Using long's has two backdraws: a.) if you use base 10 for encoding you won't make life easy from a computer's point of view - try using base 2 whenever possible. b.) it's dangerous, as you cannot make any assumptions on the size. long's could very well be 1 byte long and still comply with the ANSI standard. [sizeof( char ) <= sizeof( long )].
Btw. you're solving an 8-puzzle, not a 15-puzzle...
As far as speed is concerned your LinerConflict and MDistance make excessive use of '/' and '%', both are computationally expensive, with '%' being even worse than '/'. If you want speed, get rid of those first.
you say that manhatten distance is a good heuristic. Like I said in my previous (non-empty) post, it only speeds up the last portion of the search, but tends to slow down the rest of it in complex situations.

Hope that helps, bare with me, sorry, again,
.:fl0yd:.

 

by: techpagePosted on 2001-11-27 at 05:14:18ID: 6655044

hi, all, can i talk with you guys? i'm kinda lost in a star algorithm, i've been studying pathfinding algorithm from bryan stout's tutorial, i've tried to imitate his program in msvc++ but i'm wholly stuck in best-first search, and the a* algorithm, well... my dijkstra's algorithm runs in a bit different manner than his'... i guess, there's something wrong with the cost function (for dijkstra) and the heuristic estimate (for a* algo)... can you help me out guys? can we get in contact? my email is copet@lycos.com

thanks guys

 

by: yairyPosted on 2001-11-27 at 05:39:01ID: 6655104

Please write your questions here, I am sure fl0yd and I
will be happy to give a hand....




 

by: fl0ydPosted on 2001-11-29 at 07:20:39ID: 6659286

true. this is a forum to exchange knowledge. now what would happen if we all just posted our email-addresses? it would turn into an email-directory...

 

by: cbn20Posted on 2008-05-15 at 12:30:24ID: 21577186

does "fl0yd and yairy still exist is the forum?

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...