Advertisement
Guest User

DevQuiz2011jp - slidepuzzle

a guest
Sep 11th, 2011
306
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.92 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8.  
  9. struct _globals {
  10.     int LX; /* max Ls */
  11.     int RX; /* max Rs */
  12.     int UX; /* max Us */
  13.     int DX; /* max Ds */
  14.     int N;  /* number of pannels */
  15. } globals;
  16.  
  17. struct node {
  18.     int x;
  19.     int y;
  20.     char c;
  21.     int canl;
  22.     int canr;
  23.     int canu;
  24.     int cand;
  25.     int dist;
  26. };
  27.  
  28. struct pannel {
  29.     int x;
  30.     int y;
  31.     char *s;
  32.     char *sorted;
  33.     int md;
  34.     int round;
  35.     char move;
  36.     struct node *world;
  37.     int solved;
  38.     struct pannel *prev;
  39. };
  40.  
  41. struct taskque {
  42.     struct pannel *pannel;
  43.     struct taskque *prev;
  44.     struct taskque *next;
  45.     int depth;
  46. };
  47.  
  48. int manhattandistance(struct pannel *p, struct node *n)
  49. {
  50.     int i, len;
  51.     int posc = n->x + n->x*n->y;
  52.     int poss;
  53.     char *s = p->sorted;
  54.  
  55.     if (n->c == '=')
  56.         return 0;
  57.  
  58.     for (i=0, len=strlen(s) ; i<len ; i++, s++) {
  59.         if (n->c == *s) {
  60.             poss = i;
  61.             break;
  62.         }
  63.     }
  64.  
  65.     if (posc > poss) {
  66.         i = posc;
  67.         posc = poss;
  68.         poss = i;
  69.     }
  70.    
  71.     n->dist = poss - posc;
  72.     return n->dist;
  73. }
  74.  
  75. int md(struct pannel *pannel)
  76. {
  77.     int i, len = pannel->x * pannel->y;
  78.     struct node *n = pannel->world;
  79.  
  80.     pannel->md = 0;
  81.     for (i=0 ; i<len ; i++) {
  82.         pannel->md += manhattandistance(pannel, n++);
  83.     }
  84.  
  85.     return pannel->md;
  86. }
  87.  
  88. struct node *buildworld(struct pannel *pannel)
  89. {
  90.     struct node *world = (struct node *)
  91.         calloc(1, sizeof(struct node) * pannel->x * pannel->y);
  92.     struct node *n;
  93.     int x, y;
  94.     char *cp = pannel->s;
  95.  
  96.     if (!world) {
  97.         perror("buildworld");
  98.         exit(0);
  99.     }
  100.    
  101.     n = world;
  102.     for (y=0 ; y<pannel->y ; y++) {
  103.         for (x=0 ; x<pannel->x ; x++, n++) {
  104.             n->x = x;
  105.             n->y = y;
  106.             n->c = *cp++;
  107.             if (n->c != '=') {
  108.                 if (x != 0)
  109.                     n->canl = 1;
  110.                 if (x != pannel->x - 1)
  111.                     n->canr = 1;
  112.                 if (y != 0)
  113.                     n->canu = 1;
  114.                 if (y != pannel->y - 1)
  115.                     n->cand = 1;
  116.             }
  117.             n->dist = manhattandistance(pannel, n);
  118.             pannel->md += n->dist;
  119.         }
  120.     }
  121.  
  122.     n = world;
  123.     for (y=0 ; y<pannel->y ; y++) {
  124.         for (x=0 ; x<pannel->x ; x++, n++) {
  125.             if (n->c == '=') {
  126.                 if (x != pannel->x - 1)
  127.                     (n + 1)->canl = 0;
  128.                 if (x != 0)
  129.                     (n - 1)->canr = 0;
  130.                 if (y != pannel->y - 1)
  131.                     (n + pannel->x)->canu = 0;
  132.                 if (y != 0)
  133.                     (n - pannel->x)->cand = 0;
  134.             }
  135.         }
  136.     }
  137.  
  138.     pannel->world = world;
  139.     return world;
  140. }
  141.  
  142. void bubblesort(char *p)
  143. {
  144.     char *pp = p;
  145.     int len = strlen(p);
  146.     int i;
  147.     for (i=0 ; i<len-1 ; i++, p++) {
  148.         if (*p > *(p+1)) {
  149.             char c = *p;
  150.             *p = *(p+1);
  151.             *(p+1) = c;
  152.             bubblesort(pp);
  153.         }
  154.     }
  155. }
  156.  
  157. char *presort(char *src) {
  158.     int len = strlen(src);
  159.     int i;
  160.     char *dst = (char *)calloc(1, len + 1);
  161.     char *sorted = (char *)calloc(1, len + 1);
  162.     char *p, *q, *r;
  163.  
  164.     if (!dst || !sorted) {
  165.         perror("presort");
  166.         exit(0);
  167.     }
  168.    
  169.     for (i=0, p=dst, q=src ; i<len ; i++, q++) {
  170.         if (*q != '=' && *q != '0')
  171.             *p++ = *q;
  172.     }
  173.     bubblesort(dst);
  174.     for (i=0, p=dst, q=src, r=sorted ; i<len ; i++, q++) {
  175.         if (*q == '=')
  176.             *r++ = *q;
  177.         else if (*q != '0')
  178.             *r++ = *p++;
  179.     }
  180.     *r = '0';
  181.     free(dst);
  182.     return sorted;
  183. }
  184.  
  185. void freeapannel(struct pannel *p)
  186. {
  187.     if (p) {
  188.         if (p->world)
  189.             free(p->world);
  190.         free(p->s);
  191.         free(p->sorted);
  192.         free(p);
  193.     }
  194. }
  195.  
  196. void cleanup(struct taskque *root)
  197. {
  198.     struct taskque *q = root;
  199.    
  200.     while (q) {
  201.         struct taskque *next = q->next;
  202.         freeapannel(q->pannel);
  203.         free(q);
  204.         q = next;
  205.     }
  206. }
  207.  
  208. FILE *readglobal(char *name)
  209. {
  210.     FILE *f;
  211.     char buf[80];
  212.     f = fopen(name, "r");
  213.     fgets(buf, sizeof(buf), f);
  214.     sscanf(buf, "%d %d %d %d",
  215.            &globals.LX, &globals.RX, &globals.UX, &globals.DX);
  216.     fgets(buf, sizeof(buf), f);
  217.     sscanf(buf, "%d", &globals.N);
  218.     return f;
  219. }
  220.  
  221. struct pannel *readapannel(FILE *f)
  222. {
  223.     char buf[80]; /* max 6x6 -> 40 */
  224.     int len;
  225.     struct pannel *p;
  226.  
  227.     fgets(buf, sizeof(buf), f);
  228.     len = strlen(buf) - 4;
  229.  
  230.     p = (struct pannel *)calloc(1, sizeof(struct pannel));
  231.     if (!p) {
  232.         perror("readapannel");
  233.         exit(0);
  234.     }
  235.    
  236.     p->s = (char *)calloc(1, len + 1);
  237.     if (!p->s) {
  238.         perror("readapannel");
  239.         exit(0);
  240.     }
  241.    
  242.     sscanf(buf, "%d,%d,%s", &p->x, &p->y, p->s);
  243.     return p;
  244. }
  245.  
  246. struct node *findzero(struct pannel *p, struct node *world)
  247. {
  248.     struct node *n = world;
  249.     int i;
  250.     for (i=0 ; i<p->x*p->y ; i++, n++) {
  251.         if (n->c == '0')
  252.             return n;
  253.     }
  254.     return NULL;
  255. }
  256.  
  257. struct node *moveup(struct pannel *pannel)
  258. {
  259.     struct node *zero = findzero(pannel, pannel->world);
  260.     if (zero->canu) {
  261.         struct node *world = pannel->world;
  262.         struct node *zero = findzero(pannel, world);
  263.         struct node *u = zero - pannel->x;
  264.         char c = u->c;
  265.         zero->c = c;
  266.         u->c = '0';
  267.         *(pannel->s + zero->x + pannel->x*zero->y) = c;
  268.         *(pannel->s + u->x + pannel->x*u->y) = '0';
  269.         u->dist = 0;
  270.         pannel->md = md(pannel);
  271.         return u;
  272.     }
  273.     return NULL;
  274. }
  275.  
  276. struct node *movedown(struct pannel *pannel)
  277. {
  278.     struct node *zero = findzero(pannel, pannel->world);
  279.     if (zero->cand) {
  280.         struct node *world = pannel->world;
  281.         struct node *zero = findzero(pannel, world);
  282.         struct node *d = zero + pannel->x;
  283.         char c = d->c;
  284.         zero->c = c;
  285.         d->c = '0';
  286.         *(pannel->s + zero->x + pannel->x*zero->y) = c;
  287.         *(pannel->s + d->x + pannel->x*d->y) = '0';
  288.         d->dist = 0;
  289.         pannel->md = md(pannel);
  290.         return d;
  291.     }
  292.     return NULL;
  293. }
  294.  
  295. struct node *moveleft(struct pannel *pannel)
  296. {
  297.     struct node *zero = findzero(pannel, pannel->world);
  298.     if (zero->canl) {
  299.         struct node *world = pannel->world;
  300.         struct node *zero = findzero(pannel, world);
  301.         struct node *l = zero - 1;
  302.         char c = l->c;
  303.         zero->c = c;
  304.         l->c = '0';
  305.         *(pannel->s + zero->x + pannel->x*zero->y) = c;
  306.         *(pannel->s + l->x + pannel->x*l->y) = '0';
  307.         l->dist = 0;
  308.         pannel->md = md(pannel);
  309.         return l;
  310.     }
  311.     return NULL;
  312. }
  313.  
  314. struct node *moveright(struct pannel *pannel)
  315. {
  316.     struct node *zero = findzero(pannel, pannel->world);
  317.     if (zero->canr) {
  318.         struct node *world = pannel->world;
  319.         struct node *zero = findzero(pannel, world);
  320.         struct node *r = zero + 1;
  321.         char c = r->c;
  322.         zero->c = c;
  323.         r->c = '0';
  324.         *(pannel->s + zero->x + pannel->x*zero->y) = c;
  325.         *(pannel->s + r->x + pannel->x*r->y) = '0';
  326.         pannel->md = md(pannel);
  327.         return r;
  328.     }
  329.     return NULL;
  330. }
  331.  
  332. struct taskque *inserttask(struct taskque *r, struct pannel *p)
  333. {
  334.     struct taskque *q = (struct taskque *)calloc(1, sizeof(struct taskque));
  335.     if (!q) {
  336.         perror("inserttask");
  337.         exit(0);
  338.     }
  339.  
  340.     q->pannel = p;
  341.     if (r) {
  342.         if (r->next) {
  343.             r->next->prev = q;
  344.             q->next = r->next;
  345.         }
  346.         r->next = q;
  347.         q->prev = r;
  348.     }
  349.     return q;
  350. }
  351.  
  352. struct taskque *addtask(struct taskque *r, struct pannel *p)
  353. {
  354.     struct taskque *q = (struct taskque *)calloc(1, sizeof(struct taskque));
  355.     if (!q) {
  356.         perror("inserttask");
  357.         exit(0);
  358.     }
  359.  
  360.     q->pannel = p;
  361.     if (r) {
  362.         while (r->next) {
  363.             r = r->next;
  364.         }
  365.         if (r->next)
  366.             r->next->prev = q;
  367.         q->next = r->next;
  368.         r->next = q;
  369.         q->prev = r;
  370.     }
  371.     return q;
  372. }
  373.  
  374. struct taskque *sorttask(struct taskque *r, struct pannel *p)
  375. {
  376.     struct taskque *q = (struct taskque *)calloc(1, sizeof(struct taskque));
  377.     if (!q) {
  378.         perror("inserttask");
  379.         exit(0);
  380.     }
  381.  
  382.     q->pannel = p;
  383.     if (r) {
  384.         while (r->next) {
  385.             if (r->next->pannel->md + r->next->pannel->round \
  386.                 > q->pannel->md + q->pannel->round)
  387.                 break;
  388.             r = r->next;
  389.         }
  390.         if (r->next)
  391.             r->next->prev = q;
  392.         q->next = r->next;
  393.         r->next = q;
  394.         q->prev = r;
  395.     }
  396.     return q;
  397. }
  398.  
  399. struct pannel *copypannel(struct pannel *pannel)
  400. {
  401.     struct pannel *p = (struct pannel *)calloc(1, sizeof(struct pannel));
  402.     struct node *w = (struct node *)calloc(pannel->x * pannel->y, sizeof(struct node));
  403.     struct node *world = pannel->world;
  404.     char *s;
  405.  
  406.     if (!p || !w) {
  407.         perror("copypannel");
  408.         exit(0);
  409.     }
  410.  
  411.     memcpy(p, pannel, sizeof(struct pannel));
  412.     memcpy(w, world, pannel->x * pannel->y * sizeof(struct node));
  413.     p->world = w;
  414.     s = (char *)calloc(1, strlen(pannel->s) + 1);
  415.     if (!s) {
  416.         perror("copypannel");
  417.         exit(0);
  418.     }
  419.     strcpy(s, pannel->s);
  420.     p->s = s;
  421.  
  422.     s = (char *)calloc(1, strlen(pannel->s) + 1);
  423.     if (!s) {
  424.         perror("copypannel");
  425.         exit(0);
  426.     }
  427.     strcpy(s, pannel->sorted);
  428.     p->sorted = s;
  429.     p->round++;
  430.     p->prev = pannel;
  431.     return p;
  432. }
  433.  
  434. int isvisited(struct taskque *r, char *s)
  435. {
  436.     struct taskque *q = r;
  437.    
  438.     while (q) {
  439.         if (!strcmp(q->pannel->s, s))
  440.             return 1;
  441.         q = q->next;
  442.     }
  443.     return 0;
  444. }
  445.  
  446. int ending(int qnum, struct taskque *root, struct pannel *last)
  447. {
  448.     char *buf = (char *)calloc(1, last->round + 1);
  449.     int pos = last->round - 1;
  450.     struct pannel *p = last;
  451.     char fname[80];
  452.     FILE *handle;
  453.  
  454.     if (!buf) {
  455.         perror("copypannel");
  456.         exit(0);
  457.     }
  458.  
  459.     while (p->prev) {
  460.         *(buf + pos) = p->move;
  461.         pos--;
  462.         p = p->prev;
  463.     }
  464.  
  465.     sprintf(fname, "result/q.%d", qnum);
  466.     handle = fopen(fname, "w");
  467.     fprintf(handle, "%s", buf);
  468.     fclose(handle);
  469.     fprintf(stderr, "done: %d, %s\n", qnum, buf);
  470.     free(buf);
  471.  
  472.     pos = last->round;
  473.     root->pannel->solved = 1;
  474.     freeapannel(last);
  475.     return pos;
  476. }
  477.  
  478. int engine(int qnum, struct taskque *root, struct taskque *taskque, struct pannel *pannel)
  479. {
  480.     struct node *world = pannel->world;
  481.     struct node *zero = findzero(pannel, world);
  482.  
  483. /*
  484.     if (pannel->round > 30)
  485.         root->pannel->solved = 1;
  486. */
  487.  
  488.     /* fprintf(stderr, "%5.5d, %2.2d\r", root->depth, pannel->round); */
  489.  
  490.     if (root->pannel->solved)
  491.         return 0;
  492.    
  493.     if (root->depth > 80000)
  494.         return 0;
  495.  
  496.     if (pannel->round > 50)
  497.         goto exit;
  498.  
  499.     if (zero->canu) {
  500.         struct pannel *u = copypannel(pannel);
  501.         moveup(u);
  502.         u->move = 'U';
  503.         if (!strcmp(u->s, u->sorted)) {
  504.             return ending(qnum, root, u);
  505.         }
  506.         if (!isvisited(root, u->s)) {
  507.             root->depth++;
  508. #if 0          
  509.             sorttask(taskque, u);
  510. #endif
  511.             if (u->md + u->round <= pannel->md + pannel->round)
  512.                 inserttask(taskque, u);
  513.             else
  514.                 addtask(taskque, u);
  515.         }
  516.         else {
  517.             freeapannel(u);
  518.         }
  519.     }
  520.  
  521.     if (zero->cand) {
  522.         struct pannel *d = copypannel(pannel);
  523.         movedown(d);
  524.         d->move = 'D';
  525.         if (!strcmp(d->s, d->sorted)) {
  526.             return ending(qnum, root, d);
  527.         }
  528.         if (!isvisited(root, d->s)) {
  529.             root->depth++;
  530. #if 0          
  531.             sorttask(taskque, d);
  532. #endif
  533.             if (d->md + d->round <= pannel->md + pannel->round)
  534.                 inserttask(taskque, d);
  535.             else
  536.                 addtask(taskque, d);
  537.         }
  538.         else {
  539.             freeapannel(d);
  540.         }
  541.     }
  542.  
  543.     if (zero->canr) {
  544.         struct pannel *r = copypannel(pannel);
  545.         moveright(r);
  546.         r->move = 'R';
  547.         if (!strcmp(r->s, r->sorted)) {
  548.             return ending(qnum, root, r);
  549.         }
  550.         if (!isvisited(root, r->s)) {
  551.             root->depth++;
  552. #if 0          
  553.             sorttask(taskque, r);
  554. #endif
  555.             if (r->md + r->round <= pannel->md + pannel->round)
  556.                 inserttask(taskque, r);
  557.             else
  558.                 addtask(taskque, r);
  559.         }
  560.         else {
  561.             freeapannel(r);
  562.         }
  563.     }
  564.            
  565.     if (zero->canl) {
  566.         struct pannel *l = copypannel(pannel);
  567.         moveleft(l);
  568.         l->move = 'L';
  569.         if (!strcmp(l->s, l->sorted)) {
  570.             return ending(qnum, root, l);
  571.         }
  572.         if (!isvisited(root, l->s)) {
  573.             root->depth++;
  574. #if 0          
  575.             sorttask(taskque, l);
  576. #endif
  577.             if (l->md + l->round <= pannel->md + pannel->round)
  578.                 inserttask(taskque, l);
  579.             else
  580.                 addtask(taskque, l);
  581.         }
  582.         else {
  583.             freeapannel(l);
  584.         }
  585.     }
  586.  
  587. exit:
  588.     if (!taskque->next)
  589.         return 0;
  590.     return engine(qnum, root, taskque->next, taskque->next->pannel);
  591. }
  592.  
  593. int main(int argc, char *argv[])
  594. {
  595.     FILE *fquiz;
  596.     struct pannel *p;
  597.     struct node   *world;
  598.     struct taskque *root;
  599.     int i, mod, assigned;
  600.  
  601.     if (argc > 1) {
  602.         sscanf(argv[1], "%d", &mod);
  603.         sscanf(argv[2], "%d", &assigned);
  604.     }
  605.  
  606.     fquiz = readglobal("slidepannel.txt");
  607.     for (i=0 ; i<globals.N ; i++) {
  608.         FILE *resultf;
  609.         char fname[80];
  610.         p = readapannel(fquiz);
  611.         sprintf(fname, "result/q.%d", i);
  612.         resultf = fopen(fname, "r");
  613.         if (resultf) {
  614.             fclose(resultf);
  615.             continue;
  616.         }
  617.         if (argc > 1 && i%mod != assigned) {
  618.             freeapannel(p);
  619.             continue;
  620.         }
  621. #if 0
  622.         if (p->x > 4 && p->y > 4) {
  623.             freeapannel(p);
  624.             continue;
  625.         }
  626. #endif
  627.         p->sorted = presort(p->s);
  628.         world = buildworld(p);
  629.         root = addtask(NULL, p);
  630.         fprintf(stderr, "%d, %s\n", i, p->s);
  631.         engine(i, root, root, p);
  632.         cleanup(root);
  633.     }
  634.     fclose(fquiz);
  635.     return 0;
  636. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement