引っ越したjyokun

プログラムブログになるのかもしれない

ちょー久しぶり。ダイアリーから引っ越した。
7年以上放置している間に実社会でも60Hzから50Hzへ引っ越している。

Twitterの診断メーカーで「ことばのはしご」なるものが流行っていた。
shindanmaker.com

こーゆーのを見て、参加もせずに「任意のスタートとゴールでつなげることができるのかなあ?」などという方向ばかり考えてしまう人なので、早速「豚辞書」を読んで探索するプログラムを書いてみた。

豚辞書はこれ↓
【非公式】豚辞書 第14版【再頒布】 » う~ん、いや、気のせいじゃないの?

C#のコード。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace LadderCheck {
    class Program {
        static void Main(string[] args) {
            var length = 3;

            var list = new List<string>();
            using (var file = new StreamReader("buta014.dic", Encoding.GetEncoding("shift_jis"))) {
                while (!file.EndOfStream) {
                    var word = file.ReadLine();
                    if (word.Length == length) {
                        list.Add(word);
                    }
                }
            }

            var queueIndexes = new Queue<int>();
            queueIndexes.Enqueue(0);
            var restIndexes = Enumerable.Range(1, list.Count - 1).ToList();
            do {
                var word = list[queueIndexes.Dequeue()];
                // ループ中に削除するため逆順
                for (var i = restIndexes.Count - 1; i >= 0; i--) {
                    var j = restIndexes[i];
                    if (word.Zip(list[j], (x, y) => x == y).Count(x => x) == length - 1) {
                        queueIndexes.Enqueue(j);
                        restIndexes.RemoveAt(i);
                    }
                }
            } while (queueIndexes.Count > 0);

            Console.WriteLine($"残り{restIndexes.Count}個");
            foreach (var i in restIndexes) {
                Console.WriteLine(list[i]);
            }
        }
    }
}

とりあえず一番最初にある単語(「あーく」でした)とつながっているのを探して残ったものを表示する。
エラーなく一発で動作、数秒で実行終了。めでたい。
こんな結果になったよー。

残り11個
ごむて
ごむわ
だびで
でにむ
でぱが
ぱぷあ
ぴくる
へちま
ぺぷし
ゆれも
らぢを

これ以外の3文字単語同士は豚辞書の言葉だけでつなげることができるんだって。

久しぶり。コンビネーションのクラスが必要だったので作ってみた。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Combinations {
    public class Combinations<T> : IEnumerable<IEnumerable<T>> {
        private T[] _source;
        private int _subsetLength;

        public Combinations(IList<T> source, int subsetLength) {
            _source = source.ToArray();
            _subsetLength = subsetLength;
        }

        public IEnumerator<IEnumerable<T>> GetEnumerator() {
            int[] indices = Enumerable.Range(0, _subsetLength).ToArray();
            int lastTopIndex = _source.Length - _subsetLength;

            for (; ; ) {
                yield return indices.Select(i => _source[i]);

                for (int i = _subsetLength - 1; ; i--) {
                    if (i < 0) yield break;

                    if (indices[i] < lastTopIndex + i) {
                        indices[i]++;
                        for (int j = i + 1; j < _subsetLength; j++) {
                            indices[j] = indices[j - 1] + 1;
                        }
                        break;
                    }
                }
            }
        }

        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }
    }

    public static class Program {
        static void Main(string[] args) {
            string[] values = { "竜", "虎", "兎", "燕", "鯉", "星" };
            Combinations<string> c = new Combinations<string>(values, 2);
            foreach (IEnumerable<string> it in c) {
                Console.WriteLine(String.Join(",", it));
            }
            Console.ReadKey();
        }
    }
}