箱入り娘のプログラムを書いて思う
実家に帰った際に箱入り娘のパズルがあったのでやっていた。
全然解けなかったが、プログラムで力技で解きたいと思い、やってみた
結論として、解けずに終わった。
Pythonで再帰関数で解こうとして、再帰呼び出しの上限に引っかかって30sほどでエラーとなった。
将棋などと比較すると取ることができる手ににかなりきつい制限があるので、全探索余裕と思ってしまったのだが、完全に間違っていた。
一応、盤面を都度記録し、同じ盤面になったらそれ以上は探索しないようにしたのだが、それでも解空間は大きかった。
まず、再帰による解法の選択について。現代のプログラムにおいては、上限の大きさは違えど再帰呼出の階数には制限がある。ので、対象としている問題で想定される階数に比較してプログラミング言語の制約が十分かどうか判断しなければいけなかった。あるいは、階数をパラメータとして保持しておき、起動時に何階層まで探索するか指定するような形にすればよかった。
再帰ではなく、盤面をメモリかファイルに記録し、都度記録から次の盤面を探してスタックを使用しない形にしても良かった。
そもそも論で行くと、パズルは頭の体操として娯楽としてあるもので、力技で解くことに意味あるのか? というのもある。
今回は、初めてPythonを使って割としっかりとしたプログラムが書けたので、練習として良かったということにした。
64bit OSでのレジストリ操作時の注意事項
tack41tu.hatenablog.com でClickOnceアプリをインストールする際にレジストリを編集する必要がある事を書いた。
レジストリエディタで編集するのは面倒だし運用も大変なので、レジストリを編集するアプリを作成した。
How to: Configure the ClickOnce Trust Prompt Behavior にある以下のコードを書いて実行し、正常終了するのだがレジストリエディタで確認すると変更が反映されておらず、ClickOnceの動作も変わらない。
Microsoft.Win32.RegistryKey key; key = Microsoft.Win32.Registry.LocalMachine.CreateSubKey("SOFTWARE\\MICROSOFT\\.NETFramework\\Security\\TrustManager\\PromptingLevel"); key.SetValue("LocalIntranet", "Enabled"); key.Close();
どうもレジストリは32bit, 64bitで別の領域らしく、プログラム作成時にターゲットCPUをAnyとし、x86優先とした結果、32bitの領域を更新してしまっているらしい。
aonasuzutsuki.hatenablog.jp を参考に以下のように記載したところ、想定通りに動作するようになった。
Microsoft.Win32.RegistryKey key_base, key; key_base = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); var key = prerKey.CreateSubKey("SOFTWARE\\MICROSOFT\\.NETFramework\\Security\\TrustManager\\PromptingLevel",); key.SetValue("LocalIntranet", "Enabled"); key.Close();
Microsoft Report使用時のビルド時の警告
Visual Studio 2017にてMicrosoft Reportを使用するために、Nugetで[Microsoft Rdlc Report Designer for Visual Studio]をインストールすると、ビルド時に「同じ依存アセンブリの異なるバージョン間での競合が見つかりました。」と警告が表示される。実行自体は問題なくできる。
qiita.com を参考に出力の詳細レベルを上げて確認すると、ReportのアセンブリがSQLServer.Typesの12.0.0に依存している一方で、NugetでReportインストール時に一緒にインストールされるSQLServer.Typesは14.0.0であるためのようだ...
依存関係の解消方法が思い付かず、また動作には影響はないため以下のサイトを参考に
方法: 自動バインディング リダイレクトを有効/無効にする | Microsoft Docs 自動バインド リダイレクトを有効化したところ、警告は出なくなった。
ClickOnceでハマる
C#で開発したクライアントアプリケーションをClickOnceで配布する際にハマった2点
Windows10へのインストール
イントラのファイルサーバに置いてある証明書が設定されていないClickOnceをWindows 10で実行すると、「コンピューターにセキュリティ上の問題を発生させるため、管理者がこのアプリケーションをブロックしました。...」と表示され、[閉じる]ボタンしか表示されないために、インストールができない。 Windows 7では普通にインストールできる。
answers.microsoft.com にあるレジストリの[LocaIntranet]の値をEnabledにする必要があった。 設定変更は直ちに反映される(OS再起動は不要)
関連アセンブリの添付
上記をクリアしたうえでClickOnceを公開し、クライアントで実行すると以下のエラーが表示される。
このアプリケーションをインストールまたは実行できません。このアプリケーションでは、まずグローバルアセンブリキャッシュ(GAC)にアセンブリ Microsoft.**** バージョン *** をインストールする必要があります。
****にはVisualStudio関連のアセンブリ各種が出力される。Visual Studio 2017 Express Desktopの時は発生しなかったのだが、2017 Professionalにしたら発生した。 どうも必要なアセンブリ(.dll)を添付できていないようで、事例は異なるが、
thinkami.hatenablog.com にあるように公開設定で全てのアセンブリを「必須コンポーネント(自動)」→「含む」に変更すると解消した。
アジャイル開発手法の適用を考える
最近、アジャイル開発手法に関するセミナーや勉強会に参加している。
同開発手法が既存の手法と比較して良い面を多数含んでいることは間違いないし、勉強会や記事などでの導入事例の多さがそれを物語っている。特にベンチャーであればアジャイル以外の手法は考えられないだろう。
一方で、過去のソフトウェア資産、開発スタイルがある企業ではそう簡単な話ではない、と思っている。勉強会の参加者の話を聞くと、未だにバージョン管理も満足にできていない、という話も聞く。
セミナーや勉強会で出てくる事例は、予算や人員をある程度確保できる環境だったり、前職でアジャイル開発していて獲得したノウハウを適用するような話だったりして、自分ができる気になるところまでいかない。 また、アジャイル手法のフルセットを紹介してここがゴールというような言われ方をしたり、あるいは自分で考えて取捨選択しなさいと言われることが多い。 開発者にとってバラ色の環境を構築するための実践的な方法を期待していって、がっかりして帰ってくることの繰り返して疲れてしまっている。
現時点の自分の認識だが、アジャイル開発とは先人がまとめた優れた複数のベストプラクティスとなる開発手法である。それぞれに適用領域があり、前提条件、向いていない環境がある。ウォーターフォール開発がベスト、という環境だってある。 なので、それぞれの手法が生まれた経緯、解決する問題、前提条件を理解して自分が置かれている環境が適用可能なのかを個別に検討する必要がある。 参加する勉強会によってはこれらのいずれも示さずに、ただただ成功事例だけを提示して導入すればバラ色の未来が開けるような言い方をするところがある。多い。
既存の資産、手法、人がいてスイッチング・コストが大きく、そのコストを小さくしてくれるような手法、事例をアドバイスしてくれる奇跡的な人でもいない限り、自分で考え抜くしかないのだと気付いた。今更だが...
実行順序に依存する複数LINQ実行時の遅延評価による副作用
例えば、LINQ1にて元データよりデータを抽出し、これをデータセット1とする。 次に、LINQ2にて、元データからデータセット1を除いたデータセットに対して抽出し、これをデータセット2とする。 これをLINQ3にて、元データからデータセット1とデータセット2を除いたデータセットに対して抽出し、これをデータ・セット3とする。 ....
上記のような処理を1メソッドで行う。 後続のLINQで除外するために、除外するためのデータセットを例えばListとして保持する。
LINQ2はLINQ1の結果が決まらないと決まらない。LINQ3はLINQ2, LINQ1の結果が決まらないと決まらない。だが、後続のLINQに対して結果を伝えるのは(LINQとは無関係の)Listオブジェクト。
このような場合に、上記LINQを順番にコードで記載したとしても、除外Listの値は後続に伝わらない(ことがある?)。おそらく、プログラムの動作として最初にLINQ3の結果を参照した場合にLINQ1,LINQ2の結果を行ってから、という動きはしてくれず、結果、空の除外Listに対してLINQ3を実行してしまっているためと思われる。
遅延されるのが問題なので、LINQの実行結果 IEnumerable型のオブジェクトに対してToList()を実行してやれば即時に確定してこのような副作用は発生しなくなる。遅延評価のメリットは当然なくなるが。