Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2013
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.51 KB | None | 0 0
  1. /* This file is (c) 2013 Richard Barrell <rchrd@brrll.co.uk>, see LICENSE.txt */
  2. /* (it's the ISC license, which is 2-clause BSD with simplified wording) */
  3.  
  4. #include <stdint.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8.  
  9.  
  10. typedef struct {
  11.     int32_t x;
  12.     int32_t y;
  13. } pair;
  14.  
  15.  
  16. /* This struct defines a circular queue. */
  17. typedef struct {
  18.     /* Pointer to the beginning of the block of memory containing all of the
  19.      * elements in the queue. */
  20.     pair *pairs;
  21.     size_t size; // Number of elements in the queue
  22.     size_t head; // Index of first element in the queue
  23.     size_t tail; // Index *after* last element in the queue
  24. } queue;
  25.  
  26.  
  27. /* Start a new queue */
  28. static int initQueue(queue *q)
  29. {
  30.     q->pairs = (pair*) malloc(sizeof(pair));
  31.     if (q->pairs == NULL) {
  32.         /* Memory allocation failed */
  33.         return -1;
  34.     }
  35.     q->size = 1;
  36.     q->head = 0;
  37.     q->tail = 0;
  38.     return 0;
  39. }
  40.  
  41.  
  42. /* Clean up memory used by the queue */
  43. static void freeQueue(queue *q) {
  44.     free(q->pairs);
  45. }
  46.  
  47.  
  48. /* Return the number of elements in the queue. */
  49. static size_t getNumElements(queue *q) {
  50.     size_t gap = q->tail - q->head;
  51.     if (q->head > q->tail) {
  52.         gap += q->size;
  53.     }
  54.     return gap;
  55. }
  56.  
  57.  
  58. /* Given a pair, insert it into the queue */
  59. static int addToQueue(queue *q, pair p) {
  60.     if ((getNumElements(q) + 1) == q->size) {
  61.         /* Adding this pair would put us over the size limit, so we need
  62.          * to make more room. Allocate double the old memory used. */
  63.         size_t oldSize = q->size;
  64.         q->size = q->size * 2;
  65.         q->pairs = (pair*) realloc(q->pairs, q->size * sizeof(pair));
  66.         if (q->pairs == NULL) {
  67.             /* Memory allocation failed */
  68.             return -1;
  69.         }
  70.         if (q->tail < q->head) {
  71.             /* The active contents of the queue "wrapped around" the end of
  72.              * the ring; shuffle things around so that the bits before
  73.              * and after the wrap are now contiguous.
  74.              * (BBB***AA) -> (***********AABBB)
  75.              */
  76.             memcpy(q->pairs + oldSize, q->pairs, q->tail * sizeof(pair));
  77.             q->tail = oldSize + q->tail;
  78.         }
  79.     }
  80.     q->tail++;
  81.     if (q->tail == q->size) {
  82.         /* Hit the end of the queue; start wrapping around */
  83.         q->tail = 0;
  84.     }
  85.     q->pairs[q->tail] = p;
  86.     return 0;
  87. }
  88.  
  89.  
  90. /* Remove the oldest element from the queue and return it */
  91. static pair queuePopLeft(queue *q) {
  92.     size_t oldHead = q->head;
  93.     q->head = q->head + 1;
  94.     if (q->head == q->size) {
  95.         q->head = 0;
  96.     }
  97.     return q->pairs[oldHead];
  98. }
  99.  
  100.  
  101. static int getbit(uint8_t *u, int32_t x, int32_t y, int32_t xMax) {
  102.     int32_t pos = y * xMax + x;
  103.     return u[pos];
  104. }
  105.  
  106.  
  107. static void setbit(uint8_t *u, int32_t x, int32_t y, int32_t xMax) {
  108.     int32_t pos = y * xMax + x;
  109.     u[pos] = 1;
  110. }
  111.  
  112.  
  113. int burnHeatMap(int32_t xMax, int32_t yMax,
  114.         int32_t *heatMap,
  115.         size_t goals_length, int32_t *goals_xs, int32_t *goals_ys)
  116. {
  117.  
  118. #define IX(x, y) heatMap[(y)*xMax + (x)]
  119.  
  120.     int failing = 0;
  121.  
  122.     size_t used_sz = xMax * yMax;
  123.     uint8_t *used = (uint8_t*) calloc(used_sz, 1);
  124.  
  125.     queue cell_todo;
  126.     if (initQueue(&cell_todo) != 0) {
  127.         failing = __LINE__ || -1;
  128.         goto cleanup_none;
  129.     }
  130.  
  131.     if (used == NULL) {
  132.         failing = __LINE__ || -1;
  133.         goto cleanup_queue;
  134.     }
  135.  
  136. #define GETUSED(x, y) getbit(used, (x), (y), xMax)
  137. #define SETUSED(x, y) setbit(used, (x), (y), xMax)
  138. #define MAX(a,b) ((a)>(b)?(a):(b))
  139. #define MIN(a,b) ((a)<(b)?(a):(b))
  140.  
  141.     for (int32_t y = 0; y < yMax; y++) {
  142.         for (int32_t x = 0; x < xMax; x++) {
  143.             if (IX(x, y) != 0) {
  144.                 SETUSED(x, y);
  145.             }
  146.             IX(x, y) = -1;
  147.         }
  148.     }
  149.  
  150.     for (size_t i = 0; i < goals_length; i++) {
  151.         int32_t x = goals_xs[i], y = goals_ys[i];
  152.         IX(x, y) = 0;
  153.         SETUSED(x, y);
  154.         pair xy = {x, y};
  155.         if (addToQueue(&cell_todo, xy) != 0) {
  156.             failing = __LINE__ || -1;
  157.             goto cleanup_getNumElements;
  158.         }
  159.     }
  160.  
  161.     int count = getNumElements(&cell_todo);
  162.     while (getNumElements(&cell_todo) > 0) {
  163.         pair xy = queuePopLeft(&cell_todo);
  164.         int32_t x = xy.x, y = xy.y;
  165.         count--;
  166.         int32_t cost = IX(x, y);
  167.         for (int32_t yi = MAX(0, y - 1); yi < MIN(yMax, y + 2); yi++) {
  168.             for (int32_t xi = MAX(0, x - 1); xi < MIN(xMax, x + 2); xi++) {
  169.                 if ((x == xi && y == yi) || GETUSED(xi, yi)) {
  170.                     continue;
  171.                 }
  172.                 SETUSED(xi, yi);
  173.                 IX(xi, yi) = cost + 1;
  174.                 pair xiyi = {xi, yi};
  175.                 if (addToQueue(&cell_todo, xiyi) != 0) {
  176.                     failing = __LINE__ || -1;
  177.                     goto cleanup_getNumElements;
  178.                 }
  179.                 count++;
  180.             }
  181.         }
  182.     }
  183.  
  184.  cleanup_getNumElements:
  185.     free(used);
  186.  cleanup_queue:
  187.     freeQueue(&cell_todo);
  188.  cleanup_none:
  189.     return failing;
  190. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement