/*
   "hash_func.c" - part of "RAGMAAN, een anagrammengenerator" 

   Copyright (C) 1999 Raymond Zandbergen

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   The maintainer of this program is Raymond Zandbergen (ray@wirehub.nl)
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "ragmaan.h"
#include "hash_func.h"

void
make_hash2 (const char *s, HASH2_KEY_T * hash2)
{
  int chars[26];
  int bit_index = 0;
  int letter_index = 0;
  int chars_threshold = 1;
  int current_hash_word = 0;
  int hash_word_index = 0;

  char_count (s, chars);
  for (;;)
    {
      if (chars[letter_index] >= chars_threshold)
	current_hash_word |= (1 << bit_index);
      letter_index++;
      if (letter_index >= 26)
	{
	  letter_index = 0;
	  chars_threshold++;
	}
      bit_index++;
      if (bit_index >= NOF_HASH2_BITS)
	{
	  bit_index = 0;
	  hash2[hash_word_index] = current_hash_word;
	  hash_word_index++;
	  current_hash_word = 0;
	  if (hash_word_index >= NOF_HASH2_WORDS)
	    break;
	}
    }
}

void
char_count (const char *s, int *chars)
{
  int i;
  int c;

  for (i = 0; i < 26; i++)
    chars[i] = 0;

  for (i = 0; s[i]; i++)
    {

      c = tolower (s[i]) - 'a';
      if (c >= 0 && c < 26)
	chars[c]++;
    }
}

int
is_sub (int *chars, int *chars_sub)
{
  int i;

  for (i = 0; i < 26; i++)
    {

      if (chars_sub[i] > chars[i])
	return 0;
    }
  return 1;
}

int
is_sub2 (int *chars, const char *sub)
{
  int sub_chars[26];

  char_count (sub, sub_chars);
  return is_sub (chars, sub_chars);
}

int
is_sub3 (char *s, char *sub)
{
  int s_chars[26];
  int sub_chars[26];

  char_count (s, s_chars);
  char_count (sub, sub_chars);

  return is_sub (s_chars, sub_chars);
}

void
subtract (char *total, char *subset)
{
  int total_char_count[26];
  int subset_char_count[26];
  int i, j, k = 0;

  char_count (total, total_char_count);
  char_count (subset, subset_char_count);

  for (i = 0; i < 26; i++)
    {

      for (j = 0; j < total_char_count[i] - subset_char_count[i]; j++)
	{

	  total[k++] = 'a' + i;
	}
    }
  total[k] = 0;
}
