/*
    ragmaan/hash_func.c            (C) 2003 Raymond (zandbergen@home.nl)

    "ragmaan" is an anagram generator

    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "ragmaan.h"
#include "hash_func.h"

void
make_hash2 (const gchar * s, HASH2_KEY_T * hash2)
{
  gint chars[26];
  gint bit_index = 0;
  gint letter_index = 0;
  gint chars_threshold = 1;
  gint current_hash_word = 0;
  gint 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 gchar * s, gint * chars)
{
  gint i;
  gint 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]++;
    }
}

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

  for (i = 0; i < 26; i++)
    {
      if (chars_sub[i] > chars[i])
	return 0;
    }
  return 1;
}

gint
is_sub2 (gint * chars, const gchar * sub)
{
  gint sub_chars[26];

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

gint
is_sub3 (gchar * s, gchar * sub)
{
  gint s_chars[26];
  gint sub_chars[26];

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

  return is_sub (s_chars, sub_chars);
}

void
subtract (gchar * total, gint * subset_char_count)
{
  gint total_char_count[26];
  gint i, j, k = 0;

  char_count (total, total_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;
}

void
subtract2 (gchar * total, gint * total_char_count, gchar * subset)
{
  gint subset_char_count[26];
  gint i, j, k = 0;

  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;
}

void
subtract3 (gchar * total, gchar * subset)
{
  gint total_char_count[26];
  gint subset_char_count[26];
  gint 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;
}
