shiogi

http://homepage1.nifty.com/asagi/program/program01.html

なんか変にやる気がでたので書き直してみたら結果が違ってたヨ。

#!/usr/bin/ruby -Ku

class Char
  attr_reader(:char_j)
  attr_reader(:char_e)
  attr_reader(:vowel)
  attr_reader(:consonant)

  def initialize(char_j, char_e, vowel, consonant)
    @char_j = char_j
    @char_e = char_e
    @vowel = vowel
    @consonant = consonant
  end
end

class CharTable
  TABLE = [nil]
  [
    ['',  'a', 1, 0], ['',   'i', 1, 0], ['',   'u', 1, 0], ['',  'e', 1, 0], ['',  'o', 1, 0],
    ['', 'ka', 1, 1], ['',  'ki', 1, 1], ['',  'ku', 1, 1], ['', 'ke', 1, 1], ['', 'ko', 1, 1],
    ['', 'sa', 1, 1], ['', 'shi', 1, 2], ['',  'su', 1, 1], ['', 'se', 1, 1], ['', 'so', 1, 1],
    ['', 'ta', 1, 1], ['', 'chi', 1, 2], ['', 'tsu', 1, 2], ['', 'te', 1, 1], ['', 'to', 1, 1],
    ['', 'na', 1, 1], ['',  'ni', 1, 1], ['',  'nu', 1, 1], ['', 'ne', 1, 1], ['', 'no', 1, 1],
    ['', 'ha', 1, 1], ['',  'hi', 1, 1], ['',  'fu', 1, 1], ['', 'he', 1, 1], ['', 'ho', 1, 1],
    ['', 'ma', 1, 1], ['',  'mi', 1, 1], ['',  'mu', 1, 1], ['', 'me', 1, 1], ['', 'mo', 1, 1],
    ['', 'ya', 1, 1],                      ['',  'yu', 1, 1],                     ['', 'yo', 1, 1],
    ['', 'ra', 1, 1], ['',  'ri', 1, 1], ['',  'ru', 1, 1], ['', 're', 1, 1], ['', 'ro', 1, 1],
    ['', 'wa', 1, 1],                                                               ['',  'o', 1, 0],
    ['',  'n', 0, 1],
  ].each do |data|
    TABLE << Char.new(*data)
  end

  def self.[](index)
    TABLE[index]
  end
end


class Name
  attr_accessor(:name)
  attr_accessor(:value)
  attr_accessor(:vowels)
  attr_accessor(:consonants)

  def initialize
    @name = ""
    @value = 0
    @vowels = 0
    @consonants = 0
  end

  def add(index)
    result = self.dup
    char = CharTable[index]
    result.name += char.char_j
    result.value += index
    result.vowels += char.vowel
    result.consonants += char.consonant
    result
  end

  def to_s
    @name
  end
end


class Shiogi
  SUM_OF_VALUE = 134
  VOWELS = 8
  CONSONANTS = 7
  MIN_INDEX = 1
  MAX_INDEX = 46

  def initialize
    @count = 0
  end

  def main
    @log = open("result.log", "w")
    generate(Name.new, MIN_INDEX)
    @log.close
  end

  def generate(name, start_index)
    start_index.upto(MAX_INDEX) do |index|
      new_name = name.add(index)
      break if new_name.value > SUM_OF_VALUE
      next if new_name.vowels > VOWELS
      next if new_name.consonants > CONSONANTS
      if match?(new_name)
        print(new_name)
        break
      else
        generate(new_name, index)
      end
    end
  end

  def match?(name)
    return false unless name.value == SUM_OF_VALUE
    return false unless name.vowels == VOWELS
    return false unless name.consonants == CONSONANTS
    @count += 1
    true
  end

  def print(name)
    @log.puts sprintf("\r%10d: %s", @count, "#{name}")
    @log.flush
  end
end

Shiogi.new.main

C でも書いてみたところ、両者の結果が一致したので多分こちらが正しい。

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define MAX_LENGTH 30
#define MIN_INDEX 1
#define MAX_INDEX 46
#define SUM_OF_VALUE 134
#define MAX_VOWEL 8
#define MAX_CONSONANT 7

typedef struct {
  char name[MAX_LENGTH];
  int value;
  int vowels;
  int consonants;
} name_t;

typedef struct {
  char *j;
  char *e;
  int vowel;
  int consonant;
} char_t;

char_t table[] = {
  {  "",   "", 0, 0},
  {"あ",  "a", 1, 0}, {"い",   "i", 1, 0}, {"う",   "u", 1, 0}, {"え",  "e", 1, 0}, {"お",  "o", 1, 0},
  {"か", "ka", 1, 1}, {"き",  "ki", 1, 1}, {"く",  "ku", 1, 1}, {"け", "ke", 1, 1}, {"こ", "ko", 1, 1},
  {"さ", "sa", 1, 1}, {"し", "shi", 1, 2}, {"す",  "su", 1, 1}, {"せ", "se", 1, 1}, {"そ", "so", 1, 1},
  {"た", "ta", 1, 1}, {"ち", "chi", 1, 2}, {"つ", "tsu", 1, 2}, {"て", "te", 1, 1}, {"と", "to", 1, 1},
  {"な", "na", 1, 1}, {"に",  "ni", 1, 1}, {"ぬ",  "nu", 1, 1}, {"ね", "ne", 1, 1}, {"の", "no", 1, 1},
  {"は", "ha", 1, 1}, {"ひ",  "hi", 1, 1}, {"ふ",  "fu", 1, 1}, {"へ", "he", 1, 1}, {"ほ", "ho", 1, 1},
  {"ま", "ma", 1, 1}, {"み",  "mi", 1, 1}, {"む",  "mu", 1, 1}, {"め", "me", 1, 1}, {"も", "mo", 1, 1},
  {"や", "ya", 1, 1},                      {"ゆ",  "yu", 1, 1},                     {"よ", "yo", 1, 1},
  {"ら", "ra", 1, 1}, {"り",  "ri", 1, 1}, {"る",  "ru", 1, 1}, {"れ", "re", 1, 1}, {"ろ", "ro", 1, 1},
  {"わ", "wa", 1, 1},                                                               {"を",  "o", 1, 0},
  {"ん",  "n", 0, 1}
};

void generate(name_t*, int);
name_t* add(name_t*, int);
int is_match(name_t*);
void print_name(name_t*);
void print_time(time_t);

int count = 0;
int lognum = 0;
FILE *fp = NULL;
clock_t start_time;

int main(int argc, char *argv[]) {
  start_time = clock();
  generate(NULL, MIN_INDEX);
  print_time(start_time);
  fclose(fp);
  return 0;
}

void generate(name_t *name, int start_index) {
  int index;
  name_t *new_name = NULL;
  for (index = start_index; index <= MAX_INDEX; index++) {
    if (new_name != NULL) free(new_name);
    new_name = add(name, index);
    if (new_name->value > SUM_OF_VALUE) break;
    if (new_name->vowels > MAX_VOWEL) continue; 
    if (new_name->consonants > MAX_CONSONANT) continue;
    if (is_match(new_name)) {
      print_name(new_name);
      break;
    }
    else {
      generate(new_name, index);
    }
  }
  if (new_name != NULL) free(new_name);
}

name_t* add(name_t *name, int index) {
  name_t *new_name;
  
  new_name = malloc(sizeof(name_t));
  if (name == NULL) {
    memset(new_name, 0x00, sizeof(name_t));
  }
  else {
    memcpy(new_name, name, sizeof(name_t));
  }
  strcat(new_name->name, table[index].j);
  new_name->value += index;
  new_name->vowels += table[index].vowel;
  new_name->consonants += table[index].consonant;
  return new_name;
}

int is_match(name_t *name) {
  if (name->value != SUM_OF_VALUE) return 0;
  if (name->vowels != MAX_VOWEL) return 0;
  if (name->consonants != MAX_CONSONANT) return 0;
  return 1;
}

void print_name(name_t *name) {
  if (fp == NULL) fp = fopen("result.log", "w");
  fprintf(fp, "%10d: %s\n", ++count, name->name);
}

void print_time(time_t start_time) {
  double sec = (double)(clock() - start_time) / CLOCKS_PER_SEC;
  int hour = (int)sec / (60 * 60);
  int min = ((int)sec % (60 * 60)) / 60;
  double msec;

  sec = fmod(sec, 60.0);
  msec = fmod(sec, 1.0) * 100;
  fprintf(fp, "\n所要時間:");
  if (hour > 0) fprintf(fp, " %d 時間", hour);
  if (min > 0) fprintf(fp, " %02d 分", min);
  fprintf(fp, " %02d%02d\n", (int)sec, (int)msec);
}
$ gcc -Wall shiogi.c -o shiogi -O4 ↵
./shiogi ↵

しかしやはり C は速い。