Guest User

Untitled

a guest
Jan 23rd, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 4.21 KB | None | 0 0
  1. // main.d :
  2.  
  3.  
  4. import std.stdio, std.typecons, std.typetuple, std.format,
  5.   std.container, std.algorithm, std.range, std.array;
  6. import core.memory;
  7. import search;
  8.  
  9. auto genericAbs(T)(T a){ return a > 0 ? a : -a; }
  10.  
  11. struct State(int N)
  12. {
  13.   byte[N*N] state;
  14.   int estimate;
  15.  
  16.   auto dist(int a, int b)
  17.   {
  18.     int ai = a/N, aj = a%N;
  19.     int bi = b/N, bj = b%N;
  20.     return genericAbs(ai-bi) + genericAbs(aj-bj);
  21.   }
  22.  
  23.   void setEstimate()
  24.   {
  25.     auto n = 0;
  26.     foreach(int i,e;state)
  27.       if(e != N*N - 1)
  28.         n += dist(i,e);
  29.     estimate = n;
  30.   }
  31.  
  32.   struct Actions
  33.   {
  34.     struct  Param
  35.     {
  36.       State!N state;
  37.     }
  38.    
  39.     State!N _state;
  40.     int opApply( int delegate(ref Param) dg)
  41.     {
  42.       auto pos = countUntil(_state.state[],N*N-1);
  43.       auto i = pos / N, j = pos % N;
  44.       if(j-1>=0)
  45.       {
  46.         auto next = _state;
  47.         swap(next.state[pos],next.state[pos-1]);
  48.         next.setEstimate();
  49.         if(dg(Param(next)))
  50.           return true;
  51.       }
  52.       if(j+1<N)
  53.       {
  54.         auto next = _state;
  55.         swap(next.state[pos],next.state[pos+1]);
  56.         next.setEstimate();
  57.         if(dg(Param(next)))
  58.           return true;
  59.       }
  60.       if(i-1>=0)
  61.       {
  62.         auto next = _state;
  63.         swap(next.state[pos],next.state[pos-N]);
  64.         next.setEstimate();
  65.         if(dg(Param(next)))
  66.           return true;
  67.       }
  68.       if(i+1<N)
  69.       {
  70.         auto next = _state;
  71.         swap(next.state[pos],next.state[pos+N]);
  72.         next.setEstimate();
  73.         if(dg(Param(next)))
  74.           return true;
  75.       }
  76.       return false;
  77.     }
  78.   }
  79.  
  80.   @property auto actions() { return Actions(this); }
  81.  
  82.   string toString()
  83.   {
  84.     auto appender = appender!string();
  85.     foreach(i; 0..N)
  86.     {
  87.       foreach(j; 0..N)
  88.         formattedWrite(appender, "%.2d ", (state[i*N+j]+1)%(N*N));
  89.       formattedWrite(appender, "\n");
  90.     }
  91.     return appender.data;
  92.   }
  93. }
  94.  
  95. void main()
  96. {
  97.   GC.disable();
  98.   enum N = 4;
  99.   State!N state;
  100.   fill(state.state[],map!q{cast(byte)a}(iota(N*N-1,-1,-1)));
  101.   state.setEstimate();
  102.    
  103.   auto r = searchGraph!q{a.estimate==0}(state);
  104.  
  105.   writeln(r.states.front);
  106.  
  107.   foreach(e; r.states[])
  108.     writeln(e);
  109.   writeln(count(r.states[]));
  110. }
  111.  
  112. // search.d :
  113.  
  114. module search;
  115.  
  116. import std.container, std.stdio, std.functional, std.traits;
  117. import util;
  118.  
  119. auto estimate(T)(T t)
  120. {
  121.   static if(hasMember!(T,"estimate"))
  122.     return t.estimate;
  123.   else
  124.     return 0;
  125. }
  126.  
  127. auto distance(T)(T t)
  128. {
  129.   static if(hasMember!(T,"distance"))
  130.     return t.distance;
  131.   else
  132.     return 1;
  133. }
  134.  
  135. auto searchGraph(alias isGoal, State)(State start)
  136. {
  137.   alias typeof(estimate(State.init) +  distance(ForeachType!(typeof(State.actions)).init)) Length;
  138.  
  139.   struct Path
  140.   {
  141.     SList!State states;
  142.     Length length;
  143.     Length rank;
  144.   }
  145.  
  146.   auto frontier = GrowableHeap!(Path,q{a.rank > b.rank})(1);
  147.   int[State] explored;
  148.  
  149.   frontier.insert(Path(SList!State([start]),0,estimate(start)));
  150.  
  151.   while(!frontier.empty)
  152.   {
  153.     auto best = frontier.front;
  154.    
  155.     if(unaryFun!isGoal(best.states.front))
  156.       return  best;
  157.    
  158.     frontier.removeFront();
  159.     if(best.states.front in explored)
  160.       continue;
  161.     explored[best.states.front] = 0;
  162.    
  163.     foreach(e; best.states.front.actions)
  164.       if(!(e.state in explored))
  165.       {
  166.         auto newlen = best.length + distance(e);
  167.         frontier.insert( Path(cons(e.state, best.states),
  168.           newlen,
  169.           newlen + estimate(e.state)));
  170.       }
  171.   }
  172.   return Path.init;
  173. }
  174.  
  175. // util.d :
  176.  
  177.  
  178. module util;
  179.  
  180. import std.container, std.functional, std.traits;
  181.  
  182. auto cons(T)(T head, SList!T tail)
  183. {
  184.   tail.insertFront(head);
  185.   return tail;
  186. }
  187.  
  188.  
  189. // bugs prevent growable std.container.BinaryHeap from working so we need this
  190. struct GrowableHeap(T, alias f)
  191. {
  192.   BinaryHeap!(T[],f) heap;
  193.   T[] store;
  194.   alias heap this;
  195.   this(int n)
  196.   {
  197.     assert(n > 0);
  198.     store = new T[n];
  199.     heap = BinaryHeap!(T[],f)(store, 0);
  200.   }
  201.   void insert(T val)
  202.   {
  203.     if(heap.length == store.length)
  204.     {
  205.       auto n = store.length;
  206.       store.length = 2*n;
  207.       heap = BinaryHeap!(T[],f)(store,n);
  208.     }
  209.     heap.insert(val);
  210.   }
  211. }
Add Comment
Please, Sign In to add comment