fork download
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <stdlib.h> /* calloc(), free(), abs(), exit(), ... */
  4. #include <limits.h> /* LONG_MAX */
  5.  
  6. /* safer free() ---------------------- */
  7. #define FREE(p) \
  8. do{ \
  9. if ( (p) ) { \
  10. free( (p) ); \
  11. (p) = NULL; \
  12. } \
  13. }while(0)
  14.  
  15. /* safer fclose() -------------------- */
  16. #define FCLOSE(fp) \
  17. do { \
  18. if ( (fp) ) { \
  19. fclose((fp)); \
  20. (fp) = NULL; \
  21. } \
  22. }while(0)
  23.  
  24. typedef struct MinSum0Pair {
  25. long int small, large;
  26. } MinSum0Pair;
  27.  
  28. /* --------------------------------------------------------------
  29.  * Create buffer 'buf' and fill-it up with the contents of the file 'fname'.
  30.  * Return the length of the buffer, or 0 on error.
  31.  * --------------------------------------------------------------
  32.  */
  33. long int buffer_make_fromfile( long int **buf, const char *fname )
  34. {
  35. FILE *fp = NULL;
  36. long int i, buflen = 0;
  37.  
  38. if ( !fname || !buf ) {
  39. puts( "*** error: invalid pointer!" );
  40. goto ret_failure;
  41. }
  42.  
  43. /* open input file */
  44. if ( NULL == (fp=fopen(fname, "r")) ) {
  45. puts( "*** error: cannot open input file!" );
  46. goto ret_failure;
  47. }
  48.  
  49. /* get the 1st number (buflen) and allocate so many long ints, in buf */
  50. if ( 1 != fscanf(fp, "%ld", &buflen) ) {
  51. puts( "*** error: fscanf() failed!" );
  52. goto ret_failure;
  53. }
  54. if ( NULL == (*buf=calloc(buflen, sizeof(long int)) ) ) {
  55. puts( "*** error: out of memory!" );
  56. goto ret_failure;
  57. }
  58.  
  59. /* fill-in the buffer with the rest of long ints */
  60. for (i=0; !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]); i++ )
  61. ; /* void */
  62.  
  63. FCLOSE(fp);
  64. return buflen;
  65.  
  66. ret_failure:
  67. FCLOSE(fp);
  68. return 0;
  69. }
  70.  
  71. /* --------------------------------------------------------------
  72.  * Print the first 'maxlen' elements of the buffer 'buf', separated be a space char.
  73.  * --------------------------------------------------------------
  74.  */
  75. void buffer_print( long int buf[], long int maxlen )
  76. {
  77. long int i = 0;
  78. for (; i < maxlen; i++ )
  79. printf( "%ld ", buf[i] );
  80. puts("\b");
  81.  
  82. return;
  83. }
  84.  
  85. /* --------------------------------------------------------------
  86.  * Find in buffer 'buf' (of length 'buflen') the pair of values
  87.  * whose sum is closest to 0, and store them in '*pair'.
  88.  * Return false on error, true otherwise.
  89.  *
  90.  * Alg: Indexers 'istart' & 'iend' traverese 'buf' simultaneously, starting from its
  91.  * edges. Until they meet, they keep track of the minimum sum of pairs, along with
  92.  * the indicies that correspond to the members of the min pair ('ismall' & 'ilarge').
  93.  * --------------------------------------------------------------
  94.  */
  95. bool pair_minsum0( MinSum0Pair *pair, const long int buf[], long int buflen )
  96. {
  97. long int sum, minsum = LONG_MAX; /* current & minimum sums */
  98. long int istart = 0, iend = buflen - 1; /* array indexers (start & end)*/
  99. long int ismall = istart, ilarge = iend; /* pair's small & large indicies*/
  100.  
  101. if ( !pair || !buf ) {
  102. puts( "*** error: invalid pointer!" );
  103. goto ret_failure;
  104. }
  105. if ( buflen < 2 ) {
  106. puts("*** error: insufficient data (must be more than 2 numbers)!");
  107. goto ret_failure;
  108. }
  109.  
  110. /* traverse the buffer simultaneously from both edges */
  111. while ( istart < iend )
  112. {
  113. sum = buf[ istart ] + buf[ iend ];
  114.  
  115. /* get new minimum sum (if any) and update accordingly ismall & ilarge */
  116. if ( abs(sum) < abs(minsum) )
  117. {
  118. minsum = sum;
  119. ismall = istart;
  120. ilarge = iend;
  121. }
  122. if ( sum < 0 )
  123. istart++;
  124. else
  125. iend--;
  126. }
  127.  
  128. pair->small = buf[ ismall ];
  129. pair->large = buf[ ilarge ];
  130.  
  131. return true;
  132.  
  133. ret_failure:
  134. return false;
  135. }
  136.  
  137. /* --------------------------------------------------------------
  138.  *
  139.  * --------------------------------------------------------------
  140.  */
  141. int main( void )
  142. {
  143. char fname[] = "op2.in";
  144. long int *buf = NULL;
  145. long int buflen = 0;
  146. MinSum0Pair pair = { 0L, 0L };
  147.  
  148. /* read input-file contents into our buffer */
  149. buflen = buffer_make_fromfile( &buf, fname );
  150. if ( 0 == buflen )
  151. goto ret_failure;
  152. buffer_print( buf, buflen );
  153.  
  154. /* find & store the pair whose sum is closest to 0 */
  155. if ( !pair_minsum0( &pair, buf, buflen) )
  156. goto ret_failure;
  157.  
  158. printf( "%ld %ld\n", pair.small, pair.large );
  159.  
  160. FREE(buf);
  161. exit( EXIT_SUCCESS );
  162.  
  163. ret_failure:
  164. FREE(buf);
  165. exit( EXIT_FAILURE );
  166. }
  167.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty