前提・実現したいこと
以前に質問した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}
試したこと
以前の回答案からの変更点として
- 生成済みのアナグラム文を再度生成しない
- 日本語に変換後にローマ字が残る箇所が出来た時点で、その箇所に続く処理をスキップする(一般的なローマ字入力で変換)
例 「teratail」をアナグラム
アナグラム後の文の先頭2文字が「tr」の文→3文字目以降を追加せずに、2文字目を変更する
補足情報(FW/ツールのバージョンなど)
Eclipse IDE
・Version: 2021-03 (4.19.0)
・Java version: 11.0.9
・JavaコンパイラーはJavaSE-15
アナグラム生成箇所についての質問のため、日本語に変換する所など、生成の動作に支障が無い程度に省略している箇所があります。
個人で遊ぶ用のプログラムのため、Javaの作法から逸脱していたり、適切ではないメソッドを使用している可能性があります。
回答2件
あなたの回答
tips
プレビュー