Skyscraper

Skyscraperの説明には、セル間リンクと、関係セルの参照を用います。
Skyscraperは、LockedSet、Fishと同様にパターン型の解法で、2つの強いリンクで構成されます。 左図のように着目数字Xの2つの強いリンクがあり、4つある端セルのうち1組のみ同じHouseに属しているとします。 このとき残りの端セルと同時に関係するセル(右図の△セル)は、Lockedにより候補数字からXが除外されます。
Skyscraper

Skyscraperの解析アルゴリズムも、この図の手順とおりです。

  1. 着目数字Xの設定
  2. 2組のリンクの選択
  3. リンクの条件チェック(リンク端点の1対のみ同じHouse)
  4. 除外候補セル探索
Skyscraperは比較的やさしい解析手法で、ヒトがプレイする場合でも見つけ易いでしょう。同じ場面にいくつものSkyscraperが見つかることもあります。 次のSkyscraperの上段・下段は、それぞれ同じ場面にある3つのSkyscraperです。
Skyscraper Skyscraper Skyscraper Skyscraper Skyscraper Skyscraper

.5.....9.3...2...5..2...68.....65....8.7..4.9...9.1.5...6.5..322.5..49...7..9.5.6(上段)
56...........23.4.9.....18.6....14...592.486...16....3.36.....9.7.36...........34(下段)

Skyscraperの解析プログラム

Skyscraperの解析プログラムの処理手順は、以下のとおりです。

  1. 着目数字Xの設定

  2. 2組のリンクの選択
    2組のリンクの選択は組合せで選んでいます。リンクは方向を持つように生成します。 それらのリンク群から2組選んだとき(リンクIDが降順に選ぶ)、それらの端点セルが全て異なることを確認します。 次に、起点側セル同士に着目して、同じhouseに属するかをチェックします(ここでは起点としましたが、終点でもかまいません)。 もしも、リンクを方向なしで生成し組合せで2組を選ぶと、リンクの両端の比較が複雑になります。ここで採用した方法の方が単純に処理できます。

  3. 残りのリンク端点セルのhouse比較
    先頭同士以外の端点に共通houseがないことを確認します。これは3組(先頭-終点、終点-先頭、終点-終点)を単純に比較します。

  4. Lockedセルの探索
    2つの終点セルの影響圏の共通部分にあり、かつ 2つの始点セルの影響圏にないセルについて、候補数字Xの有無をチェックします。 あれば、Skyscraperが成立します。

public partial class CellLinkGen: AnalyzerBaseV2{
    public CellLinkMan  CeLKMan;
    public List<UCell>  BVCellLst; //BV:bivalue

    public CellLinkGen( GNPX_AnalyzerMan pAnMan ): base(pAnMan){
        CeLKMan=new CellLinkMan(pAnMan);
        BVCellLst=null;
    }

    public override void Initialize(){
        CeLKMan.Initialize();
        BVCellLst=null;
    }

    public bool Skyscraper(){ //StrongLinkを使う方法
        CeLKMan.PrepareCellLink(1);    //strongLink生成

        for( int no=0; no<9; no++ ){
            int noB=(1<<no);
            var SSLst = CeLKMan.IEGetNoType(no,1).ToList();
            if( SSLst.Count<=2 ) continue;

            var prm=new Permutation(SSLst.Count,2);
            int nxtX=99;
            while( prm.Successor(nxtX) ){
                UCellLink UCLa=SSLst[prm.Pnum[0]], UCLb=SSLst[prm.Pnum[1]];
                nxtX=0;
                if( UCLa.ID<UCLb.ID ) continue; //2リンクはID降順
                nxtX=1;
                if( (UCLa.B81|UCLb.B81).Count!=4 )  continue;
                //全てセルは異なる

                Bit81 ConA1=ConnectedCells[UCLa.rc1], ConA2=ConnectedCells[UCLa.rc2];
                if( !ConA1.IsHit(UCLb.rc1) || ConA1.IsHit(UCLb.rc2) ) continue;
                if(  ConA2.IsHit(UCLb.rc1) || ConA2.IsHit(UCLb.rc2) ) continue;
                //(UCLa.rc1)(UCLb.rc1)のみ同じハウスに属している

                Bit81 candHit = ConA2 & ConnectedCells[UCLb.rc2];
                candHit = candHit - (ConA1 | ConnectedCells[UCLb.rc1]);

                bool SSfond=false;
                foreach( UCell P in candHit.IEGetUCeNoB(pBDL,noB) ){
                    P.CancelB = P.FreeB&noB;
                    SSfond=true;
                }

                if(SSfond) {
            #region 結果
                    SolCode =2;
                    pBDL[UCLa.rc1].SetNoBBgColor(noB,AttCr,SolBkCr);
                    pBDL[UCLa.rc2].SetNoBBgColor(noB,AttCr,SolBkCr);
                    pBDL[UCLb.rc1].SetNoBBgColor(noB,AttCr,SolBkCr);
                    pBDL[UCLb.rc2].SetNoBBgColor(noB,AttCr,SolBkCr);

                    string msg2="";
                    if(SolInfoDsp){
                        string msg = "\r";
                        msg += "  on " + (no+1) + " in";
                        msg += " r" + (UCLa.rc1/9+1) + "c" + (UCLa.rc1%9+1);
                        msg += " r" + (UCLb.rc1/9+1) + "c" + (UCLb.rc1%9+1);
                        msg += "\r  connected by";
                        msg += " r" + (UCLa.rc2/9+1) + "c" + (UCLa.rc2%9+1);
                        msg += " r" + (UCLb.rc2/9+1) + "c" + (UCLb.rc2%9+1);
                        msg += "\r  eliminated ";

                        foreach( UCell P in candHit.IEGetUCeNoB(pBDL,noB) ){
                            msg2 += " "+P.rc.ToRCString();
                        }

                        msg2=msg2.ToString_SameHouseComp();
                        ResultLong = "Skyscraper" + msg+msg2;
                        Result = "Skyscraper #"+(no+1) +" in "+msg2;
                    }
                    else Result = "Skyscraper #"+(no+1);
            #endregion 結果
                    if( !AnMan.SnapSaveGP(true) )  return true;
                }
            }
        }
        return false;
    }
}


Top