(1)セル間リンク

セル間リンクには、強いリンクと弱いリンクの2種類があります。

strong link weak link



(2)セル間リンクの要素クラス(UCellLink)

セル間リンクの要素クラスは、GNPZ_Analyzerクラスの内部クラスとして定義しています。 流れでこのようになっていますが、単独のクラスでもよいでしょう。GNPXでも変更の可能性があります。

public class UCellLink: IComparable{
    public int               ID;       //初期値はtfx 外部で再設定する
    public int               tfx;
    public int               type;
    public bool              SFlag;    //T:Strong
    public bool              LoopFlag; //ループ形成の最後のリンク
    public bool              BVFlag;   //両端セルがbivalue
    public readonly int      no;
    public readonly UCell    UCe1;
    public readonly UCell    UCe2;
    public int               rc1{ get{ return UCe1.rc; } }
    public int               rc2{ get{ return UCe2.rc; } }
    public readonly Bit81    B81;

    public UCellLink(){}
    public UCellLink( int tfx, int type, int no, UCell UCe1, UCell UCe2, bool SFlag=false ){
        this.tfx=tfx; this.type=type; this.no=no; this.SFlag=SFlag; 
        this.UCe1=UCe1; this.UCe2=UCe2; this.ID=tfx;
        BVFlag = UCe1.FreeBC==2 && UCe2.FreeBC==2;
        B81=new Bit81(rc1); B81.BPSet(rc2);
    }
7
    public UCellLink Reverse(){
        UCellLink ULK=new UCellLink(tfx,type,no,UCe2,UCe1,SFlag);
        return ULK;
    }
                    
    public int CompareTo( object obj ){
        UCellLink Q = obj as UCellLink;
        if( this.type!=Q.type ) return (this.type-Q.type);
        if( this.no  !=Q.no   ) return (this.no-Q.no);
        if( this.rc1 !=Q.rc1  ) return (this.rc1-Q.rc1);
        if( this.rc2 !=Q.rc2  ) return (this.rc2-Q.rc2);
        return (this.ID-Q.ID);
    }
    public override bool Equals( object obj ){
        UCellLink Q = obj as UCellLink;
        if( Q==null )  return true;
        if( this.type!=Q.type || this.no!=Q.no )   return false;
        if( this.rc1!=Q.rc1   || this.rc2!=Q.rc2 ) return false;
        return true;
    }
    public override string ToString(){
        string st="ID:"+ID.ToString().PadLeft(2)+ " type:"+type +" no:"+no;
        st +=  " rc1:"+rc1.ToString().PadLeft(2)+ " rc2:"+rc2.ToString().PadLeft(2); 
        return st;
    }
}


(3)セル間リンクの管理用クラス(CellLinkMan)

セル間リンクの管理用クラスです。リンクの生成やリンク利用での補助的関数を持ちます。

public class CellLinkMan{
    private GNPX_AnalyzerMan pAnMan;
    private List<UCell>   pBDL{ get{ return pAnMan.pBDL; } }      
    private Bit81[]       pHouseCells;
    public  int           SWCtrl;
    public  List<UCellLink>[] CeLK81;//セルチエインの制御

    public CellLinkMan( GNPX_AnalyzerMan pAnMan ){
        this.pAnMan = pAnMan;
        this.pHouseCells = AnalyzerBaseV2.HouseCells;
        SWCtrl=0;
    }

    public void Initialize(){ SWCtrl=0; }
            
    public void PrepareCellLink( int swSW ){
        if( (swSW.DifSet(SWCtrl))==0 )  return;

        if( SWCtrl==0 ) CeLK81=new List<UCellLink>[81];
        _SrtongLinkSearch(true); //strong link
        _WeakLinkSearch( );      //weak link
        SWCtrl |= swSW;

        foreach( var P in CeLK81 ) if(P!=null) P.Sort();
    }
        
    public void  ResetLoopFlag(){
        foreach( var P in CeLK81.Where(p=>p!=null) ){ P.ForEach(Q=>Q.LoopFlag=false); }
    }
    private void _SrtongLinkSearch( bool weakOn ){
        for( int tfx=0; tfx<27; tfx++ ){
            for( int no=0; no<9; no++){
                int noB = 1<<no;
                List<UCell> PLst = pBDL.IEGetCellInHouse(tfx,noB).ToList();
                if( PLst.Count!=2 ) continue;
                UCell UC1=PLst[0], UC2=PLst[1];

                SetLinkList(tfx,1,no,UC1,UC2);
                SetLinkList(tfx,1,no,UC2,UC1);
                    
                if( weakOn ){
                    SetLinkList(tfx,2,no,UC1,UC2);
                    SetLinkList(tfx,2,no,UC2,UC1);
                }
            }
        }
    #region Debug Print
    //    foreach( var P81 in CeLK81.Where(p=>p!=null) ) P81.Sort();
    //    __NLPrint( CeLK81 );
    #endregion Debug Print
    }
    private void _WeakLinkSearch( ){
        for( int tfx=0; tfx<27; tfx++ ){
                for( int no=0; no<9; no++){
                int noB = 1<<no;
                List<UCell> PLst = pBDL.IEGetCellInHouse(tfx,noB).ToList();
                if( PLst.Count<=2 ) continue;

                bool SFlag=(PLst.Count==2);
                for( int n=0; n<PLst.Count-1; n++){
                    UCell UC1=PLst[n];
                    for( int m=n+1; m<PLst.Count; m++ ){
                        UCell UC2=PLst[m];
                        SetLinkList(tfx,2,no,UC1,UC2,SFlag);
                        SetLinkList(tfx,2,no,UC2,UC1,SFlag);
                    }
                }
            }
        }
    #region Debug Print
    //    foreach( var P81 in CeLK81.Where(p=>p!=null) ) P81.Sort();
    //    __NLPrint( CeLK81 );
    #endregion Debug Print
    }
    private void __NLPrint( List<UCellLink>[] CeLkLst ){
        Console.WriteLine();
        int nc=0;
        foreach( var P81 in CeLkLst.Where(p=>p!=null) ){
            foreach( var P in P81 ){
                int type = P.type;
                int no   =  P.no;
                int rc1  =  P.rc1;
                int rc2  = P.rc2;

                string st = "  No:" + (nc++).ToString().PadLeft(3);
                st += "  type:" + type + "  no:" + (no+1);
                if( type <= 2 ){
                    st += "  rc[" + rc1.ToString("00") + "]r" + ((rc1/9)+1);
                    st +=  "c" + ((rc1%9)+1) + "-b" + (rc1.ToBlock()+1);
                    st += " --> rc[" + rc2.ToString("00") + "]r" + ((rc2/9)+1);
                    st += "c" + ((rc2%9)+1) + "-b" + (rc2.ToBlock()+1);
                }
                else{
                    st += " " + ((rc1<10)? "r"+rc1: "c"+(rc1-10));
                    st += ((rc2<10)? "r"+rc2: "c"+(rc2-10));
                }
                Console.WriteLine(st);
            }
        }
        // Console.WriteLine( "Capacity:" + CellLinkList.Capacity );
    }

    public  void SetLinkList( int tfx, int type, int no, UCell UC1, UCell UC2, bool SFlag=false ){
        var LK =new UCellLink(tfx,type,no,UC1,UC2,SFlag);
        int rc1=UC1.rc;
        if( CeLK81[rc1]==null ) CeLK81[rc1]=new List<UCellLink>();
        if( !CeLK81[rc1].Contains(LK) )  CeLK81[rc1].Add(LK);
    }

    public bool ContainsLink( UCellLink LK ){
        List<UCellLink> P=CeLK81[LK.rc1];
        return (P!=null && P.Contains(LK));
    }
    public IEnumerable<UCellLink> IEGetCellInHouse( int typB ){
        foreach( var P in CeLK81.Where(p=>p!=null) ){
            foreach( var Q in P.Where(q=>((q.type&typB)>0)) ) yield return Q;
        }
    }
    public IEnumerable<UCellLink> IEGetNoType( int no, int typB ){
        foreach( var P in CeLK81.Where(p=>p!=null) ){
            foreach( var Q in P.Where(q=>((q.no==no)&&(q.type&typB)>0)) ) yield return Q;
        }
    }

    public IEnumerable<UCellLink> IEGetRcNoType( int rc, int no, int typB  ){
        var P=CeLK81[rc];
        if( P==null ) yield break;
        foreach( var LK in P.Where(p=> ((p.no==no)&&(p.type&typB)>0)) ){
            yield return LK;
        }
        yield break;
    }
    public IEnumerable<UCellLink> IEGet_CeCeSeq( UCellLink LKpre ){
        var P=CeLK81[LKpre.rc2];
        if( P==null ) yield break;
        foreach( var LKnxt in P ){
            if( Check_CellCellSequence(LKpre,LKnxt) ) yield return LKnxt;
        }
        yield break;
    }
    public IEnumerable<UCellLink> IEGetRcNoBTypB( int rc, int noB, int typB ){
        var P=CeLK81[rc];
        if( P==null ) yield break;
        foreach( var LK in P ){
            if( ((1<<LK.no)&noB)>0 && ((LK.type&typB)>0) ) yield return LK;
        }
        yield break;
    }

    public bool Check_CellCellSequence( UCellLink LKpre, UCellLink LKnxt ){ 
        int noP=LKpre.no, noN=LKnxt.no;
        UCell UCX=LKpre.UCe2;
        switch(LKpre.type){
            case 1:
                switch(LKnxt.type){
                    case 1: return (noP!=noN);  //S->S
                    case 2: return (noP==noN);  //S->W
                }
                break;
            case 2:
                switch(LKnxt.type){
                    case 1: return (noP==noN);  //W->S
                    case 2: return ((noP!=noN)&&(UCX.FreeBC==2)); //W->W
                }
                break;
        }
        return false;
    }
}


(3)関係セルの参照(ConnectedCells)

1つのセルから関係する全セルを参照する方法(Bit81[]型の変数 ConnectedCells)を導入します。 着目セルから見た影響圏や、2つのセル間に共通のHouseがないことの確認などに使います。 ConnectedCellsはクラスBit81型の配列で、要素は他のBit81型変数と集合演算ができます。この配列は様々な解析アルゴリズムで用います。 これらは、解析アルゴリズムの基本クラスの静的関数として定義します。

ConnectedCells

public partial class AnalyzerBaseV2{
    static public Bit81[] ConnectedCells;    //軸セル(rc)に関連するセル
    static public Bit81[] ConnectedCellsRev; //軸セル(rc)に関連しないセル(廃止予定)
    static public Bit81[] HouseCells;        //行列ブロック(0-26)の関連セル
        
    static  AnalyzerBaseV2( ){
        SetConnectedCells(); //関連性フィルター作成
    }
    
    static private void SetConnectedCells(){
        if( ConnectedCells!=null )  return;
        ConnectedCells    = new Bit81[81];
        ConnectedCellsRev = new Bit81[81];

        for( int rc=0; rc<81; rc++ ){
            Bit81 BS = new Bit81();
            foreach( var q in __IEGetCellsConnectedRC(rc) ) BS.BPSet(q);
            BS.BPReset(rc);
            ConnectedCells[rc]    = BS;
            ConnectedCellsRev[rc] = BS ^ 0x7FFFFFF;
        }

        HouseCells = new Bit81[27];
        for( int tfx=0; tfx<27; tfx++ ){
            Bit81 tmp=new Bit81();
            foreach( var q in __IEGetCellInHouse(tfx) ) tmp.BPSet(q);
            HouseCells[tfx] = tmp;
        }
    }
    static private IEnumerable<int> __IEGetCellsConnectedRC( int rc ){
        int r=0, c=0;
        for( int kx=0; kx<27; kx++ ){
            switch(kx/9){
                case 0: r=rc/9; c=kx%9; break; //行
                case 1: r=kx%9; c=rc%9; break; //列
                case 2: int b=rc/27*3+(rc%9)/3; r=(b/3)*3+(kx%9)/3; c=(b%3)*3+kx%3; break;//ブロック
            }
            yield return r*9+c;
        }
    }
    static private IEnumerable<int> __IEGetCellInHouse( int tfx ){ //nx=0...8
        int r=0, c=0, tp=tfx/9, fx=tfx%9;
        for( int nx=0; nx<9; nx++ ){
            switch(tp){
                case 0: r=fx; c=nx; break;//行
                case 1: r=nx; c=fx; break;//列
                case 2: r=(fx/3)*3+nx/3; c=(fx%3)*3+nx%3; break;//ブロック
            }
            yield return (r*9+c);
        }
    }
}


Top