#include <iostream>
#include <fstream>
#include "mpi.h"
using namespace std; 

int main(int argc, char *argv[]) {
		int *array, *results, length, i, j, k, look, rank, size, tag = 0;
		ifstream in;			// in and out files.  Should only be accessed
		ofstream out;			// by node 0!
		MPI_Status status;

		MPI_Init(&argc, &argv);	// start up MPI, find out rank & size 
		MPI_Comm_rank(MPI_COMM_WORLD, &rank);	// individually
		MPI_Comm_size(MPI_COMM_WORLD, &size);

		if (rank == 0) {		// read length and target, then share it
				in.open("array.in");
				in >> length >> look;
		}
		MPI_Bcast(&length, 1, MPI_INT, 0, MPI_COMM_WORLD);
		MPI_Bcast(&look, 1, MPI_INT, 0, MPI_COMM_WORLD);

		if (rank == 0) {		// read whole array, get space for answers
				array = new int[length];
				results = new int[length];
				i = 0;
				j = 0;
				while(in >> array[i++]) { }
				for (i = 1; i < size; i++)	// send chunks to correct process
						MPI_Send(&array[length/size*i], length/size, 
										MPI_INT, i, tag, MPI_COMM_WORLD);
				for (i = 0; i < length/size; i++)	// take care of chunk
						if (array[i] == look) results[j++] = i;
				for (i = 1; i < size; i++) {
						MPI_Recv(&k, 1, MPI_INT, i, tag, MPI_COMM_WORLD, 
										&status);	//how many results?
						MPI_Recv(&results[j], k, MPI_INT, i, tag,	// data!! 
										MPI_COMM_WORLD, &status);
						j += k;	// advance pointer, sorta
				}
				for (i = length/size*size; i < length; i++) //extras, anyone?
						if (array[i] == look) results[j++] = i;
				out.open("array.out");
				for (i = 0; i < j; i++) out << results[i] << '\t';
		} else {
				j = 0;
				array = new int[length/size];
				results = new int[length/size];	// make arrays, get chunk
				MPI_Recv(array, length/size, MPI_INT, 0, tag, MPI_COMM_WORLD,
								&status);
				for (i = 0; i < length/size; i++)	// take care of chunk
						if (array[i] == look) 
								results[j++] = i + size/length * rank;
				MPI_Send(&j, 1, MPI_INT, 0, tag, MPI_COMM_WORLD);
				MPI_Send(array, j, MPI_INT, 0, tag, MPI_COMM_WORLD);
		}

		delete [] array;
		delete [] results;

		MPI_Finalize();
		return 0;
}

