Sudoku Algorithm 4

Remote Pair

RemotePair is an analysis algorithm that connects bivalue cells with a strong link.
As shown in the following figure, bivalue cells (candidate numbers are xy) are linked by a strong link. In the figure, the cells are displayed in two groups. There are two cells(□ and ○) with an even number of distances, and the cell(▲) connected with these by weak links can not be either x or y.

Remote Pair Remote Pair

An example of Remote Pair

Remote Pair Remote Pair

.3..9.68...9.64..2..7..8.5.84.6.9....26...41....2.1.96.9.4..1..6..81.5...14.5..6.
2..8..1...8.4..6.3...2968...1..3.2.43.......69.5.8..3...1324...6.2..8.1...8..1..2

RemotePair program

It shows the basic structure of spreading search used in some analysis algorithms. The basic technique is queue.

It can also be constructed by a recursive method. However, recursion has overhead of calling and returning, and the method of developing recursion is advantageous.


public bool RemotePair( ){     //RemotePairs
    Prepare(); 
    if( BVCellLst==null )  BVCellLst = pBDL.FindAll(p=>(p.FreeBC==2)); //BV:bivalue
    if( BVCellLst.Count<3 ) return false;  

    foreach( var (CRL,FreeB) in _RPColoring()){
        bool RPFound=false;
        foreach( var P in pBDL.Where(p=>(p.FreeB&FreeB)>0) ){
            if( (CRL[0]&ConnectedCells[P.rc]).IsZero() )  continue;
            if( (CRL[1]&ConnectedCells[P.rc]).IsZero() )  continue;                  
            P.CancelB = P.FreeB&FreeB; RPFound=true;
        }

        if(RPFound){ //=== found ===
            SolCode = 2;
            string SolMsg="Remote Pair #"+FreeB.ToBitStringN(9);
            Result=SolMsg;
            if(!SolInfoB) return true;
            ResultLong = SolMsg;

            //*** Solution screen display ***
            // ...

            RPFound = false;
        }
    }
    return false;
}

RemotePair / Generation function


private IEnumerable<(Bit81[],int)> _RPColoring( ){
    if( BVCellLst.Count<4 )  yield break;
    
    // --- coloring with bivalue cells ---
    Bit81 BivalueB = new Bit81(BVCellLst); 
        
    Bit81 usedB = new Bit81();
    var QueTupl = new Queue<(int,int)>();

    Bit81[] CRL=new Bit81[2]; 
    CRL[0]=new Bit81(); CRL[1]=new Bit81(); 
    int  rc0;
    while( (rc0=BivalueB.FindFirst_rc())>=0 ){              //Start searching from rc0
        BivalueB.BPReset(rc0);

        CRL[0].Clear(); CRL[1].Clear();                     //Clear chain
        
        QueTupl.Clear();                                    //Queue(QueTupl) initialization
        QueTupl.Enqueue( (rc0,0) );
        
        int FreeB = pBDL[rc0].FreeB;
        usedB.Clear();
        while( QueTupl.Count>0 ){
            var (rc1,color1) = QueTupl.Dequeue();           //Get Current Cell
            usedB.BPSet(rc1);
            CRL[color1].BPSet(rc1);
            int color2 = 1-color1;                          //color inversion

            Bit81 Chain = BivalueB & ConnectedCells[rc1];
            foreach( var rc2 in Chain.IEGet_rc().Where(rc=> !usedB.IsHit(rc)) ){
                if( pBDL[rc2].FreeB!=FreeB ) continue;              
                QueTupl.Enqueue( (rc2,color2) );
                CRL[color2].BPSet(rc2);
            }
        }
        
        yield return (CRL,FreeB);
        BivalueB -= (CRL[0]|CRL[1]);
    }
    yield break;
}