『今週の問題』第200回 記念問題その1 解答


◆熊本県 mit さんからの解答。

【問題1】

ライツアウトには次の特徴があります。

  1. 同じボタンを2度押すと同じ状態に戻る。

  2. ボタンを押す順番は関係ない。
    押す順番を変えても結果は同じ。
これらのことから答えで2度以上押すボタンは存在しない事がいえます。

ある答えで、偶数回押したボタンは押す必要はなく、奇数回押したボタンは1回押せばよいことになります。
(これを『性質a』とします)

これを利用すれば最短手数でなくても基本図に戻せる答えが見つかれば最短手数に近い手数の解を得る事ができます。

下の図はこれを利用して得られた結果の一例です。
●→押すボタン、○→押さないボタン

●●○●●●○○○●○●●●●○●
○○●○●○○●○○●○○○●●○
●●○○○○○●●○○○○○●○●
○○●○●○○●○●○○●●○●○
●○○○●●○●○○○●●●○○●
●●○●●○○○●●○○○●●○○
●○●○●○●○○○○●●●○●○
しかし、これだけでは最短手数を見つける事ができない場合があるのもまた事実です。
そこで次のようなパターンを利用します。
パターン1
●●○●●○●●○●●○●●○●●
○○○○○○○○○○○○○○○○○
●●○●●○●●○●●○●●○●●
○○○○○○○○○○○○○○○○○
●●○●●○●●○●●○●●○●●
○○○○○○○○○○○○○○○○○
●●○●●○●●○●●○●●○●●

パターン2
●○○○●○●○○○●○●○○○●
●●○●●○●●○●●○●●○●●
●○○○●○●○○○●○●○○○●
○○○○○○○○○○○○○○○○○
●○○○●○●○○○●○●○○○●
●●○●●○●●○●●○●●○●●
●○○○●○●○○○●○●○○○●

パターン3
○●○●○○○●○●○○○●○●○
●●○●●○●●○●●○●●○●●
○●○●○○○●○●○○○●○●○
○○○○○○○○○○○○○○○○○
○●○●○○○●○●○○○●○●○
●●○●●○●●○●●○●●○●●
○●○●○○○●○●○○○●○●○
これらのパターンに従ってボタンを押すと、2度押したボタンが一つもないのにもかかわらず、押す前の状態に戻ってしまうという現象が起こります。

いずれも押すボタンの数は48個なので、求めた解とこれらのパターンと比べてみて、もし押すボタンの重複が24個より多い場合、性質aから求めた解よりも少ない手数の解を得られることになります。
ちなみにちょうど24個の場合は別解を求める事ができます。

この場合の押すボタンの重複は上二つは24個、一番下は20個なので、これより少ない手数は見つけられないことになります。
よって解は下の図の通り。(54手)

●●○●●●○○○●○●●●●○●
○○●○●○○●○○●○○○●●○
●●○○○○○●●○○○○○●○●
○○●○●○○●○●○○●●○●○
●○○○●●○●○○○●●●○○●
●●○●●○○○●●○○○●●○○
●○●○●○●○○○○●●●○●○
Full Pushによって生成されるパターンを基本図に戻すのに必要な手数に41手の解があることから、
上の3つの他に17×7−41=78手の『押す前の状態に戻ってしまうパターン』が存在するはずなのですが、これは見つけられませんでした。

もしかしたらそれを使ったらもっと少ない手数の解が見つかるかもしれません。


◆東京都 oidon さんからの解答。

セル(X,Y)のライトが点灯しており,Xより左は全てスイッチ操作により消灯しているものとする.
ただしX>1とする.

このとき(X,Y)を消すためには(X+1,Y)のスイッチを押さなければならない.

このようにして左から順番に消すことを考えると,
最も左の列のスイッチを押すパターン(28=256)通りを調べれば全ての解が得られることになる.

そこで以下のプログラムによって全ての場合を考え,全てのライトが消灯する中で最も手数の少ないものを解とした.

この結果得られた最小手数は50手であり,解は

(1, 4), (1, 6), (2, 3), (2, 4), (2, 6), (2, 7), (3, 4), (3, 6), (3, 7), (4, 1),
(4, 2), (4, 3), (4, 4), (4, 5), (5, 3), (6, 1), (6, 5), (7, 1), (7, 2), (7, 3), 
(7, 4), (7, 5), (7, 6), (8, 6), (9, 2), (9, 3), (10, 6), (10, 7), (11, 1), (11, 2),
(11, 3), (11, 4), (11, 5), (11, 7), (12, 1), (12, 5), (12, 7), (13, 3), (14, 5),
(14, 6), (15, 1), (15, 3), (16, 3), (16, 5), (16, 6), (16, 7), (17, 2), (17, 4), 
(17, 6), (17, 7)
となった.なお,計算時間は0.5秒である.
#!/usr/bin/python

import re, string, sys, os
data =\
     """
     ..X...XXXXX.XXXXX
     .XXX..X...X.X...X
     ..X...X...X.X...X
     ..X...XXXXX.XXXXX
     ..X.......X.....X
     ..X...X...X.X...X
     .XXX..XXXXX.XXXXX
     """
regex = re.compile( "[^\\.\\w]+", re.M ) 

class Field:
    def __init__( self, data ):
        lines = regex.split( data )
        field = []
        min_columns = 999
        for i in range( len( lines ) ):
            columns = len( lines[ i ] )
            if columns > 0:
                if columns < min_columns:

                    min_columns = columns
                    pass
                row = []
                for x in lines[ i ]:
                    if x == "X":
                        row.append( 1 )
                    else:
                        row.append( 0 )
                        pass
                    pass
                field.append( row )
                pass
            pass
        self.__field = field
        self.__rows = len( field )
        self.__columns = min_columns
        pass

    def __repr__( self ):
        str = ""
        for row in self.__field:
            line = ""
            for x in row:
                if x == 0:
                    line += " "
                elif x == 1:
                    line += "O"
                    pass
                pass
            str += line + "\n"
            pass
        return str

    def push( self, x, y ):
        left   = x - 1
        right  = x + 1
        top    = y  - 1

bottom = y + 1
        if x < 0 or x >= self.__columns or y < 0 or y >= self.__rows:
            return
        if left < 0                : left = 0
        if right >= self.__columns : right = self.__columns - 1
        if top < 0                 : top = 0
        if bottom >= self.__rows   : bottom = self.__rows - 1
        v = top
        while v <= bottom:
            self.__field[ v ][ x ] = 1 - self.__field[ v ][ x ]
            v += 1
            pass
        h = left
        while h <= right:
            if x != h: 
                self.__field[ y ][ h ] = 1 - self.__field[ y ][ h ]
                pass
            h += 1
            pass
        return

    def get_columns( self ):
        return self.__columns

    def get_rows( self ):
        return self.__rows

    def is_on( self, x, y ):
        if x < 0 or x >= self.__columns or y < 0 or y >= self.__rows:
            return False
        return ( self.__field[ y ][ x ] == 1 )

    def is_off( self, x, y ):
        if x < 0 or x >= self.__columns or y < 0 or y >= self.__rows:
            return False
        return ( self.__field[ y ][ x ] == 0 )

    def is_all_off( self ):
        for row in self.__field:
            for cell in row:
                if cell != 0:
                    return False
                pass
            pass
        return True
    pass

f = Field( data )
print f

code = 0
min_steps = f.get_columns() * f.get_columns()
answer = None
while code < 256:
    f = Field( data )
    bit = 1
    num_switch = 0
    pushed = []
    for i in range( 0, 8 ):
        if ( bit & code ) != 0:
            f.push( 0, i )
            num_switch += 1
            pushed.append( ( 1, i + 1 ) )
            pass
        bit *= 2
        pass
    for x in range( 1, f.get_columns() ):
        for y in range( 0, f.get_rows() ):
            if f.is_on( x - 1, y ):
                f.push( x, y )
                pushed.append( ( x + 1, y + 1 ) )
                num_switch += 1

                pass
            pass
        pass
    if f.is_all_off():
        if min_steps > num_switch:
            min_steps = num_switch
            answer = pushed
        pass
    code += 1
    pass

print min_steps
print answer

◆東京都 ぽこぺん さんからの解答。

【Lights Out の性質】

(1) 座標(定義): 盤面を m×n の長方形とし,行列方式(左上からの行・列の番号)で点に座標を付ける。

(2) 被覆(定義): 点 (i,j) を中心とする十字形
   C(i,j) = {(i, j), (i-1, j), (i+1, j), (i, j-1), (i, j+1)}
を被覆と呼ぶ。
ただし,被覆の一部が盤面の外にはみ出すときには,その部分を無視する。

(3) 反転操作(定義): 被覆 C(i,j) に覆われる点の on/off を逆にする操作を,C(i,j) に対応する反転操作と呼ぶ。
なお,被覆の記号を代用して,その被覆に対応する 1 回の反転操作も表す。

(4) 偶奇性・縮退: 初期状態から始めて有限回の反転操作を行った結果,一つの点の on/off の状態は,その上に乗る被覆の枚数のみによって決まり,反転操作の順序によらない。
被覆の枚数が偶数ならば初期状態と同じ,奇数ならば初期状態の反対である。

したがって,同じ点を中心とする被覆(同一の被覆)が複数枚あるとき,偶数枚ならばその被覆は 0 枚と同じ,奇数枚ならば 1 枚と同じと考えてよい。
これを縮退と呼ぶことにする。

以下では被覆は縮退した形で考える。

(5) 重ね合わせの原理: 状態が on の点の集合 A,B が共有点を持たないとき,それぞれに有限回の反転操作 R を施した 結果(の on の点の集合)を A',B' とすると,
A∪B に R を施した結果は A' と B' の対称差 (A'∪B')-(A'∩B') となる。

(6) 可逆性: 盤面上の点の集合 S に対し,被覆の集合 {C(i,j) | (i,j)∈S} に対応する反転操作の集合により盤面の状態 A が状態 B に変わるとき,同じ反転操作の集合により B は A に変わる。

(7) 無限盤面の問題: 上下左右に無限に広がった盤面においては,その中の 1 点だけが on である初期状態から出発して,有限回の反転操作ですべての点を off にすることはできない。

(証明)所与の初期状態から始めて,同じ点を中心とする反転操作を複数回行わずに有限回の反転操作を行った結果,被覆が占める領域の最も外側の点は 1 枚だけの被覆により覆われるから,その領域には必ず on の点が含まれる。■

(8) 有限盤面の問題: 前項の結果,有限の盤面において,もし同じ初期状態から始めてすべての点を off にすることができたとすると,被覆が占める領域は必ず盤面の周辺(第 1 行,第 n 行,第 1 列,第 n 列の少なくとも 1 つ)と共有点を持つ。

【掃引操作】

(1) 掃引操作(定義): 盤面上のすべての on の点の集合 L に対して

j_max = max{j | (i, j)∈L}

によって定まる j_max が 1 より大きいとき,被覆の集合

{C(i,j_max - 1) | (i, j_max)∈L}

に対応する反転操作を 1 ステップとし,それを可能な限り繰り返す操作を,行方向の負の掃引操作と呼ぶ。

1 ステップごとに,j_max の値は 1 以上小さくなるので,この操作は有限回の繰り返しで終了する。
また,同様に行方向の正の掃引操作,列方向の正・負の掃引操作を定義する。

(2) 周辺配置(定義): 与えられた盤面上のすべての on の点の集合 L に対して,行方向の負の掃引操作により第 1 列に集められた on の点の集合 R_b(L) を L に対する第 1 列の周辺配置と呼ぶ。

 同様に,それぞれ第 n 列,第 1 行,第 m 行の周辺配置 R_f(L),C_b(L),C_f(L) を定義する。

【問題の解答】

(1) m = 7, n = 17 の場合,第 6 列の各点 L_i = {(i, 6)} に対する第 1 列と第 n 列の周辺配置は次図のようになる。

ただし,i > 4 に対する周辺配置は,i < 4 の図の上下を対称移動したものだから,図は省略する。

たとえば,L_1 に対しては,第 1 列の周辺配置は
M_r-(L_1) = {(2, 1), (3, 1), (5, 1), (6, 1)} の 4 点となり,
第 n 列の周辺配置は M_r+(L_1) = φ(空)となる。

(2) 解の存在定理: 第 1 列の周辺配置に (4, 1) が含まれず,上下対称であれば,その問題には解が存在する。

(証明)周辺配置が {(1, 1), (7, 1)} であるとき,重ね合わせの原理により
L_1 ∪ L_2 からの負の掃引操作が存在する。
したがって,可逆性を用いれば,この周辺配置から L_1 ∪ L_2 を作ることができ,そこからの正の掃引操作で点を消去することができる。

一般に,

M_r-(L_1 ∪ L_2) = {(1, 1), (7, 1)}
M_r-(L_1 ∪ L_2 ∪ L_3) = {(2, 1), (6, 1)}
M_r-(L_2 ∪ L_3) = {(3, 1), (5, 1)}

および,この L_1,L_2,L_3 を それぞれ L_7,L_6,L_5 に個別に入れ替えた式が成立するから,定理が成り立つ。

(注)明らかに,この定理は第 17 列の周辺配置に対しても同様の形で成立する。

(3) 問題1(『199』)

問題の初期配置を I とする。このとき,

M_r-(I) = {(2, 1), (3, 1), (5, 1), (6, 1)}

となるので I には解が存在する。

行方向の負および正の掃引操作,さらに掃引操作に含まれない反転操作を行ってすべての点を off にすることができた操作の集合の例(大きさ50)を次に示す。

ただし,反転操作 C(i, j) を (i, j) と略記する。

{(1, 4), (1, 6), (1, 7), (1, 11), (1, 12), (1, 15), (2, 4), (2, 7), (2, 9), (2, 11), 
 (2, 17), (3, 2), (3, 4), (3, 5), (3, 7), (3, 9), (3, 11), (3, 13), (3, 15), (3, 16),
 (4, 1), (4, 2), (4, 3), (4, 4), (4, 7), (4, 11), (4, 17), (5, 4), (5, 6), (5, 7), 
 (5, 11), (5, 12), (5, 14), (5, 16), (6, 1), (6, 2), (6, 3), (6, 7), (6, 8), (6, 10), 
 (6, 14), (6, 16), (6, 17), (7, 2), (7, 3), (7, 10), (7, 11), (7, 12), (7, 16), (7, 17)}
この解も含め,解となる操作集合の例を下図に掲げる。
解の大きさは,50,54,56,58,60,62,64 である。
おそらくこれですべての解を尽くしていると考えられるが,証明はできていない。

(4) 問題2(『200』)

問題の初期配置を I とする。このとき,

M_r-(I) = {(1, 1), (3, 1), (6, 1), (7, 1)}

となるので定理の条件を満たしていない。

このうち,定理の対称性を崩しているのは点 (3, 1) と (6, 1) であるが,

M_r-({(7, 5)}) = {(3, 1)}
M_r-({(2, 11)}) = {(6, 1)}

であるから,I に対して点 (7, 5) と (2, 11) の on/off を反転させたものは定理の条件を満たす。

このとき,初期配置は

□■■■□□□■■■□□□■■■□
■□□□■□■□□□□□■□□□■
□□□□■□■□□□■□■□□□■
□□□■□□■□□□■□■□□□■
□□■□□□■□□□■□■□□□■
□■□□□□■□□□■□■□□□■
■■■■□□□■■■□□□■■■□
となり,これに対して大きさ 45 の次のような解の例がある。
{(1, 3), (1, 5), (1, 7), (1, 11), (1, 14), (2, 4), (2, 5), (2, 7), (2, 9), (2, 11),
 (2, 12), (2, 13),(2, 16), (3, 1), (3, 7), (3, 9), (3, 11), (3, 12), (3, 13), (3, 15), 
 (3, 16), (4, 1), (4, 2), (4, 4), (4, 6), (4, 7), (4, 16), (5, 1), (5, 8), (5, 9),
 (5, 12), (6, 3), (6, 4), (6, 6), (6, 7), (6, 10), (6, 12), (6, 16), (6, 17), (7, 1),
 (7, 7), (7, 10), (7, 11), (7, 15), (7, 17)}
【感想】


◆静岡県 medaka さんからの解答。

【問題1】

50手(Push位置を■で表す)

□□□■□■■□□□■■□□■□□
□□□■□□■□■□■□□□□□■
□■□■■□■□■□■□■□■■□
■■■■□□■□□□■□□□□□■
□□□■□■■□□□■■□■□■□
■■■□□□■■□■□□□■□■■
□■■□□□□□□■■■□□□■■
【問題2】

少なくとも、2ケ所を修正する必要があります。
例えば、下図のように(3,a),(6,a)の2ケ所の位置を■に変更するのが、あまり修正が目立たなくてよいでしょう。

 abcdefghijklmnopq
1□■■■□□□■■■□□□■■■□
2■□□□■□■□□□■□■□□□■
3■□□□■□■□□□■□■□□□■
4□□□■□□■□□□■□■□□□■
5□□■□□□■□□□■□■□□□■
6■■□□□□■□□□■□■□□□■
7■■■■■□□■■■□□□■■■□
この図の解は、44手(以下のPushパターン)
□□■□□□□□■□■□□■□□□
□□□□□□□□□■■■■□□■□
■□■□■□■□□□■■■□■■□
□□■□□□□■□□□□□□□■□
■■□□■□■■■□□■□□□□□
□□■■■□■□□■□■□□□■■
□■□■■□■□□■■□□□■□■
【おまけ】

最多手数は、68手。

   68手の問題の1例
■□□□□□□□□□□□□□□□■
□■■■■■■■■■■■■■■■□
□■■■■■■■■□□■□□■□■
■□□□□■□□■□□■□□□□■
■■■■□■□■■□■■■□■□□
□□□□■■■□□□■■■□□□□
□□□□■□■□□□■□■□□□□
上記の問題の解 (Push パターン)
■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■
■■■■■■■■■□□■□□■□□
□□□□□■□□□□□■□□□□□
□□□□□■□□□□□■□□□□□
□□□□□■□□□□□■□□□□□

◆東京都 明 さんからの解答。

【問題1】

Push数 50回

手順

( 4, 1)→( 6, 1)→( 3, 2)→( 4, 2)→( 6, 2)→
( 7, 2)→( 4, 3)→( 6, 3)→( 7, 3)→( 1, 4)→
( 2, 4)→( 3, 4)→( 4, 4)→( 5, 4)→( 3, 5)→
( 1, 6)→( 5, 6)→( 1, 7)→( 2, 7)→( 3, 7)→
( 4, 7)→( 5, 7)→( 6, 7)→( 6, 8)→( 2, 9)→
( 3, 9)→( 6,10)→( 7,10)→( 1,11)→( 2,11)→
( 3,11)→( 4,11)→( 5,11)→( 7,11)→( 1,12)→
( 5,12)→( 7,12)→( 3,13)→( 5,14)→( 6,14)→
( 1,15)→( 3,15)→( 3,16)→( 5,16)→( 6,16)→
( 7,16)→( 2,17)→( 4,17)→( 6,17)→( 7,17)→
押したボタンの種類が同じであれば、順番には係わりません。

<求め方>

各ボタンに番号を付け、押したボタン毎に変化するパターンをすべて書き下ろすと、例えば7×3の場合は下記のようになり ます。

ただし、番号は(1,1)(2,1)・・・(6,3)(7,3)の順に付け、上から順に1〜21、左から順に1〜21とします。

1  1  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0 
1  1  1  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0 
0  1  1  1  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0 
0  0  1  1  1  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0 
0  0  0  1  1  1  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0 
0  0  0  0  1  1  1  0  0  0  0  0  1  0  0  0  0  0  0  0  0 
0  0  0  0  0  1  1  0  0  0  0  0  0  1  0  0  0  0  0  0  0 
1  0  0  0  0  0  0  1  1  0  0  0  0  0  1  0  0  0  0  0  0 
0  1  0  0  0  0  0  1  1  1  0  0  0  0  0  1  0  0  0  0  0 
0  0  1  0  0  0  0  0  1  1  1  0  0  0  0  0  1  0  0  0  0 
0  0  0  1  0  0  0  0  0  1  1  1  0  0  0  0  0  1  0  0  0 
0  0  0  0  1  0  0  0  0  0  1  1  1  0  0  0  0  0  1  0  0 
0  0  0  0  0  1  0  0  0  0  0  1  1  1  0  0  0  0  0  1  0 
0  0  0  0  0  0  1  0  0  0  0  0  1  1  0  0  0  0  0  0  1 
0  0  0  0  0  0  0  1  0  0  0  0  0  0  1  1  0  0  0  0  0 
0  0  0  0  0  0  0  0  1  0  0  0  0  0  1  1  1  0  0  0  0 
0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  1  1  1  0  0  0 
0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  1  1  1  0  0 
0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  1  1  1  0 
0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  1  1  1 
0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  1  1 
ボタン毎に、押したときのパターンのオン、オフの変化は、上記パタ ーン(ベクトル)の排他的論理和であることを考えると、【問題1】は 与えられた初期パターンを上記ベクトルに展開することになります。

上記表から類推されるように、7×17=119のベクトルは明らかに一次独立な112個のベクトルと、7個(下の7個としました)のベクトルで構成されています。

以下は計算機の力を借りて考察しました。

7個のベクトルは3個の独立なベクトルと4個の従属なベクトルです。
従って【問題1】は初期パターンを115個から一意に選ばれたベクトルと4個の剰余ビットに展開することで解くことができます。
ただし4個の従属な(異なる)ベクトルがありますので、最終的には16通りの回答が得られます。

解を求めるためのプログラムを10進BASICで作りました。(下記)

【問題1】の回答はこの中で最小のものです。


LET AX=7          !配列の縦列数
LET AY=17         !配列の横列数
LET DM=AX*AY      !ベクトルの次元    
DIM B(DM+1,DM)    !ベクトル配列表  DM+1:ワークエリア  
DIM PR(AX+2,DM)   !AX個のベクトルの構成メモリ  AX+1,AX+2:ワークエリア
DIM BF(AX)        !作業用バッファ
DIM BFC(AX)       !作業用バッファ
DIM DR(5,2)       !周辺位置指定メモリ
DATA 0,0,0,-1,-1,0,1,0,0,1
MAT READ DR

CALL becset          !ベクトル配列表を求める  
! CALL prnarr          !ベクトル配列表出力
CALL convbe          !AX個のベクトルを変換する
! CALL prnpro          !AX個のベクトルの構成成分の出力
! CALL prnrem          !AX個のベクトルの変換後出力
CALL caldim          !AX個のベクトルの独立数を求める
! PRINT "独立数 :";ID  !独立数出力
! CALL prnrem          !AX個のベクトルの再変換後出力

REM 初期パターンの生成
DIM G(DM)
DATA 0,0,0,0,0,0,0
DATA 0,1,0,0,0,0,1
DATA 1,1,1,1,1,1,1
DATA 0,1,0,0,0,0,1
DATA 0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0
DATA 1,1,1,1,0,1,1
DATA 1,0,0,1,0,0,1
DATA 1,0,0,1,0,0,1
DATA 1,0,0,1,0,0,1
DATA 1,1,1,1,1,1,1
DATA 0,0,0,0,0,0,0
DATA 1,1,1,1,0,1,1
DATA 1,0,0,1,0,0,1
DATA 1,0,0,1,0,0,1
DATA 1,0,0,1,0,0,1
DATA 1,1,1,1,1,1,1

MAT READ G
PRINT "初期パターン"
FOR IX=1 TO AX
   FOR IY=1 TO AY
      IF G(AX*(IY-1)+IX)=1 THEN PRINT "■"; ELSE PRINT "□";
   NEXT IY
   PRINT
NEXT IX
PRINT

REM 初期パターンを基本配列に戻す
FOR J=1 TO DM
   LET B(DM+1,J)=G(J)
NEXT J
FOR J=DM TO AX+1 STEP -1 
   IF B(DM+1,J)=1 THEN
      LET IX2=J-AX
      CALL addbec(B,DM+1,IX2)
      LET PR(AX+1,IX2)=MOD(PR(AX+1,IX2)+1,2)
   END IF
NEXT J
MAT BFC=BF
FOR J=AX TO 1 STEP -1
   FOR K=1 TO AX
      IF BFC(K)=1 AND B(DM-AX+K,J)=1 THEN
         LET BFC(K)=0 
         IF B(DM+1,J)=1 THEN   
            CALL addbec(B,DM+1,DM-AX+K)
            CALL addbec(PR,AX+1,K)
            EXIT FOR
         END IF
      END IF
   NEXT K
NEXT J

PRINT "剰余ビット :";
FOR J=1 TO 4
   PRINT B(DM+1,J);
NEXT J
PRINT
PRINT

PRINT "基本配列へ戻すためのボタン配列"
FOR J=0 TO 2^(AX-ID)-1
   CALL addbec(PR,AX+2,AX+1)
   LET ADC=J
   FOR K=1 TO AX
      IF BF(K)=0 THEN
         IF MOD(ADC,2)=1 THEN CALL addbec(PR,AX+2,K)
         LET ADC=INT(ADC/2)
      END IF
   NEXT K
    
   LET PCT=0
   FOR K=1 TO DM
      IF PR(AX+2,K)=1 THEN LET PCT=PCT+1
   NEXT K
    
   PRINT "PATTERN No : ";J+1 
   PRINT "手数 : ";PCT
   CALL outpat
   PRINT
   CALL addbec(PR,AX+2,AX+2)
NEXT J

SUB becset
   MAT B=ZER
   LET BRW=0   
   FOR K=1 TO AY
      FOR J=1 TO AX
         LET BRW=BRW+1
         FOR L=1 TO 5
            LET IX=J+DR(L,1)
            LET IY=K+DR(L,2)
            IF IX>=1 AND IX<=AX AND IY>=1 AND IY<=AY THEN
               LET BCL=(IY-1)*AX+IX
               LET B(BRW,BCL)=1
            END IF
         NEXT L
      NEXT J
   NEXT K
END SUB

SUB prnarr
   FOR J=1 TO DM
      FOR K=1 TO DM
         PRINT B(J,K);
      NEXT K
      PRINT
   NEXT J
END SUB

SUB convbe
   MAT PR=ZER
   FOR J=1 TO AX
      LET IX=DM-AX+J
      LET IY=DM
      LET PR(J,IX)=1
      DO
         IF B(IX,IY)=1 THEN 
            LET IX2=0
            DO
               LET IX2=IX2+1
               IF IX2>DM THEN STOP
               IF B(IX2,IY)=1 THEN
                  CALL addbec(B,IX,IX2)
                  LET PR(J,IX2)=1
                  EXIT DO
               END IF
            LOOP
         END IF
         LET IY=IY-1
      LOOP UNTIL IY=AX
   NEXT J
END SUB

SUB addbec(ARR(,),IX,IX2)
   FOR L=1 TO DM
      LET arr(IX,L)=MOD(ARR(IX,L)+ARR(IX2,L),2)
   NEXT L
END SUB

SUB prnpro
   FOR J=1 TO AX
      PRINT "ベクトルNo : ";DM-AX+J
      LET PCT=0
      FOR K=1 TO DM
         IF PR(J,K)=1 THEN 
            PRINT K;
            LET PCT=PCT+1
            IF MOD(PCT,10)=0 THEN PRINT
         END IF
      NEXT K
      PRINT      
      PRINT "構成個数 : ";PCT
      PRINT
   NEXT J
END SUB
 
SUB prnrem
   FOR J=DM-AX+1 TO DM
      FOR K=1 TO AX
         PRINT B(J,K);
      NEXT K
      PRINT
   NEXT J
   PRINT
END SUB

SUB caldim
   MAT BF=ZER
   LET BX=DM-AX
   LET ID=0
   FOR J=AX TO 1 STEP -1
      LET SF=0
      FOR K=1 TO AX
         IF B(BX+K,J)=1 THEN
            IF SF=0 AND BF(K)=0 THEN 
               LET SF=1
               LET IK=K
               LET BF(K)=1
               LET ID=ID+1
            ELSEIF BF(K)=0 THEN               
               CALL addbec(B,BX+K,BX+IK)
               CALL addbec(PR,K,IK)
            END IF
         END IF
      NEXT K
   NEXT J
END SUB 

SUB outpat
   FOR IX=1 TO AX
      FOR IY=1 TO AY
         IF PR(AX+2,AX*(IY-1)+IX)=1 THEN PRINT "■"; ELSE PRINT "□";
      NEXT IY
      PRINT
   NEXT IX
END SUB

END

【問題2】

同じプログラムで剰余ビットを求めると、0,1,1,0(ビット1〜4)となり、解がないことがわかります。

剰余ビットを0とするため、別に、ビット毎に剰余ビットを求め、同じ剰余になるものを探しました。
1ビットのみでは適合するものは存在せず、2ビットの剰余の排他的論理和で条件に合ったものを作ることができます。

例として、(2,1)、(1,13)をオンとした下記パターンが適合します。

□■■■□□□■■■□□■■■■□
■■□□■□■□□□■□■□□□■
□□□□■□■□□□■□■□□□■
□□□■□□■□□□■□■□□□■
□□■□□□■□□□■□■□□□■
□■□□□□■□□□■□■□□□■
■■■■■□□■■■□□□■■■□
【おまけ】

4個の従属なベクトルのグループは以下の通りです。

ベクトルNo :  116 
 2  4  6  8  9  11  13  14  16  20 
 24  25  26  32  46  52  53  54  58  62 
 64  65  67  69  70  72  74  76  86  88 
 90  92  93  95  97  98  100  104  108  109 
 110  116 
構成個数 :  42 

ベクトルNo :  117 
 1  7  8  9  13  14  15  17  19  21 
 23  24  26  27  31  33  45  47  51  52 
 54  55  57  59  61  63  64  65  69  70 
 71  77  85  91  92  93  97  98  99  101 
 103  105  107  108  110  111  115  117 
構成個数 :  48 

ベクトルNo :  118 
 2  6  8  9  10  12  13  14  22  23 
 24  26  27  28  30  34  44  48  50  51 
 52  54  55  56  64  65  66  68  69  70 
 72  76  86  90  92  93  94  96  97  98 
 106  107  108  110  111  112  114  118 
構成個数 :  48 

ベクトルNo :  119 
 3  5  9  10  12  13  15  17  19  21 
 22  23  27  28  29  35  43  49  50  51 
 55  56  57  59  61  63  65  66  68  69 
 73  75  87  89  93  94  96  97  99  101 
 103  105  106  107  111  112  113  119 
構成個数 :  48
全体をまとめると以下のようになります。
従属ベクトルのグループ
 1  2  3  4  5  6  7  8  9  10 
 11  12  13  14  15  16  17  19  20  21 
 22  23  24  25  26  27  28  29  30  31 
 32  33  34  35  43  44  45  46  47  48 
 49  50  51  52  53  54  55  56  57  58 
 59  61  62  63  64  65  66  67  68  69 
 70  71  72  73  74  75  76  77  85  86 
 87  88  89  90  91  92  93  94  95  96 
 97  98  99  100  101  103  104  105  106  107 
 108  109  110  111  112  113  114  115  116  117 
 118  119 
構成個数 :  102 

独立ベクトルのグループ
 18  36  37  38  39  40  41  42  60  78 
 79  80  81  82  83  84  102 
構成個数 :  17
基本図に戻すのに一番手数のかかる配置は、以上の従属のグループのどのような組み合わせでも、ベクトルの半分が選択されるように ベクトルを選択することにより求められます。
(さらに独立のグループを加えたものが解となります。)

上記4つのグループにより分割される15種のサブグループ内のベクトルは、求めてみると、すべて0もしくは偶数個になっていますので 丁度1/2ずつ選択することができます。
例として以下のような選択があります。

ボタンの指定
■■■■■■■■■□□■□□□□□
■■■■■■■■■■■■□□□□□
■■■■■■■■■□□■□□□□□
■■■■■■■■■□□■□□■□□
■■■■■■■■□□□■□□□□□
■■■■■■□□□□□■□□□□□
■■■■■■■■□□□■□□□□□
ボタン数 : 68

この選択により生成されるパターンは下記のとおりです。

■□□□□□□□■□□□■□□□□
□■■■■■■■■■■□■□□□□
□■■■■■■■□□□■■□■□□
□■■■■■■■■■■■■■■■□
□■■■■■□■□□■■■□■□□
□■■■■□■□□□■■■□□□□
■□□□□□■□■□■□■□□□□
このパターンはPush数68で基本図に戻ります。


◆愛知県 Y.M.Ojisan さんからの解答。

【問題1】  50回


    図中青い数字はプッシュの順番号です。

【問題2】 下図2個追加  52回



【おまけ】  68回 

 例えば下記のパターンが存在しています。
 本結果はPCプログラムによるもので、プッシュ数極大化+モンテカルロ法を行っています。
 多数解があるので容易に何らかの解に達します。

 

証明と機械的作り方

 まず、基本図を基本図に戻すプッシュパターンを考えます。
1列目のプッシュパターンを決めると2列目以降は必然的に決まります。
従って、プッシュなしを含む128パターンを調べればよく、その結果その内16パターンが基本図を基本図に戻すパタ−ンであることがわかりました。
これらは下記4次元の単位パターンの組み合わせ(排他論理和)で表すことが可能です。

1 2
22 23

 そして、プッシュを1としてこれら4パターンを2進法的に足し合わせると、下記のパターンが得られます。

    119=7×17

 値が「0」のところは17ヶ所あり、これらの位置はプッシュしておけば常にプッシュすべき位置となります。
他の位置は必ず全部パターンの半分のパターンでプッシュされます。
よって、2=16個のパターンを作用させた後のプッシュパターン合計のプッシュ数平均値は
  17+(119−17)×0.5=68 です。
 つまり、68より多いプッシュパターンがあるときは68未満のプッシュパターンもあることになり、68が最大であることがわかります。
 次に作り方ですが、「0」以外のところは都合よく全て偶数個ずつあります。
従って、おのおのその半分の個数の位置を適当にプッシュすべき位置とすれば、プッシュ数がパターンにより変わることはなく全部68回となります。
 下に示す例は、プッシュ位置が可能な限り上半分に在るプッシュパターンから得た初期状態です。
上図は、そのプッシュパターンで操作したもの、下図は別のプッシュパターンで操作したもので、いずれも68回です。



 ◆ 問題へもどる

 ◆ 今週の問題

数学の部屋へもどる