Advertisement
kaenan

Max Subarray

Jan 15th, 2018
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.83 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdbool.h>
  5. #include <limits.h>
  6.  
  7.  
  8. /* Utitlites. TO BE IGNORED. */
  9. /* ======================================================================== */
  10. #define NEWLINE puts("");
  11. #define dd printf("HERE %d\n", __LINE__); // Used for debugging.
  12.  
  13. #define NELEMS(x) (sizeof(x)/sizeof(x[0]))
  14. #define max(x,y) (((x) > (y)) ? (x) : (y))
  15. #define min(x,y) (((x) > (y)) ? (y) : (x))
  16.  
  17. /* For itr = [start, end]; */
  18. #define forIn(itr, start, end) \
  19.     for (unsigned int itr = (start); (itr) < (end); ++(itr))
  20.  
  21. #define assert(expr, err_msg, err_expr)         \
  22.     if (!(expr)) {                              \
  23.         printf(err_msg);                        \
  24.         err_expr;                               \
  25.     }
  26.  
  27. /* Array concatenation. */
  28. #define arrcat(t, t_nelems, s, s_nelems) {      \
  29.     forIn(s_index, 0, s_nelems) {               \
  30.             t[t_nelems + s_index] = s[s_index]; \
  31.     } }
  32.  
  33. /* Error codes. */
  34. enum errcode {
  35.     SUCCESS,
  36.     ERROR,
  37.     NULL_INPUT = -'I',
  38.     DOMAIN_ERR,  // Input does not belong to the domanin of the function.
  39.     NOT_FOUND = 404,
  40.     FOUND = -404,
  41.     NIL = '0',
  42.     RESOURCE_ACQUISITION_FAILED = 7
  43. };
  44. typedef enum errcode errcode;
  45.  
  46.  
  47. /* Error checked malloc, realloc and calloc. */
  48. void *ec_malloc(size_t);
  49. void *ec_realloc(void *, size_t);
  50. void *ec_calloc(size_t, size_t);
  51.  
  52. /* Allocate memory for an array of the given type. */
  53. #define mem_arr(type, ptr, size) \
  54.     (ptr) = (type *) ec_malloc((size) * sizeof(type))
  55. #define mem_arr_calloc(type, ptr, size) \
  56.     (ptr) = (type *) ec_calloc(size, sizeof(type));
  57.  
  58. /* Allocate a matrix of any type. */
  59. #define mem_matrix(type, matrix, rows, cols)    \
  60.     mem_arr(type*, matrix, rows);               \
  61.     forIn (i, 0, rows) {                        \
  62.         mem_arr(type, matrix[i], cols);         \
  63.     }
  64. #define mem_matrix_calloc(type, matrix, rows, cols)     \
  65.     mem_arr_calloc(type*, matrix, rows);                \
  66.     forIn (i, 0, rows) {                                \
  67.         mem_arr_calloc(type, matrix[i], cols);          \
  68.     }
  69.  
  70. /* Deallocate a matrix of any type. */
  71. #define free_matrix(matrix, rows)               \
  72.     forIn (i, 0, rows) {                        \
  73.         free(matrix[i]);                        \
  74.     }                                           \
  75.     free(matrix);
  76.  
  77. /* Variable length TAB. */
  78. #define TAB(length) printf("%" #length "c", 0)
  79.  
  80. /* Strtol wrapper. */
  81. #define strtol_(str, identifier, calling_fn, err_expr) {                        \
  82.     identifier = strtol(str, &err, 10);                                         \
  83.     if (*err) {                                                                 \
  84.             printf("[Error] " #calling_fn ": \"%s\" is not a number.\n", str);  \
  85.             err_expr;                                                           \
  86.     } }
  87.  
  88. typedef struct {
  89.     char *s;
  90.     unsigned int len;
  91. } String;
  92.  
  93. /* Return a token from a given file descriptor. */
  94. String ftok(FILE *fd, const char *del);
  95.  
  96. #define assert_ftok(fd, token, del, err_expr)   \
  97.         assert((token = ftok(fd, del)).len, "", \
  98.             free(token.s); err_expr);
  99.  
  100. /* Erorr checked fopen(). */
  101. FILE *ec_fopen(const char *file_path, const char *mode);
  102.  
  103. /* Assert if file at =file_path= is empty. */
  104. #define file_isEmpty(file_path, eof_expr) do {                                              \
  105.     FILE *fd_test = ec_fopen(file_path, "a+");                                              \
  106.     assert(fgetc(fd_test) != EOF && !feof(fd_test), "",                                     \
  107.                printf("File %s is empty.\n", file_path); fclose(fd_test); eof_expr; break); \
  108.     fclose(fd_test);                                                                        \
  109.     } while(0)
  110.  
  111. /* Read array. */
  112. #define freadarr(fd, format_specifier, arr, nelems)  do {       \
  113.         forIn (i, 0, nelems) {                                  \
  114.             if (EOF == fscanf(fd, format_specifier, arr + i)) { \
  115.                 nelems = i; break;                              \
  116.             }                                                   \
  117.         }                                                       \
  118.     } while(0)
  119. /* Print array. */
  120. #define fprintarr(fd, format_specifier, arr, nelems)    \
  121.     forIn (i, 0, nelems) {                              \
  122.         fprintf(fd, format_specifier, *(arr + i));      \
  123.     }                                                   \
  124.     NEWLINE;                                            \
  125.  
  126. /* Read matrix. */
  127. #define freadmat(fd, format_specifier, matrix, rows,  cols)  do {                           \
  128.     int err = 0;                                                                            \
  129.         forIn (ln_index, 0, rows) {                                                         \
  130.             forIn (col_index, 0, cols) {                                                    \
  131.                 if ( EOF == fscanf(fd, format_specifier,matrix[ln_index] + col_index)) {    \
  132.                     if ((!col_index && !ln_index) || col_index) cols = col_index;           \
  133.                     err = 1;                                                                \
  134.                 }                                                                           \
  135.             }                                                                               \
  136.             if (err) { rows = ln_index; break; }                                            \
  137.         }                                                                                   \
  138.     } while(0)
  139. /* Print matrix. */
  140. #define fprintmat(fd, format_specifier, matrix, rows,  cols)                \
  141.     NEWLINE;                                                                \
  142.     forIn (ln_index, 0, rows) {                                             \
  143.         forIn (col_index, 0, cols) {                                        \
  144.             fprintf(fd, format_specifier " ",matrix[ln_index][col_index]);  \
  145.         }                                                                   \
  146.         NEWLINE;                                                            \
  147.     }                                                                       \
  148.     NEWLINE;
  149. /* ======================================================================== */
  150.  
  151.  
  152. /* BEGIN */
  153.  
  154. typedef struct Subarray_Sum {
  155.     int sum;
  156.     unsigned int left_i, right_i;
  157. } Subarray_Sum;
  158.  
  159. Subarray_Sum find_max_crossing_subarray(int arr[], int lo, int mid, int hi);
  160. Subarray_Sum find_max_subarray(int arr[], int lo, int hi);
  161.  
  162. #define INPUT_FILE "input.txt"
  163.  
  164. int main(int argc, char **argv)
  165. {
  166.     int arr[100];
  167.     unsigned int nelems = 100;
  168.  
  169.     file_isEmpty(INPUT_FILE, return -1);
  170.  
  171.     FILE *input = ec_fopen(INPUT_FILE, "r");
  172.     freadarr(input, "%d", arr, nelems);
  173.  
  174.     Subarray_Sum max_subarray = find_max_subarray(arr, 0, nelems - 1);
  175.  
  176.     fprintarr(stdout, "%d ",
  177.         arr + max_subarray.left_i,
  178.         max_subarray.right_i - max_subarray.left_i + 1);
  179.  
  180.     printf("%d\n", max_subarray.sum);
  181.  
  182.     return 0;
  183. }
  184.  
  185. Subarray_Sum find_max_subarray(int arr[], int lo, int hi)
  186. {
  187.     if (hi == lo) {
  188.         return (Subarray_Sum) { arr[hi], lo, hi };
  189.     }
  190.  
  191.     Subarray_Sum left_sub, right_sub, crossing_sub;
  192.     int mid;
  193.  
  194.     mid = (lo + hi) / 2;
  195.  
  196.     left_sub = find_max_subarray(arr, lo, mid);
  197.     right_sub = find_max_subarray(arr, mid + 1, hi);
  198.     crossing_sub = find_max_crossing_subarray(arr, lo, mid, hi);
  199.  
  200.     if (left_sub.sum >= right_sub.sum && left_sub.sum >= crossing_sub.sum) {
  201.         return left_sub;
  202.     }
  203.     if (right_sub.sum >= left_sub.sum && right_sub.sum >= crossing_sub.sum) {
  204.         return right_sub;
  205.     }
  206.     return crossing_sub;
  207. }
  208.  
  209. Subarray_Sum find_max_crossing_subarray(int arr[], int lo, int mid, int hi)
  210. {
  211.     int left_i, right_i, sum = 0, left_sum = INT_MIN, right_sum = INT_MIN;
  212.  
  213.     for (int i = mid; i >= lo; --i) {
  214.         sum += arr[i];
  215.         if (sum > left_sum) {
  216.             left_sum = sum;
  217.             left_i = i;
  218.         }
  219.     }
  220.  
  221.     sum = 0;
  222.     for (int i = mid + 1; i <= hi; ++i) {
  223.         sum += arr[i];
  224.         if (sum > right_sum) {
  225.             right_sum = sum;
  226.             right_i = i;
  227.         }
  228.     }
  229.  
  230.     return (Subarray_Sum) { right_sum + left_sum, left_i, right_i };
  231. }
  232.  
  233. /* END */
  234.  
  235.  
  236.  
  237.  
  238.  
  239. /* Utilites. TO BE IGNORED. */
  240. /* ======================================================================== */
  241. /* Return a token from a given file descriptor. */
  242. String ftok(FILE *fd, const char *del)
  243. {
  244.     String token;
  245.     unsigned int size = 30, s_index = 0;
  246.     char c;
  247.  
  248.     mem_arr(char, token.s, size);
  249.  
  250.     /* Ignore initial delimiters. */
  251.     while ((c = fgetc(fd)) != EOF && strchr(del, c)) { ; }
  252.  
  253.     if (c == EOF) {
  254.         free(token.s);
  255.         return (String) { NULL, 0 };
  256.     }
  257.  
  258.     do {
  259.         if (s_index >= size) {
  260.             token.s = (char *)ec_realloc(token.s, size += 30);
  261.         }
  262.         *(token.s + s_index) = c;
  263.         ++s_index;
  264.     } while ((c = fgetc(fd)) != EOF && !strchr(del, c));
  265.  
  266.     token.s = (char *)ec_realloc(token.s, s_index + 1); // "Tight fitting" string.
  267.     token.s[s_index] = 0; // End string.
  268.     token.len = s_index;
  269.  
  270.     return token;
  271. }
  272.  
  273. /* I/O handling. */
  274. FILE *ec_fopen(const char *file_path, const char *mode)
  275. {
  276.     FILE *fd;
  277.  
  278.     fd = fopen(file_path, mode);
  279.  
  280.     if (NULL == fd) {
  281.         puts("[Error] fopen() returned NULL.");
  282.         exit(RESOURCE_ACQUISITION_FAILED);
  283.     }
  284.  
  285.     return fd;
  286. }
  287.  
  288. /* Memory management. */
  289. #define assert_alloc(allocator_name)                            \
  290.     assert((new_ptr != NULL),                                   \
  291.            "[Error] " #allocator_name "() returned NULL.\n",    \
  292.            exit(RESOURCE_ACQUISITION_FAILED));
  293. void *ec_calloc(size_t nitems, size_t size)
  294. {
  295.     void *new_ptr;
  296.  
  297.     new_ptr = calloc(nitems, size);
  298.     assert_alloc(calloc);
  299.  
  300.     return new_ptr;
  301. }
  302. void *ec_realloc(void *ptr, size_t size)
  303. {
  304.     void *new_ptr;
  305.  
  306.     new_ptr = realloc(ptr, size);
  307.     assert_alloc(realloc);
  308.  
  309.     return new_ptr;
  310. }
  311. void *ec_malloc(size_t size)
  312. {
  313.     return ec_realloc(NULL, size);
  314. }
  315. /* ======================================================================== */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement