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

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

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

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

Q&A

解決済

1回答

1036閲覧

Javaでのアナグラム・置き換え処理を改善(早く)したい

777_superlucky

総合スコア7

Java

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

0グッド

0クリップ

投稿2020/08/05 02:45

前提・実現したいこと

以前に 入力された文を、母音が一緒の文字に入れ替えたい で回答していただいた事や調べた事をまとめて、文字列をアナグラム・同じ段(例 てはえ段)にある文字で置き換えをするコードを書いたのですが、実際に処理をする際は文字列が10文字以上になる事が多く、実行時間がとても長くなります。
他に同じようなコードがあまり無いため、処理の時間が適正なのかそうでないのか分からないのですが、改善点などありましたら回答をお願いしたいです。

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

処理に時間がかかる原因(無駄な処理など)を減らしたい

該当のソースコード

Java

1import java.io.*; 2import java.nio.file.*; 3import java.util.*; 4 5public class AmRt{ 6 public static void main(String args[]){ 7 Sakusei("てらている", "テラテイル"); 8 } 9 10 public static void Sakusei(String Target, String FileName){ 11 String Ans = ""; 12 String Indicate = ""; 13 String FilePath = "/home/lucky/Test/"; 14 ArrayList<String> List = new ArrayList<String>(); 15 Pn(Target, Ans, Indicate, FilePath, FileName, List); 16 Rt(Target, Ans, Indicate, FilePath, FileName, List); 17 } 18 19 20 public static void Pn(String Pq, String PAns, String PIn, String PFP, String PFN, ArrayList PLi){ 21 PFN = ("アナグラム_ひらがな_" + PFN + ".txt"); 22 FileDeletionMaking(PFP, PFN); 23 Permutation(Pq, PAns, PIn, PFP, PFN, PLi); 24 } 25 26 public static void Permutation(String Pq, String Pans, String PIn, String PFP, String PFN, ArrayList PLi){ 27 if(Pq.length()<=1){ 28 PIn = Pans + Pq; 29 PLi.add(PIn); 30 if(PLi.size() == 1000000){ 31 FileWriting(PFP, PFN, PLi); 32 } 33 }else{ 34 for(int Pa=0; Pa<Pq.length(); Pa++){ 35 Permutation(Pq.substring(0, Pa) + Pq.substring(Pa+1), Pans + Pq.charAt(Pa), PIn, PFP, PFN, PLi); 36 } 37 } 38 FileWriting(PFP, PFN, PLi); 39 } 40 41 42 public static void Rt(String Rq, String RAns, String RIn, String RFP, String RFN, ArrayList RLi){ 43 RFN = "置き換え_ひらがな_" + RFN + ".txt"; 44 FileDeletionMaking(RFP, RFN); 45 Replacement(Rq, RAns, RIn, RFP, RFN, RLi); 46 } 47 48 public static void Replacement(String Rq, String Rans, String RIn, String RFP, String RFN, ArrayList RLi){ 49 final String[] RHi = { 50 "あかさたなはまやらわ", 51 "いきしちにひみりゐ", 52 "うくすつぬふむゆる", 53 "えけせてねへめれゑ", 54 "おこそとのほもよろを", 55 "ん", 56 "がざだば", 57 "ぎじぢび", 58 "ぐずづぶ", 59 "げぜでべ", 60 "ごぞどぼ", 61 "ぱ", 62 "ぴ", 63 "ぷ", 64 "ぺ", 65 "ぽ", 66 "ぁゃゎ", 67 "ぃ", 68 "ぅゅ", 69 "ぇ", 70 "ぉょ", 71 "っ" 72 }; 73 74 for (int Ri = 0; Ri < Rq.length(); Ri++) { 75 int Rj = getDan(Rq.charAt(Ri), RHi); 76 } 77 char[] Rca = new char[Rq.length()]; 78 gen(0, Rq, Rans, RHi, Rca, RFP, RFN, RLi); 79 FileWriting(RFP, RFN, RLi); 80 } 81 82 public static int getDan(char Rc, String[] RHi) { 83 for (int Rx = 0; Rx < RHi.length; Rx++){ 84 if (RHi[Rx].indexOf(Rc) >= 0){ 85 return Rx; 86 } 87 } 88 return -1; 89 } 90 91 public static void gen(int R, String Rq, String Rans, String[] RHi, char[] Rca, String RFP, String RFN, ArrayList RLi) { 92 int Rj = 0; 93 int Rk = 0; 94 if (R == Rq.length()){ 95 Rans = new String(Rca); 96 RLi.add(Rans); 97 if(RLi.size() == 1000000){ 98 FileWriting(RFP, RFN, RLi); 99 } 100 } else { 101 Rj = getDan(Rq.charAt(R), RHi); 102 Rk = RHi[Rj].length(); 103 for (int Ry = 0; Ry < Rk; Ry++) { 104 Rca[R] = RHi[Rj].charAt(Ry); 105 gen(R+1, Rq, Rans, RHi, Rca, RFP, RFN, RLi); 106 } 107 } 108 } 109 110 111 112 public static void FileDeletionMaking(String DMP, String DMN){ 113 try{ 114 if(Files.exists(Paths.get(DMP, DMN))){ 115 Files.delete(Paths.get(DMP, DMN)); 116 } 117 Files.createFile(Paths.get(DMP, DMN)); 118 }catch(IOException ex){ 119 ex.printStackTrace(); 120 } 121 } 122 123 public static void FileWriting(String FWP, String FWN, ArrayList FWL){ 124 try{ 125 Files.write(Paths.get(FWP, FWN), FWL, StandardOpenOption.APPEND); 126 }catch(IOException ey){ 127 System.out.println("FWP=" + FWP + ", FWN=" + FWN); 128 } 129 FWL.clear(); 130 } 131}

試したこと

・アナグラムや置き換えを行った結果を1回ずつ書き込むのではなく、リストに格納し あとからまとめて書き込むように変えた
・処理結果の文字列を表示させなくした

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

Oracle VirtualBox Ver.6.1.12
CentOS 7.5.1804

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

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

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

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

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

YT0014

2020/08/05 04:09

このアナグラムソフトが動くことだけが重要で、javaの作法などには興味がない、という前提でよろしいでしょうか? あまりにも、一般的な作法から逸脱しているので、確認をさせてください。
777_superlucky

2020/08/05 06:48

個人で使う物のため、ファイルに実行結果が保存されれば良いのですが、一般的な作法も教えていただければ勉強になり 嬉しいです。
guest

回答1

0

ベストアンサー

支配的な時間がかかるのは、ファイル出力だと思うので、どう頑張っても結果的に似たような速度になると思います。
下のコードはそんなに速くもないし、汚く、保守しにくくなっているのですが、以下の視点で変更しています。

  • ループの中でオブジェクトの生成をなるべくせず、なるべくプリミティブな型で済ませる
  • 極端なケースや環境によってはスタックが心配になる場合もあるので、再帰呼び出しをループに変える
  • 本当に急ぎたいときはメソッドを細かく分けない(分けても速い場合もあります)
  • スレッドやプロセスなどを使い、処理を並列化し、処理系の性能を使い切る(要件次第)

ちなみに下記コードは以下の問題もあります。

  • 出力を一定数溜め込んでから書き込む処理を消した
  • 1文字の単語に対応していない
  • 非同期I/Oをやめた
  • 例外処理を消した

ただし、出力先を/dev/null(unix系の場合)とかにすればごくごく僅かに速度向上を見る事ができます。

Java

1import java.io.*; 2 3public class AmRt { 4 public static void main(String args[]) throws IOException { 5 permutate("てらている", "permutate.txt"); 6 replace("てらている", "replace.txt"); 7 } 8 9 private static String newLine = System.lineSeparator(); 10 11 private static void permutate(final String word, final String filename) throws IOException { 12 // 入力文字列の長さ 13 final int wordLength = word.length(); 14 // 順列出力時のN文字目が残りの文字の何番目かを保持する 15 int[] permutationIndexesOfRest = new int[wordLength]; 16 // 順列出力時に元文字列のN文字目が出力済みかどうかを保持する 17 boolean[] originalStringIsOutputted = new boolean[wordLength]; 18 19 for (int i = 0; i < wordLength; ++i) { 20 permutationIndexesOfRest[i] = 0; 21 } 22 23 Writer out = new BufferedWriter(new FileWriter(filename)); 24 while (true) { 25 for (int i = 0; i < wordLength; ++i) { 26 originalStringIsOutputted[i] = false; 27 } 28 for (int i = 0; i < wordLength; ++i) { 29 for (int j = 0, index = 0; j < wordLength; ++j) { 30 if (! originalStringIsOutputted[j]) { 31 if (index == permutationIndexesOfRest[i]) { 32 originalStringIsOutputted[j] = true; 33 out.write(word.charAt(j)); 34 break; 35 } else { 36 ++index; 37 } 38 } 39 } 40 } 41 out.write(newLine); 42 boolean breakable = true; 43 for (int i = wordLength - 1; i >= 0; --i) { 44 if (permutationIndexesOfRest[i] < wordLength - i - 1) { 45 ++permutationIndexesOfRest[i]; 46 breakable = false; 47 break; 48 } else { 49 permutationIndexesOfRest[i] = 0; 50 } 51 } 52 if (breakable) 53 break; 54 } 55 out.close(); 56 } 57 58 private static void replace(final String word, final String filename) throws IOException { 59 // 入力文字列の長さ 60 final int wordLength = word.length(); 61 // 同子音の分類 62 final String[] classified = { "あかさたなはまやらわ", "いきしちにひみりゐ", "うくすつぬふむゆる", "えけせてねへめれゑ", "おこそとのほもよろを", "ん", "がざだば", "ぎじぢび", 63 "ぐずづぶ", "げぜでべ", "ごぞどぼ", "ぱ", "ぴ", "ぷ", "ぺ", "ぽ", "ぁゃゎ", "ぃ", "ぅゅ", "ぇ", "ぉょ", "っ" }; 64 // 元の文字列のN文字目が何番目の同子音グループに属するかを保持する 65 int[] originalCharToClassified = new int[wordLength]; 66 // 同子音でずらして出力する際、N文字目の文字がグルーブの何番目の文字を出力するかを保持する 67 int[] classifiedIndexes = new int[wordLength]; 68 69 for (int i = 0; i < wordLength; ++i) { 70 char ch = word.charAt(i); 71 for (int j = 0; j < classified.length; ++j) { 72 int index = classified[j].indexOf(ch); 73 if (index >= 0) { 74 originalCharToClassified[i] = j; 75 break; 76 } 77 } 78 } 79 80 Writer out = new BufferedWriter(new FileWriter(filename)); 81 for (int i = 0; i < wordLength; ++i) { 82 classifiedIndexes[i] = 0; 83 } 84 while (true) { 85 for (int i = 0; i < wordLength; ++i) { 86 out.write(classified[originalCharToClassified[i]].charAt(classifiedIndexes[i])); 87 } 88 out.write(newLine); 89 boolean breakable = true; 90 for (int i = wordLength -1; i >= 0; --i) { 91 if (classified[originalCharToClassified[i]].length() > ++classifiedIndexes[i]) { 92 breakable = false; 93 break; 94 } else { 95 classifiedIndexes[i] = 0; 96 } 97 } 98 if (breakable) break; 99 } 100 out.close(); 101 } 102}

投稿2020/08/05 22:03

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

777_superlucky

2020/08/15 08:12

回答ありがとうございました。 試してみたところ、動作が早くなりました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問