#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>			/* calloc(), free(), abs(), exit(), ... */
#include <limits.h>			/* LONG_MAX */

/* safer free() ---------------------- */
#define FREE(p)				\
	do{				\
		if ( (p) ) {		\
			free( (p) );	\
			(p) = NULL;	\
		}			\
	}while(0)

/* safer fclose() -------------------- */
#define FCLOSE(fp)			\
	do {				\
		if ( (fp) ) {		\
			fclose((fp));	\
			(fp) = NULL;	\
		}			\
	}while(0)

typedef struct MinSum0Pair {
	long int small, large;
} MinSum0Pair;

/* --------------------------------------------------------------
 * Create buffer 'buf' and fill-it up with the contents of the file 'fname'.
 * Return the length of the buffer, or 0 on error.
 * --------------------------------------------------------------
 */
long int buffer_make_fromfile( long int **buf, const char *fname )
{
	FILE *fp = NULL;
	long int i, buflen = 0;

	if ( !fname || !buf ) {
		puts( "*** error: invalid pointer!" );
		goto ret_failure;
	}

	/* open input file */
	if ( NULL == (fp=fopen(fname, "r")) ) {
		puts( "*** error: cannot open input file!" );
		goto ret_failure;
	}

	/* get the 1st number (buflen) and allocate so many long ints, in buf */
	if ( 1 != fscanf(fp, "%ld", &buflen) ) {
		puts( "*** error: fscanf() failed!" );
		goto ret_failure;
	}
	if ( NULL == (*buf=calloc(buflen, sizeof(long int)) ) ) {
		puts( "*** error: out of memory!" );
		goto ret_failure;
	}

	/* fill-in the buffer with the rest of long ints */
	for (i=0; !feof(fp) && 1 == fscanf(fp, "%ld", &(*buf)[i]); i++ )
		; /* void */

	FCLOSE(fp);
	return buflen;

ret_failure:
	FCLOSE(fp);
	return 0;
}

/* --------------------------------------------------------------
 * Print the first 'maxlen' elements of the buffer 'buf', separated be a space char.
 * --------------------------------------------------------------
 */
void buffer_print( long int buf[], long int maxlen )
{
	long int i = 0;
	for (; i < maxlen; i++ )
		printf( "%ld ", buf[i] );
	puts("\b");

	return;
}

/* --------------------------------------------------------------
 * Find in buffer 'buf' (of length 'buflen') the pair of values
 * whose sum is closest to 0, and store them in '*pair'.
 * Return false on error, true otherwise.
 *
 * Alg: Indexers 'istart' & 'iend' traverese 'buf' simultaneously, starting from its
 *	edges. Until they meet, they keep track of the minimum sum of pairs, along with
 * 	the indicies that correspond to the members of the min pair ('ismall' & 'ilarge').
 * --------------------------------------------------------------
 */
bool pair_minsum0( MinSum0Pair *pair, const long int buf[], long int buflen )
{
	long int sum, minsum = LONG_MAX;		/* current & minimum sums      */
	long int istart = 0, iend = buflen - 1;		/* array indexers (start & end)*/
	long int ismall = istart, ilarge = iend;	/* pair's small & large indicies*/

	if ( !pair || !buf ) {
		puts( "*** error: invalid pointer!" );
		goto ret_failure;
	}
	if ( buflen < 2 ) {
		puts("*** error: insufficient data (must be more than 2 numbers)!");
		goto ret_failure;
	}

	/* traverse the buffer simultaneously from both edges */
	while ( istart < iend )
	{
		sum = buf[ istart ] + buf[ iend ];

		/* get new minimum sum (if any) and update accordingly ismall & ilarge */
		if ( abs(sum) < abs(minsum) )
		{
			minsum = sum;
			ismall = istart;
			ilarge = iend;
		}
		if ( sum < 0 )
			istart++;
		else
			iend--;
	}

	pair->small = buf[ ismall ];
	pair->large = buf[ ilarge ];

	return true;

ret_failure:
	return false;
}
 
/* --------------------------------------------------------------
 *
 * --------------------------------------------------------------
 */
int main( void )
{
	char 		fname[] = "op2.in";
	long int 	*buf 	= NULL;
	long int 	buflen 	= 0;
	MinSum0Pair	pair 	= { 0L, 0L };

	/* read input-file contents into our buffer */
	buflen = buffer_make_fromfile( &buf, fname );
	if ( 0 == buflen )
		goto ret_failure;
	buffer_print( buf, buflen );

	/* find & store the pair whose sum is closest to 0 */
	if ( !pair_minsum0( &pair, buf, buflen) )
		goto ret_failure;

	printf( "%ld %ld\n", pair.small, pair.large );

	FREE(buf);
	exit( EXIT_SUCCESS );

ret_failure:
	FREE(buf);
	exit( EXIT_FAILURE );
}
