質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

解決済

2回答

1682閲覧

アナグラム生成プログラムを再帰などで汎用性を高くしたい

777_superlucky

総合スコア7

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

0グッド

1クリップ

投稿2021/04/07 08:31

編集2021/04/09 09:22

前提・実現したいこと

以前に質問したJavaでのアナグラム・置き換え処理を改善(早く)したいでの回答プログラムを使用して、アナグラムをしていました。最近はローマ字の文をアナグラムした結果を日本語変換して遊んでいたのですが、長文(大体13文字以上)をアナグラムしようとすると処理に半日以上かかってしまいました。
そのため、変換時の処理など考えプログラムを改良した所、処理時間が大分短くなったのですが、文字数に合わせて事前にプログラミングしないといけないような記述になってしまっているため、事前に文字数がわかっていなくても対応できる(1つのプログラムで複数の文字数に対応できる)プログラムを作る事が出来るか質問しました。
もしかしたら以前の回答プログラムで実現したい事が可能なのかもしれないですが、自分では分からなかったため、改善点を指摘していただけるとありがたいです。

発生している問題・エラーメッセージ

文字数が異なる文が複数ある場合、その文字数に合わせたプログラムを用意する必要がある

該当のソースコード

「teratail」(8文字)を対象とした例(この場合、文字数が8文字以外の文字列を扱う事が出来ない)

Java

1import java.io.IOException; 2import java.nio.file.Files; 3import java.nio.file.Path; 4import java.nio.file.Paths; 5import java.nio.file.StandardOpenOption; 6import java.util.ArrayList; 7import java.util.Arrays; 8import java.util.List; 9import java.util.regex.Matcher; 10import java.util.regex.Pattern; 11 12public class Anagram{ 13 static Path path; 14 static String sword; //作成中のアナグラム文 15 static String[] targetArray; //アナグラムの元となる文字列を1文字ずつ配列(後の処理が簡単なためString) 16 static int intA, intB, intC, intD, intE, intF, intG, intH; //targetArrayの要素番号用 17 static List<String> arrayList = new ArrayList<String>(1000000); //作成されたアナグラム文の保管場所 18 19 public static void main(String[] args) { 20 final String targetWord = "teratail"; 21 path = Paths.get("C:\programming\anagram_teratail.txt"); 22 createFile(); 23 targetArray = targetWord.split(""); 24 Arrays.sort(targetArray); 25 one(); 26 } 27 28 static void one() { 29 List<String> oneList = new ArrayList<String>(10); //作成中のアナグラム文の保管場所(eightListまで同様) 30 for(int ai=0; ai<targetArray.length; ai++) { 31 intA = ai; 32 sword = targetArray[ai]; 33 if(notListed(oneList)) { //oneListにswordが無いかチェック(既に作成されていないか確認) 34 oneList.add(sword); 35 two(); //進む 36 } //ある場合、保存時に重複してしまうためそれ以降の文字を追加せずにスキップ 37 sword = sword.substring(0, sword.length()-1); //swordの末尾を削除(次の先頭文字に進むため) 38 } 39 } 40 41 static void two() { 42 List<String> twoList = new ArrayList<String>(10); 43 for(int bi=0; bi<targetArray.length; bi++) { 44 intB = bi; 45 if(intA!=intB) { //targetArrayの要素番号が被っていないかチェック(被る=アナグラムでは無くなるため) 46 sword += targetArray[bi]; 47 if(notListed(twoList)){ 48 twoList.add(sword); 49 three(); 50 } 51 sword = sword.substring(0, sword.length()-1); 52 } 53 } 54 } 55 56 static void three() { 57 List<String> threeList = new ArrayList<String>(10); 58 for(int ci=0; ci<targetArray.length; ci++) { 59 intC = ci; 60 if(intA!=intC && intB!=intC) { 61 sword += targetArray[ci]; 62 if(notListed(threeList) && canString(sword)) { 63 threeList.add(sword); 64 four(); 65 } 66 sword = sword.substring(0, sword.length()-1); 67 } 68 } 69 } 70 71 static void four() { 72 List<String> fourList = new ArrayList<String>(10); 73 for(int di=0; di<targetArray.length; di++) { 74 intD = di; 75 if(intA!=intD && intB!=intD && intC!=intD) { 76 sword += targetArray[di]; 77 if(notListed(fourList) && canString(sword)) { 78 fourList.add(sword); 79 five(); 80 } 81 sword = sword.substring(0, sword.length()-1); 82 } 83 } 84 } 85 86 static void five() { 87 List<String> fiveList = new ArrayList<String>(10); 88 for(int ei=0; ei<targetArray.length; ei++) { 89 intE = ei; 90 if(intA!=intE && intB!=intE && intC!=intE && intD!=intE) { 91 sword += targetArray[ei]; 92 if(notListed(fiveList) && canString(sword)) { 93 fiveList.add(sword); 94 six(); 95 } 96 sword = sword.substring(0, sword.length()-1); 97 } 98 } 99 } 100 101 static void six() { 102 List<String> sixList = new ArrayList<String>(10); 103 for(int fi=0; fi<targetArray.length; fi++) { 104 intF = fi; 105 if(intA!=intF && intB!=intF && intC!=intF && intD!=intF && intE!=intF) { 106 sword += targetArray[fi]; 107 if(notListed(sixList) && canString(sword)) { 108 sixList.add(sword); 109 seven(); 110 } 111 sword = sword.substring(0, sword.length()-1); 112 } 113 } 114 } 115 116 static void seven() { 117 List<String> sevenList = new ArrayList<String>(10); 118 for(int gi=0; gi<targetArray.length; gi++) { 119 intG = gi; 120 if(intA!=intG && intB!=intG && intC!=intG && intD!=intG && intE!=intG && intF!=intG) { 121 sword += targetArray[gi]; 122 if(notListed(sevenList) && canString(sword)) { 123 sevenList.add(sword); 124 eight(); 125 } 126 sword = sword.substring(0, sword.length()-1); 127 } 128 } 129 } 130 131 static void eight() { 132 List<String> eightList = new ArrayList<String>(10); 133 for(int hi=0; hi<targetArray.length; hi++) { 134 intH = hi; 135 if(intA!=intH && intB!=intH && intC!=intH && intD!=intH && intE!=intH && intF!=intH && intG!=intH) { 136 sword += targetArray[hi]; 137 if(notListed(eightList)){ 138 if(canString(sword)){ 139 eightList.add(sword); 140 arrayList.add(sword); 141 System.out.println(sword); 142 if(arrayList.size() == 1000000) { 143 fileWriting(); 144 arrayList.clear(); 145 } 146 } 147 } 148 sword = sword.substring(0, sword.length()-1); 149 } 150 if(intA==7 && intB==6 && intC==5 && intD==4 && intE==3 && intF==2 && intG==1 && intH==0) { //targetWordで作成出来るアナグラムを最後まで作成したかチェック 151 fileWriting(); 152 arrayList.clear(); 153 } 154 } 155 } 156 157 static boolean notListed(final List<String> list) { //リストにswordがないかチェック(ある場合→既に作成されている) 158 if(!(list.contains(sword))){ 159 return true; 160 }else { 161 return false; 162 } 163 } 164 165 static boolean canString(final String Sword) { //日本語に変換されない箇所があるかチェック(実際には複数対応へ) 166 final Pattern patternTwo = Pattern.compile("l[rt]|r[lt]|t[lr]"); //日本語に変換できない文字列(2文字) 167 final Pattern patternThree = Pattern.compile("tt[lr]"); //日本語に変換できない文字列(3文字) 168 final Pattern patternEnd = Pattern.compile("[lrt]$"); 169 Matcher matcherTwo = patternTwo.matcher(Sword); 170 Matcher matcherThree = patternThree.matcher(Sword); 171 Matcher matcherEnd = patternEnd.matcher(Sword); 172 if(!(matcherTwo.find()) && !(matcherThree.find()) && !(matcherEnd.find())) { 173 return true; 174 }else { 175 return false; 176 } 177 } 178 179 public static void createFile(){ //書き込み先のファイルがあるか確認(ある→削除し作成、ない→作成) 180 try { 181 if(Files.exists(path)){ 182 Files.delete(path); 183 } 184 Files.createFile(path); 185 }catch(IOException e) { 186 System.out.println(e); 187 } 188 } 189 190 191 public static void fileWriting(){ //ファイルにリストを追記で書き込み 192 try { 193 Files.write(path, arrayList, StandardOpenOption.APPEND); 194 }catch(IOException e) { 195 System.out.println(e); 196 } 197 } 198}

試したこと

以前の回答案からの変更点として

  1. 生成済みのアナグラム文を再度生成しない
  2. 日本語に変換後にローマ字が残る箇所が出来た時点で、その箇所に続く処理をスキップする(一般的なローマ字入力で変換)

例 「teratail」をアナグラム
アナグラム後の文の先頭2文字が「tr」の文→3文字目以降を追加せずに、2文字目を変更する

補足情報(FW/ツールのバージョンなど)

Eclipse IDE
・Version: 2021-03 (4.19.0)
・Java version: 11.0.9
・JavaコンパイラーはJavaSE-15

アナグラム生成箇所についての質問のため、日本語に変換する所など、生成の動作に支障が無い程度に省略している箇所があります。
個人で遊ぶ用のプログラムのため、Javaの作法から逸脱していたり、適切ではないメソッドを使用している可能性があります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/04/07 10:39

コードを動かして完全に追っている訳ではないので確信は無いのですが、 [Javaでのアナグラム・置き換え処理を改善(早く)したい] https://teratail.com/questions/282663 の質問文中のご提示のコードで、Permutation()メソッドやgen()メソッドが自らを呼び出す再帰/再帰呼び出し(recursion/recursive call)を使っていて、もともと複数の文字列を扱うことができる汎用的なかたちになっていたように思えます。
777_superlucky

2021/04/07 11:31

確かにそのコードの方が汎用的な形をしているのですが、今回の条件(同じ文を再生成しない・日本語変換後にローマ字が残さない)に合うように書き換えるのが出来ず、今回の質問文にあるようなコードになってしまいました。
dodox86

2021/04/07 11:38

なるほど、そう言った経緯を踏まえ、現状のコードを基に、汎用的にしたいと言う主旨ですね。(単なる確認です)
guest

回答2

0

自己解決

質問投稿後も調べたりしたところ、8クイーン問題と今回考えている事が似ていると感じ、アレンジしたコードを書いてみました。
テストとして「teratail」をアナグラムしたところ、考えていたような動作を行う事が出来ました。
ただ、実際に日本語に変換したり、複数の対象文に正規表現を対応させるなどと言った点で改善点が数多くありますが、今回の質問にて解決したかった事が出来たので、自己解決とさせていただきます。
回答やコメントしていただきありがとうございました。
また質問する機会がありましたら、その時も回答していただけるととても助かります。

java

1import java.io.IOException; 2import java.nio.file.Files; 3import java.nio.file.Path; 4import java.nio.file.Paths; 5import java.nio.file.StandardOpenOption; 6import java.util.ArrayList; 7import java.util.Arrays; 8import java.util.regex.Matcher; 9import java.util.regex.Pattern; 10 11 12public class Anagram{ 13 static int targetSize; 14 static Path path; 15 static boolean[] flag; 16 static int[] targetCount; 17 static String[] anagramArray, targetArray; 18 static String[] alphabetArray = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}; 19 static ArrayList<Integer> aList = new ArrayList<Integer>(); 20 static ArrayList<Integer> bList = new ArrayList<Integer>(); 21 static ArrayList<Integer> cList = new ArrayList<Integer>(); 22 static ArrayList<Integer> dList = new ArrayList<Integer>(); 23 static ArrayList<Integer> eList = new ArrayList<Integer>(); 24 static ArrayList<Integer> fList = new ArrayList<Integer>(); 25 static ArrayList<Integer> gList = new ArrayList<Integer>(); 26 static ArrayList<Integer> hList = new ArrayList<Integer>(); 27 static ArrayList<Integer> iList = new ArrayList<Integer>(); 28 static ArrayList<Integer> jList = new ArrayList<Integer>(); 29 static ArrayList<Integer> kList = new ArrayList<Integer>(); 30 static ArrayList<Integer> lList = new ArrayList<Integer>(); 31 static ArrayList<Integer> mList = new ArrayList<Integer>(); 32 static ArrayList<Integer> nList = new ArrayList<Integer>(); 33 static ArrayList<Integer> oList = new ArrayList<Integer>(); 34 static ArrayList<Integer> pList = new ArrayList<Integer>(); 35 static ArrayList<Integer> qList = new ArrayList<Integer>(); 36 static ArrayList<Integer> rList = new ArrayList<Integer>(); 37 static ArrayList<Integer> sList = new ArrayList<Integer>(); 38 static ArrayList<Integer> tList = new ArrayList<Integer>(); 39 static ArrayList<Integer> uList = new ArrayList<Integer>(); 40 static ArrayList<Integer> vList = new ArrayList<Integer>(); 41 static ArrayList<Integer> wList = new ArrayList<Integer>(); 42 static ArrayList<Integer> xList = new ArrayList<Integer>(); 43 static ArrayList<Integer> yList = new ArrayList<Integer>(); 44 static ArrayList<Integer> zList = new ArrayList<Integer>(); 45 static ArrayList<ArrayList<Integer>> azList = new ArrayList<ArrayList<Integer>>(26); 46 static ArrayList<String> arrayList = new ArrayList<String>(1000000); 47 48 public static void main(String[] args) { 49 preparation("teratail"); 50 } 51 52 public static void preparation(final String tsc) { 53 path = Paths.get("C:\programming\anagram_" + tsc + ".txt"); 54 createFile(); 55 anagramArray = new String[targetSize]; 56 targetArray = tsc.split(""); 57 Arrays.sort(targetArray); 58 targetSize = tsc.length(); 59 int[] alphabetCount = new int[alphabetArray.length]; 60 for(int x=0; x<targetArray.length; x++) { 61 for(int y=0; y<alphabetArray.length; y++) { 62 if(targetArray[x].equals(alphabetArray[y])) { //対象文に含まれている文字が何回目の登場なのか計算 63 targetArray[x] += alphabetCount[y]; //英文字の後ろに登場回数を追加 64 alphabetCount[y]++; 65 } 66 } 67 } 68 flag = new boolean[targetSize]; 69 for(int f=0; f<flag.length; f++) { 70 flag[f] = false; 71 } 72 anagramArray = new String[targetSize]; 73 listReset(); 74 set(0); 75 fileWriting(); //書き込めなかったarrayListを書き込み 76 } 77 78 static void set(int i) { 79 for(int f=0; f<targetSize; f++) { 80 if(flag[f]==false) { 81 for(int a=i+1; a<targetSize; a++) { 82 anagramArray[a] = null; 83 } 84 anagramArray[i] = targetArray[f]; 85 if(anagramCheck(anagramArray) && regularExpression(anagramArray)) { //保存しない条件(日本語に変換出来ないなど)を満たすかどうか 86 if(i == targetSize-1) { 87 print(anagramArray); 88 }else { 89 flag[f] = true; 90 set(i+1); 91 flag[f] = false; 92 } 93 } 94 } 95 } 96 } 97 98 static void print(final String[] psa) { 99 String ps = ""; 100 for(int i=0; i<targetSize; i++) { 101 ps += psa[i].replaceAll("[0-9]", ""); 102 } 103 Pattern patternEnd = Pattern.compile("[lrt]$"); 104 Matcher matcherEnd = patternEnd.matcher(ps); 105 if(!(matcherEnd.find())) { 106 arrayList.add(ps); 107 if(arrayList.size() == 1000000) { 108 fileWriting(); 109 arrayList.clear(); 110 } 111 } 112 } 113 114 static boolean anagramCheck(final String[] acsa) { 115 listReset(); 116 for(int i=0; i<acsa.length; i++) { 117 if(acsa[i]!=null) { 118 final String oneCharacter = acsa[i].replaceAll("[0-9]", ""); 119 final int number = Integer.parseInt(acsa[i].replaceAll("[a-z]", "")); 120 switch(oneCharacter) { 121 case "a" -> azList.get(0).add(number); //対象文を先頭から見ていき、どの英文字がどんな順番で含まれているかを保存 122 case "b" -> azList.get(1).add(number); 123 case "c" -> azList.get(2).add(number); 124 case "d" -> azList.get(3).add(number); 125 case "e" -> azList.get(4).add(number); 126 case "f" -> azList.get(5).add(number); 127 case "g" -> azList.get(6).add(number); 128 case "h" -> azList.get(7).add(number); 129 case "i" -> azList.get(8).add(number); 130 case "j" -> azList.get(9).add(number); 131 case "k" -> azList.get(10).add(number); 132 case "l" -> azList.get(11).add(number); 133 case "m" -> azList.get(12).add(number); 134 case "n" -> azList.get(13).add(number); 135 case "o" -> azList.get(14).add(number); 136 case "p" -> azList.get(15).add(number); 137 case "q" -> azList.get(16).add(number); 138 case "r" -> azList.get(17).add(number); 139 case "s" -> azList.get(18).add(number); 140 case "t" -> azList.get(19).add(number); 141 case "u" -> azList.get(20).add(number); 142 case "v" -> azList.get(21).add(number); 143 case "w" -> azList.get(22).add(number); 144 case "x" -> azList.get(23).add(number); 145 case "y" -> azList.get(24).add(number); 146 case "z" -> azList.get(25).add(number); 147 } 148 }else { 149 break; 150 } 151 } 152 for(int x=0; x<azList.size(); x++) { 153 if(azList.get(x).size()==1) { //各リストの先頭の数字が0かどうか(0ではない→再生成の可能性大) 154 if(azList.get(x).get(0)!=0) { 155 return false; 156 } 157 }else if(1<azList.get(x).size()) { 158 for(int y=0; y<azList.get(x).size()-1; y++) { 159 if(azList.get(x).get(y+1)<azList.get(x).get(y)) { //各リストの要素が小さい順かどうか(大きい順→再生成の可能性大) 160 return false; 161 } 162 } 163 } 164 } 165 return true; 166 } 167 168 static boolean regularExpression(final String[] resa) { 169 String res = ""; 170 for(int i=0; i<resa.length-1; i++) { 171 if(resa[i] == null) { 172 break; 173 }else { 174 res += resa[i].replaceAll("[0-9]", ""); 175 } 176 } 177 Pattern patternFirst = Pattern.compile("^tt"); 178 Pattern patternTwo = Pattern.compile(".*l[rt]|r[lt]|t[lr].*"); 179 Pattern patternThree = Pattern.compile(".*tt[lr].*"); 180 Matcher matcherFirst = patternFirst.matcher(res); 181 Matcher matcherTwo = patternTwo.matcher(res); 182 Matcher matcherThree = patternThree.matcher(res); 183 184 if(2<=resa.length) { 185 if(matcherFirst.find() || matcherTwo.find()) { 186 return false; 187 } 188 } 189 if(3<=resa.length) { 190 if(matcherThree.find()) { 191 return false; 192 } 193 } 194 return true; 195 } 196 197 public static void createFile(){ 198 try { 199 if(Files.exists(path)){ 200 Files.delete(path); 201 } 202 Files.createFile(path); 203 }catch(IOException e) { 204 System.out.println(e); 205 } 206 } 207 208 public static void fileWriting(){ 209 try { 210 Files.write(path, arrayList, StandardOpenOption.APPEND); 211 }catch(IOException e) { 212 System.out.println(e); 213 } 214 } 215 216 public static void listReset(){ //上手く動作するようにリセット 217 aList.clear(); 218 bList.clear(); 219 cList.clear(); 220 dList.clear(); 221 eList.clear(); 222 fList.clear(); 223 gList.clear(); 224 hList.clear(); 225 iList.clear(); 226 jList.clear(); 227 kList.clear(); 228 lList.clear(); 229 mList.clear(); 230 nList.clear(); 231 oList.clear(); 232 pList.clear(); 233 qList.clear(); 234 rList.clear(); 235 sList.clear(); 236 tList.clear(); 237 uList.clear(); 238 vList.clear(); 239 wList.clear(); 240 xList.clear(); 241 yList.clear(); 242 zList.clear(); 243 azList.clear(); 244 245 azList.add(0, aList); 246 azList.add(1, bList); 247 azList.add(2, cList); 248 azList.add(3, dList); 249 azList.add(4, eList); 250 azList.add(5, fList); 251 azList.add(6, gList); 252 azList.add(7, hList); 253 azList.add(8, iList); 254 azList.add(9, jList); 255 azList.add(10, kList); 256 azList.add(11, lList); 257 azList.add(12, mList); 258 azList.add(13, nList); 259 azList.add(14, oList); 260 azList.add(15, pList); 261 azList.add(16, qList); 262 azList.add(17, rList); 263 azList.add(18, sList); 264 azList.add(19, tList); 265 azList.add(20, uList); 266 azList.add(21, vList); 267 azList.add(22, wList); 268 azList.add(23, xList); 269 azList.add(24, yList); 270 azList.add(25, zList); 271 } 272}

投稿2021/04/18 12:57

777_superlucky

総合スコア7

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

static int intA, intB, intC, intD, intE, intF, intG, intH; //targetArrayの要素番号用

これをリストにしてしまえばいろいろできるようになると思われますが。

投稿2021/04/07 08:39

y_waiwai

総合スコア87800

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

777_superlucky

2021/04/18 13:00

回答ありがとうございました。 今回は自己解決となりましたが、思いついていなかった解決案を頂けて嬉しかったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問