安野光雅しりとりファンのブログ

絵本「しりとり」について書いてます

安野光雅しりとりファンのブログ2

しりとりのパターンをプログラミングで調べる、と言ったものの、むか〜しむかしに学校でC++を少し齧った程度で、もう何年もコードなど書いていないのです。

初歩から勉強し直すことだし、いい機会なので、まだ触ったことのない言語でやってみることにしました。javaです。本屋さんの理工書の棚にあるjavaの本の中で一番優しそうな顔をしている「javaの絵本」というのを買ってきました。これを選んだのは大正解でした。図が多いし平易な言葉で書いてくれているので、ページがサクサク進んで、「学習が捗っている実感」があるのです。

他の本とは厚みや文字の量が全然違うので、初心者向けのかなりざっくりとした内容なのだろうな…と若干気にはなりますが、ひとまずはこの1冊を理解しよう、と決めて進めていきました。C++と共通点が多いことがわかり、懐かしい気持ちでサンプルプログラムを書いたり、エラーを直したりするうちに半分くらい終わり、ここらへんでもうしりとり書けそうだな、と思ったので、学習と並行して書き始めました。

完成したのがこれです。

   class Annosiritori{
	public static void main(String[] args){
		Word word=new Word();
		word.s=0;
		String[]def1={"さる","きびだんご","くま","しるこ","こあら","すもも","そば","ごま","せなか","あさひ","うし","えんどうまめ","いわし","おに","けんびきょう","かれーらいす"};
		String[]def2={"かじか","るーれっと","ばすけっと","すし","にんにく","めがね","ものほしざお","ごぼう","ます","らむね","しか","ひしもち","うみがめ","こなや"};
		String[]def3={"すもう","かけす","やじろべえ","くつ","おかめ","とうがらし","かめ","ねじりあめ","ちからこぶ","とけい","からす","ねずみ","うめ","しじみ","めぐすり"};
		String[]def4={"しんでれら","いぬ","うきわ","りんごのき","めんたいこ","めがね","つるはし","ぶるどっぐ","めかくし","すずめ","みつば","えんま","するめ","めざし","みそ"};
		String[]def5={"ばす","そば","ぐらんぷり","しらうお","まらかす","らっぱ","こだいこ","ねこ","しまうま","めだか","きうい","しらさぎ","わまわし","ぬすびとはぎ"};
		String[]def6={"しろ","こめ","いなほ","こま","ぎょうじ","すもう","ばんぺい","かっぱ","りんご","おっとせい","かいこ","まき","すいか","ぎんぱい","ぱんけーき"};
		String[]def7={"じんちょうげ","いど","ほね","いか","めざし","きもの","ぱんだ","ごりら","ろうそく","いも","かずのこ","きのこ","うぐいす","まさかり","こたつ","かっぱのこ"};
		String[]def8={"くびわ","すべりだい","つき","だんご","こんぶ","もも","のこぎり","げた","りす","かぶと","らっきょう","ねぎ","こうもりがさ","しま","どうだんつつじ"};
		String[]def9={"わかめ","たいこ","さい","じしゃく","ぶーつ","とかげ","ぎんか","きのこ","うま","すずめ","まんねんひつ","もみじ","りんどう","ごま","いしがき"};
		String[]def10={"かに","じどうしや","めいろ","こがたな","つくえ","つきみそう","こすもす","げた","まんとひひ","めじろ","きじ","くつ","まんと","いけ","うずら"};
		String[]def11={"ひこうき","らっぱ","にじ","じんべい","えもんかけ","すのこ","けむし","ろば","うき","とき","たいこ","やし","ろうそく","つきみ","なす"};
		String[]def12={"いす","す","こぶ","しない","くつべら","こもり","ばけつ","きんこ","きつつき","けいと","じしゃく","みつばち","ぱーま","きつね","しらぎく"};
		String[]def13={"くものす","こおろぎ","きんのしゃちほこ","りす","ちえのわ","すべりひゆ","ぶらんこ","ねこ","とうもろこし","いんき","つぼ","らくご","まつ","すいか","くじら"};
		String[]def14={"ゆうれい","すみ","わさび","すいか","ぼんぼり","かたばみ","こいし","こども","らくだ","ぎんこう","ごみばこ","つきみそう","こまつな","しい","きんもくせい"};
		String[]def15={"しめなわ","かものはし","うみう","みそさざい","うめぼし","だいがく","いのこづち","うずら","こおり","ももたろう","なきむし","みちしるべ","びわ","いわ","りんご","いも"};
		String[]def16={"りぼん","らん","ちょうちん","もん","べーこん","わん"};
		String[]bt1=word.comp(def1,def2);
		String[]bt2=word.comp(def3,def4);
		String[]bt3=word.comp(def5,def6);
		String[]bt4=word.comp(def7,def8);
		String[]bt5=word.comp(def9,def10);
		String[]bt6=word.comp(def11,def12);
		String[]bt7=word.comp(def13,def14);
		String[]bt8=word.comp(def15,def16);
		String[]ct1=word.comp(bt1,bt2);
		String[]ct2=word.comp(bt3,bt4);
		String[]ct3=word.comp(bt5,bt6);
		String[]ct4=word.comp(bt7,bt8);
		String[]dt1=word.comp(ct1,ct2);
		String[]dt2=word.comp(ct3,ct4);
		String[]ans=word.comp(dt1,dt2);
		int count=0;
		for(int i=0;i<ans.length;i++){
			if(ans[i]!=null) System.out.println(1+i+" "+ans[i]);
		}
	}
}
class Word{
	int s;
	String[]comp(String[]st, String[]st2){
		String[]bt=new String[1650];
		for(int y=0;y<(st2.length);y++){
			if(st2[y]==null) continue;
			for(int x=0;x<(st.length);x++){
				if(st[x]==null) break;
				int len=st[x].length();
				String bottom=st[x].substring(len-1,len);
				String top=st2[y].substring(0,1);
				int jud=bottom.compareTo(top);
				if(jud==0){
					bt[s]=st[x]+st2[y];
					s++;
				}
			}
		}
		s=0;
		return bt;
	}
} 

正直言ってめちゃくちゃ恥ずかしいのですが。

「基本が分かってないなー」

「普通そういう書き方しないんだよ」

「この部分効率悪くない?」

とか思われるんだろうなと。やっぱりこんなブログやめようかなと思うくらいなのですが。

でも学習過程を残すのは意味のあることと思うので、恥を忍んで、続けます。

最初、別の方法で書いたのですが、メモリが足りないのか、実行しても途中で止まってしまうので、メモリに優しそうな方法を考えました。

1ページ(def1)の単語と2ページ(def2)の単語をそれぞれひとつずつ抽出して比較し、しりとりになっていれば、そのふたつを繋げた文字列を新たに配列bt1に格納していくやり方です。

例えば

「さる」「かじか」→しりとりにならないので、次の単語に進む

「きびだんご」「かじか」→しりとりにならないので、次の単語に進む

「くま」「かじか」→しりとりにならな

(省略)

「せなか」「かじか」→しりとりになるので、「せなかかじか」を新たに作る

これを全ての組み合わせで行うと

1 せなかかじか

2 さるるーれっと

3 そばばすけっと

4 かれーらいすすし

5 おににんにく

6 えんどうまめめがね

7 すももものほしざお

8 きびだんごごぼう

9 くまます

10 ごまます

11 こあららむね

12 うししか

13 いわししか

14 あさひひしもち

15 けんびきょううみがめ

16 しるここなや

この16個の文字列が、配列bt1[0]〜bt1[15]に格納されます。

同じように3ページ目(def3)と4ページ目(def4)の単語も比較して、しりとりになっていれば繋げて、配列bt2に格納します。 さらに続けます。

def5とdef6を繋げたものをbt3

def7とdef8を繋げたものをbt4

(省略)

def15とdef16を繋げたものをbt8

これで最後のページまで来ました。

次は、さっきの工程で新しく出来た配列bt1からbt8までを比較していきます。

bt1とbt2を繋げたものをct1に格納します。ct1の中身はこうなります。

1 さるるーれっととうがらししんでれら

2 そばばすけっととうがらししんでれら

3 さるるーれっととけいいぬ

4 そばばすけっととけいいぬ

5 くまますすもううきわ

6 ごまますすもううきわ

7 けんびきょううみがめめぐすりりんごのき

8 すももものほしざおおかめめんたいこ

9 せなかかじかかめめんたいこ

10 うししかかめめんたいこ

11 いわししかかめめんたいこ

12 えんどうまめめがねねじりあめめんたいこ

13 こあららむねねじりあめめんたいこ

14 きびだんごごぼううめめんたいこ

15 すももものほしざおおかめめがね

16 せなかかじかかめめがね

17 うししかかめめがね

18 いわししかかめめがね

19 えんどうまめめがねねじりあめめがね

20 こあららむねねじりあめめがね

21 きびだんごごぼううめめがね

22 おににんにくくつつるはし

23 あさひひしもちちからこぶぶるどっぐ

24 すももものほしざおおかめめかくし

25 せなかかじかかめめかくし

26 うししかかめめかくし

27 いわししかかめめかくし

28 えんどうまめめがねねじりあめめかくし

29 こあららむねねじりあめめかくし

30 きびだんごごぼううめめかくし

31 せなかかじかかけすすずめ

32 うししかかけすすずめ

33 いわししかかけすすずめ

34 せなかかじかからすすずめ

35 うししかからすすずめ

36 いわししかからすすずめ

37 えんどうまめめがねねずみみつば

38 こあららむねねずみみつば

39 かれーらいすすししじみみつば

40 しるここなややじろべええんま

41 せなかかじかかけすするめ

42 うししかかけすするめ

43 いわししかかけすするめ

44 せなかかじかからすするめ

45 うししかからすするめ

46 いわししかからすするめ

47 すももものほしざおおかめめざし

48 せなかかじかかめめざし

49 うししかかめめざし

50 いわししかかめめざし

51 えんどうまめめがねねじりあめめざし

52 こあららむねねじりあめめざし

53 きびだんごごぼううめめざし

54 えんどうまめめがねねずみみそ

55 こあららむねねずみみそ

56 かれーらいすすししじみみそ

1ページから4ページまでのしりとりが全パターンありそうです。

この調子で続けて、最終的に1ページから16ページまでのしりとりが、配列ansに入ります。

ansの中身を全て載せると長いので、とりあえず数だけ書いておきます。

897です。 897通りのパターンで、ゴールできるようです。

合っているか分かりません。どうですかね?すごい凡ミスがあるかもしれません。だからこんなブログ書いてます。

ちなみにclass Wordの部分は最初は無くて、mainのほうだけで書いたのですが、それだとjavaを勉強している意味がないと思って、半ば無理やり分離しています。 クラスを効果的に使えるプログラムを書けるようになりたいな、と思います。

次回は検証のため、別のコードを載せてみます。