Sudoku Algorithm 4

X-Wing(Fish)

Assume that the digit X is arranged as follows.
In column c0, the position of the digit X is one of the rows r01, and also in row c1, it is either row r01. At this time, the digit X can be excluded from candidate digits in cell r0cx(○). This is due to the fact that the four cells of r01c01 are Locked for the digit X.


X-Wing

X-Wing

In the BaseSet(solid line) column, one of the two cells X is true.
CoverSet(dashed line) completely includes BaseSet. CoverSet also contains cells(circles) in addition.
If the digit X at the position of a circle is true, it is not possible to place the digit X at the position of BaseSet.
The digit X at the position of the circle is excluded.(BaseSet, CoverSet described below)

X-Wing


X-Wing sample Focusing on the digit 4, the establishment of X-Wing of BaseSet(r57), CoverSet(c26).
The digit 4 is excluded from the cell of r47c2.

X-Wing sometimes uses another name, "Fish". Third and higher order fish also have names. For a more general description, we will all use fish below.

If only to solve a Sudoku, doesn't need Fish of the fifth or higher order. When Fish of 5th order or higher is established, Fish of 4th order or less is established at complementary position. Complementary Fish actually shown below.

In Fish of 3rd order or higher order, Fish is established even for a pattern where a part is missing as shown in the figure. This missing part may be a confirmed cell, or there may not be a focused digit just for that cell candidate.

SwordFish

Extensions to several methods are known for Fish based algorithms(treat them below). Define "BaseSet", "CoverSet" as preparation.

BseSet/CoverSet(no overlap)

In Fish based solution, use 2 sets of house. Focus on the digit X, select N houses containing up to N digits X (N is the order) and call this BaseSet. The BaseSet does not overlap.
And, choose another set of N House to completely include BaseSet . call this CoverSet. The common part of such BaseSet, CoverSet is in Locked. In House of BaseSet, although somewhere is not decided, one cell is always the digit X. The same is true for CoverSet. Check Locked with SwordFish(3rd order Fish) on the left. CoverSet completely contains BaseSet, but it may also contain cells other than BaseSet. As a solution, including other cells Z is meaningful. If the cell Z digit X is true, it breaks the BaseSet Locked. In other words, the digit X can be excluded from the candidate digit of cell Z.

To summarize, it will be as follows.

Nth Fish

Focus on the digit X. If N houses containing N or fewer X are selected(BaseSet) and N other houses(CoverSet) completely contain BaseSet, BaseSet is Locked. Candidate digit X in the position to break Locked can be excluded. It is assumed that there is no overlap between BaseSet and CoverSet.

he following figure is an example of SwordFish (3D-Fish) and JellyFish (4D-Fish). These are Complementary Fish of the same scene of the same problem. Excluded cells·Candidate digits are the same.

SwordFish #7
(3D-Fish)
BaseSet : c139
CoverSet : r169


JellyFIsh #7
(4D-Fish)
BaseSet : r2345
CoverSet : c2567


...6.8...6...9...529.....483.1...4.64..3.1..2...8.6....1.4.2.7..6.7.9.5.....8....


Fish program

The program solves the FISH using the general-purpose Fish subprogram(ExtFishSub). ExtFishSub can solve Basic Fish, Finned Fish, (with Fin)Franken/Mutant Fish.

public partial class FishGen: AnalyzerBaseV2{
    public FishGen( GNPX_AnalyzerMan AnMan ): base(AnMan){ }

    //Fish
    public bool XWing(){     return Fish_Basic(2); }
    public bool SwordFish(){ return Fish_Basic(3); }
    public bool JellyFish(){ return Fish_Basic(4); }
    public bool Squirmbag(){ return Fish_Basic(5); }
    public bool Whale(){     return Fish_Basic(6); }
    public bool Leviathan(){ return Fish_Basic(7); }

    public bool Fish_Basic( int sz, bool fin=false ){
        int rowSel=0x1FF, colSel=(0x1FF<<9);
        for( int no=0; no<9; no++ ){
            if( ExtFishSub(sz,no,18,rowSel,colSel,FinnedF:fin) ) return true;
            if( ExtFishSub(sz,no,18,colSel,rowSel,FinnedF:fin) ) return true;
        }
        return false;
    }

    public bool ExtFishSub( int sz, int no, int FMSize, int BaseSel, int CoverSel, bool FinnedF ){       
        int noB=(1<<no);
        var FMan=new FishMan(this,FMSize,no,sz);
        foreach( var Bas in FMan.IEGet_BaseSet(BaseSel) ){            //BaseSet
            foreach( var Cov in FMan.IEGet_CoverSet(Bas,CoverSel,FinnedF) ){  //CoverSet  
                Bit81 FinB81 = Cov.FinB81;

                Bit81 ELM =null;
                if( FinB81.IsZero() ){  //===== without Fin =====
                    if( !FinnedF && (ELM=Cov.CoverB81-Bas.BaseB81).Count>0 ){                      
                        foreach( var P in ELM.IEGetUCeNoB(pBDL,noB) ){ P.CancelB=noB; SolCode=2; }
                        if(SolCode>0){
                            .
                            . (Solution report code)
                            .
                            return true;
                        }
                    }
                }
                else if( FinnedF ){     //===== with Fin =====
                    Bit81 Ecand=Cov.CoverB81-Bas.BaseB81;
                    ELM=new Bit81();
                    foreach( var P in Ecand.IEGetUCeNoB(pBDL,noB) ){
                        if( (FinB81-ConnectedCells[P.rc]).Count==0 ) ELM.BPSet(P.rc);
                    }
                    if(ELM.Count>0){                           
                        .
                        . (Solution report code)
                        .
                        return true;
                    }
                }
                continue;
            }
        }
        return false;
    }
}