<?xml version="1.0" encoding="utf-8" ?>
<rss version='2.0'><channel><title>プログラム不要の「制約プログラミング手習い」</title
><link>http://karetta.jp/book/withoutprogramming</link
><description></description
><lastBuildDate>Wed, 11 Mar 2009 16:54:00 +0900</lastBuildDate
><item><title>少し大きな問題で実験</title
><link>http://karetta.jp/book-node/withoutprogramming/240962</link
><pubDate>Wed, 11 Mar 2009 16:54:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;５×５の問題でうまくいったけれど、小さいサイズでは偶然できることも多々ある。
もうすこし大きな問題で実験を続けよう。
ここでは、７×７のサイズの問題で試してみる。
&lt;/p
&gt;&lt;p&gt;用意した７×７の問題は次である。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-10.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-10.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、一応、自分の頭で解いておくべきだ。が、答えはここには示さない。
&lt;/p
&gt;&lt;p&gt;この問題を、プログラムにしてしまおう。
サイズが変わった以外、プログラム： planeloop1-5.csp　とまったく同じであるので説明は省略し、
プログラムと結果を示す。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop2-1.csp&#39;&gt;planeloop2-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop2-1.txt&#39;&gt;planeloop2-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;この結果だが、実はとんでもないことになっているのだ。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-11.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-11.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;５×５のとき、ちゃんと１つのループになってくれたのに、今回は４個のループに分かれてしまった。
&lt;/p
&gt;&lt;blockquote&gt;&lt;p&gt;しかし、プログラムには、ループは１つというのが入っているはずなのだが、
なぜおかしくなってしまったのだろうか？
&lt;/p
&gt;&lt;/blockquote
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>単一ループ</title
><link>http://karetta.jp/book-node/withoutprogramming/239677</link
><pubDate>Fri, 27 Feb 2009 16:31:26 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;とりあえず、ループになったが、まだループが１つという保証はない。
&lt;/p
&gt;&lt;p&gt;単一ループにするというのは、
&lt;a href=&#39;http://karetta.jp/book-node/withoutprogramming/230995&#39;&gt;スリザーリンク／単一ループ&lt;/a
&gt;
で検討したことがある。
このときは、ループ上のあるマスを起点として、１から順に番号を振った。
すべてのループのマスには、１からループ長さまでの連続した数が入る。
こうなっていると、１の個数とループの個数が同じになるので、
「１の個数が１つでなくてはならない」という制約で調べた。
&lt;/p
&gt;&lt;p&gt;同じ方法を使えば解けると思うのだが、それでは面白くない。
ここでは、何か別の方法を考えてみよう。
できれば、もっと素直な方法を考えてみたい。
&lt;/p
&gt;&lt;p&gt;「同一ループのマスには同じ数字を入れる」のが自然だと思う。
この線で、プログラムを作っていくことにしよう。
&lt;/p
&gt;&lt;p&gt;ところで、ループ毎に異なる数字を割り当てるには、どうしたらよいだろうか。
&lt;/p
&gt;&lt;p&gt;で、ちょっと考えた。
&lt;/p
&gt;&lt;p&gt;すべてのマスに、１〜順に値を対応させる。白マス、黒マスの区別をせずに順番に次のように入れる。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-7.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-7.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;各ループについて、そのループが通過するマスの値すべてが、通過するマスのうちの一番小さい数になるようにしよう。
&lt;/p
&gt;&lt;p&gt;上の２つのループに対してこの処理をすると、値が２と、値が１６のループができる。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-8.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-8.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;このやり方では、ループが異なれば、必ず異なる番号が割り当てられる。
用意した番号（１〜マスの総数）に対して、ループに使われている数が何個か調べる。
&lt;/p
&gt;&lt;p&gt;上の例では、２と１６が使われているので（ループの中の○の位置が、それぞれのループでの最小値の位置）、
これからループ数が２つと分かり、この状態は却下される。
&lt;/p
&gt;&lt;blockquote&gt;&lt;p&gt;さて、これをどうやったら実現できるだろうか？
&lt;/p
&gt;&lt;/blockquote
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;矢印の向きを決める配列とは別に、ループ毎の番号のための配列を用意しよう。
&lt;/p
&gt;&lt;pre&gt;(domain dn 1 25)
(domain dz 0 0)

int n11 dz)(int n21 dn)(int n31 dn)(int n41 dn)(int n51 dn)
(int n12 dn)(int n22 dn)(int n32 dz)(int n42 dn)(int n52 dn)
(int n13 dn)(int n23 dn)(int n33 dn)(int n43 dn)(int n53 dn)
(int n14 dn)(int n24 dn)(int n34 dn)(int n44 dn)(int n54 dn)
(int n15 dn)(int n25 dn)(int n35 dz)(int n45 dn)(int n55 dn)
&lt;/pre
&gt;&lt;p&gt;この配列の中身が、
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-8.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-8.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;の数字になればよい。
そのためには、どのような制約、predicateを用意すればよいか考えてみよう。
&lt;/p
&gt;&lt;p&gt;変数 nij を決めるのに何が欲しいだろうか。
&lt;/p
&gt;&lt;p&gt;1. aij そのマスの矢印の方
&lt;/p
&gt;&lt;p&gt;2. n?? 矢印の先にあるマスの中の nij なのだが、実際には現在マスの上下左右のマスのnij（ループ値）
&lt;/p
&gt;&lt;p&gt;3. nij 注目しているマスのループ値
&lt;/p
&gt;&lt;p&gt;4. 各マスが異なるようにするための値(cn セル番号)、つまり次の図の値である。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-7.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-7.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;これを、numbering というpredicateにしてみた。
&lt;/p
&gt;&lt;pre&gt;(predicate (numbering a n_e n_s n_w n_n an cn)
        (or  (and (= a 0) (= an 0))
             (and (= a 1) (= an (min n_e cn)))
             (and (= a 2) (= an (min n_s cn)))
             (and (= a 3) (= an (min n_w cn)))
             (and (= a 4) (= an (min n_n cn))) ))
&lt;/pre
&gt;&lt;p&gt;aは、矢印の方向&lt;br /&gt;
となりマスのnij（ループ値）は、n_e n_s n_w n_n であり、最後の1文字が方向を示す。&lt;br /&gt;
an は、注目マスのループ値。&lt;br /&gt;
cn は、マスの識別番号
&lt;/p
&gt;&lt;p&gt;となっているのだが、上のpredicateは、
まず黒マスの場合、ループ番号も0と決めている。これは問題ないだろう。
&lt;/p
&gt;&lt;p&gt;次に、各方向について、「マスの識別番号」と「隣マスのループ番号」の小さい方を、
そのマスのループ番号としている。
&lt;/p
&gt;&lt;p&gt;分かっただろうか。
&lt;/p
&gt;&lt;p&gt;つまり、これで、ループが通過するマスの識別番号のうち最小の値がループ全体に伝搬するはずである。
たぶんそうなるはずなんだ。
&lt;/p
&gt;&lt;p&gt;上は定義だけなので、実際には、これを次のように使わないといけない。
&lt;/p
&gt;&lt;pre&gt;(numbering a11 n21 n12  0   0  n11)
(numbering a21 n31 n22 n11  0  n21)
(numbering a31 n41 n32 n21  0  n31)
(numbering a41 n51 n42 n31  0  n41)
(numbering a51  0  n52 n41  0  n51)
(numbering a12 n22 n13  0  n11 n12)
(numbering a22 n32 n23 n12 n21 n22)
(numbering a32 n42 n33 n22 n31 n32)
(numbering a42 n52 n43 n32 n41 n42)
(numbering a52  0  n53 n42 n51 n52)
(numbering a13 n23 n14  0  n12 n13)
(numbering a23 n33 n24 n13 n22 n23)
(numbering a33 n43 n34 n23 n32 n33)
(numbering a43 n53 n44 n33 n42 n43)
(numbering a53  0  n54 n43 n52 n53)
(numbering a14 n24 n15  0  n13 n14)
(numbering a24 n34 n25 n14 n23 n24)
(numbering a34 n44 n35 n24 n33 n34)
(numbering a44 n54 n45 n34 n43 n44)
(numbering a54  0  n55 n44 n53 n54)
(numbering a15 n25  0   0  n14 n15)
(numbering a25 n35  0  n15 n24 n25)
(numbering a35 n45  0  n25 n34 n35)
(numbering a45 n55  0  n35 n44 n45)
(numbering a55  0   0  n45 n54 n55)
&lt;/pre
&gt;&lt;p&gt;この制約でちゃんとなる（と思う）。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop1-4.csp&#39;&gt;planeloop1-4.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop1-4.txt&#39;&gt;planeloop1-4.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果のループ番号部分だけ示すと次のようになっている。
&lt;/p
&gt;&lt;pre&gt;a n11   0
a n21   2
a n31   2
a n41   2
a n51   2
a n12   2
a n22   2
a n32   0
a n42   2
a n52   2
a n13   2
a n23   2
a n33   2
a n43   2
a n53   2
a n14   16
a n24   16
a n34   2
a n44   2
a n54   2
a n15   16
a n25   16
a n35   0
a n45   2
a n55   2
&lt;/pre
&gt;&lt;p&gt;つまり、２と１６の２つのループがあるということで、次図の番号と一致している。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-8.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-8.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;ということで、「めでたしめでたし」なのだが、実はループが１つというのがルールだった。
&lt;/p
&gt;&lt;p&gt;ループが１つというのは、以前にもやった気がする。思い出してみよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;このループの決め方には、１つの特徴があった。
ループの値は、ループが通過するマス（１〜２５の番号が順に各マスに対応：マスID）のうち、
最小の値がループの値になっているはずだ。
&lt;/p
&gt;&lt;p&gt;だとすると、マスの値と、ループの値が一致しているマスが、そのループが通過するマスIDで一番小さいはずだ。
そして、そうなっているのは、各ループ毎に１つしか存在しない。
&lt;/p
&gt;&lt;p&gt;ということは、マスIDとループ番号が一致している個数を調べれば、ループ数を計算できる。
そして、そのループ数は１でなければならない。
&lt;/p
&gt;&lt;p&gt;ということで、ループ数１の制約を次のように書いた。
&lt;/p
&gt;&lt;pre&gt;; single loop
(= 1 
   (+ (if (= n11  1) 1 0)
      (if (= n21  2) 1 0)
      (if (= n31  3) 1 0)
      (if (= n41  4) 1 0)
      (if (= n51  5) 1 0)
      (if (= n12  6) 1 0)
      (if (= n22  7) 1 0)
      (if (= n32  8) 1 0)
      (if (= n42  9) 1 0)
      (if (= n52 10) 1 0)
      (if (= n13 11) 1 0)
      (if (= n23 12) 1 0)
      (if (= n33 13) 1 0)
      (if (= n43 14) 1 0)
      (if (= n53 15) 1 0)
      (if (= n14 16) 1 0)
      (if (= n24 17) 1 0)
      (if (= n34 18) 1 0)
      (if (= n44 19) 1 0)
      (if (= n54 20) 1 0)
      (if (= n15 21) 1 0)
      (if (= n25 22) 1 0)
      (if (= n35 23) 1 0)
      (if (= n45 24) 1 0)
      (if (= n55 25) 1 0)))
&lt;/pre
&gt;&lt;p&gt;マスの数だけ行数が増えるが、難しいところはないだろう。
&lt;/p
&gt;&lt;p&gt;上記を追加してプログラムを走らせたら、次のようになった。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop1-5.csp&#39;&gt;planeloop1-5.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop1-5.txt&#39;&gt;planeloop1-5.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;この結果を図にすると、次のようになっていた。
すべての白マスのループ番号は２であったので、ちゃんと１つのループになっているはずだ。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-9.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-9.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;ということで、一応成功のようだ。
&lt;/p
&gt;&lt;p&gt;では、次からもっと大きなサイズで試してみよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>ループ表現戦略</title
><link>http://karetta.jp/book-node/withoutprogramming/239576</link
><pubDate>Thu, 12 Feb 2009 20:29:17 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;例題は小さすぎるし、問題は大きすぎるので、次の問題に対して、プログラムしていこう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-3.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-3.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;すべての白マスを通過するループを作るパズルであるので、まず、ループの表現方法を考えよう。
ループは、どうも有向ループを考えるのが良いらしいことは、いままでの経験でなんとなく想像できる。
&lt;/p
&gt;&lt;p&gt;今回は、書くマスに対して、次のマスへの矢印でループを示すことにしよう。
&lt;/p
&gt;&lt;p&gt;図で、きちんと示そう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-4.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-4.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;白マスには、上下左右のいずれかに向いた矢印が入る。
この矢印の方向に、ループを回ることができることにする。
&lt;/p
&gt;&lt;p&gt;４方向を、図にあるように、各方向に、１〜４の値を割り当てる。
そして、矢印の入らないマスは、０を割り当てる。
&lt;/p
&gt;&lt;p&gt;これで、例題の盤面は、次のように表現できる。
&lt;/p
&gt;&lt;pre&gt;(domain da 1 4)
(domain dz 0 0)

; arrow
(int a11 dz)(int a21 da)(int a31 da)(int a41 da)(int a51 da)
(int a12 da)(int a22 da)(int a32 dz)(int a42 da)(int a52 da)
(int a13 da)(int a23 da)(int a33 da)(int a43 da)(int a53 da)
(int a14 da)(int a24 da)(int a34 da)(int a44 da)(int a54 da)
(int a15 da)(int a25 da)(int a35 dz)(int a45 da)(int a55 da)
&lt;/pre
&gt;&lt;table class=&#39;inbody&#39; border=&#39;1&#39; cellspacing=&#39;0&#39;&gt;&lt;tr class=&#39;inbody&#39;&gt;&lt;td class=&#39;inbody&#39;&gt;da
&lt;/td
&gt;&lt;td class=&#39;inbody&#39;&gt;1〜4
&lt;/td
&gt;&lt;td class=&#39;inbody&#39;&gt;白マス
&lt;/td
&gt;&lt;/tr
&gt;&lt;tr class=&#39;inbody&#39;&gt;&lt;td class=&#39;inbody&#39;&gt;dz
&lt;/td
&gt;&lt;td class=&#39;inbody&#39;&gt;0
&lt;/td
&gt;&lt;td class=&#39;inbody&#39;&gt;黒マス
&lt;/td
&gt;&lt;/tr
&gt;&lt;/table
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop1-1.csp&#39;&gt;planeloop1-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;これだけでは何も決まらない。
ループにするにはどうすれば良いだろうか？
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;注目しているマスから次へマスへの矢印の決め方を
&lt;/p
&gt;&lt;pre&gt;(predicate (next  a e s w n)
　　　.... )
&lt;/pre
&gt;&lt;p&gt;という書き方で作ってみよう。&lt;br /&gt;
aが注目しているマス、e s w n はそれぞれ、
そのマスの東西南北の方向の隣マスである。
&lt;/p
&gt;&lt;p&gt;nextを定義する前に、nextの使い方を先に示しておこう。
各マスは、aijで示されるので、それを各マスに対して延々と書き連ねると次のようになる。
0は、盤面の外側であることを示している。
&lt;/p
&gt;&lt;pre&gt;(next a11 a21 a12  0   0 )
(next a21 a31 a22 a11  0 )
(next a31 a41 a32 a21  0 )
(next a41 a51 a42 a31  0 )
(next a51  0  a52 a41  0 )
(next a12 a22 a13  0  a11)
(next a22 a32 a23 a12 a21)
      ...
(next a35 a45  0  a25 a34)
(next a45 a55  0  a35 a44)
(next a55  0   0  a45 a54)
&lt;/pre
&gt;&lt;p&gt;まず、aが黒マスだった場合を考えよう。
黒マスだったら、隣のマスから、この黒マスへの矢印があってはダメである。
だから、黒マスの場合、次が成り立つ。
&lt;/p
&gt;&lt;pre&gt;(and (= a 0) (and (!= w 1) (!= n 2) (!= e 3) (!= s 4)))
&lt;/pre
&gt;&lt;p&gt;矢印の方向が黒マスに向かっていてはいけないので、
１、２、３、４が上のように入る。
&lt;/p
&gt;&lt;p&gt;次に、白マスの場合を考えよう。
白マスの値は１〜４であり、東西南北いずれかの方向に出て行く。
つまり、白マスから出て行く矢印は１つである。
&lt;/p
&gt;&lt;p&gt;次に、その白マスに入ってくる矢印の数について考えよう。
当然、ループで枝分かれしないのだから、どのマスで考えても、
出るのも１つ、入るのも１つでなければならない。
入るのが１つというのは、東西南北の隣マスを順番に調べて、
それらが、今注目している白マスの方向に向いているかどうかを数えれば良いだろう。
&lt;/p
&gt;&lt;pre&gt;  (+ (if (= w 1) 1 0)
   　(if (= n 2) 1 0)
     (if (= e 3) 1 0)
     (if (= s 4) 1 0))
&lt;/pre
&gt;&lt;p&gt;これで、入ってくる数が決まる。
そして入ってくる数は１でなければならない。
そういうことを全部考えると、nextは次のようになるだろう。
&lt;/p
&gt;&lt;pre&gt;(predicate (next  a e s w n)
        (or  (and (= a 0) (and (!= w 1) (!= n 2) (!= e 3) (!= s 4)))
             (and (!= a 0)
                  (= 1 
                     (+ (if (= w 1) 1 0)
                        (if (= n 2) 1 0)
                        (if (= e 3) 1 0)
                        (if (= s 4) 1 0))))))
&lt;/pre
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop1-2.csp&#39;&gt;planeloop1-2.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、実行した結果はどうなったであろうか。
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop1-2.txt&#39;&gt;planeloop1-2.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;わかりやすいように、図に示した。（作るの面倒なんだ）
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-5.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-5.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;1,2,3,4の値は、全部矢印の向きに直して示してある。
黒い矢印は、ちゃんとループになっている。
しかし、赤い矢印の部分がダメだ。
&lt;/p
&gt;&lt;p&gt;なぜ？
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;矢印が互いにぶつかってしまっていたのを取り除かねばいけない。
&lt;/p
&gt;&lt;p&gt;つまり、もうすこし(predicate (next  a e s w n) ... ) の条件を増やさねばならない。
&lt;/p
&gt;&lt;p&gt;具体的に考えてみよう。右向きの矢印（a=1）だったら、
右のマスは、左向きの矢印であってはいけない(!= e 3)。
つまり、
&lt;/p
&gt;&lt;pre&gt;(and (= a 1) (!= e 3)）
&lt;/pre
&gt;&lt;p&gt;となる。
つまり、白マスならば、aは1〜4のいずれかなので、
&lt;/p
&gt;&lt;pre&gt;    (or (and (= a 1) (!= e 3)）
        (and (= a 2) (!= s 4))
        (and (= a 3) (!= w 1))
        (and (= a 4) (!= n 2)))
&lt;/pre
&gt;&lt;p&gt;を条件に加えれば良いはずだ。
&lt;/p
&gt;&lt;pre&gt;(predicate (next  a e s w n)
        (or  (and (= a 0) (and (!= w 1) (!= n 2) (!= e 3) (!= s 4)))
             (and (!= a 0)
                  (or (and (= a 1) (!= e 3))
                      (and (= a 2) (!= s 4))
                      (and (= a 3) (!= w 1))
                      (and (= a 4) (!= n 2)))
                  (= 1 
                     (+ (if (= w 1) 1 0)
                        (if (= n 2) 1 0)
                        (if (= e 3) 1 0)
                        (if (= s 4) 1 0))))))
&lt;/pre
&gt;&lt;p&gt;(!= a 0) は、無駄なので省略できるので、次のようになる。
&lt;/p
&gt;&lt;pre&gt;(predicate (next  a e s w n)
        (or  (and (= a 0) (and (!= w 1) (!= n 2) (!= e 3) (!= s 4)))
             (and (or (and (= a 1) (!= e 3))
                      (and (= a 2) (!= s 4))
                      (and (= a 3) (!= w 1))
                      (and (= a 4) (!= n 2)))
                  (= 1 
                     (+ (if (= w 1) 1 0)
                        (if (= n 2) 1 0)
                        (if (= e 3) 1 0)
                        (if (= s 4) 1 0))))))
&lt;/pre
&gt;&lt;p&gt;こう直したプログラムを示す。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop1-3.csp&#39;&gt;planeloop1-3.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/planeloop1-3.txt&#39;&gt;planeloop1-3.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;図示したものを示す。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-6.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-6.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;ループがちゃんと閉じているので一応成功だ。
&lt;/p
&gt;&lt;p&gt;しかし、２つのループになってしまった。これは今まで、他のパズルでも経験したことであり、
別途制約を加えることで対応していこう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>ルール</title
><link>http://karetta.jp/book-node/withoutprogramming/239556</link
><pubDate>Mon, 09 Feb 2009 16:40:27 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;いろいろなパズルを紹介してきたが、今回は非常にルールが簡単、それも超簡単なやつである。
&lt;/p
&gt;&lt;p&gt;ジャンルとしては、ループ系のパズルで、すべてのマスを通るループの作成だ。
&lt;/p
&gt;&lt;p&gt;まずは、ルールから。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-1.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-1.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;もう説明の余地がないほど簡単だ。
&lt;/p
&gt;&lt;p&gt;このパズルは、実は、
&lt;a href=&#39;http://puzzle.gr.jp/show/Japanese/hima&#39;&gt;『ひまつぶしパズル集』&lt;/a
&gt;
の
&lt;a href=&#39;http://puzzle.gr.jp/kahua/kahua-web/hima/plain.pdf&#39;&gt;プレーンループ　全てのマスを一度ずつ通る&lt;/a
&gt;(PDF)
そのものである。
&lt;/p
&gt;&lt;p&gt;とりあえず、同じページの問題も載せておこう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-planeloop-2.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-planeloop-2.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;この問題を解きながら、sugarプログラム作成の戦略を次回までに考えよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>完全虫食算</title
><link>http://karetta.jp/book-node/withoutprogramming/238602</link
><pubDate>Wed, 04 Feb 2009 17:06:03 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;調子に乗って、さらに上のレベルの問題である、すべてのマスが虫食いの問題に挑戦してみよう。
&lt;/p
&gt;&lt;p&gt;といっても、その中にもいろいろなレベルが存在する。
&lt;/p
&gt;&lt;p&gt;次の問題では、最後に綺麗に割り切れるので０が存在する。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-009.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-009.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;商の部分に「.」があるが、小数点である。
&lt;/p
&gt;&lt;p&gt;筆算での割り算表記は国により若干の相違があり、割りきれてしまう、
引いたとき何も残らないとき、普通に線を引くのではなく、
２重線を引いて割り切れたことを示すというのがあり、
その場合には０も書かないので、「完全虫食い算」として扱うのである。
&lt;/p
&gt;&lt;p&gt;完全虫食い算になったからといって、プログラミングは何も変わらない。
制約がどんどん少なくなるので、ちゃんともとまるのかどうかが不安になるだけである。
&lt;/p
&gt;&lt;p&gt;それでは、まず、自分で解いてみよう。自分の頭で解くもよし、プログラムで解くもよし。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;完全虫食い算になったからといって、何も変わりはしない。
縛りが少なくなるので、もしかしたら強烈に遅くなってしまわないかという懸念だけである。
&lt;/p
&gt;&lt;p&gt;今までと同様に、
上から順に、各数（□のまとまり）についてaから順に変数を割り当てた。
次の図では、割り当てたアルファベットを赤で示してある。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-010.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-010.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;プログラムは、完全虫食い算になったため、制約が少なくなる。
小数点が存在するが、小数点以下が０の場合にマスがなくなるが、
プログラム上では０になるだけである
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan5-1.csp&#39;&gt;mushikuizan5-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、実行速度はどうであろうか。帰ってくるだろうか。
&lt;/p
&gt;&lt;p&gt;では実行してみよう。今回は遅いかもしれない。
&lt;/p
&gt;&lt;pre&gt;$ time sugar mushikuizan5-1.csp &amp;gt; mushikuizan5-1.txt

real    0m1.232s
user    0m0.964s
sys     0m0.132s
$ 
&lt;/pre
&gt;&lt;p&gt;今回も、１秒で求まった。良かった。
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan5-1.txt&#39;&gt;mushikuizan5-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;　　　　　　１０１１１００８
　　　ーーーーーーーーーーー
６２５）６３１９３８
　　　　６２５
　　　　ーーーーー
　　　　　　６９３
　　　　　　６２５
　　　　　　ーーーー
　　　　　　　６８８
　　　　　　　６２５
　　　　　　　ーーーー
　　　　　　　　６３０
　　　　　　　　６２５
　　　　　　　　ーーーー
　　　　　　　　　　５０００
　　　　　　　　　　５０００
　　　　　　　　　　ーーーー
　　　　　　　　　　　　　０
&lt;/pre
&gt;&lt;p&gt;小数点は書きにくかったので省略してある。
&lt;/p
&gt;&lt;p&gt;ということで、これで終わりとしても良いのだが、割り切れることを示す０も無くしたいと思わないか。
つまり、数字がまったく現れない正真正銘の完全虫食い算は存在しないのだろうか？
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;最後の虫食い算として、０も存在しない問題を紹介しよう。
&lt;/p
&gt;&lt;p&gt;１９２１年に、オランダのFred Schuchが
「American Mathematical Monthly」に発表した問題である。
&lt;/p
&gt;&lt;p&gt;同じ問題は、青空文庫の佐野昌一の『虫喰い算大会』の第28会場にも見られる。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-011.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-011.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;０を失したかわりに、一番上の数（商）の上に、「・」が２箇所ある。
これは、何だろうか？
&lt;/p
&gt;&lt;p&gt;循環小数であるが、循環小数なんて覚えているだろうか？
&lt;/p
&gt;&lt;p&gt;上の黒点は、点と点の間（両端の点もともに含む）が永久に繰り替えされるということである。
&lt;/p
&gt;&lt;blockquote&gt;&lt;p&gt;さて、これはどうやってプログラムを組めば良いのだろうか。
つまり、循環小数であることをどういう制約にすればよいのだろうか。
&lt;/p
&gt;&lt;/blockquote
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;今までと違うところは、循環小数の部分である。
&lt;/p
&gt;&lt;p&gt;そもそも、循環小数とは何か、筆算の上ではどのようになるか調べたであろうか。
&lt;/p
&gt;&lt;p&gt;まあ、調べたとして、話を進めよう。
&lt;/p
&gt;&lt;pre&gt;    . .
1.23456
&lt;/pre
&gt;&lt;p&gt;とは、
&lt;/p
&gt;&lt;pre&gt;1.23456456456456456
&lt;/pre
&gt;&lt;p&gt;ということで、上の点がついている数字を両端とする数字列が延々と繰り替えされることである。
これは、1.23 の余りを割ると456となり、さらにその余りを割ると456tなり、というのが永久に繰り替えされることを示している。
&lt;/p
&gt;&lt;p&gt;これを、虫食算で示すと、次図の空色マスの部分が一致することである。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-012.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-012.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;ということで、分かって欲しい。
&lt;/p
&gt;&lt;p&gt;これ以上書くのは面倒なのだ！
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;さて、いつものように、各数字に、a〜uまでの記号を割り当ててると、次図のようになる。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-013.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-013.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;桁数も多いし、段数も多く、プログラムが長くなってしまった。
延々と書くだけであるが、一発でバグを入れずに書くのは難しく、実際には徐々に試して行った。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan6-1.csp&#39;&gt;mushikuizan6-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行してみよう。
&lt;/p
&gt;&lt;pre&gt;$ time sugar mushikuizan6-1.csp &amp;gt; mushikuizan6-1.txt

real    3m2.152s
user    3m2.407s
sys     0m0.412s
$
&lt;/pre
&gt;&lt;p&gt;３分もかかって、やっと結果が出てきた。結果はどうだろうか。
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan6-1.txt&#39;&gt;mushikuizan6-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;　　　　　　　　　　　　　　　・　　　　　　　・
　　　　　　　　　　　　１１６１６８８３０００１
　　　　　　ーーーーーーーーーーーーーーーーーーー
６６７３３４）７７５２３４１
　　　　　　　６６７３３４
　　　　　　ーーーーーーーーー
　　　　　　　１０７９００１
　　　　　　　　６６７３３４
　　　　　　　ーーーーーーーーー
　　　　　　　　４１１６６７０
　　　　　　　　４００４００４
　　　　　　　ーーーーーーーーーー
　　　　　　　　　１１２６６６０
　　　　　　　　　　６６７３３４
　　　　　　　　　ーーーーーーーーー
　　　　　　　　　　４５９３２６０
　　　　　　　　　　４００４００４
　　　　　　　　　ーーーーーーーーーー
　　　　　　　　　　　５８９２５６０
　　　　　　　　　　　５３３８６７２
　　　　　　　　　　ーーーーーーーーーー
　　　　　　　　　　　　５５３８８８０
　　　　　　　　　　　　５３３８６７２
　　　　　　　　　　　ーーーーーーーーーー
　　　　　　　　　　　　　２００２０８０
　　　　　　　　　　　　　２００２００２
　　　　　　　　　　　　ーーーーーーーーーーーーー
　　　　　　　　　　　　　　　　　　７８００００
　　　　　　　　　　　　　　　　　　６６７３３４
　　　　　　　　　　　　　　　　　ーーーーーーーー
　　　　　　　　　　　　　　　　　　１１２６６６
&lt;/pre
&gt;&lt;p&gt;ということで、３分かかったものの、ちゃんと解けているようだ。
&lt;/p
&gt;&lt;p&gt;もっと大きな虫食算、さらには『世界最大の虫食い算』などもあるが、そこまで頑張るのは宿題にしておこう。
&lt;/p
&gt;&lt;p&gt;虫食算は以上で終わりにしておく。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>孤独の７</title
><link>http://karetta.jp/book-node/withoutprogramming/238604</link
><pubDate>Sun, 25 Jan 2009 22:25:55 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;同じく、割り算の虫食算であるが、今度は７が１つだけのを紹介しよう。
最後が割りきれて０になってしまうので０もあるのだが、これはそういうものだと納得しよう。
&lt;/p
&gt;&lt;p&gt;これは、ドイツのアッカーマン（Wilhelm Ackermann, 1896〜1962)の１９２５年に出された「Scientific Paradoxes and Problems」
に、E.F.オドリング(Egbert F. Odling)の「孤独の７」という問題である。
&lt;/p
&gt;&lt;p&gt;アッカーマンは、あのアッカーマン関数という悪魔のように計算量が爆発する関数を考案した数学者として有名である。
&lt;/p
&gt;&lt;p&gt;さて、そのアッカーマンの本に掲載された、オドリングの問題は次である。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-007.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-007.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;途中の７が１つと、最後の０しか情報がないので大変に見えるかもしれない。
今日は問題だけ示しておくので、ぜひ解いてみよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;「７つの７の問題」と同様に解くことができる。
上から順に、各数（□のまとまり）についてaから順に変数を割り当てた。
次の図では、割り当てたアルファベットを赤で示してある。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-008.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-008.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;プログラムは、「７つの７の問題」とまったく同じようにして作れる。
そして、問題のサイズは小さくなっているので、プログラムは短くなっってしまったので、
プログラムだけ載せておく。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan4-1.csp&#39;&gt;mushikuizan4-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、実行速度はどうであろうか。前回と違って、制約が少なくなってしまった。
最後の０を入れても、数字が明示されているのは２つである。
&lt;/p
&gt;&lt;p&gt;では実行してみよう。今回は遅いかもしれない。
&lt;/p
&gt;&lt;pre&gt;$ time sugar mushikuizan4-1.csp &amp;gt; mushikuizan4-1.txt

real    0m0.990s
user    0m1.028s
sys     0m0.092s
$ 
&lt;/pre
&gt;&lt;p&gt;今回も、１秒で求まった。
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan4-1.txt&#39;&gt;mushikuizan4-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;　　　　　　　９７８０９
　　　ーーーーーーーーー
１２４）１２１２８３１６
　　　　１１１６
　　　　ーーーーー
　　　　　　９６８
　　　　　　８６８
　　　　　　ーーーー
　　　　　　１００３
　　　　　　　９９２
　　　　　　　ーーーーー
　　　　　　　　１１１６
　　　　　　　　１１１６
　　　　　　　　ーーーー
　　　　　　　　　　　０
&lt;/pre
&gt;&lt;p&gt;さて、ここまでできるのなら、次は、まったく数字が現れない「完全虫食算」に挑戦しよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>7つの7の問題</title
><link>http://karetta.jp/book-node/withoutprogramming/238600</link
><pubDate>Sun, 25 Jan 2009 22:37:08 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;虫食算は百年以上の歴史があり、歴史的な名作を実際に解いてみよう。
&lt;/p
&gt;&lt;p&gt;まずは、７が７つ現れる問題を紹介しよう。
&lt;/p
&gt;&lt;p&gt;これは、英国の数学者ベリック（W.E.H.Berwick, 1888〜1944)が１９０６年に
「The School World」に掲載したものである。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-005.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-005.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;これは、あまりにも有名な古典的名作だそうである。
この問題によって、虫食算が知的な大人の遊びとして認識されたとのことだ。
（『数のパズル読本』秋山久義著、新紀元社　よりの受け売り。より詳しくは、この本を読まれたし。）
&lt;/p
&gt;&lt;p&gt;今日は、問題の提供だけにとどめておくので、ぜひ自分でプログラムしてみよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;前回と同様に、上から順に、各数（□のまとまり）についてaから順に変数を割り当てた。
次の図では、割り当てたアルファベットを赤で示してある。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-006.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-006.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;掛け算と割り算では、見かけは違うが、実はそれほど差はない。
筆算における割り算とは、結局掛け算と引き算を行っているだけに過ぎないので、
特別な説明は不要だと思う。
&lt;/p
&gt;&lt;p&gt;ただし、プログラムで、１つだけ工夫というか、横着している部分があるので、
その点だけを示すにどどめる。
&lt;/p
&gt;&lt;p&gt;用意したプログラムには、実は引き算は使っていない。
引き算を、足し算に直して計算している。
&lt;/p
&gt;&lt;p&gt;つまり、　c - d = e があったら、　c = d + e に直してプログラムした。
&lt;/p
&gt;&lt;p&gt;これだけ頭に入れてプログラムを見れば、プログラムはただただ書いているだけというのが分かるだろう。
&lt;/p
&gt;&lt;p&gt;プログラムは140行にもなってしまったので、リンクだけにしておいた。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan3-1.csp&#39;&gt;mushikuizan3-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;では、実行してみよう。本格的（？）な虫食算だと、どのくらい時間がかかるだろうか？
&lt;/p
&gt;&lt;pre&gt;$ time sugar mushikuizan3-1.csp &amp;gt; mushikuizan3-1.txt

real    0m1.486s
user    0m1.740s
sys     0m0.188s
$
&lt;/pre
&gt;&lt;p&gt;何と、またまたすぐに解けてしまった。
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan3-1.txt&#39;&gt;mushikuizan3-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;本当に正しいか、確認が必要だ。長くなるから、結果は実行結果ファイルを見てもらうことにして、
筆算の形に直したものだけ載せておこう。
&lt;/p
&gt;&lt;pre&gt;　　　　　　　　　　　　５８７８１
　　　　　　ーーーーーーーーーーーー
１２５４７３）７３７５４２８４１３
　　　　　　　６２７３６５
　　　　　　　ーーーーーーー
　　　　　　　１１０１７７８
　　　　　　　１００３７８４
　　　　　　　ーーーーーーーー
　　　　　　　　　９７９９４４
　　　　　　　　　８７８３１１
　　　　　　　　　ーーーーーーー
　　　　　　　　　１０１６３３１
　　　　　　　　　１００３７８４
　　　　　　　　　ーーーーーーーー
　　　　　　　　　　　１２５４７３
　　　　　　　　　　　１２５４７３
　　　　　　　　　　　ーーーーーー
　　　　　　　　　　　　　　　　０
&lt;/pre
&gt;&lt;p&gt;今回の問題は、７が７つも存在したわけで、たくさんの制約があり、それで高速になっただけかもしれない。
もうちょっと制約の少ない問題を探すことにしよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>多倍長整数演算</title
><link>http://karetta.jp/book-node/withoutprogramming/238459</link
><pubDate>Tue, 20 Jan 2009 10:10:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;虫食算や覆面算では、非常に桁数の多い問題も存在する。
&lt;/p
&gt;&lt;p&gt;sugarで整数がどこまで使えるか、ちょっと試しておこう。
&lt;/p
&gt;&lt;p&gt;まず、a + b = c の計算をしてみよう。
ただし、a=12345, b=67890 とやや大きな数にしておく。
&lt;/p
&gt;&lt;pre&gt;; long.csp

(domain num 0 999999)

(int a num)
(int b num)
(int c num)

(= (+ a b) c)

(= a 12345)
(= b 67890)
&lt;/pre
&gt;&lt;p&gt;これを実行すると、
&lt;/p
&gt;&lt;pre&gt;$ sugar long.csp
s SATISFIABLE
a a     12345
a b     67890
a c     80235
a
$
&lt;/pre
&gt;&lt;p&gt;となり、和の80235がちゃんと得られた。
&lt;/p
&gt;&lt;p&gt;ここで、domainの範囲だけを拡大してみた。
&lt;/p
&gt;&lt;pre&gt;; long.csp

(domain num 0 9999999999)

(int a num)
(int b num)
(int c num)

(= (+ a b) c)

(= a 12345)
(= b 67890)
&lt;/pre
&gt;&lt;p&gt;これを実行すると、
&lt;/p
&gt;&lt;pre&gt;$ sugar long.csp
c 0     ERROR Exception Illegal domain instantiation 0 -2
s UNKNOWN
$
&lt;/pre
&gt;&lt;p&gt;となってしまった。
&lt;/p
&gt;&lt;p&gt;変数の値は変更していなくて、変数のドメインを変更しただけなのに、それだけで　Illegal domain　に成り果てたようだ。」
&lt;/p
&gt;&lt;p&gt;つまり、９桁はOKだが、１０桁の計算はできないということだ。
&lt;/p
&gt;&lt;p&gt;となると、１０桁以上がどこかに現れる虫食算はsugarでは不可能ということだ。
&lt;/p
&gt;&lt;p&gt;しかし、それでは、大型虫食算といわれる虫食算の大作には挑戦できないということだ。
ちと情けないではないか。筆算には桁数制限などないのである。何万桁の虫食算だった作れるのだ。
たぶん世界最大の虫食算は安福氏の『世界最大の虫食い算』文春新書に掲載されている2万桁の虫食算であろう。
&lt;/p
&gt;&lt;p&gt;まあ、こんな無茶な問題は別として、10桁以上が現れる虫食算はいくらでも存在する。
そういうのもちゃんと解けるようにするには、sugarの桁数制限を突破しなくてはならない。
&lt;/p
&gt;&lt;blockquote&gt;&lt;p&gt;さて、どうすれば桁数制限のない計算が可能になるのだろうか？
&lt;/p
&gt;&lt;/blockquote
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;例題の一部に対して、いくら桁が長くなっても大丈夫な方法で計算することを考えてみよう。
&lt;/p
&gt;&lt;p&gt;まず、以下の赤い部分だけの計算を考える。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-003.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-003.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;５桁　×　１桁　⇒　５桁
&lt;/p
&gt;&lt;p&gt;の計算である。そのうち、一部の桁については、数字が決まっている。
&lt;/p
&gt;&lt;p&gt;この計算を、１桁毎にやっていくことを考えよう。
そのためには、桁上がりが必要なので、次のように大文字の Cn を用いた。cnが積を示すのに対し、
その途中の桁上がりについては、変数を大文字にして使うことにした。
&lt;/p
&gt;&lt;p&gt;sugarでの変数は、大文字、小文字を区別する。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-004.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-004.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;上の図をsugarで示すと次のようになる。
&lt;/p
&gt;&lt;pre&gt;(= (+ (* a1 b1)  0) (+ (* C1 10) c1))
(= (+ (* a2 b1) C1) (+ (* C2 10) c2))
(= (+ (* a3 b1) C2) (+ (* C3 10) c3))
(= (+ (* a4 b1) C3) (+ (* C4 10) c4))
(= (+ (* a5 b1) C4) (+ (* C5 10) c5))
(= C5 0)
&lt;/pre
&gt;&lt;p&gt;と言いたいところだが、sugarでは変数同士の掛け算ができないので、工夫が必要である。
&lt;/p
&gt;&lt;p&gt;上の積の部分は、mul1 を用いて、中間の変数に１桁同士の掛け算の結果を記憶し、
後で使うようにした。まあ、使い捨て変数みたいなものであるが、sugarでは必要だ。
&lt;/p
&gt;&lt;pre&gt;(predicate (mul1 a b c)
           (element b ((* a 1) (* a 2) (* a 3)
                       (* a 4) (* a 5) (* a 6)
                       (* a 7) (* a 8) (* a 9))
                    c))

(mul1 a1 b1 a1b1) (= (+ a1b1  0) (+ (* C1 10) c1))
(mul1 a2 b1 a2b1) (= (+ a2b1 C1) (+ (* C2 10) c2))
(mul1 a3 b1 a3b1) (= (+ a3b1 C2) (+ (* C3 10) c3))
(mul1 a4 b1 a4b1) (= (+ a4b1 C3) (+ (* C4 10) c4))
(mul1 a5 b1 a5b1) (= (+ a5b1 C4) (+ (* C5 10) c5))
(= C5 0)
&lt;/pre
&gt;&lt;p&gt;上記の計算のために、変数をあれこれ前もって宣言しておかねばならない。
&lt;/p
&gt;&lt;pre&gt;(domain num 0 9)
(domain nn  0 99)

(int a5 num)(int a4 num)(int a3 num)(int a2 num)(int a1 num)
(int b1 num)
(int c5 num)(int c4 num)(int c3 num)(int c2 num)(int c1 num)
(int C5 num)(int C4 num)(int C3 num)(int C2 num)(int C1 num)

(int a5b1 nn)(int a4b1 nn)(int a3b1 nn)(int a2b1 nn)(int a1b1 nn)

(!= a5 0)
(!= b1 0)
(!= c5 0)
&lt;/pre
&gt;&lt;p&gt;そして、最初から決まっている箇所を指定する。
&lt;/p
&gt;&lt;pre&gt;(= a3 7)
(= c4 0) (= c2 7)
(!= b1 1)
&lt;/pre
&gt;&lt;p&gt;ここまでの説明を全部まとめたのが次のプログラムである。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan2-1.csp&#39;&gt;mushikuizan2-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;虫食算の一部だけなのだが、一応実行してみよう。
&lt;/p
&gt;&lt;pre&gt;$ sugar mushikuizan2-1.csp
s SATISFIABLE
a a5    1
a a4    7
a a3    7
a a2    1
a a1    9
a b1    4
a c5    7
a c4    0
a c3    8
a c2    7
a c1    6
a C5    0
a C4    3
a C3    2
a C2    0
a C1    3
a a5b1  4
a a4b1  28
a a3b1  28
a a2b1  4
a a1b1  36
a
$
&lt;/pre
&gt;&lt;p&gt;つまり、次の計算ができた。
&lt;/p
&gt;&lt;pre&gt;　　１７７１９
　×　　　　４
ーーーーーーーー
　　７０８７６　
&lt;/pre
&gt;&lt;p&gt;このやり方だと、桁数はまったく関係ない。
&lt;/p
&gt;&lt;p&gt;さて、これで、
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-001.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-001.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;を解いたらどうなるだろうか。
&lt;/p
&gt;&lt;p&gt;前は、16分30秒ほど掛かっているが、この1桁毎のバラバラ事件で解くと、どのくらい掛かるだろうか？
速くなるだろか、遅くなるだろうか、予想してみよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;まず、最下段の最終的な積の部分を無視したプログラムを作った。
&lt;/p
&gt;&lt;p&gt;考え方は、前回示した mushikuizan2-1.csp の方法を３度繰り替えしただけであるので
詳しい説明は省略し、プログラムを別ファイルで示す。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan2-2.csp&#39;&gt;mushikuizan2-2.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さあ、これを実行してみよう。どのくらい時間がかかるかも測定したいので、timeで計測しよう。
&lt;/p
&gt;&lt;pre&gt;$ time sugar mushikuizan2-2.csp &amp;gt; mushikuizan2-2.txt

real    0m0.977s
user    0m0.984s
sys     0m0.100s
$ 
&lt;/pre
&gt;&lt;p&gt;おかしい、前回16分30秒、つまり990秒もかかったのに、今回は1秒弱である。
速度が1000倍になってしまった。こんなことはあるのだろうか。
&lt;/p
&gt;&lt;p&gt;もしかして、解が求まっていないのではないだろうか。
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan2-2.txt&#39;&gt;mushikuizan2-2.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;a a5    1
a a4    2
a a3    7
a a2    1
a a1    8
a b3    6
a b2    7
a b1    4
a c5    5
a c4    0
a c3    8
a c2    7
a c1    2
....
&lt;/pre
&gt;&lt;p&gt;ということで、１２７１８×６７４になっているので正解だ。
&lt;/p
&gt;&lt;p&gt;恐ろしく早くなってしまった。
&lt;/p
&gt;&lt;p&gt;ついでに、最下段の積の部分も３つの積の和を求めることで完成させてみよう。
この問題では影響はないが、普通は影響がでる。
&lt;/p
&gt;&lt;p&gt;最後の積（途中の３つの積の和）を求めるときにも、桁上がりのための変数を大文字の変数として用意した。
その他はまったく同様にしてできるのと、図を描くのが面倒なので、図は省略し、プログラムを示す。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan2-3.csp&#39;&gt;mushikuizan2-3.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;$ time sugar mushikuizan2-3.csp &amp;gt; mushikuizan2-3.txt

real    0m0.958s
user    0m1.064s
sys     0m0.140s
$
&lt;/pre
&gt;&lt;p&gt;最下段を加えても、今回はトラブルも発生せず、ほぼ同じ時間で計算できてしまった。
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan2-3.txt&#39;&gt;mushikuizan2-3.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;結果は正しいと思うので、疑い深い人は確認されたし。
&lt;/p
&gt;&lt;blockquote&gt;&lt;h4 id=&#39;H-f64tdd&#39;&gt;sugarは虫食算には向かないかと思ったが、もしかして向いているかも。
&lt;/h4
&gt;&lt;/blockquote
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>とりあえず解いてみよう</title
><link>http://karetta.jp/book-node/withoutprogramming/238351</link
><pubDate>Sun, 18 Jan 2009 21:46:14 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;虫食い算は、どこかな算に非常に近い。
周囲に矢印で数字の入る位置（列）を示すのではなく、
一部の数字が決まっている。
&lt;/p
&gt;&lt;p&gt;説明を書くのも面倒なので、さっさと例題を示すことにしよう。
&lt;/p
&gt;&lt;p&gt;例題は、青空文庫の
&lt;a href=&#39;http://www.aozora.gr.jp/cards/000160/files/43533_16824.html&#39;&gt;『虫喰い算大会』佐野昌一著&lt;/a
&gt;
から引用することにしよう。
&lt;/p
&gt;&lt;p&gt;第二十一会場の（１）の問題である。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-001.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-001.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;この問題を、まずは虫食い算のところでやったような方法でプログラムしてみよう。
&lt;/p
&gt;&lt;p&gt;その前に、自分で頭と手で解いてみますか。
ちゃんと解ければ、正月ボケはもう直っているでしょう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;さっそくプログラムを用意した。「どこかな算」より簡単である。
&lt;/p
&gt;&lt;pre&gt;; mushikuizan1-1.csp

(domain num 0 9)

(int a5 num)(int a4 num)(int a3 num)(int a2 num)(int a1 num)
(int b3 num)(int b2 num)(int b1 num)
(int c5 num)(int c4 num)(int c3 num)(int c2 num)(int c1 num)
(int d5 num)(int d4 num)(int d3 num)(int d2 num)(int d1 num)
(int e5 num)(int e4 num)(int e3 num)(int e2 num)(int e1 num)
(int f7 num)(int f6 num)(int f5 num)(int f4 num)(int f3 num)(int f2 num)(int f1 num)

(= a3 7)
(= b2 7)
(= c4 0)(= c2 7)
(= d3 0)
(= e5 7)(= e2 0)

(predicate (mul1 a b c)
           (element b ((* a 1) (* a 2) (* a 3)
                       (* a 4) (* a 5) (* a 6)
                       (* a 7) (* a 8) (* a 9))
                    c))

(int na   10000  99999)  (= na (+ (* a5 10000) (* a4 1000) (* a3 100) (* a2 10) a1))
(int nb     100    999)  (= nb (+ (* b3 100) (* b2 10) b1))
(int nc   10000  99999)  (= nc (+ (* c5 10000) (* c4 1000) (* c3 100) (* c2 10) c1))
(int nd   10000  99999)  (= nd (+ (* d5 10000) (* d4 1000) (* d3 100) (* d2 10) d1))
(int ne   10000  99999)  (= ne (+ (* e5 10000) (* e4 1000) (* e3 100) (* e2 10) e1))
(int nf   1000000  9999999)  
    (= nf (+ (* f7 1000000) (* f6 100000) (* f5 10000) (* f4 1000) (* f3 100) (* f2 10) f1))

(mul1 na b1 nc)
(mul1 na b2 nd)
(mul1 na b3 ne)
(= (+ nc (* nd 10) (* ne 100)) nf)
&lt;/pre
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan1-1.csp&#39;&gt;mushikuizan1-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;では実行してみよう。
&lt;/p
&gt;&lt;pre&gt;$ sugar mushikuizan1-1.csp

........ずっと待たされて

c 3758  ERROR Exception Too large /tmp/sugar25053.cnf
s UNKNOWN
$
&lt;/pre
&gt;&lt;p&gt;となる。一体何が起きたのだろか？
&lt;/p
&gt;&lt;p&gt;/tmpの下には、きっとテンポラリ・ファイルができるだろうから、
それが巨大になってどうにもならなくなって、Too large を出されて終わったようだ。
&lt;/p
&gt;&lt;p&gt;う〜む、やさしくはないけれど、この程度の問題で爆発してしまうのでは困るなぁ。
リソースを食いつぶしやすいプログラムであると言われているのは、こういうことなんだろね。
&lt;/p
&gt;&lt;p&gt;さて、どうすれば良いだろうか？ここで引き下がってはいけない。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;どうやったらリソースの浪費を減らせるであろうか。
&lt;/p
&gt;&lt;p&gt;問題をじーっと見つめていると、この問題には大いなる無駄がある。
つまり、下図の赤で括っている部分である。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-mushikuizan-002.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-mushikuizan-002.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;この赤い部分は、単に上の3行の和になっているだけで、
問題に何の制約を加えている訳でもない。
桁数も、上の３行を加えても、８桁になることはありえないので、
７桁であること自体も解く手がかりを一切与えてくれない。
&lt;/p
&gt;&lt;p&gt;つまり、赤で括った積の部分は無くても問題としては何も変化がない。
&lt;/p
&gt;&lt;p&gt;パズル的に頭は使いたくなかったのだが、今回は特別に上記のことを考慮してプログラムを変更した。
&lt;/p
&gt;&lt;p&gt;以下に、変更部分（コメントアウト）だけを示す。最下段に関する部分を消すだけである。
&lt;/p
&gt;&lt;pre&gt;.....
;(int f7 num)(int f6 num)(int f5 num)(int f4 num)(int f3 num)(int f2 num)(int f1 num)
.....
;(int nf   1000000  9999999)
;     (= nf (+ (* f7 1000000) (* f6 100000) (* f5 10000) (* f4 1000) (* f3 100) (* f2 10) f1))
.....
;(= (+ nc (* nd 10) (* ne 100)) nf)
&lt;/pre
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan1-2.csp&#39;&gt;mushikuizan1-2.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;これをもう一度実行し、我慢強く待っていると(16分も待っているのは大変だ！)
&lt;/p
&gt;&lt;pre&gt;$ time sugar mushikuizan1-2.csp &amp;gt; mushikuizan1-2.txt

real    16m35.745s
user    16m28.370s
sys     0m3.916s
&lt;/pre
&gt;&lt;p&gt;今度は、次の結果が得られた。
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/mushikuizan1-2.txt&#39;&gt;mushikuizan1-2.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;a na    12718
a nb    674
a nc    50872
a nd    89026
a ne    76308
&lt;/pre
&gt;&lt;p&gt;最後の積（和）は自分で計算すると、次の解が得られていた。
&lt;/p
&gt;&lt;pre&gt;　　　１２７１８
　　×　　６７４
ーーーーーーーーー
　　　５０８７２
　　８９０２６
　７６３０８
ーーーーーーーーー
　８５７１９３２
&lt;/pre
&gt;&lt;p&gt;最下段は他から自動的に決まってしまうのだが、そういう判断は勝手にはやってくれず、
最下段の変数の値も色々変更して探索しようとしてリソースを食いつぶしていたようだ。
&lt;/p
&gt;&lt;p&gt;ちょっとプログラム以外の手を使ってしまったが、まあこんな感じで虫食い算もなんとかできそうだ。
&lt;/p
&gt;&lt;p&gt;しかし、虫食い算にも色々あるので、まったく別の解き方を次から考えてみよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>年賀パズル2009</title
><link>http://karetta.jp/book-node/withoutprogramming/237950</link
><pubDate>Mon, 12 Jan 2009 19:19:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;年賀状に載せるパズルにはずいぶん悩むものだ。
これで正しく受け取った相手が悩んでくれるか心配になる。
難しすぎてもいけないし、やさし過ぎてもいけない。
このところ、ナンプレが流行ってしまったので止むなくナンプレの問題にしていたが、
それではまったく「ナンプレ・ボケ」しているのかと思われてしまう。
&lt;/p
&gt;&lt;p&gt;それで、今年はまったく別の考案されたパズルにしたわけである。
&lt;/p
&gt;&lt;p&gt;能書きよりも、どんな問題かを示そう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-009.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-009.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;とりあえずは手で解いて、次はプログラムで自分の頭の正常さ加減を調べるのが手順というものだろう。
&lt;/p
&gt;&lt;p&gt;プログラムは次回に示すので、まずは頭（手）で解いてみよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;少し大きくなった分だけプログラムが長くなったが、
まったく同様にして解くことができた。
詳しい説明は不要と思う。
実際のプログラムは、以下を参照のこと。
&lt;/p
&gt;&lt;p&gt;プログラム　&lt;a href=&#39;http://karetta.jp/images/552/dokokana8-1.csp&#39;&gt;dokokana8-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;では、早速実行してみよう。
&lt;/p
&gt;&lt;p&gt;結果　　　　&lt;a href=&#39;http://karetta.jp/images/552/dokokana8-1.txt&#39;&gt;dokokana8-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;肝心な部分を示す。
&lt;/p
&gt;&lt;pre&gt;a na    257
a nb    7
a nc    1800
a nd    14
a ne    40
a nf    35
a ng    50
a nh    49
a ni    1
&lt;/pre
&gt;&lt;p&gt;筆算の形に直したのが次である。
&lt;/p
&gt;&lt;pre&gt;　　　２５７
　ーーーーー
７）１８００
　　１４
　　ーーー
　　　４０
　　　３５
　　　ーーー
　　　　５０
　　　　４９
　　　　ーー
　　　　　１
&lt;/pre
&gt;&lt;p&gt;どこかな算は、虫食い算、それもすべてのマスが虫に食われている虫食い算である「完全虫食い算」に対して、
少々ヒントを与えて、答えをユニークにしたものである。
&lt;/p
&gt;&lt;p&gt;ここで、基本に戻って、次は虫食い算についてやろう。
&lt;/p
&gt;&lt;p&gt;内容は同じようになってしまうと予想しているかも知れないが、決してそんなことはない。
乞うご期待。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>割り算</title
><link>http://karetta.jp/book-node/withoutprogramming/237742</link
><pubDate>Sat, 10 Jan 2009 17:38:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;今度は割り算だ。
&lt;/p
&gt;&lt;p&gt;まずは簡単な例題を示そう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-007.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-007.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;こういうのを解くのであるが、どういう準備が必要だろうか。
&lt;/p
&gt;&lt;p&gt;そのために、掛け算のときを振り返ってみよう。
&lt;/p
&gt;&lt;p&gt;次のような１桁の割り算を用意した。
&lt;/p
&gt;&lt;pre&gt;(predicate (mul1 a b c)
           (element b ((* a 1) (* a 2) (* a 3)
                       (* a 4) (* a 5) (* a 6)
                       (* a 7) (* a 8) (* a 9))
                    c))
&lt;/pre
&gt;&lt;p&gt;これに習って、今度は１桁の数で割るのを用意しなければならない、のかなぁ。
&lt;/p
&gt;&lt;p&gt;いや、割る数は、１桁とは限らない。例題では偶然除数（カッコの左側の数）が1桁だが、
通常は複数桁に及ぶし、そうでないとパズルとしては面白くない。
&lt;/p
&gt;&lt;p&gt;一体何を用意すれば、割り算が簡単にプログラムできるのか考えてみよう。
&lt;/p
&gt;&lt;p&gt;そのために、もう１つ例題を示しておく。つまり、こういうのが解きやすいようにするには、
何を用意しておけば良いかということである。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-008.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-008.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;blockquote&gt;&lt;h3 id=&#39;H-44cgsx&#39;&gt;宿題
&lt;/h3
&gt;&lt;p&gt;割り算のためには、どんなpredicateを用意しておけば良いでしょうか？
&lt;/p
&gt;&lt;/blockquote
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;割り算のためのpredicateは準備できましたか。
&lt;/p
&gt;&lt;p&gt;では、さっそく最初の例題から解いてみよう。
&lt;/p
&gt;&lt;p&gt;あまり何も考えずに、変数を次のように上から順に規則的に決めた。
&lt;/p
&gt;&lt;pre&gt;　　　  na
    --------
nb  )   nc
        nd
      ------ 
        ne
&lt;/pre
&gt;&lt;p&gt;この例題では、ncだけが２桁で、その他は全部1桁の数に過ぎないのだが、
それぞれ、各桁毎に別に変数を掛け算のときと同じように用意した。
&lt;/p
&gt;&lt;p&gt;1桁の場合は簡単なので、とりあえず一気にプログラムを見せてしまおう。
&lt;/p
&gt;&lt;pre&gt;(domain num 0 9)

                               (int a1 num)
(int b1 num)      (int c2 num) (int c1 num)
                               (int d1 num)
                               (int e1 num)

(predicate (mul1 a b c)
           (element b ((* a 1) (* a 2) (* a 3)
                       (* a 4) (* a 5) (* a 6)
                       (* a 7) (* a 8) (* a 9))
                    c))

(int na   1   9)  (= na a1)
(int nb   1   9)  (= nb b1)
(int nc  10  99)  (= nc (+ (* c2 10) c1))
(int nd   1   9)  (= nd d1)
(int ne   0   9)  (= ne e1)

(mul1 nb a1 nd)       ; nb * a1 = nd
(= (- nc nd) ne)

(predicate (exist4 v x1 x2 x3 x4)
    (or (= v x1) (= v x2) (= v x3) (= v x4)))

(exist4 7  a1 c1 d1 e1)
(exist4 8  -1 b1 c2 c1)
&lt;/pre
&gt;&lt;p&gt;ちょっとだけ付け加えておくと、余りのneに関しては０もありうるので、注意が必要だ。
&lt;/p
&gt;&lt;p&gt;プログラム　&lt;a href=&#39;http://karetta.jp/images/552/dokokana6-1.csp&#39;&gt;dokokana6-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;では、早速実行してみよう。
&lt;/p
&gt;&lt;p&gt;結果　　　　&lt;a href=&#39;http://karetta.jp/images/552/dokokana6-1.txt&#39;&gt;dokokana6-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;結果の肝心な部分を以下に示す。
&lt;/p
&gt;&lt;pre&gt;a na    1
a nb    8
a nc    17
a nd    8
a ne    9
&lt;/pre
&gt;&lt;p&gt;これを筆算の形になおすと次のようになる。
&lt;/p
&gt;&lt;pre&gt;　　　１
　ーーー
８）１７
　　　８
　　ーー
　　　９
&lt;/pre
&gt;&lt;p&gt;ちゃんとできていることを確かめて、次へ進もう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;さて、以下の筆算をちゃんと確認しただろうか。
&lt;/p
&gt;&lt;pre&gt;　　　１
　ーーー
８）１７
　　　８
　　ーー
　　　９
&lt;/pre
&gt;&lt;p&gt;これはもちろん不正解で、こんな筆算をしていたのでは小学校で落第してしまう。
&lt;/p
&gt;&lt;p&gt;では、どこがダメなのだろうか。
&lt;/p
&gt;&lt;p&gt;８で割っているのに、余りが９になっているからダメなのである。
&lt;/p
&gt;&lt;blockquote&gt;&lt;p&gt;余りは、割る数より小さくなければならない。
&lt;/p
&gt;&lt;/blockquote
&gt;&lt;p&gt;これを数式で表すと、
&lt;/p
&gt;&lt;pre&gt;nb &amp;gt; ne 
&lt;/pre
&gt;&lt;p&gt;となる。
&lt;/p
&gt;&lt;p&gt;sugarでは、
&lt;/p
&gt;&lt;pre&gt;(&amp;gt; nb ne)
&lt;/pre
&gt;&lt;p&gt;である。
&lt;/p
&gt;&lt;p&gt;これを加えたプログラムを示す。
&lt;/p
&gt;&lt;p&gt;プログラム　&lt;a href=&#39;http://karetta.jp/images/552/dokokana6-2.csp&#39;&gt;dokokana6-2.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;では、早速実行してみよう。
&lt;/p
&gt;&lt;p&gt;結果　　　　&lt;a href=&#39;http://karetta.jp/images/552/dokokana6-2.txt&#39;&gt;dokokana6-2.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;a na    1
a nb    8
a nc    15
a nd    8
a ne    7
&lt;/pre
&gt;&lt;p&gt;より
&lt;/p
&gt;&lt;pre&gt;　　　１
　ーーー
８）１５
　　　８
　　ーー
　　　７
&lt;/pre
&gt;&lt;p&gt;となり、商は相変わらず１であるが、余りの７は割る数８より小さくなった。
&lt;/p
&gt;&lt;p&gt;今度は大丈夫なようだ。
&lt;/p
&gt;&lt;p&gt;では、次の大きな問題にチャレンジしよう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-008.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-008.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;問題が大きくなった分だけsugarのプログラムが長くなったが、
特別なことは何もしていないので、詳しくはプログラムを参照のこと。
&lt;/p
&gt;&lt;p&gt;プログラム　&lt;a href=&#39;http://karetta.jp/images/552/dokokana7-1.csp&#39;&gt;dokokana7-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;では、早速実行してみよう。
&lt;/p
&gt;&lt;p&gt;結果　　　　&lt;a href=&#39;http://karetta.jp/images/552/dokokana7-1.txt&#39;&gt;dokokana7-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;結果の肝心な部分は以下である。
&lt;/p
&gt;&lt;pre&gt;a na    38
a nb    19
a nc    740
a nd    57
a ne    170
a nf    152
a ng    18
&lt;/pre
&gt;&lt;p&gt;これを、筆算に反映すると、次のようになる。
&lt;/p
&gt;&lt;pre&gt;　　　　３８
　　ーーーー
１９）７４０
　　　５７
　　　ーーー
　　　１７０
　　　１５２
　　　ーーー
　　　　１８
&lt;/pre
&gt;&lt;p&gt;もうここまでくれば、どんな「どこかな算」でも大丈夫と思うがどうだろか。
&lt;/p
&gt;&lt;p&gt;次は、年賀パズル2009として年賀状にて全国に出題された問題を解いてみよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>掛け算</title
><link>http://karetta.jp/book-node/withoutprogramming/237639</link
><pubDate>Mon, 05 Jan 2009 14:12:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;では、掛け算の場合の「どこかな算」の問題を示そう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-005.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-005.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;掛け算になったからといって、特別なことはない。
同じようにプログラムすれば良いはずだ。
&lt;/p
&gt;&lt;p&gt;ということで、プログラムしてみた。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/dokokana4-1.csp&#39;&gt;dokokana4-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;(domain num 0 9)

(int a2 num) (int a1 num)
             (int b1 num)
(int c2 num) (int c1 num)

(int na  10  99)  (= na (+ (* a2 10) a1))
(int nb   1   9)  (= nb b1)
(int nc  10  99)  (= nc (+ (* c2 10) c1))
(= (* na nb) nc)

(predicate (exist3 v x1 x2 x3)
    (or (= v x1) (= v x2) (= v x3)))
(exist3 5  a1 b1 c1)
(exist3 7  a1 b1 c1)
&lt;/pre
&gt;&lt;p&gt;説明する必要があるような箇所はないと思う。
&lt;/p
&gt;&lt;p&gt;それでは実行してみよう。
&lt;/p
&gt;&lt;pre&gt;$ sugar dokokana4-1.csp
c 1     ERROR Exception Unsupported (mul na nb)
s UNKNOWN
$
&lt;/pre
&gt;&lt;p&gt;何とエラーだ。(mul na nb)がダメらしい。
&lt;/p
&gt;&lt;p&gt;でも、これってタダの掛け算ではないか。何か間違ったかな？？
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;掛け算でエラーが出てしまった。
こういう時には、マニュアルを調べ直すに限る。
&lt;/p
&gt;&lt;pre&gt;At least one argument of mul should be an integer constant. 
However, some special cases (such as (&amp;lt; (* x y) 0)) 
are allowed. 
&lt;/pre
&gt;&lt;p&gt;困った。英語である。
&lt;/p
&gt;&lt;p&gt;掛け算の場合、どうも少なくとも１つのアーギュメント（引数）は整数定数でないといけないようだ。
でも、結果が負の場合は許されるらしい。なんでかなぁ、まあいいや。
&lt;/p
&gt;&lt;p&gt;この但し書きに引っかかってしまったようだ。
しかし、「どこかな算」では、どこも変数なのである。定数では問題にそもそもならないではないか。
&lt;/p
&gt;&lt;p&gt;でも、何とか解決する方法はないだろうか。
&lt;/p
&gt;&lt;p&gt;今解こうとしているのは、「どこかな算」であって、普通の掛け算ではない。
どこかな算が解けるようにさえなれば充分だ。
&lt;/p
&gt;&lt;p&gt;どこかな算の場合、　a * b = c の式において、乗数のbは、すべて1桁（１〜９）と仮定しても構わない。
&lt;/p
&gt;&lt;p&gt;それで、この条件の掛け算を行う mul1 というpredicateをでっち上げてみた。
&lt;/p
&gt;&lt;pre&gt;(predicate (mul1 a b c)
           (element b ((* a 1) (* a 2) (* a 3)
                       (* a 4) (* a 5) (* a 6)
                       (* a 7) (* a 8) (* a 9))
                    c))
&lt;/pre
&gt;&lt;p&gt;ここで、elementというのを使ってみた。シンタックスは次のようになっている。
&lt;/p
&gt;&lt;pre&gt;ElementConstraint ::=
    (element Index (Term+) Value)
Index ::=
    Term
Value ::=
    Term
&lt;/pre
&gt;&lt;p&gt;bをインデックスにし、(Term+)つまりリストに結果を１から順に並べて用意しておく。
そして、このリストのインデックスで示される項は、リストの後に書かれている項（値）に一致するということだ。
&lt;/p
&gt;&lt;p&gt;文で説明するのは分かりづらい。ブログラムを見てほしい。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/dokokana4-2.csp&#39;&gt;dokokana4-2.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/dokokana4-2.txt&#39;&gt;dokokana4-2.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;a na    17
a nb    5
a nc    85
&lt;/pre
&gt;&lt;p&gt;より、
&lt;/p
&gt;&lt;pre&gt;　１７
×　５
ーーー
　８５
&lt;/pre
&gt;&lt;p&gt;が分かる。
&lt;/p
&gt;&lt;p&gt;例題は、もっとも小さなサイズの掛け算の問題だった。もうちょっと大きな、普通の問題を示しておこう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-006.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-006.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;さて、上の問題を解いてみよう。
&lt;/p
&gt;&lt;p&gt;といっても、至って簡単である。
&lt;/p
&gt;&lt;pre&gt;(domain num 0 9)

                          (int a2 num) (int a1 num)
                          (int b2 num) (int b1 num)
             (int c3 num) (int c2 num) (int c1 num)
(int d3 num) (int d2 num) (int d1 num)
(int e4 num) (int e3 num) (int e2 num) (int e1 num)

(predicate (mul1 a b c)
           (element b ((* a 1) (* a 2) (* a 3)
                       (* a 4) (* a 5) (* a 6)
                       (* a 7) (* a 8) (* a 9))
                    c))

(int na   10   99)  (= na (+ (* a2 10) a1))
(int nb   10   99)  (= nb (+ (* b2 10) b1))
(int nc  100  999)  (= nc (+ (* c3 100) (* c2 10) c1))
(int nd  100  999)  (= nd (+ (* d3 100) (* d2 10) d1))
(int ne 1000 9999)  (= ne (+ (* e4 100) (* e3 100) (* e2 10) e1))

(mul1 na b1 nc)
(mul1 na b2 nd)
(= (+ nc (* nd 10)) ne)

(predicate (exist3 v x1 x2 x3)
    (or (= v x1) (= v x2) (= v x3)))
(exist3 4  c3 c2 c1)
(exist3 5  d3 d2 d1)
(exist3 9  -1 d3 e4)
&lt;/pre
&gt;&lt;p&gt;上から順に、横に並んだ数を na,nb,nc,nd,ne とし、各□に対して、a1,a2 のように変数を割り当てた。
そして、掛け算を１桁ずつ実行し、結果を全部足せばよい。
&lt;/p
&gt;&lt;p&gt;最後に、矢印で示された条件を追加したに過ぎない。
&lt;/p
&gt;&lt;p&gt;プログラム　&lt;a href=&#39;http://karetta.jp/images/552/dokokana5-1.csp&#39;&gt;dokokana5-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;結果　　　　&lt;a href=&#39;http://karetta.jp/images/552/dokokana5-1.txt&#39;&gt;dokokana5-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;結果の肝心な部分は
&lt;/p
&gt;&lt;pre&gt;a na    38
a nb    49
a nc    342
a nd    152
a ne    1862
&lt;/pre
&gt;&lt;p&gt;であり、これを筆算の形にすると次のようになる。
&lt;/p
&gt;&lt;pre&gt;　　３８
×　４９
ーーーー
　３４２
１５２
ーーーー
１８６２
&lt;/pre
&gt;&lt;p&gt;もう、ここまでできれば、もっと大きな掛け算の「どこかな算」も平気であろう。
&lt;/p
&gt;&lt;p&gt;次から割り算の説明をしよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>足し算</title
><link>http://karetta.jp/book-node/withoutprogramming/237627</link
><pubDate>Sat, 03 Jan 2009 09:36:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;例題として非常にやさしい問題を示したが、
もうちょっと普通に難しい足し算の「どこかな算」の問題を２題示しておく。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-004.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-004.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-003.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-003.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;矢印１つにつき、２つ以上の数字が示されていることもある。最初の例では、１つの矢印に６と８があるが、
矢印の方向のどこかに、６もあり、８もあるということである。
&lt;/p
&gt;&lt;p&gt;プログラム的にも、人間が解くにしても、これは条件が増えるだけなので、解きやすくなるだけである。
&lt;/p
&gt;&lt;p&gt;今日は、答えは出さないので、自分の頭で解くか、sugarで解くか、
はたまた何らかのプログラミング言語で解くかしてみよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;とても簡単だっただろうか。
&lt;/p
&gt;&lt;p&gt;それぞれのsugarのプログラムを結果を示そう。
&lt;/p
&gt;&lt;h3 id=&#39;H-15pyzzo&#39;&gt;問題　その１
&lt;/h3
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/dokokana2-1.csp&#39;&gt;dokokana2-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;(domain num 0 9)
             (int a1 num)
(int b2 num) (int b1 num)
(int c2 num) (int c1 num)
(int d2 num) (int d1 num)

(int na 1 9)    (= na a1)
(int nb 10 99)  (= nb (+ (* b2 10) b1))
(int nc 10 99)  (= nc (+ (* c2 10) c1))
(int nd 10 99)  (= nd (+ (* d2 10) d1))
(= (+ na nb nc) nd)

(predicate (exist2 v x1 x2)
    (or (= v x1) (= v x2)))
(predicate (exist4 v x1 x2 x3 x4)
    (or (= v x1) (= v x2) (= v x3) (= v x4)))
(exist4 6  -1 b2 c2 d2)
(exist4 8  -1 b2 c2 d2)
(exist4 0  a1 b1 c1 d1)
(exist2 9  -1 a1)
(exist2 6  b2 b1)
(exist2 5  c2 c1)
&lt;/pre
&gt;&lt;p&gt;結果　&lt;a href=&#39;http://karetta.jp/images/552/dokokana2-1.txt&#39;&gt;dokokana2-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;a na    9
a nb    60
a nc    15
a nd    84
&lt;/pre
&gt;&lt;p&gt;より
&lt;/p
&gt;&lt;pre&gt;　　９
　６０
＋１５
ーーー
　８４
&lt;/pre
&gt;&lt;p&gt;が得られた。
&lt;/p
&gt;&lt;h3 id=&#39;H-15pyzzt&#39;&gt;問題　その２
&lt;/h3
&gt;&lt;p&gt;プログラム　&lt;a href=&#39;http://karetta.jp/images/552/dokokana3-1.csp&#39;&gt;dokokana3-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;(domain num 0 9)

             (int a2 num) (int a1 num)
(int b3 num) (int b2 num) (int b1 num)
(int c3 num) (int c2 num) (int c1 num)

(int na  10  99)  (= na (+ (* a2 10) a1))
(int nb 100 999)  (= nb (+ (* b3 100) (* b2 10) b1))
(int nc 100 999)  (= nc (+ (* c3 100) (* c2 10) c1))
(= (+ na nb) nc)

(predicate (exist3 v x1 x2 x3)
    (or (= v x1) (= v x2) (= v x3)))
(exist3 3  -1 b3 c3)
(exist3 8  a2 b2 c2)
(exist3 5  a1 b1 c1)
(exist3 4  -1 a2 a1)
(exist3 0  b3 b2 b1)
(exist3 9  c3 c2 c1)

&lt;/pre
&gt;&lt;p&gt;結果　&lt;a href=&#39;http://karetta.jp/images/552/dokokana3-1.txt&#39;&gt;dokokana3-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;a na    84
a nb    305
a nc    389
&lt;/pre
&gt;&lt;p&gt;より
&lt;/p
&gt;&lt;pre&gt;　　８４
＋３０５
ーーーー
　３８９
&lt;/pre
&gt;&lt;p&gt;が得られた。
&lt;/p
&gt;&lt;p&gt;「どこかな算」あるいは「虫食い算」の足し算はここまでにしておく。
&lt;/p
&gt;&lt;p&gt;次は「引き算」と考えるのが普通だろうが、引き算はあまり好まれない。
内容的に、足し算とあまり変わらないからである。
そして、複数の項を足したり引いたりするためには、それぞれの前に＋ーをつけなければいけなくて、
どうも美的センスに欠ける、つまりパズルとして美しくないのだ。美しくないパズルがあっては良くない。
ということかどうかは知らないが、引き算は省略する。
&lt;/p
&gt;&lt;p&gt;本当におもしろくなるのは、掛け算や割り算なので、次からそちらに進む。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>とりあえずプログラミング</title
><link>http://karetta.jp/book-node/withoutprogramming/237579</link
><pubDate>Thu, 01 Jan 2009 18:48:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;とりあえず、次の問題でsugarのプログラムをでっちあげてみよう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-001.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-001.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;まず、マスには０〜９の数字が入る、０〜９の数字しか入らないという制約のために、
numというdomainを用意しておこう。
&lt;/p
&gt;&lt;pre&gt;(domain num 0 9)
&lt;/pre
&gt;&lt;p&gt;□は、場所によっては０が入らなくなるのだが、
それは別の方法で制約しよう。
&lt;/p
&gt;&lt;p&gt;すると、マスの配置にしたがって、次のように変数を用意した。
問題の形に合わせて、適当に空白が入っている。
&lt;/p
&gt;&lt;pre&gt;             (int a1 num)
(int b2 num) (int b1 num)
(int c2 num) (int c1 num)
&lt;/pre
&gt;&lt;p&gt;次に、足し算が成り立っていることをsugarで書いてみる。
そのために、各横列が示す数を上から、na, nb, nc として計算した。
&lt;/p
&gt;&lt;pre&gt;(int na 1 9)    (= na a1)
(int nb 10 99)  (= nb (+ (* b2 10) b1))
(int nc 10 99)  (= nc (+ (* c2 10) c1))
(= (+ na nb) nc)
&lt;/pre
&gt;&lt;p&gt;ここまでで実行してみよう。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/dokokana1-1.csp&#39;&gt;dokokana1-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/dokokana1-1.txt&#39;&gt;dokokana1-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、この結果はどうだっただろうか？
&lt;/p
&gt;&lt;pre&gt;a na    2
a nb    97
a nc    99
&lt;/pre
&gt;&lt;p&gt;より
&lt;/p
&gt;&lt;pre&gt;　　２
＋９７
ーーー
　９９
&lt;/pre
&gt;&lt;p&gt;となっていることが分かる。
&lt;/p
&gt;&lt;p&gt;確かに足し算としては正しいが、周囲の矢印で示された条件はまだ満たしていない。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;周囲のヒント（数字）に対処していこう。
&lt;/p
&gt;&lt;p&gt;そのために、１つだけ道具を用意しよう。
Nマスにある数（つまり矢印のところの数）の存在を確かめる制約を作ってみた。
&lt;/p
&gt;&lt;p&gt;マスの並びは２マスと３マスがあるが、多ければ少ない方はなんとかなるだろうから
３マスの場合に対応したpredicateを作った。
&lt;/p
&gt;&lt;pre&gt;(predicate (exist3 v x1 x2 x3)
    (or (= v x1) (= v x2) (= v x3)))
&lt;/pre
&gt;&lt;p&gt;順番に等しいかどうか確認しているだけなので、何も説明はいらないだろう。
&lt;/p
&gt;&lt;p&gt;そして、これを周囲の、１、７、４について適用してみた。
&lt;/p
&gt;&lt;pre&gt;(exist3 1  -1 b2 c2)
(exist3 7  a1 b1 c1)
(exist3 4  -1 c2 c1)
&lt;/pre
&gt;&lt;p&gt;１や４は２マスに対するヒントなので、１つ使われない引数が存在するが、
そこには「-1」を入れておいた。これは、-1ならば、絶対にマスに入れられない数値であり、
偶然一致することがないからである。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/dokokana1-2.csp&#39;&gt;dokokana1-2.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/dokokana1-2.txt&#39;&gt;dokokana1-2.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;pre&gt;a na    7
a nb    17
a nc    24
&lt;/pre
&gt;&lt;p&gt;より、
&lt;/p
&gt;&lt;pre&gt;　　７
＋１７
ーーー
　２４
&lt;/pre
&gt;&lt;p&gt;であることが分かり、条件を満たしている。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>どこかな算とは</title
><link>http://karetta.jp/book-node/withoutprogramming/237572</link
><pubDate>Thu, 01 Jan 2009 16:14:51 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;小学校の算数には「何とか算」という名前が付いた特徴ある計算方式がたくさんあったのを覚えているだろうか。
ここでは、「どこかな算」というのを、sugarを使って解いてみるこのだが、
もう「どこかな算」はどんなものだったか思い出しただろうか。
&lt;/p
&gt;&lt;p&gt;次が問題である。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-001.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-001.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;これだけでは、何だか「虫食い算」みたいだろう。
実は、虫食い算にちょっと工夫がされて、小学校でも使えるように工夫されたものだ。
大きな違いは、矢印があって、そこに数字が書かれていることである。
&lt;/p
&gt;&lt;p&gt;まず、「どこかな算」のルールなるものを紹介しておこう。
&lt;/p
&gt;&lt;blockquote&gt;&lt;p&gt;ルール
&lt;/p
&gt;&lt;ul&gt;&lt;li&gt;空いている□に数字を入れて、正しい筆算にしてください。
&lt;/li
&gt;&lt;li&gt;まわりの数字は、その列のどこかに必ず入ります。
&lt;/li
&gt;&lt;/ul
&gt;&lt;/blockquote
&gt;&lt;p&gt;さあ、上の問題を解いてみよう。
&lt;/p
&gt;&lt;p&gt;答えは来年になったら教えることにしよう。
&lt;/p
&gt;&lt;p&gt;なお、虫食い算と同じで、２桁以上になっているところの最上位桁の□には０は入らない。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;年も明けたので、問題の答えを示そう。
まさか解けなかった人はいないと思うが、念のため答えを示す。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-002.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/sugar-dokokana-sample-002.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、「どこかな算」は「虫食い算」にヒントを加えたものになっていることが分かっただろうか。
&lt;/p
&gt;&lt;p&gt;矢印のヒントがないと虫食い算になってしまう。
とくに、すべての数字が虫に食われている虫食い算を「完全虫食い算」という。
そして、「完全虫食い算」の問題は非常に作り難いし、解くのも大変である。少なくとも人間には。
&lt;/p
&gt;&lt;p&gt;普通の虫食い算は、いくつかの数字が最初からあって、それらを手がかりにして解いていく。
&lt;/p
&gt;&lt;p&gt;それに対して、「どこかな算」は、完全虫食い算の形にしておいて、縦や横の並びに対して、
こういう数字が入っているよ、というヒントを加えたものである。
&lt;/p
&gt;&lt;p&gt;これにより、問題自体も作りやすくなるし、問題自体も非常に教育的で、
このところ小学校や学習塾で非常にはやっていると風の噂に聞いている。
周りに知っている人がいるかぜひ確かめて欲しい。
&lt;/p
&gt;&lt;p&gt;それでは、次から、sugarで問題を解いていこう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>木構造</title
><link>http://karetta.jp/book-node/withoutprogramming/236867</link
><pubDate>Thu, 25 Dec 2008 18:18:22 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;ルールの中にループがあってはいけないというのがあったのだが、
得られた図はループだらけであった。
&lt;/p
&gt;&lt;p&gt;ループをなくすには、どうすれば良いだろうか。
&lt;/p
&gt;&lt;p&gt;これには、木構造にするのが便利である。
最初から完全な木構造にする前に、各頂点に関する条件をすこしずつ考えていこう。
&lt;/p
&gt;&lt;p&gt;枝（矢印）は、末端からルート（頂点）に向かっていくものとする。
&lt;/p
&gt;&lt;p&gt;今まで、頂点につながっている矢印の数（出入りともにカウント）を数えていたが、
出るのと、入るのと、両方別々に数えることにしよう。
&lt;/p
&gt;&lt;p&gt;そのために、cixy, coxy, cnxy という３種の変数を考える。
x, y の部分は、座標を示す。
&lt;/p
&gt;&lt;p&gt;cixyは頂点xyに入る矢印数、coxyは頂点xyから出る矢印数、
そして、cnxyは、その頂点に出入りする矢印数で、
&lt;/p
&gt;&lt;pre&gt;cnxy = cixy + coxy
&lt;/pre
&gt;&lt;p&gt;が当然成り立つ。
また、木構造にしたことで、頂点から出る矢印数は高々１になった。
&lt;/p
&gt;&lt;p&gt;このために、まず、以下を削除し、
&lt;/p
&gt;&lt;pre&gt;;;　削除
(domain d8 0 8)
(int c11 d8) (int c21 d8) (int c31 d8) (int c41 d8) (int c51 d8) (int c61 d8) (int c71 d8)
(int c12 d8) (int c22 d8) (int c32 d8) (int c42 d8) (int c52 d8) (int c62 d8) (int c72 d8)
(int c13 d8) (int c23 d8) (int c33 d8) (int c43 d8) (int c53 d8) (int c63 d8) (int c73 d8)
(int c14 d8) (int c24 d8) (int c34 d8) (int c44 d8) (int c54 d8) (int c64 d8) (int c74 d8)
(int c15 d8) (int c25 d8) (int c35 d8) (int c45 d8) (int c55 d8) (int c65 d8) (int c75 d8)
(int c16 d8) (int c26 d8) (int c36 d8) (int c46 d8) (int c56 d8) (int c66 d8) (int c76 d8)
(int c17 d8) (int c27 d8) (int c37 d8) (int c47 d8) (int c57 d8) (int c67 d8) (int c77 d8)
&lt;/pre
&gt;&lt;p&gt;この代わりに、次の配列を用意した。
&lt;/p
&gt;&lt;pre&gt;;; 追加

(domain d8 0 8)
(int cn11 d8) (int cn21 d8) (int cn31 d8) (int cn41 d8) (int cn51 d8) (int cn61 d8) (int cn71 d8)
(int cn12 d8) (int cn22 d8) (int cn32 d8) (int cn42 d8) (int cn52 d8) (int cn62 d8) (int cn72 d8)
(int cn13 d8) (int cn23 d8) (int cn33 d8) (int cn43 d8) (int cn53 d8) (int cn63 d8) (int cn73 d8)
(int cn14 d8) (int cn24 d8) (int cn34 d8) (int cn44 d8) (int cn54 d8) (int cn64 d8) (int cn74 d8)
(int cn15 d8) (int cn25 d8) (int cn35 d8) (int cn45 d8) (int cn55 d8) (int cn65 d8) (int cn75 d8)
(int cn16 d8) (int cn26 d8) (int cn36 d8) (int cn46 d8) (int cn56 d8) (int cn66 d8) (int cn76 d8)
(int cn17 d8) (int cn27 d8) (int cn37 d8) (int cn47 d8) (int cn57 d8) (int cn67 d8) (int cn77 d8)

(int ci11 d8) (int ci21 d8) (int ci31 d8) (int ci41 d8) (int ci51 d8) (int ci61 d8) (int ci71 d8)
(int ci12 d8) (int ci22 d8) (int ci32 d8) (int ci42 d8) (int ci52 d8) (int ci62 d8) (int ci72 d8)
(int ci13 d8) (int ci23 d8) (int ci33 d8) (int ci43 d8) (int ci53 d8) (int ci63 d8) (int ci73 d8)
(int ci14 d8) (int ci24 d8) (int ci34 d8) (int ci44 d8) (int ci54 d8) (int ci64 d8) (int ci74 d8)
(int ci15 d8) (int ci25 d8) (int ci35 d8) (int ci45 d8) (int ci55 d8) (int ci65 d8) (int ci75 d8)
(int ci16 d8) (int ci26 d8) (int ci36 d8) (int ci46 d8) (int ci56 d8) (int ci66 d8) (int ci76 d8)
(int ci17 d8) (int ci27 d8) (int ci37 d8) (int ci47 d8) (int ci57 d8) (int ci67 d8) (int ci77 d8)

(domain d1 0 1)
(int co11 d1) (int co21 d1) (int co31 d1) (int co41 d1) (int co51 d1) (int co61 d1) (int co71 d1)
(int co12 d1) (int co22 d1) (int co32 d1) (int co42 d1) (int co52 d1) (int co62 d1) (int co72 d1)
(int co13 d1) (int co23 d1) (int co33 d1) (int co43 d1) (int co53 d1) (int co63 d1) (int co73 d1)
(int co14 d1) (int co24 d1) (int co34 d1) (int co44 d1) (int co54 d1) (int co64 d1) (int co74 d1)
(int co15 d1) (int co25 d1) (int co35 d1) (int co45 d1) (int co55 d1) (int co65 d1) (int co75 d1)
(int co16 d1) (int co26 d1) (int co36 d1) (int co46 d1) (int co56 d1) (int co66 d1) (int co76 d1)
(int co17 d1) (int co27 d1) (int co37 d1) (int co47 d1) (int co57 d1) (int co67 d1) (int co77 d1)
&lt;/pre
&gt;&lt;p&gt;次に、頂点の接続数に関する count predicate を変更した。
&lt;/p
&gt;&lt;p&gt;変更前のものは
&lt;/p
&gt;&lt;pre&gt;(predicate (count c nwst nth nest est sest sth swst wst)
  (= (+ (abs nwst) (abs nth) (abs nest) (abs est)
        (abs sest) (abs sth) (abs swst) (abs wst))
     c))
&lt;/pre
&gt;&lt;p&gt;頂点への出入りの方向は考えていなかったので単に絶対値をとって加えただけだったが、
今度は、ちゃんと方向を考えながら加えるようにした。
そうしたら長くなってしまった。
&lt;/p
&gt;&lt;pre&gt;;; 変更後

(predicate (count cn ci co nwst nth nest est sest sth swst wst)
  (and
     (= (+ (if (= wst   1) 1 0)
           (if (= nwst  1) 1 0)
           (if (= nth   1) 1 0)
           (if (= nest  1) 1 0)
           (if (= est  -1) 1 0)
           (if (= sest -1) 1 0)
           (if (= sth  -1) 1 0)
           (if (= swst -1) 1 0))
         ci)
     (= (+ (if (= wst  -1) 1 0)
           (if (= nwst -1) 1 0)
           (if (= nth  -1) 1 0)
           (if (= nest -1) 1 0)
           (if (= est   1) 1 0)
           (if (= sest  1) 1 0)
           (if (= sth   1) 1 0)
           (if (= swst  1) 1 0))
         co)
     (= cn (+ ci co))))
&lt;/pre
&gt;&lt;p&gt;前との違いは、前は矢印の数を示す引数が１つだけ(c)だったのが、
変更後は　cn ci co の３個になってしまった。
&lt;/p
&gt;&lt;p&gt;これにより、count を使っている箇所の書き方が変更になった。
変更は以下のとおり、規則的である。
&lt;/p
&gt;&lt;pre&gt;変更前  (count c42 d31 v41 e51 h42 d42 v42 e42 h32)

変更後　(count cn42 ci42 co42 d31 v41 e51 h42 d42 v42 e42 h32)
&lt;/pre
&gt;&lt;p&gt;ただし、countは、頂点の数だけ、この制約が並ぶことになる。
この変更は省略する。
&lt;/p
&gt;&lt;p&gt;では、プログラムと実行結果をみてみよう。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/oct3-3.csp&#39;&gt;oct3-3.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/oct3-3.txt&#39;&gt;oct3-3.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、図を示したいところだが、長くなったので、次回にしよう。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;図示すると、つぎのようになった。
赤い箇所がルールに従っていない。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct3-4.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct3-4.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;この赤い部分全体がルートになっていると言えば良いだろうか。
このように、最上位のレベルがルートになってしまうことがある。
&lt;/p
&gt;&lt;p&gt;まず、ルートとはなんであろうか。
&lt;/p
&gt;&lt;blockquote&gt;&lt;h3 id=&#39;H-1i7shf2&#39;&gt;ルート
&lt;/h3
&gt;&lt;p&gt;入力矢印が１つ以上存在し、出力矢印が存在しない箇所である。
&lt;/p
&gt;&lt;/blockquote
&gt;&lt;p&gt;これに基づいて判断すると、ループに含まれる点は出力矢印があるわけだから、
ルートにはなれない。
&lt;/p
&gt;&lt;p&gt;したがって、上図は、ルート個数が０個ということになる。
&lt;/p
&gt;&lt;p&gt;ルートとなる点が１つという制約をつけてみよう。
&lt;/p
&gt;&lt;p&gt;まず、各頂点が、ルートだったときに１になり、
そうでないとき０になるようにしよう。
bool変数（true/false）するのが普通だと思うが、それには訳がある。
&lt;/p
&gt;&lt;p&gt;まず、rootというpredicateを作った。
&lt;/p
&gt;&lt;pre&gt;(predicate (root rt ci co)
           (= rt (if (and (= co 0) (&amp;gt; ci 0)) 1 0)))
&lt;/pre
&gt;&lt;p&gt;ルートかどうかを、上で定義したとおりの方法で判定している。
&lt;/p
&gt;&lt;p&gt;パラメータの意味は、rt がルート判定を示し、
ciが入力矢印数、coが出力矢印数を示す。
&lt;/p
&gt;&lt;p&gt;これを全頂点について適用する。
&lt;/p
&gt;&lt;pre&gt;(root rt11 ci11 co11)
(root rt21 ci21 co21)
(root rt31 ci31 co31)
(root rt41 ci41 co41)
(root rt51 ci51 co51)
(root rt61 ci61 co61)
(root rt71 ci71 co71)
..... 以下省略
&lt;/pre
&gt;&lt;p&gt;これで、各頂点がルートになっているかどうかを 1/0 で求められる。
&lt;/p
&gt;&lt;p&gt;ループしないためには、また複数に分かれないためには、
ルート（根っこ）の個数が１でなければならない。
&lt;/p
&gt;&lt;p&gt;これを実現するには、全頂点の、ルート判定変数 rtxy を加えると、
これがルートの個数を示すので、それが１であるという制約にした。
&lt;/p
&gt;&lt;pre&gt;(= 1 (+ rt11 rt21 rt31 rt41 rt51 rt61 rt71
        rt12 rt22 rt32 rt42 rt52 rt62 rt72
        rt13 rt23 rt33 rt43 rt53 rt63 rt73
        rt14 rt24 rt34 rt44 rt54 rt64 rt74
        rt15 rt25 rt35 rt45 rt55 rt65 rt75
        rt16 rt26 rt36 rt46 rt56 rt66 rt76
        rt17 rt27 rt37 rt47 rt57 rt67 rt77))
&lt;/pre
&gt;&lt;p&gt;最後の、ルートが１個の場合に、
こういう方法を使うのは常套手段なのだろう。
何だったか忘れたが、
&lt;a href=&#39;http://bach.istc.kobe-u.ac.jp/sugar/puzzles/&#39;&gt;パズルをSugar制約ソルバーで解く&lt;/a
&gt;
で勉強したのであった。
&lt;/p
&gt;&lt;p&gt;では、プログラムと実行結果をみてみよう。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/oct3-4.csp&#39;&gt;oct3-4.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/oct3-4.txt&#39;&gt;oct3-4.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;そして、結果はこうなった。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct3-5.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct3-5.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;空色がルートである。
&lt;/p
&gt;&lt;p&gt;木構造では、ルートの場所はどこでも大丈夫になる。
これは知っていないとまずい。なお、理由は、自分で考えてみよう。
&lt;/p
&gt;&lt;p&gt;ということで、オクトパスは、これで終わりとする。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>黒点では交差しない</title
><link>http://karetta.jp/book-node/withoutprogramming/236452</link
><pubDate>Wed, 17 Dec 2008 11:05:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;うまく行かなかった結果について、問題点の１つを赤で示した。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct3-2.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct3-2.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;ここで問題としているのは、黒点のマスは、線が通過するだけで、
枝分かれや交差してはいけないのだが、上手の赤の点では交差している。
&lt;/p
&gt;&lt;p&gt;これを取り除くための制約について考えよう。
&lt;/p
&gt;&lt;p&gt;現在、数字の入っている白丸についてだけ次のような制限を加えている。
&lt;/p
&gt;&lt;pre&gt;(predicate (cchk a c)
   (=&amp;gt; (&amp;gt; a 0) (= a c)))
&lt;/pre
&gt;&lt;p&gt;(&amp;gt; a 0)　つまり、a が正（数字の値）のときだけ、実際の接続数(c)と丸数字の値(a)
が一致という条件になっている。
&lt;/p
&gt;&lt;p&gt;これに、黒点の時、つまり a が -1（あるいは負）の時の条件を付け加えてみた。
&lt;/p
&gt;&lt;pre&gt;(predicate (cchk a c)
   (or (and (&amp;gt; a 0) (= a c))
       (= a 0)
       (and (&amp;lt; a 0) (or (= c 0) (= c 2)))))
&lt;/pre
&gt;&lt;p&gt;調べていることは、とても簡単である。
&lt;/p
&gt;&lt;ol&gt;&lt;li&gt;正：白丸に正の数字が入っている場合、丸数字の値と接続数は一致する。
&lt;/li
&gt;&lt;li&gt;０：白丸のままの場合、何も制限を加えない。
&lt;/li
&gt;&lt;li&gt;負：黒点の場合、接続数は0または2（通過）でなければならない。
&lt;/li
&gt;&lt;/ol
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/oct3-2.csp&#39;&gt;oct3-2.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/oct3-2.txt&#39;&gt;oct3-2.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、これを図示すると
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct3-3.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct3-3.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;となり、黒点に関しては正常になった。
&lt;/p
&gt;&lt;p&gt;しかし、まだいろいろな問題が残っているようだ。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>より大きな問題</title
><link>http://karetta.jp/book-node/withoutprogramming/235839</link
><pubDate>Thu, 11 Dec 2008 19:28:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;４×４という非常に小さな問題が解けただけではいけない。
より大きな問題について試していこう。
&lt;/p
&gt;&lt;p&gt;といっても、まずは５×５にしておこう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct2-1.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct2-1.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;この問題に対する sugarのプログラムを作ってみよう。
&lt;/p
&gt;&lt;p&gt;単に作るのでは面白くないので、１つだけ工夫をした。
ただの黒点について通過するというだけの predicate であるが、
これは本当の黒点についてだけ制約を書いたのだが、
これでは問題を見て、黒点についてだけ制約をつけるということになり汎用性が低い。
白丸、黒点を一切考えることなく規則的にというか、機械的に処理できるようにしてみた。
&lt;/p
&gt;&lt;pre&gt;(predicate (through a nwst nth nest est sest sth swst wst)
  (=&amp;gt; (&amp;lt; a 0)
    (and (= nwst sest)
         (= nth  sth )
         (= nest swst)
         (= est  wst ))))
&lt;/pre
&gt;&lt;p&gt;各点について、axyの値を引数に加え、axyの値が負だった場合には通過の判断をし、
そうでない場合（白丸）には何もしないようにした。
&lt;/p
&gt;&lt;p&gt;各点に関する制約は、次のように機械的に書ける。
&lt;/p
&gt;&lt;pre&gt;(through a11  0   0   0  h11 d11 v11  0   0 )
(through a21  0   0   0  h21 d21 v21 e21 h11)
(through a31  0   0   0  h31 d31 v31 e31 h21)
(through a41  0   0   0  h41 d41 v41 e41 h31)
(through a51  0   0   0   0   0  v51 e51 h41)
(through a12  0  v11 e21 h12 d12 v12  0   0 )
(through a22 d11 v21 e31 h22 d22 v22 e22 h12)
(through a32 d21 v31 e41 h32 d32 v32 e32 h22)
(through a42 d31 v41 e51 h42 d42 v42 e42 h42)
(through a52 d41 v51  0   0   0  v52 e52 h42)
(through a13  0  v12 e22 h13 d13 v13  0   0 )
(through a23 d12 v22 e32 h23 d23 v23 e23 h13)
(through a33 d22 v32 e42 h33 d33 v33 e33 h23)
(through a43 d32 v42 e52 h43 d43 v43 e43 h33)
(through a53 d42 v52  0   0   0  v53 e53 h43)
(through a14  0  v13 e23 h14 d14 v14  0   0 )
(through a24 d13 v23 e33 h24 d24 v24 e24 h14)
(through a34 d23 v33 e43 h34 d34 v34 e34 h24)
(through a44 d33 v43 e53 h44 d44 v44 e44 h34)
(through a54 d43 v53  0   0   0  v54 e54 h44)
(through a15  0  v14 e24 h15  0   0   0   0 )
(through a25 d14 v24 e34 h25  0   0   0  h15)
(through a35 d24 v34 e44 h35  0   0   0  h25)
(through a45 d34 v44 e54 h45  0   0   0  h35)
(through a55 d44 v54  0   0   0   0   0  h45)
&lt;/pre
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/oct2-1.csp&#39;&gt;oct2-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/oct2-1.txt&#39;&gt;oct2-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、この結果はどうだろうか？
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct2-2.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct2-2.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;この５×５の問題は大丈夫のようだ。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;node-set&gt;&lt;p&gt;では、待望の、７×７の次の問題に挑戦してみよう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct0-7.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct0-7.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;説明は省略し、sugarのプログラムと結果を見てみよう。
&lt;/p
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/oct3-1.csp&#39;&gt;oct3-1.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/oct3-1.txt&#39;&gt;oct3-1.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、これを図示すると
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct3-1.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct3-1.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;のように無茶苦茶になってしまった。
&lt;/p
&gt;&lt;p&gt;さて、どこから手をつけようか。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>黒点は通過</title
><link>http://karetta.jp/book-node/withoutprogramming/233925</link
><pubDate>Wed, 26 Nov 2008 21:06:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;現状の図を見てみよう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct0-t.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct0-t.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;そして、答えも見てみよう。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct0-2.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct0-2.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;丸数字は色々な接続が可能だが、黒点に関しては、そこはまっすぐ通過するだけである。
&lt;/p
&gt;&lt;p&gt;線分だけ見れば、直線になっていて通過するように見えるのにも、次の３種類がある。
&lt;/p
&gt;&lt;pre&gt;(1) →・→
(2) →・←
(3) ←・→
&lt;/pre
&gt;&lt;p&gt;ここでは、(1)の、文字通り通過するものだけをOKとする。
&lt;/p
&gt;&lt;p&gt;方向としては、ー、｜、＼、／の４つの方向があり、さらに、それぞれに向きがある。
各方向について、通過する点（・）の両端の有向辺（矢印）が、もし存在するならば、
同じ方向を向いていなければならない。ということは、同じ値でなければならない。
また、共に存在しない(0)というのもOKなので、
通過する点（・）の両端の有向辺の値は同じということになる。
&lt;/p
&gt;&lt;pre&gt;点（・）の周囲の有向辺の値
 nwst nth nest est sest sth swst wst
に対して、４方向の通過は次のように示せる。
　　　　　
(= nwst sest)   北西：南東
(= nth  sth )　   北：南
(= nest swst)   北東：南西
(= est  wst )　   東：西
&lt;/pre
&gt;&lt;p&gt;これより、
&lt;/p
&gt;&lt;pre&gt;(predicate (through nwst nth nest est sest sth swst wst)
    (and (= nwst sest)
         (= nth  sth )
         (= nest swst)
         (= est  wst )))
&lt;/pre
&gt;&lt;p&gt;を用意し、すべての黒点（丸数字の点を除く）について、調べれば良い。
&lt;/p
&gt;&lt;pre&gt;(through  0   0   0  h31 d31 v31 e31 h21)
(through  0  v11 e21 h12 d12 v12  0   0 )
(through d11 v21 e31 h22 d22 v22 e22 h12)
(through d31 v41  0   0   0  v42 e42 h32)
(through  0  v12 e22 h13 d13 v13  0   0 )
(through d22 v32 e42 h33 d33 v33 e33 h23)
(through d32 v42  0   0   0  v43 e43 h33)
(through d13 v23 e33 h24  0   0   0  h14)
&lt;/pre
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/oct1-3.csp&#39;&gt;oct1-3.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/oct1-3.txt&#39;&gt;oct1-3.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、この結果はどうだろうか？
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct0-p.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct0-p.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;正解になっているようだ、めでたし、めでたし。プログラムは完成だ。
&lt;/p
&gt;&lt;p&gt;と喜んで良いのだろうか。
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
><item><title>交差</title
><link>http://karetta.jp/book-node/withoutprogramming/233923</link
><pubDate>Thu, 20 Nov 2008 14:54:00 +0900</pubDate
><description>&lt;div&gt;&lt;node-set&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct1-1.txt&#39;&gt;oct1-1.txt&lt;/a
&gt;の実行結果を図にしてみた。
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct0-x.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct0-x.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;全部の丸はつながっているのだが、右上の赤とマゼンダで示した２つの矢印が重なっている。
&lt;/p
&gt;&lt;p&gt;ということで、重なりを禁止してみよう。
&lt;/p
&gt;&lt;pre&gt;(predicate (nocross d e) .... )
&lt;/pre
&gt;&lt;p&gt;という nocross というのを作ってみよう。
dおよびeは、それぞれ、対角線方向（＼）、逆対角線方向（／）の矢印を示す
位置的に重なる矢印変数である。
つまり、dにはdで始まる変数、eにはeで始まる変数が入る。
&lt;/p
&gt;&lt;p&gt;上の宣言ができているとして、どう使うかをまず考えてみよう。
簡単だから、以下に並べておく。
全部で９箇所重なる場所があり、それを禁止するために、以下の制約を加える。
&lt;/p
&gt;&lt;pre&gt;(nocross d11 e21) (nocross d21 e31) (nocross d31 e41)
(nocross d12 e22) (nocross d22 e32) (nocross d32 e42)
(nocross d13 e23) (nocross d23 e33) (nocross d33 e43)
&lt;/pre
&gt;&lt;p&gt;さて、 (nocross d e)　はどう書けばよいのだろうか。
&lt;/p
&gt;&lt;p&gt;矢印が交わるということは、dとeがともに矢印として同時に存在することだ。
矢印の向きは関係ないので、言葉どおりに、
２つの矢印が同時に存在してはいけないという書き方をすると次のようになる。
&lt;/p
&gt;&lt;pre&gt;(predicate (nocross d e)
  (not (and (!= 0 d)
            (!= 0 e) )))
&lt;/pre
&gt;&lt;p&gt;同じことだが、次のように書き直すこともできる。
&lt;/p
&gt;&lt;pre&gt;(predicate (nocross d e)
  (or (= 0 d)
      (= 0 e) ))
&lt;/pre
&gt;&lt;p&gt;プログラム：
&lt;a href=&#39;http://karetta.jp/images/552/oct1-2.csp&#39;&gt;oct1-2.csp&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;実行結果：
&lt;a href=&#39;http://karetta.jp/images/552/oct1-2.txt&#39;&gt;oct1-2.txt&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;さて、この結果はどうだろうか？
&lt;/p
&gt;&lt;p&gt;&lt;a href=&#39;http://karetta.jp/images/552/oct0-t.gif&#39;&gt;&lt;img src=&#39;http://karetta.jp/images/552/oct0-t.gif&#39; style=&#39;margin:0 0 5px 0;padding:4px;border:1px solid #ccc;float:none&#39; /&gt;&lt;/a
&gt;
&lt;/p
&gt;&lt;p&gt;矢印が交差するのは消えた。めでたし、めでたし。
&lt;/p
&gt;&lt;p&gt;さて、次は何をちゃんとしようか？
&lt;/p
&gt;&lt;/node-set
&gt;&lt;/div
&gt;</description
></item
></channel
></rss
>