teratail header banner
teratail header banner
質問するログイン新規登録
Java

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

3回答

4264閲覧

数独を最短で完全な解を導くアルゴリズム (Java)

anpan___

総合スコア28

Java

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

2クリップ

投稿2019/07/25 04:26

0

2

現在Javaで数独のコーディングを行っています。
数独を最短で、完全に解くことのできるコーディングを目指しております。

自分の中で考えるロジックは以下の通りです。

1、消去法を用いる。
一つのセルに対し、3×3のブロック、行、列の数字を確認し、8種類の値があれば残りの一種類を代入する。

実際このコードは完成したのですが、問題が複雑になるにつれ、解答しきれないものが出てくることに気が付きました。

この対策として、
2、背理法を用いる。
消去法⇔背理法をすべてのマスが埋まるまで、繰り返す。

この方法を用いれば、ある程度の数独は解けると考えております。
しかしながら、そのロジック(フローチャート)が実際に、コードに起こすことができず行き詰っています。

また、現在はこれが最速だと、思い込んでいますが、ほかのアルゴリズムのほうが、いいのでは?というものがあれば教えていただければ幸いです。

実際のコードはこちらです。
以前似たような質問を行っておりますが、そちらからは数個修正させていただいているので記載させていただきます。

Java

1public class sudoku { 2 static int[][] data = { 3 {0,9,0,0,0,0,0,0,8}, 4 {5,0,6,4,0,9,3,0,1}, 5 {0,7,0,1,0,0,0,0,0}, 6 {3,5,0,0,0,2,7,0,0}, 7 {0,0,0,3,0,0,0,0,0}, 8 {0,1,0,7,0,0,0,0,9}, 9 {0,8,0,5,0,0,0,0,4}, 10 {0,0,0,0,0,0,0,0,0}, 11 {0,4,7,0,0,6,9,0,0}}; 12 13 public static void main(String[] args) { 14 Sub.print(data); 15 Sub.solve(data, data); 16 Sub.print(data); 17 } 18} 19 20public class Sub extends sudoku { 21 22 public static void print(int[][] data) { 23 for(int i = 0; i < 9; i++) { 24 for(int j = 0; j < 9; j++) { 25 if(data[i][j] != 0) { 26 System.out.print(" " + data[i][j] + " "); 27 } else { 28 System.out.print("( )"); 29 } 30 } 31 System.out.println(); 32 } 33 System.out.println("---------------------------"); 34 } 35 36 public static void solve(int[][]data, int[][] field) { 37 boolean tf = false; 38 do { 39 check(data); 40 if(field == data) { 41 //背理法を用いたメソッドを作成 42          //ここでコーディング方法がわからずに困っています 43 check2(data); 44 } 45 print(data); 46 int count = 0; 47 for(int r = 0; r < 9; r++) 48 for(int c = 0; c < 9; c++) { 49 if(data[r][c] != 0) 50 count++; 51 } 52 if(count == 81) 53 tf = true; 54 } while(!(tf)); 55 } 56 57//消去法を行うメソッド 58 public static void check(int[][]data) { 59 int[][] field = data; 60 61 for(int r = 0; r < 9; r++) 62 for(int c = 0; c < 9; c++) { 63 int[] num = {0,0,0,0,0,0,0,0,0}; 64 if(data[r][c] == 0) { 65 int count = 0; 66 int key = 0; 67 int sr = r / 3; 68 int sc = c / 3; 69 for(int i = 0; i < 9; i++) {//列 70 if(data[r][i] != 0) 71 num[data[r][i] -1] = 1; 72 } 73 for(int i = 0; i < 9; i++) {//行 74 if(data[i][c] != 0) 75 num[data[i][c] -1] = 1; 76 } 77 for(int s = 3 * sr; s < 3 * sr + 3; s++) {//ブロック 78 for(int b = 3 * sc; b < 3 * sc + 3; b++) { 79 if(data[s][b] != 0) 80 num[data[s][b] -1] = 1; 81 } 82 } 83 for(int a = 0; a < 9 ; a++) { 84 if(num[a] == 1) 85 count++; 86 else 87 key = a + 1; 88 } 89 if(count == 8) { 90 field[r][c] = key; 91 solve(data, field); 92 } 93 } 94 } 95 }

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

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

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

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

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

mather

2019/07/25 04:51

当人の中では「背理法」が自明なのかもしれませんが、具体的に一手一手の手法を書き出してみましょう。 それができればコードもかけるはずです。 質問は再編集できますので、書き出してみてもわからないというときは質問に追記してみてください。
anpan___

2019/07/25 05:10

matherさん かしこまりました! 一度自分なりに考えたコードをもう一度手直しし、記載させていただきます!
anpan___

2019/07/25 05:12

ozwkさん はい!そちらの記事を閲覧し、また他のサイトからも情報を得て 提示いただいたサイトの内部の「探索」が、「背理法」であると分かりました。
coco_bauer

2019/07/25 05:39

「最速」という事を考えないで、必ず政界に到達する方法を考えましょう。動的計画法で扱うような問題は、上のほうから調べ始めたほうが早く解ける問題、下のほうから調べ始めたほうが早く解ける問題、、というように同じアルゴリズムで使って解いても、回答に至るコスト(時間)は問題に依存します(そして、解いてみないと、どこから手掛けるのが最適なのかは分からない)。
anpan___

2019/07/25 05:45

coco_bauerさん なるほど!速度はスタート位置でも変わりますね!頭に入っていませんでした。 まず確実に正解することが、確かにベストな答えです。 上記を完成させて確実に、正しい回答のできるものを意識してコーディングします。
guest

回答3

0

ベストアンサー

その方法では、ごく簡単なものしか解けないんじゃないでしょうか?
私なら動的計画法を考えます。

まずすべてのマスについて、そこに入れることが可能な数字のリストを作成します。入れることが可能な数字が一つだけなら、それは正解として確定します。

次に、候補の数が最も少ないマスの中から一つ選び、リスト中から一つ選んで入れてみます。これを正解と仮定した上で他のマスのリストを作り直します。すべての数値が確定しなかった場合、この候補は正解と仮定したまま他のマスを選んで同様の処理を行います。これを再帰的に行い、破綻したところでバックトラックを行います。そして、すべてのマスが確定したところで終了します。

投稿2019/07/25 05:17

編集2019/07/25 05:18
Zuishin

総合スコア28675

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

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

anpan___

2019/07/25 05:21

丁寧にありがとうございます。 APIを用いないように努めておりますので、配列等使って一度そちらの考えを再現させる努力を行います! ありがとうございます。
Zuishin

2019/07/25 05:27

API は無関係ですね。動的計画法を調べてみてください。ozwk さんが貼られているリンク先でも使われています。
ozwk

2019/07/25 05:29

質問者さんは 確定できるところは確定させ(質問者は消去法と表現)し できなくなったら適当なマスに対して探索を行う(質問者は背理法と表現) という方針を考えているようなので、言っていることが結局一緒ではないでしょうか
Zuishin

2019/07/25 05:44

私は前の質問を読んでいなかったので、背理法が何を意味するかわかりませんでしたが、それは私の知っている背理法とは違うようです。
Zuishin

2019/07/25 05:50 編集

背理法は、ある命題が偽であると仮定したときに生じる矛盾をもってその命題が真であることを証明するものという認識です。つまり、あるマスが 1 であることを証明するためには、そのマスは 1 ではないと仮定しなければいけません。
coco_bauer

2019/07/25 06:02

「やってみて、破綻したら、バックトラックして別解を求めてゆく」という動的計画法での解法を質問者が意図していたことを、質問の文章から判断することは無理じゃないでしょうか。
guest

0

根本的な所なんですけど、プログラムを書く前に
解き方を徹底的に洗ったほうが良い気がします。
候補が複数あっても、埋められる事もありますし。


例)
123|○○○|78●
○○○|○○○|○○○
○○○|○9○|○○○

●は4569が候補ですが、
9は左のマスの2段目のいずれかに入る為、
右のマスの2段目には9が入れられません。
よって9で確定します。


やってみないとな所はありますが、
総当りを減らすことにより、スピードアップに繋がるのではないでしょうか。

投稿2019/07/25 06:04

torisan

総合スコア678

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

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

0

パズル作家です。私は速さのところだけ 反応しますね。

まずjavaでは最速のものは作れないのではないかと思います。
#とりあえず C か Rust か delphi(一部マシン語)ぐらいですかね。

さらに、本当に速さを求めるなら、
メモリを動的に確保する方法は諦めましょう。

ではどうするか。なぜこのパズルが存在するのか、という点に
立ち返ればいいのです。そうすれば人間がそれを楽しめなくては
意味がない、ことが分かるでしょう。

つまり、人間が解けることを前提として作られている、
あるいは そういう理念で作られたと判断されたものだけが
数独のパズルとして出来するのであって、
そうであれば、人間が用いる いくつかの「解法」を
静的に実施するようインプリメントすればいいだけなのです。

そしてそれらは常に、人間が把握できるレベルのわずかな
メモリしか必要とせず、静的に持っておける範囲に収まります。

きちんと数独の解法を整理すれば、アルゴリズム的には
6,7つほどを実装すれば、ニコリ社さんの出版されている
全ての数独が静的に解けることが分かるでしょう。

あとはbit演算などに落とし込めば 速さを追求することには
もはや興味を失う(※)というレベルまで速くすることができます。

※なぜなら問題を読み込む ファイル I/O のほうがはるかに時間がかかるから。

投稿2019/11/25 08:36

okayu3

総合スコア200

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問