Example #1
0
 /// <summary>Add a row to the table.</summary>
 /// <param name="values">the columns that are satisfied by this row</param>
 public virtual void AddRow(bool[] values)
 {
     DancingLinks.Node <ColumnName> prev = null;
     for (int i = 0; i < values.Length; ++i)
     {
         if (values[i])
         {
             DancingLinks.ColumnHeader <ColumnName> top = columns[i];
             top.size += 1;
             DancingLinks.Node <ColumnName> bottom = top.up;
             DancingLinks.Node <ColumnName> node   = new DancingLinks.Node <ColumnName>(null, null
                                                                                        , bottom, top, top);
             bottom.down = node;
             top.up      = node;
             if (prev != null)
             {
                 DancingLinks.Node <ColumnName> front = prev.right;
                 node.left  = prev;
                 node.right = front;
                 prev.right = node;
                 front.left = node;
             }
             else
             {
                 node.left  = node;
                 node.right = node;
             }
             prev = node;
         }
     }
 }
Example #2
0
 /// <summary>Make one move from a prefix</summary>
 /// <param name="goalRow">the row that should be choosen</param>
 /// <returns>the row that was found</returns>
 private DancingLinks.Node <ColumnName> Advance(int goalRow)
 {
     DancingLinks.ColumnHeader <ColumnName> col = FindBestColumn();
     if (col.size > 0)
     {
         CoverColumn(col);
         DancingLinks.Node <ColumnName> row = col.down;
         int id = 0;
         while (row != col)
         {
             if (id == goalRow)
             {
                 DancingLinks.Node <ColumnName> node = row.right;
                 while (node != row)
                 {
                     CoverColumn(node.head);
                     node = node.right;
                 }
                 return(row);
             }
             id += 1;
             row = row.down;
         }
     }
     return(null);
 }
Example #3
0
 public DancingLinks()
 {
     head       = new DancingLinks.ColumnHeader <ColumnName>(null, 0);
     head.left  = head;
     head.right = head;
     head.up    = head;
     head.down  = head;
     columns    = new AList <DancingLinks.ColumnHeader <ColumnName> >(200);
 }
Example #4
0
 internal Node(DancingLinks.Node <ColumnName> l, DancingLinks.Node <ColumnName> r, DancingLinks.Node
               <ColumnName> u, DancingLinks.Node <ColumnName> d, DancingLinks.ColumnHeader <ColumnName
                                                                                            > h)
 {
     left  = l;
     right = r;
     up    = u;
     down  = d;
     head  = h;
 }
Example #5
0
        /// <summary>Find a solution to the problem.</summary>
        /// <param name="partial">
        /// a temporary datastructure to keep the current partial
        /// answer in
        /// </param>
        /// <param name="output">the acceptor for the results that are found</param>
        /// <returns>the number of solutions found</returns>
        private int Search(IList <DancingLinks.Node <ColumnName> > partial, DancingLinks.SolutionAcceptor
                           <ColumnName> output)
        {
            int results = 0;

            if (head.right == head)
            {
                IList <IList <ColumnName> > result = new AList <IList <ColumnName> >(partial.Count);
                foreach (DancingLinks.Node <ColumnName> row in partial)
                {
                    result.AddItem(GetRowName(row));
                }
                output.Solution(result);
                results += 1;
            }
            else
            {
                DancingLinks.ColumnHeader <ColumnName> col = FindBestColumn();
                if (col.size > 0)
                {
                    CoverColumn(col);
                    DancingLinks.Node <ColumnName> row = col.down;
                    while (row != col)
                    {
                        partial.AddItem(row);
                        DancingLinks.Node <ColumnName> node = row.right;
                        while (node != row)
                        {
                            CoverColumn(node.head);
                            node = node.right;
                        }
                        results += Search(partial, output);
                        partial.Remove(partial.Count - 1);
                        node = row.left;
                        while (node != row)
                        {
                            UncoverColumn(node.head);
                            node = node.left;
                        }
                        row = row.down;
                    }
                    UncoverColumn(col);
                }
            }
            return(results);
        }
Example #6
0
        /// <summary>Find the column with the fewest choices.</summary>
        /// <returns>The column header</returns>
        private DancingLinks.ColumnHeader <ColumnName> FindBestColumn()
        {
            int lowSize = int.MaxValue;

            DancingLinks.ColumnHeader <ColumnName> result  = null;
            DancingLinks.ColumnHeader <ColumnName> current = (DancingLinks.ColumnHeader <ColumnName
                                                                                         >)head.right;
            while (current != head)
            {
                if (current.size < lowSize)
                {
                    lowSize = current.size;
                    result  = current;
                }
                current = (DancingLinks.ColumnHeader <ColumnName>)current.right;
            }
            return(result);
        }
Example #7
0
 /// <summary>Uncover a column that was hidden.</summary>
 /// <param name="col">the column to unhide</param>
 private void UncoverColumn(DancingLinks.ColumnHeader <ColumnName> col)
 {
     Log.Debug("uncover " + col.head.name);
     DancingLinks.Node <ColumnName> row = col.up;
     while (row != col)
     {
         DancingLinks.Node <ColumnName> node = row.left;
         while (node != row)
         {
             node.head.size += 1;
             node.down.up    = node;
             node.up.down    = node;
             node            = node.left;
         }
         row = row.up;
     }
     col.right.left = col;
     col.left.right = col;
 }
Example #8
0
 /// <summary>Hide a column in the table</summary>
 /// <param name="col">the column to hide</param>
 private void CoverColumn(DancingLinks.ColumnHeader <ColumnName> col)
 {
     Log.Debug("cover " + col.head.name);
     // remove the column
     col.right.left = col.left;
     col.left.right = col.right;
     DancingLinks.Node <ColumnName> row = col.down;
     while (row != col)
     {
         DancingLinks.Node <ColumnName> node = row.right;
         while (node != row)
         {
             node.down.up    = node.up;
             node.up.down    = node.down;
             node.head.size -= 1;
             node            = node.right;
         }
         row = row.down;
     }
 }
Example #9
0
 /// <summary>Add a column to the table</summary>
 /// <param name="name">
 /// The name of the column, which will be returned as part of
 /// solutions
 /// </param>
 /// <param name="primary">Is the column required for a solution?</param>
 public virtual void AddColumn(ColumnName name, bool primary)
 {
     DancingLinks.ColumnHeader <ColumnName> top = new DancingLinks.ColumnHeader <ColumnName
                                                                                 >(name, 0);
     top.up   = top;
     top.down = top;
     if (primary)
     {
         DancingLinks.Node <ColumnName> tail = head.left;
         tail.right = top;
         top.left   = tail;
         top.right  = head;
         head.left  = top;
     }
     else
     {
         top.left  = top;
         top.right = top;
     }
     columns.AddItem(top);
 }
Example #10
0
 /// <summary>Generate a list of prefixes down to a given depth.</summary>
 /// <remarks>
 /// Generate a list of prefixes down to a given depth. Assumes that the
 /// problem is always deeper than depth.
 /// </remarks>
 /// <param name="depth">the depth to explore down</param>
 /// <param name="choices">an array of length depth to describe a prefix</param>
 /// <param name="prefixes">a working datastructure</param>
 private void SearchPrefixes(int depth, int[] choices, IList <int[]> prefixes)
 {
     if (depth == 0)
     {
         prefixes.AddItem(choices.MemberwiseClone());
     }
     else
     {
         DancingLinks.ColumnHeader <ColumnName> col = FindBestColumn();
         if (col.size > 0)
         {
             CoverColumn(col);
             DancingLinks.Node <ColumnName> row = col.down;
             int rowId = 0;
             while (row != col)
             {
                 DancingLinks.Node <ColumnName> node = row.right;
                 while (node != row)
                 {
                     CoverColumn(node.head);
                     node = node.right;
                 }
                 choices[choices.Length - depth] = rowId;
                 SearchPrefixes(depth - 1, choices, prefixes);
                 node = row.left;
                 while (node != row)
                 {
                     UncoverColumn(node.head);
                     node = node.left;
                 }
                 row    = row.down;
                 rowId += 1;
             }
             UncoverColumn(col);
         }
     }
 }