// note - example from class used MAX_I=10, and insert 7, 12, 75, 22, 104, 72
//        this is in test.txt, so we can run it with ./a.out < test.txt

#include <stdio.h>
#include <stdlib.h>

// pre-processor definition
#define MAX_I 1 000 000
#define H_EMPTY -1
#define TRUE 1
#define FALSE 0

// note - we're going to assume non-negative, with -1 indicating empty.
int A[MAX_I];

int h(int data);
void ht_init(int *A); hash_T *A
void ht_insert(int value);
void ht_print();
int ht_num_collisions();


int main(int argc, char * argv[]) {

  ht_init();
  
  int x, num_items = 0;

  while (scanf("%d", &x) == 1) {
    ht_insert(x);
    num_items++;
  }

  //ht_print(FALSE);

  int num_collide = ht_num_collisions();
  printf("# collisions = %d, (%f%% of the number of items)\n", num_collide,
	 100.0 * num_collide / num_items);

  return 0;
}

int h(int data) {
  // let's just use a very simple h function so we can see what's happening
  return (data % MAX_I);
}

void ht_init() {
  for(int i=0; i < MAX_I; i++) A[i] = H_EMPTY;
}


void ht_insert(int value) {
  int i, count;
  
  count = 0; // how many spots did we check

  // look for an empty spot in table, starting at h(value)
  i = h(value);  
  while (A[i] != H_EMPTY &&
	 count < MAX_I) { // if we have looked at all of the spots, table is full
    i = (i + 1) % MAX_I; // try next spot
    count++;
  }

  // weren't able to find an empty spot
  if (A[i] != H_EMPTY) {
    printf("Error inserting - full hash table.\n");
    exit(0);
  }

  // if we're here we found an empty spot
  A[i] = value;
}

void ht_print(int printEmpty) {
  printf("index: value\n"
	 "------------\n");
  
  for(int i=0; i < MAX_I; i++) {
    if (A[i] != H_EMPTY)
      printf("%5d: %4d\n", i, A[i]);
    else {
      if (printEmpty)
	printf("%5d: empty\n", i);
    }
  }
}


// return number of items with a hash value that
//  does not match their index
int ht_num_collisions() {
  int count = 0;
  
  for(int i=0; i < MAX_I; i++) {
    if (A[i] == H_EMPTY) continue;
    // if location i is not empty
    //   i != (hash of value at location i)
    if (i != h(A[i])) {
      count++;
    }
  }
  
  return count;
}