#include <stdio.h>

#define hash wt_hash5
#define BUCKETS 2048
static unsigned int occ[BUCKETS];
char line[1024];

unsigned int test_hash(const char *s, int len)
{
	unsigned int i;

	i = 0;
	while (*s) {
		i ^= *s;
		i = (i << (*s >> 3)) | (i >> (32-(*s >> 3)));
		s++;
	}

	return i;
}

unsigned wt_hash ( const void *key, int len )
{
	unsigned char *p = (unsigned char *)key;
	unsigned h = 0x783c965aUL;
	unsigned step = 16;

	for (; len > 0; len--) {
		h ^= ((unsigned int)*p) * 9;
		p++;
		h = (h << step) + (h >> (32-step));
		step ^= h;
		step &= 0x1F;
	}
	return h;
}

unsigned wt_hash5 ( const void *key, int len )
{
	unsigned char *p = (unsigned char *)key;
	unsigned h0 = 0xa53c965aUL;
	unsigned h1 = 0x5CA6953AUL;
	unsigned step0 = 19;
	unsigned step1 = 13;

	for (; len > 0; len--) {
		unsigned int t;

		t = ((unsigned int)*p);
		p++;
      
		//t *= 0x00DB7531;
		t *= 13;

		h0 -= t;
		h1 += t;

		t  = (h1 << step0) | (h1 >> (32-step0));
		h1 = (h0 << step1) | (h0 >> (32-step1));
		h0 = t;

		t = ((h0 >> 16) ^ h1) & 0xffff;
		step0 = t & 0x1F;
		step1 = t >> 11;
	}
	return h0 ^ h1;
}

main() {
	unsigned int i, j, min, max, avg, tot;
	unsigned max_occ, max_ent;
	char *c;

	avg = 0; tot = 0;
	max = 0; min = ~0UL;

	while (fgets(line, sizeof(line), stdin) != NULL) {
		tot++;
		c = line;
		while (*c && *c != '\n')
			c++;
		*c = 0;

		i = hash(line, c - line);

		occ[i % BUCKETS]++;
	}

	for (i = 0; i < BUCKETS; i++) {
		avg += occ[i];
		if (occ[i] < min)
			min = occ[i];
		if (occ[i] > max)
			max = occ[i];
	}

	fprintf(stderr,
		"tot=%d, min=%d, avg=%f, max=%d\n",
		tot, min, (double)avg/(double)BUCKETS, max);

	fprintf(stderr, "Distribution: (#entries => #times)\n");
	max_occ = max_ent = 0;
	for (j = 1; j <= max; j++) {
		int k = 0;
		for (i = 0; i < BUCKETS; i++) {
			if (occ[i] == j)
				k++;
		}
		if (k > max_occ) {
			max_occ = k;
			max_ent = j;
		}
		printf("%d %d\n", j, k);
	}
	fprintf(stderr, "Most frequent number of entries: %d (%d times)\n",
		max_ent, max_occ);
}

