61
LINQ を使ったナンプレの解 法を作ったお話 momo_*(@tututen)

LINQ を使ったナンプレの解法を作ったお話

Embed Size (px)

DESCRIPTION

7/7 七夕 プログラミング生放送+CLR/H+Sapporo.cpp 勉強会@札幌 #pronamaclrhsapporocppで発表した内容

Citation preview

Page 1: LINQ を使ったナンプレの解法を作ったお話

LINQ を使ったナンプレの解

法を作ったお話

momo_*(@tututen)

Page 2: LINQ を使ったナンプレの解法を作ったお話

自己紹介

● 某北見市で働く職業プログラマ● 趣味でもプログラム書くことがあります● お仕事:C言語、(Python、C#)● 趣味:ほぼ何でも(※アセンブリを除く)● パネルでポン(以下、パネポン)ができます● タグ「友達がいないとこうなります」で検索!● あと、手元を映したUst動画もあったりします

Page 3: LINQ を使ったナンプレの解法を作ったお話

地図

Page 4: LINQ を使ったナンプレの解法を作ったお話

地図

Page 5: LINQ を使ったナンプレの解法を作ったお話

自己紹介

● 某北見市で働く職業プログラマ● 趣味でもプログラム書くことがあります● お仕事:C言語、(Python、C#)● 趣味:ほぼ何でも(※アセンブリを除く)● パネルでポン(以下、パネポン)ができます● タグ「友達がいないとこうなります」で検索!● あと、手元を映したUst動画もあったりします

Page 6: LINQ を使ったナンプレの解法を作ったお話

検索結果

Page 7: LINQ を使ったナンプレの解法を作ったお話

最近のタグ(7/7 13:00現在)

Page 8: LINQ を使ったナンプレの解法を作ったお話

Ust風景

http://www.ustream.tv/recorded/20923039

Page 9: LINQ を使ったナンプレの解法を作ったお話

お品書

● LINQの簡易説明● ナンプレの解法手順1● 実装1● ナンプレの解法手順2● 実装2● デモ

Page 10: LINQ を使ったナンプレの解法を作ったお話

LINQについて

Language Integrated Query の略称で、 C# や VB などの .NET Framework 対応言語に、 リレーショナルデータや XML に対するデータ操作構文を組み込む (+ データベースや XML 操作用のライブラリ)

引用:http://ufcpp.net/study/csharp/sp3_linq.html

Page 11: LINQ を使ったナンプレの解法を作ったお話

LINQについて

クエリ式

拡張メソッド

Page 12: LINQ を使ったナンプレの解法を作ったお話

ナンバープレース

引用:http://www.sudokugame.org/ 2012/7/4 最高級

 9×9のマスの中に、1から9までの数字を入れていくパズルである。 次のような三つのルールは守らなければならない。

● 一列で同じ数字を使ってはいけない

● 一行で同じ数字を使ってはいけない

● 一つのブロックで同じ数字を使ってはいけ

ない

Page 13: LINQ を使ったナンプレの解法を作ったお話

定義

● フィールドは1次元のint配列で定義● 配列にはそれぞれ[0-9]が入り、0は空白を示す

Page 14: LINQ を使ったナンプレの解法を作ったお話

解法手順1

1. 空白場所を探す2. たて・横・ブロックを見て、

現状で空白に入る数字をリストアップする3. 2で得た数字を入れてみる4. 1に戻る5. 2で数字が見つからなければ、

一つ前の空白に戻り、違う数字を入れる

Page 15: LINQ を使ったナンプレの解法を作ったお話

解法手順1

1. 空白場所を探す2. たて・横・ブロックを見て、

現状で空白に入る数字をリストアップする3. 2で得た数字を入れてみる4. 1に戻る5. 2で数字が見つからなければ、

一つ前の空白に戻り、違う数字を入れるここでLINQ使える!

Page 16: LINQ を使ったナンプレの解法を作ったお話

0.使う構造体

各マスの構造体Valはマスの値、

Indexはマスの場所、

NumListは入れることの出来る数字のリストです

Page 17: LINQ を使ったナンプレの解法を作ったお話

0.使う構造体の初期化

● 通常

Page 18: LINQ を使ったナンプレの解法を作ったお話

0.使う構造体の初期化

● LINQ

Page 19: LINQ を使ったナンプレの解法を作ったお話

1.空白の場所を探す(1)

● 通常

Page 20: LINQ を使ったナンプレの解法を作ったお話

1.空白の場所を探す(2)

● LINQ

Page 21: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ブロックの…(1)

今いるセルのたての列の値を取得したい場合

・・・今見てる空白マス

Page 22: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ブロックの…(2)

・・・今見てる空白マス

Page 23: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ブロックの…(3)

今いるセルの横の列の値を取得したい場合

・・・今見てる空白マス

Page 24: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ブロックの…(4)

・・・今見てる空白マス

Page 25: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ブロックの…(5)

今いるセルのボックスの列の値を取得したい場合

・・・今見てる空白マス

Page 26: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ボックスの…

・・・今見てる空白マス

Page 27: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ブロックの…(7)

たて・横・ボックスに存在しない数字を「候補リスト」として扱う

・・・今見てる空白マス

Page 28: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ブロックの…(8)

Page 29: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ブロックの…(9)

最後に1-9のリストと差分をとって「候補リスト」ができる↓差集合を取る

Page 30: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ブロックの…(A)

LINQを使うと・・・

・・・今見てる空白マス

Page 31: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ボックスの…

LINQを使うと・・・

Page 32: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ボックスの…

LINQを使うと・・・

たて・横・ブロックマスの抽出

Page 33: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ボックスの…

LINQを使うと・・・

空白除去・重複要素除去

Page 34: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ボックスの…

LINQを使うと・・・

各スペースに候補リスト代入

Page 35: LINQ を使ったナンプレの解法を作ったお話

解法手順1

1. 空白場所を探す2. たて・横・ブロックックスを見て、

現状で空白に入る数字をリストアップする3. 2で得た数字を入れてみる4. 1に戻る5. 2で数字が見つからなければ、

一つ前の空白に戻り、違う数字を入れる

省略!

Page 36: LINQ を使ったナンプレの解法を作ったお話

解法手順1の問題点

● 空白マスが多く深く探索後に間違いに気づく問題の場合酷く時間がかかる

● 空白の多いマスで実行すると7~8時間帰って来ないことがある

● 再帰関数の呼び出し回数が1000万超えることも…

Page 37: LINQ を使ったナンプレの解法を作ったお話

解法手順2

1. 候補が絞れている物は埋めてしまう2. 空白場所を探す3. たて・横・ブロックックスを見て、

現状で空白に入る数字をリストアップする4. 3で得た数字を入れてみる5. 2に戻る6. 3で数字が見つからなければ、

一つ前の空白に戻り、違う数字を入れる

Page 38: LINQ を使ったナンプレの解法を作ったお話

解法手順2

1. 候補が絞れている物は埋めてしまう2. 空白場所を探す3. たて・横・ブロックックスを見て、

現状で空白に入る数字をリストアップする4. 3で得た数字を入れてみる5. 2に戻る6. 3で数字が見つからなければ、

一つ前の空白に戻り、違う数字を入れる

追加!ここもLINQ使える!!

Page 39: LINQ を使ったナンプレの解法を作ったお話

手法

[4, 5, 7, 9]

[4, 5, 7]

[3, 5, 7]

[4, 5, 9]

[4, 9]

● ある列を抜き出した物● マスの横にあるものを候補リストとす

引用:http://www.geocities.jp/m_hiroi/func/abcscm41.html

Page 40: LINQ を使ったナンプレの解法を作ったお話

手法

3

[4, 5, 7, 9]

[4, 5, 7]

[3, 5, 7]

[4, 5, 9]

[4, 9]

● この列の候補リストの中で[3, 5, 7]中の3だけ候補リストに存在する

● このマス以外に3を入れるとルール上崩れるのでこのマスに3を入れることが出来る

● これを検索するプログラムを書きました

Page 41: LINQ を使ったナンプレの解法を作ったお話

2.たて・横・ボックスの…

LINQを使うと・・・

Page 42: LINQ を使ったナンプレの解法を作ったお話
Page 43: LINQ を使ったナンプレの解法を作ったお話

たて・横・ブロックに属するマスを取得

Page 44: LINQ を使ったナンプレの解法を作ったお話

平坦化するIEnumerable<IEnumerable<TmpData>> { たて, 横, ブロック

}を、IEnumerable<TmpData> { たて, 横, ブロック}にする

Page 45: LINQ を使ったナンプレの解法を作ったお話

たて・横・ブロックの候補リストを取得し候補の数字をキーにグループ化

Page 46: LINQ を使ったナンプレの解法を作ったお話

グループ化した要素の個数が1個のものを取得し、リスト化する

Page 47: LINQ を使ったナンプレの解法を作ったお話

1つだけの候補の位置を探しだし

その位置に数字を埋める

Page 48: LINQ を使ったナンプレの解法を作ったお話

比較

● http://www.sudokugame.org/ の2012/07/05 中級の問題

● 解法1○ 解答時間 5.3851703秒○ 関数呼び出し回数: 3090回

● 解法2○ 解答時間 0.0805433秒○ 関数呼び出し回数: 4回

Page 49: LINQ を使ったナンプレの解法を作ったお話

比較

● http://www.sudokugame.org/ の2012/07/05 最高級の問題

● 解法1○ 解答時間 測定不能(8h以上)○ 関数呼び出し回数: 1000万回以上

● 解法2○ 解答時間 0.3522107秒○ 関数呼び出し回数: 15回

Page 50: LINQ を使ったナンプレの解法を作ったお話

DemoLINQ!! LINQ!!

Page 51: LINQ を使ったナンプレの解法を作ったお話

まとめ

● このアプリ作成使ったループ文は1個!● LLじゃなくても1ライナー!(但し文字数多い)● わーいLINQ、@tututen LINQ大好き!

Page 52: LINQ を使ったナンプレの解法を作ったお話

おまけ

● 画像処理もLINQ

Page 53: LINQ を使ったナンプレの解法を作ったお話

今回の裏機能

Page 54: LINQ を使ったナンプレの解法を作ったお話

今回の裏機能

Page 55: LINQ を使ったナンプレの解法を作ったお話

主な流れ

● フォームのサイズでキャプチャ● キャプチャした画像をグレースケール→二値化● 予め用意した数字の画像とマッチング

Page 56: LINQ を使ったナンプレの解法を作ったお話

主な流れ

● フォームのサイズでキャプチャ● キャプチャした画像をグレースケール→二値化● 予め用意した数字の画像とマッチング

ここでもLINQ使える!!

Page 57: LINQ を使ったナンプレの解法を作ったお話

二値化

Page 58: LINQ を使ったナンプレの解法を作ったお話

二値化

Page 59: LINQ を使ったナンプレの解法を作ったお話

マッチング

Page 60: LINQ を使ったナンプレの解法を作ったお話

マッチング

Page 61: LINQ を使ったナンプレの解法を作ったお話

ご静聴

ありがとう

ございました

LINQ!! LINQ!!