自主制作アニメの話とか… Katsushiro
※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

  • 注意:これは、Pascal語によるプログラムの基礎講座です。Visitor No. - : - : -
  • beパズルの解答はケツにあります。

カックロを解いてみよう。

  • これは、朝日新聞の土曜日に掲載されるカックロを解くカツシロを作ろう!なのです。
  • クロなんでシロつけてカツシロってプログラム名がよいですね。アイコンもカツシロにしましょう。
  • 「ところでカツシロ、今日は存分に働けよ...んっっ....おまえも、ゆうべから もう大人だ」
  • アイコン
  • 独りで作るわけですから、フローチャートなんてありません。ましてや、カックロなんて解いたこともありません。ああでもない...こうでもない...と試行錯誤しながら作っていきます。(2008/6/29開始)
  • リアルタイムで作りながらここの記述をしているので、途中で「挫折」という結末もあり得ます。
  • また、自分でこのパズルを解く根性がないので、新聞にある解き方説明をプログラムしています。数毒は、一応自分で解いて、効率のよい方法を考えたつもりですが....

問題の入力装置を作ってみる

  • この手のプログラムを解くには、総当りなんて時間のかかる手を使いますが、数独を解く私のプログラムを使った人は、わかると思いますが、問題を入力する傍から問題を解き始めて行きます。各コマには、123456789が入っていて、1つ確定すると縦、横、3x3の他のコマの中から、その数字を削除していきます。解くというよりは、可能性のなくなった数字を次々と排除しているだけ。カックロではこの手は使えない。全ての問題の数字を入力することで、それぞれの素となる数字の数が確定するため。
  • 最初の発想
    • 縦の問題入れ、横の問題いれ、縦の可能性の或る数字入れ、横の可能性の或る数字入れ、4層の10x10の入れ物(配列)を用意する。最長は、1+2+3+4+5+6+7+8+9=45です。長さはstring[9]でOK
    • 文字列での処理が楽。空欄には、答えの入るコマと用のないコマがある。これを''(何もなし)と'0'で区別する
    • 入力にはImage上の座標から読み取る。古~いボロノートパソコンでもできるようにImageは、480x480にして、コマの位置は、座標 div 48 で割り出せる。
    • じゃあ斜めの線の上下はどうするのか? 私の時代は中学の数学でやった2元1次不等式の解の領域を求める方法である。y<x+nで区分けする。
    • ついでに、製作中に何度も問題を入力するのは面倒なので、配列を丸ごとのHDD入出力部分も。Turbo Pascal 2.2 for CP/M-80でも結構高速な読み書きが可能な方法でした。
    • Panel 3個は、うまく座標を取れるかの確認目的。1にxコマ座標、2にy、3に斜め線の上下を表示する入れ物。
    • 入れ物(配列)は、一旦typeで設定します。HDDの入出力で同じものをもう一度使う為。
    • sqは、1つのコマのサイズ、File_Nameは、とりあえず、ここで解く予定のカックロ問題の掲載された新聞の日付で固定。
    • ファイル名を変更して保存とか、その辺は後回し。
    • 次は起動時の設定。配列の初期化(一応念のため)
    • コマと斜め線を描く部分です。面倒だし、全部描いて解く時に空欄を埋める。
    • Image1上でマウスポインタを移動させて、うまくコマの位置が検出できるか、3つのPanelに表示しながら実験。とりあえず、形ができたので、なんとなくやった気になる。が、中身は何もない。(2008/7/1)

  • さて、ここで、PopUpメニューはImage1にくっつけて配列に入力した数値を格納する、また、Image1に表示する部分を記述する。
    • 問題の表示と配列への格納は、1つの手続きでもいいような気もするが、HDDから呼び出したときは表示だけが必要になる。
    • と、いうことで、2つの手続きに分ける。
    • 表示部分だけ
    • 下の問題を配列に入れる手続き内に2桁に限定してしまう関数を作る。
    • この関数は上位を押し出して常に2桁を維持させるものである。
    • そして、これが、PopUpMenuの設定と手続き全部。
    • HDDとの入出力を扱う部分。
    • 読み込むときには、Image1への表示を付ける。
    • 書き込むときには、縦横の片方だけの部分について、残りの部分に0を入れるようにする。
    • この程度は入力で手作業でも...でも、面倒くさいから
    • この入出力は、かなり大きいものでもできます。typeで30人分の名前1月分の勤務それも、付随する記号を書くために4重、当直1ヶ月分、行事1ヶ月という設定で勤務入力支援ソフトを作ったときに使いました。i486sx25MHzのボロノートパソコンでも快適にHDDの入出力が可能です。
    • 簡単だし、いろいろなところで利用できると思います。(2008/7/2)

一通りしかない合計数の利用

  • ここで、Memo1の利用。Hint.txtってファイルに一通りしかない合計数を入力してヒントに使う。
    • まず広域変数を増やす。
    • 2次配列kは、何コマの合計かを入れる入れ物。これは、次の項目で使う。
    • soは、元の文字列としての一通りしかない組み合わせ。
    • keは、そのコマ数
    • acは、合計数

問題を解くためのdataを準備して配置する

    • Q配列逆さまに勘定していくと意外と簡単にできました。最初は、空空空空13で、合計13の位置のk配列に4を入れる。
    • はじめは頭から勘定してその数の分を戻ったk配列にいれて......途中まで数えたQ配列の続きを......と考え込んでいい案が浮かばない。で、前述の通り。
    • Q配列のZ=2,3に答えの可能性のある数字の羅列を配置する。
    • 問題は、2通り以上の組み合わせが考えられる場合に'123456789'を入れるのかというところ。
    • 11行目のif thenのところが苦労したいい加減な上限数字の計算式
  • ここまでが準備、やっと完了

いよいよ解くプログラム

    • 見ての通り、文字列S中の一部を入れ替えるもの。
    • 縦に入る場合の可能性のあるものと横のそれには、最低1個共通する数字がある、それを求める関数。
    • 共通の数字が1つの場合は、その数字を返し、2つ以上なら''(空)を返す。
    • 共通の数字が1つ確定したら、その関連するコマから、確定した数字を消去。
    • 確定した数字も表示する。
    • たとえば4項和のうち3項が確定すれば残りの1つが確定する。これを縦横について調べる。
  • 問題を入力して保存する。間違いがないか、充分にチェックして保存。
  • そしたら、面倒なので、Button1,2のEnabledをfalseにする。
  • Button3,4を配置して、Button3に全ての準備を詰め込む。
  • Button4に解法として記述した部分を詰め込む。
    • Action5Execute(Self);
    • Action6Execute(Self);
  • コンパイルしたら、Button3をクリックで準備完了。
  • Button4をクリックし続けて....
  • ....解けません。(って、ここまで2008/7/3)
  • う~~~~ん
    • Memo1は、最初の準備で使って以降用がないので、ここに各コマの中身を表示してみることにした。
    • 意外! 共通の無回答コマの縦の可能性と、横の可能性の共通の可能性が絞られていないと解る。
    • そんな訳で、未回答コマの可能性の絞込みの手順を作成し、Button4に
    • Action7Execute(Self);を入れて、コンパイル。
    • あらら、前より悪い。悪くなるはずなかった予定が各コマの状態を確認しても、中身に問題はない。
    • う~~~~ん
    • う~~~~~~~ん
    • ってことで、風呂入って寝ることにしました。(2008/7/4)

  • ゆうべお風呂で考えたのは、人間的な発想で、解けないなら、2項のところで合計が正しくなる組み合わせを探すことだった
    • 2コマ(2項和)になっている部分のそれぞれのコマの可能性を、失敗だった前のsakujoで厳選し、総当たり戦を実行。
    • 合計和になる順列が1個だけ決まったときにそれを解として、コマに入れる。
    • そしてButton4から
    • Action7Execute(Self);を削除。
    • Action8Execute(Self);を入れて、コンパイル。
    • Button4をクリックし続けて......出た!
    • 答えが全部出たかチェックする関数を設定、OKならtrueを結果として出す。
    • チェック方法は、Q配列のz=2,3の解の可能性として入っている文字列が全て桁数0か1であればOKと考える。
    • 一気に求めるために。Button4に組み込んで、コンパイル。
    • 一個答えが出ないというか、Image1のそのコマをクリックすると、Memo1に解が出ていると表示される。
    • つまり、解の表示をAction5Executeに組み込んだからとの次の6、8で全部の解を確定しても表示されない。
    • 6,5,8の順番にすれば、とりあえず全部表示できた。
    • 解の表示は、本来Checkに組み込むべき、または、Checkが完了後にまとめて表示することにすれば、OK
    • とりあえず、2008/5/24のカックロは解けた。(2008/7/5)
  • 次の回の問題が解けるか試すことが必要

次の問題(2008/6/28)で試す。

  • まるっきし、解けない。1通りしかない照合のところの該当なしの部分に次の選別を付加。
  • if (koma=2) and (kei mod 2=0) then dam:=irekae(dam,IntToStr(kei div 2),'');
  • 合計数が偶数で、二つに分けるときに、同じ数がだめだよという意味。
    • 10コマ増えただけ......
  • こうなると フラクタルな発想 である。
  • 1通りしかない照合のところの該当なしとなったところについて、4コマ中2個確定すれば合計から確定部分を引いて残りの2個について、もう一度一通りのケースで照合する。もう今日はや~めた...(2008/7/6)

  • 今日はヤッターマンの日、旧と違ってアイちゃんの体型が今時のアニメですね.....
  • フラクタルな発想の前に、もう1つ素となる数字の候補を絞り込むのは簡単だし、試す価値はある。
    • 級数の発想で最大最小、それぞれ式で表せそうな気がするが、考えるのも面倒だし、case ofで楽に処理。
    • 9項和まで調べているが、実際には、6項和までしかないし、数字が変化するところで計算式を立て、9以上は全て9、1以下は全て1とする。
    • この2つは、Action4Executeの内部に組み込んで、LocalにしてもOK、ただし、kanoseiの前に入れてあることが必要。
    • で、昨日追加した部分も含めて、矢印の3行を書き換え。
    • Let's Compile!
    • あ...その前に言うのを忘れてましたが、Button4の中身から、repeat untilを無効にしておかないと問題が解けないと無限ループに入ってしまいます。
    • { }は、移動して後ろにも付けないといけませんが、//は先頭につけるとその行の//以降をメモと認識します。
    • Button4、何回クリックしても前と一緒.........
  • 確定できない部分を再度「一通り」と照合する
    • 手順としては.....
    • 一通りを確定できない問題を探す。
    • そのコマの中の確定している答え以外の部分のコマ数と合計値を算出。
    • 一通りと照合。
    • 一致するものがあれば、その候補を決まってない部分に再度入力。
    • って、ことで......Let's Compile!
    • Button4、クリックし続けると.........
    • 解けた!
    • 次の問題は、2,3週後?(2008/7/7)

ネットで10x10の難問を探して.....

  • と、 全く解かないじゃないか.....カツシロ
  • 原因として考えられるのは、
    • ヒントに頼っている、朝日新聞のは、一通りしかない組み合わせに該当するものが多い。
    • 長い壁ができている、つまり、和を記入するコマがつながって壁になっている。極端なこと言えば、10x10ますを上下2つのカックロに作ることもできるじゃないか.......
  • 他にも簡単にプログラムできる確定方法も見つけた。
    • 3個以上残っているとき、一個以外が同じ可能性を持っている場合、その1個は数字が確定する。
    • けど、面倒くさい。
    • 数毒のプログラムの失敗を踏まえて今回は作っているので、この時の準備はしてある。
    • こんなこともあろうかと、ひそかに、問題を保存するのに、わざわざ、可能性の数字を入れる配列まで、含め4重の10x10を保存しているのが役に立つときがきた。
    • このシンプルなHDDの入出力は、このためのもの
  • 基本的な考え方は 数毒の配布のところの通り
    • 一旦保存する。
    • 可能性2個のところで順に片方の数字を入れて解かせる。
    • 矛盾がでたら、一旦保存を呼び出して駄目な数字を消す
    • 矛盾は出ないが、全部解けないなら、二旦保存....
    • 次の可能性2個を同様に処理していく
  • という具合。構想だけで、全く具体的なソースコードは浮かばない。(2008/7/10)
  • 出典 朝日新聞社『暮らしの風』8月号
  • やはり、簡単な問題は解ける。(2008/7/27)
    • 無限ループ脱出を追加。
    • 脱出後に完成していなければ、前述の 基本的な考え方を を実行することになる。
    • 一桁数字になっても矛盾があるかないかチェックするものを作らないと.......(2008/7/29)

朝日新聞

2008.0802 ついでにC=12。やっぱり、簡単な問題は解ける。(2008/8/2)
2008.0920 やっぱり、簡単な問題は解ける。
2008.1025 ついでにC=4。やっぱり、簡単な問題は解ける。
2009.0221 あんまりにも久しぶりで、プログラムの構造思い出すのに時間がかかったし、修正点も発見!
2009.0328 難易度4の割りにあっという間に解けた
2009.0502
2009.0808 難易度4の割りにボタン2クリックで解けた。ルールと解き方を参考にソースを記述しただけなんですが、人間が感じる難易度で星の数が決まっているのでしょうか? ついでに、この日の吸毒は、私のプログラムでは、星2レベルでした。つまり、最も簡単な発想の最初のボタンだけで解が求められるものはこれまでは星1~2です。

2009.1010 2009.1128 2010.0130 2010.0320
ボタン1クリックで ボタン1クリック ボタン1クリック ボタン1クリック