taki のすべての投稿

プログラマーはエラー処理に頭を悩ませる。

プログラムというのは、目的通りに動いていればいい、という訳ではありません。

目的通りに動かすのは「当たり前」で、それ以上に頭を悩ませるのがエラー処理なんです。

具体的には、なんらかの要因で正しい処理が行えなくなった場合でも、正しい状態を保つ、ということをプログラミングしなければなりません。

前者が「正常系」と呼ぶのに対し、後者は「準正常系」と呼んでいました。

ちなみに、それ以外の深刻な問題が発生したときは「異常系」と呼んで、オペレーターに異常を知らせる処理を実行します。主にハードウェアの故障などがこれに該当します。

準正常系は、入力データの異常や割り込み処理などが該当します。

ソフトウェア設計者は、こういった準正常系の処理を全て網羅して、あらかじめエラーを検出し、本来の正常な動作を保つように設計しなければなりません。

設計者が頭を悩ませるのが、「準正常系に漏れが無いよね?」ということなんです。

我々がニュースなどで耳にする「ソフトウェアの異常」というのは、大抵、準正常系の考慮が漏れていたことに起因します。

そして、本番でこういうことが起きないように、出荷前に様々なテストデータを用意して、徹底的にいじめます。

特に組み込み系のファームウェアは、簡単にアップデートできないので、出荷から当分の間はヒヤヒヤします。

トラブルがあったら現場大炎上なので。

では、どうすれば良いかというと、これも難しい話で、経験を積み重ねるしか無いんですよ。

ベテラン技術者にレビューして貰うのも一つの手です。

まぁ、ソフトウェア製品の開発にはこんな事があるんですよ、ということで理解して貰えれば。

【防災】3.11から9年。災害対策できてますか?

まぁ、3.11のような規模の災害は当分起きないとは思いますが、用心するに越したことはないので。

オイラは、北海道胆振東部地震をきっかけに、少しずつ災害対策を始めました。

具体的には、ライフライン(電気、ガス、水道)が無くても、数日は耐えられるように、と想定しています。

電池で動く携帯ラジオ。

停電で電気が使えないとなると、最も頼りになる情報元は地域のラジオです。

スマホのradikoではダメですよ!

基地局がバッテリー切れしたらインターネットもできなくなりますからね!

小型のコンロ。

燃料。

中型の焚き火台。

この上でお湯も沸かせます。

燃料となる薪も少し用意しています。

乾電池で動くLEDランタン。

念のため、ガスコンロも用意しています。

LOHACOで買ったお水。

こっちの方が長期保存ができます。

食料は、今、カップラーメンを発注しています。

これだけあれば、ちょっとしたキャンプぐらいできそうです。

それともう一つ、

これらのアイテムは持っているだけではダメで、きちんと動くことを定期的に確認することも大事。

買ったは良いけど使い方がわからない、なんて事が無いように、点検しておくべき。

軽く、デイキャンなんてどうですかね?

北海道はまだ無理だけど、暖かくなったらデイキャンなんて良いかもしれません。

結局はやってみないと、いざというときに使い物にならないわけで。

これを機に点検してみてはいかがでしょう。

【C#】【数独】仮置きロジック簡略化の修正を元に戻した。

前回までの状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/sudoku

修正を戻したのは、重大な欠陥に気がついたためです。

仮置きロジックを再起実行させたときに矛盾を検出した場合、正しく処理されない、という動きが発生していました。

やはり、面倒でも、仮置きロジックを再起処理から全てリターンして、値を一つずつ確定していくのが一番良い方法だと思います。

このコードでもう少し問題を解いてみます。

そして、最高難度の問題でも解けるかを確認していきたいと思います。

北海道って、ネットオークションには向かない

特に、食品。

先日、お風呂に入りながら、ヤフオクの1円スタートの食品をポチポチやっていたら、

見事に1円で落札できたのですが、

送料がとんでもない金額になることに気がついたのです。

食品は冷凍、冷蔵物もあるから、それに該当すると、もっと高くなります。

ホント、離島価格ですよ。

北海道は離島で僻地ですよ。(知ってた)

入札するときは、商品の説明欄を確認して、送料を確認しなくちゃいけない。

それはまだ良い方で、

落札するまで送料がわからないケースも多々ありまして。

それだったら、送料が確定しているAmazonとか、楽天とか、Yahooショッピングのほうがまだマシかも。

と思えた今日この頃でした。

また余計な出費しちゃったよ。

みんなも(特に道民)送料には気をつけよう。

ぼっちニートである事の問題点とか不安とか

現在、オイラは絶賛ぼっちニートです。

1日部屋から外出しないこともありますし、誰ともしゃべらないことも多いです。

この生活も、人にほとんど関わらないので、ぼっちにとってはものすごい快適なのですが、

ちょっと不安というか、問題点がありまして、

この生活がこの先ずっと続くことで会話ができなくなるんじゃないかって思うんです。

つまりは、しゃべらないことでしゃべれなくなってしまうことが考えられるので、

必要最低限の快適な生活を行う上で、会話ができないのはちょっとマズイ気がしてきたのです。

さて、どうしようか。

せっかく昔買ったマイクがあるので、声を録音して、ブログで公開しましょうか。

このまま眠らせておくのはもったいない。

ちょっと何かしら対策を考えます。

【C#】【数独】仮置きロジックを簡略化する。

前回までの状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/sudoku

前回、仮置きロジックを完成させたのですが、

このコード、結構無駄な処理をやっていることに気がついたんですよ。

        private Square doKarioki(Square[,] squares)
        {
            Square ret = null;
            List<Square> kariokiList = searchKariokiSquare(squares);
            foreach (var s in kariokiList)
            {
                bool roop = true;
                int kariValue = GetUnconfirmedValue(s.GetCandidate());
                if (kariValue == 0)
                {
                    return null;
                }
                Square[,] copySquare = makeClone(squares);
                copySquare[s.Row, s.Col].SetValue(kariValue);
                int now_count = 0;
                int prev_coount = 0;
                while (roop)
                {
                    for (int row = 0; row < 9; row++)
                    {
                        for (int col = 0; col < 9; col++)
                        {
                            if (copySquare[row, col].isConfirmed() == false)
                            {
                                Candidate candidate = new Candidate();
                                searchRowLine(copySquare, row, candidate);
                                searchColLine(copySquare, col, candidate);
                                search9Area(copySquare, row, col, candidate);
                                copySquare[row, col].checkCandidate(candidate);
                            }
                        }
                    }
                    searchNumber(copySquare);

                    if (checkContradict(copySquare))
                    {
                        break;
                    }

                    prev_coount = now_count;
                    now_count = countInputedNumber(copySquare);

                    if (prev_coount == now_count)
                    {
                        Console.WriteLine("仮置きロジック");
                        Square s2 = doKarioki(copySquare);
                        if (s2 == null)
                        {
                            Console.WriteLine("失敗しました");
                            return null;
                        }
                        else
                        {
                            copySquare[s2.Row, s2.Col].SetValue(s2.GetValue());
                        }
                    }

                    if (checkEnd(copySquare) == true)
                    {
             ★
                        roop = false;
                        s.SetValue(kariValue);
                        Console.WriteLine("[{0},{1}] = {2}", s.Row, s.Col, s.GetValue());
                        ret = s;
                    }
                    FileAccess.Output(copySquare);
                }
                if(ret != null)
                {
                    break;
                }
            }
            return ret;
        }

今までは★に入ったタイミングで仮置きした値が確定して、という処理を行っていたんですが、

実はここに入った時点で解析結果が判明しているんですよね。

なので、この時点で解析結果を出力して終了、という処理にすれば、大幅に処理が短くなるはずです。

詳細はgitHubのソースコードを参照して頂ければ。

ついでに関数ヘッダにコメント入れました。

【C#】【数独】矛盾チェック処理と仮置きロジック再帰処理の実装

前回までの状況はこちら。

最新ソースはこちら(gitHub)

いやーロジック考えるのに時間かかりました。

まず、仮置きロジックを完成させるには、仮置きした結果、矛盾が発生した、ということを検出できる用にしなければならなくて。

これが、以外と難しい。

実際のコードは短くなっても、そこにたどり着くのが難しいのです。

オイラはこのように書きました。

        private bool checkContradict(Square[,] squares)
        {
            for (int row = 0; row < 9; row++)
            {
                for (int col = 0; col < 9; col++)
                {
                    if(squares[row,col].isConfirmed() == false)
                    {
                        Candidate candidate = new Candidate();
                        searchRowLine(_square, row, candidate);
                        searchColLine(_square, col, candidate);
                        search9Area(_square, row, col, candidate);
                        if(candidate.Count() == 9)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

値は確定していない、しかし、縦、横、9マスを調べた結果、置ける数字が無い場合、という風に考えました。

これを使って仮置きロジックを作成します。

        private Square doKarioki(Square[,] squares)
        {
            Square ret = null;
            List<Square> kariokiList = searchKariokiSquare(squares);
            foreach (var s in kariokiList)
            {
                bool roop = true;
                int kariValue = GetUnconfirmedValue(s.GetCandidate());
                if (kariValue == 0)
                {
                    return null;
                }
                Square[,] copySquare = makeClone(squares);
                copySquare[s.Row, s.Col].SetValue(kariValue);
                int now_count = 0;
                int prev_coount = 0;
                while (roop)
                {
                    for (int row = 0; row < 9; row++)
                    {
                        for (int col = 0; col < 9; col++)
                        {
                            if (copySquare[row, col].isConfirmed() == false)
                            {
                                Candidate candidate = new Candidate();
                                searchRowLine(copySquare, row, candidate);
                                searchColLine(copySquare, col, candidate);
                                search9Area(copySquare, row, col, candidate);
                                copySquare[row, col].checkCandidate(candidate);
                            }
                        }
                    }
                    searchNumber(copySquare);

                    if (checkContradict(copySquare))
                    {
                        break;
                    }

                    prev_coount = now_count;
                    now_count = countInputedNumber(copySquare);

                    if (prev_coount == now_count)
                    {
                        Console.WriteLine("仮置きロジック");
                        Square s2 = doKarioki(copySquare);
                        if (s2 == null)
                        {
                            Console.WriteLine("失敗しました");
                            return null;
                        }
                        else
                        {
                            copySquare[s2.Row, s2.Col].SetValue(s2.GetValue());
                        }
                    }

                    if (checkEnd(copySquare) == true)
                    {
                        roop = false;
                        s.SetValue(kariValue);
                        Console.WriteLine("[{0},{1}] = {2}", s.Row, s.Col, s.GetValue());
                        ret = s;
                    }
                    FileAccess.Output(copySquare);
                }
                if(ret != null)
                {
                    break;
                }
            }
            return ret;
        }

難しかったのが、仮置きロジックの計算中に再び仮置きロジックが必要になった場合。

そう、このロジックを再帰的に実行する処理が必要なのです。

これを実装するために、これ以外の所もかなりの広範囲で書き換えています。

しかし、これでようやく解を得ることができました。

138964275
624715398
957283614
285637941
796841523
341529786
512476839
479358162
863192457

このロジックでいろいろな問題を解いてみようと思います。