オヤジギャグジェネレーティングエンジンSeenya

オヤジギャグ生成エンジンです。洒落にしたい言葉をローマ字で引数に渡すと、辞書から母音が同じ言葉を抽出して出力します。

辞書ファイルは、je-edict-kanji.txtですが、探せない人のために、<a href="https://github.com/fygar256/dic.txt/blob/master/je-edict-kanji.txt">ここ</a>に置いておきます。
n(ん)の後の母音や「やゆよ」の前には、nの後に'を付けて値渡しをしてください。
for ex. seenya shin\'ya

コードをccでコンパイルして、辞書ファイルと同じディレクトリに置いて、実行してください。
`$ cc seenya.c -o seenya`

```seenya.c
/*
 * 'seenya' oyaji joking engine ver 0.84
 */

#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <stdbool.h>
#include  <ctype.h>

#define WL  256
#define RS  4
char  *romaji[]={"a","i","u","e","o",
                "ka","ki","ku","ke","ko",
                "sa","si","su","se","so",
                "ta","ti","tu","te","to",
                "na","ni","nu","ne","no",
                "ha","hi","hu","he","ho",
                "ma","mi","mu","me","mo",
                "ya","yi","yu","ye","yo",
                "ra","ri","ru","re","ro",
                "wa","wi","wu","we","wo",
                "ga","gi","gu","ge","go",
                "za","zi","zu","ze","zo",
                "ja","ji","ju","je","jo",
                "da","di","du","de","do",
                "ba","bi","bu","be","bo",
                "pa","pi","pu","pe","po",
                "fa","fi","fu","fe","fo",
                "ta","ti","tsu","te","to",
                "n",
                "dza","dzi","dzu","dze","dzo",
                "kya","kyi","kyu","kye","kyo",
                "sha","shi","shu","she","sho",
                "cha","chi","chu","che","cho",
                "nya","nyi","nyu","nye","nyo",
                "hya","hyi","hyu","hye","hyo",
                "mya","myi","myu","mye","myo",
                "rya","ryi","ryu","rye","ryo",
                "gya","gyi","gyu","gye","gyo",
                "dya","dyi","dyu","dye","dyo",
                "bya","byi","byu","bye","byo",
                "pya","pyi","pyu","pye","pyo", };
char  origword[WL][RS];
char  vowels[WL][RS];
int   beats;
char  infile[]="/home/gar/dic/je-edict-kanji.txt";
#define SOT (30*5)

bool  isvowel(char c) {
  switch(c) {
    case 'a': case 'i': case 'u':
    case 'e': case 'o': return(true);
    default:
      return(false);
  }
}

int decomposite_word(char *o,char word[WL][RS]) {
    int i,j,l;

    j=0;
    while(1) {

      if (*o=='\0') { // 行末か？
        word[j][0]='\0';
        return(j);
        }

      if (!isvowel(*o)&&(*o==*(o+1))) { // 小さい 'っ'の処理
        word[j][0]='x';
        word[j][1]='\0';
        o++;
        j++;
        continue;
        }

/*
      if (*o=='n') { // "ん"の処理

        if (*(o+1)=='\0') { // 次に行末
          word[j][0]='u';
          word[j][1]='\0';
          o++;
          j++;
          return(j);
          }

        if (*(o+1)=='\'') { // 次に '
          word[j][0]='u';
          word[j][1]='\0';
          o+=2;
          o++;
          j++;
          continue;
          }

        if (!isvowel(*(o+1))&&(*(o+1)!='y')) { // 次に子音か
          word[j][0]='u';
          word[j][1]='\0';
          o++;
          j++;
          continue;
          }

        }
*/

      for(i=0;i<SOT;i++) {  // ローマ字テーブルにマッチするか？
        l=strlen(romaji[i]);
        if (strncmp(romaji[i],o,l)==0) {
          strcpy(&(word[j][0]),romaji[i]);
          o+=l;
          j++;

          if (*o=='-') { // 長音　−　の処理 (母音を重ねる）
            l=strlen((char *)(&(word[j-1][0])));
            word[j][0]=word[j-1][l-1];
            word[j][1]='\0';
            o++;
            j++;
            } 
          break;
          }
        }

      if (i==SOT) {   // 標準以外の記法の文字の場合
        while(*o!='\0') {
          if (!isvowel(*o++))
            continue;
          word[j][0]=*(o-1);
          word[j][1]='\0';
          j++;
          break;
          }
        }
    }
}

void  get_vowels(char word[WL][RS]) {
  int   l;
  for(int i=0;word[i][0]!='\0';i++) {
    l=strlen((char *)(&(word[i][0])));
    vowels[i][0]=word[i][l-1];
    vowels[i][1]='\0';
    }
}

int eval_word(char w[WL][RS]) {
  int l;
  for(int i=0;w[i][0]!='\0';i++) {
    l=strlen((char *)(&(w[i][0])));
    if (vowels[i][0]!=w[i][l-1])
      return(0);
    }
  return(1);
}

void  printword(char word[WL][RS]) {
  int i;
  for(i=0;word[i][0]!='\0';i++) {
    printf("%s ",(char *)&(word[i][0]));
    }
  printf("\n");
}

void  printjoke1(char *line) {
  char  d1[1024];

  sscanf(line,"%s",d1);  //最初の単語を飛ばす
  line+=strlen(d1)+1;

  if (!isdigit(*line)) { // ナンバリングされてない（ひとつ）か？
    sscanf(line,"%s",d1);
    printf("%s\n",d1);
    return;
    }
  // ナンバリングされている
  while(1) {
    if (*line=='\0')
       return;
    if (isdigit(*line)&&(*(line+1)=='.')&&(*(line+2)==' ')) {
      line+=3;
      sscanf(line,"%s",d1);
      printf("%s\n",d1);
      line+=strlen(d1)+1;
      while(1) {
        if (isdigit(*line)&&(*(line+1)=='.')&&(*(line+2)==' '))
          break;
        if (*line=='\0')
          break;
        line++;
        }
      } else return;
   }
}

void  joke(char *o,FILE *fp) {
  char  lw[WL];
  char  lword[WL][RS];
  char  line[1024];
  int f;
  int b;

  beats=decomposite_word(o,origword);
  get_vowels(origword);

  while(1) {
      if(fgets(line,1024,fp)==NULL)
        return;
      sscanf(line,"%s",lw);

      b=decomposite_word(lw,lword);

      if (strcmp(lw,o)==0)  // 同じ発音
        continue;
      if (b!=beats)         // 違う拍数
        continue;
      f=eval_word(lword);
      if (f==1)
        printjoke1(line);
    }
}
    
int main(int argc,char *argv[]) {
  char  orig[WL];
  FILE  *fp;

  if (argc==1)
    fscanf((FILE *)stdin,"%s",orig);
  else if (argc==2)
    strcpy(orig,argv[1]);
  else {
    fprintf(stderr,"Usage: %s word\n",argv[0]);
    exit(1);
    }

  fp=fopen(infile,"r");
  if (fp==NULL) {
    fprintf(stderr,"File open error.\n");
    exit(1);
    }
  joke(orig,fp);
  
  fclose(fp);
  exit(0);
}

```

# 実行例
①

```
$ ./seenya oyaji
母体
母胎
土塊
五戒
誤解
五彩
後妻
五体
魚介
魚雷
火先
穂先
除外
古代
誇大
個体
古体
固体
恐い
怖い
肥やし
巨大
去来
お菓子
同じ
書斎
所帯
書体
疎外
阻害
鼠害
疎開
租界
空似
トカイ
都会
都内
隣
トライ
渡来
弱い
齢
弱気
```