marunomaruno-memo

marunomaruno-memo

[Java] アナグラムを作る

2012年03月19日 | Java
[Java] アナグラムを作る
================================================================================

アナグラム (anagram) とは、言葉遊びのひとつ。単語または文の中の文字をいくつか入れ替えることによってまったく別の意味にさせる遊びである。
(ウィキペディア、http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%8A%E3%82%B0%E3%83%A9%E3%83%A0 より)

ただ、今回のプログラムは、意味はなく、文字を入れ替えるだけである。
ただし、つぎの点には気をつけた。
・同じ文字列にならない
・単語の先頭に行頭禁則和字が来ない

行頭禁則和字は以下の文字とする。
    ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎ


実際に必要なメソッドは、つぎの 2 つ。

public static String anagram(String s)        文字列のアナグラムを作る。
private static boolean isIllegalCharacters(List<Character> list) 
                                              不正な文字列かどうか判断する。 

これとは別に、単なる配列検索のユーティリティとして、つぎのメソッドを用意した。

private static int search(char[] a, char key) 配列から値を検索する。


□ Anagram.java
---
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Anagram {

    public static void main(String[] args) {

        System.out.println(anagram(""));
        System.out.println(anagram("ア"));
        System.out.println(anagram("アイスクリーム"));
        System.out.println(anagram("ドック"));
        System.out.println(anagram("キャット"));
    }

    /**
     * 文字列のアナグラムを作る。
     * ただし、アナグラムを作れないような文字数のときは、その文字列をそのまま返す。
     * 
     * @param s
     *            文字列
     * @return s のアナグラム
     */
    public static String anagram(String s) {
        if (s.length() < 2) {
            return s;
        }
        
        List<Character> list = new ArrayList<Character>();
        for (char c : s.toCharArray()) {
            list.add(c);
        }

        char[] cs;
        
        do {    // 同じ文字列でないようにする
            do {    // 不正な文字列でないようにする
                Collections.shuffle(list);
            } while (isIllegalCharacters(list));
            
            cs = new char[list.size()];
            for (int i = 0; i < cs.length; i++) {
                cs[i] = list.get(i);
            }
            
        } while (String.valueOf(cs).equals(s));
        
        return String.valueOf(cs);
    }

    /**
     * 不正な文字列かどうか判断する。 
     * ここでは、行頭禁則文字があると、不正な文字列とする。
     * 行頭禁則和字は以下の文字
     *     ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎ
     * @param list
     *            文字列を表すリスト
     * @return 不正な文字列であれば、true
     */
    private static boolean isIllegalCharacters(List<Character> list) {
        final char[] START_LINE_ILLEGAL_CHARACTERS = { 
            'ヽ', 'ヾ', 'ー', 
            'ァ', 'ィ', 'ゥ', 'ェ', 'ォ', 'ッ', 'ャ', 'ュ', 'ョ', 'ヮ', 'ヵ', 'ヶ', 
            'ぁ', 'ぃ', 'ぅ', 'ぇ', 'ぉ', 'っ', 'ゃ', 'ゅ', 'ょ', 'ゎ',
        };

        return search(START_LINE_ILLEGAL_CHARACTERS, list.get(0)) != -1;
    }

    /**
     * 指定された char 値の配列から指定された値を検索する。
     * @param a 検索される配列
     * @param key 検索される値
     * @return 配列に検索キーがある場合は検索キーのインデックス。 検索キーがリストにない場合は -1.
     */
    private static int search(char[] a, char key) {
        for (int i = 0; i < a.length; i++) {
            if (a[i] == key) {
                return i;
            }
        }

        return -1;
    }

}
---

□ 実行結果例
---
リアイクースム
ドクッ
キットャ
---
                                                                            以上


最新の画像もっと見る

コメントを投稿