2010-06-10 12 views
5

Chciałbym zwrócić większą uwagę na zajęcia matematyczne z powrotem w Uni. :)Rozwiązywanie nagich trików w Sudoku

Jak zaimplementować tę formułę matematyczną dla nagich trójek?

nagie Potrójne
trzy małe komórki C = {C1, C2, C3, że udział} jednostkę U. trzy małe liczby N = {N1, N2, N3}. Jeśli każda komórka w C ma jako kandydatów ci ⊆ N, możemy usunąć wszystkie inne komórki w U. **

Mam metodę, która przyjmuje jednostkę (np. Pole, wiersz lub kolumna) jako parametr. Jednostka zawiera 9 komórek, dlatego muszę porównać wszystkie kombinacje 3 komórek w tym samym czasie, co z pudełka, być może umieścić je w stosie lub zbiorze do dalszych obliczeń.

Kolejnym krokiem byłoby połączenie tych trzech kombinacji komórek pojedynczo i porównanie ich kandydatów z 3 liczbami. Znowu te 3 numery mogą być dowolną kombinacją od 1 do 9. To wszystko, czego potrzebuję.

Ale jak to zrobić? Ile kombinacji otrzymam? Czy otrzymam 3 x 9 = 27 kombinacji dla komórek, a następnie to samo dla liczb (N)?

Jak rozwiązać ten problem w klasycznych pętlach C#? Nie wyrażenia Lambda proszę jestem już dość zdezorientowany :)

Kod: Musiałem przerwać zajęcia w celu ich reprezentowania tutaj.

public class Cell : INotifyPropertyChanged 
    { 

public ObservableCollection<ObservableCollection<Candidate>> CandidateActual {...} 

public int Id { ... } 

//Position of the Cell inside a box if applicable 
public int CellBoxPositionX { get; private set; } 
public int CellBoxPositionY { get; private set; } 

//Position of the Cell inside the game board 
public int CellBoardPositionX { get; private set; } 
public int CellBoardPositionY { get; private set; } 

//Position of the Box inside the game board 
public int BoxPositionX { get; private set; } 
public int BoxPositionY { get; private set; } 

public int CountCandidates { ... }  
public int? Value { ...} 

public Candidate this[int number] 
     { 
      get 
      { 
       if (number < 1 || number > PossibleValues.Count) 
       { 
        throw new ArgumentOutOfRangeException("number", number, "Invalid Number Index"); 
       } 

       switch (number) 
       { 
        case 1: 
         return CandidateActual[0][0]; 
        case 2: 
         return CandidateActual[0][1]; 
        case 3: 
         return CandidateActual[0][2]; 
        case 4: 
         return CandidateActual[1][0]; 
        case 5: 
         return CandidateActual[1][1]; 
        case 6: 
         return CandidateActual[1][2]; 
        case 7: 
         return CandidateActual[2][0]; 
        case 8: 
         return CandidateActual[2][1]; 
        case 9: 
         return CandidateActual[2][2]; 
        default: 
         return null; 
       } 
      } 
     } 
} 

Kandydat

public class Candidate : INotifyPropertyChanged 
    { 

     private int? _value; 

     public int? Value { ... } 

    } 

Box:

public class Box : INotifyPropertyChanged 
    { 

public ObservableCollection<ObservableCollection<Cell>> BoxActual { ... } 

public Cell this[int row, int column] 
     { 
      get 
      { 
       if(row < 0 || row >= BoxActual.Count) 
       { 
        throw new ArgumentOutOfRangeException("row", row, "Invalid Row Index"); 
       } 
       if(column < 0 || column >= BoxActual.Count) 
       { 
        throw new ArgumentOutOfRangeException("column", column, "Invalid Column Index"); 
       } 
       return BoxActual[row][column]; 
      } 
     } 
} 

Board

public class Board : INotifyPropertyChanged 
    { 

public ObservableCollection<ObservableCollection<Box>> GameBoard {...} 

public Cell this[int boardRowPosition, int boardColumnPosition] 
     { 
      get 
      { 
       int totalSize = GameBoard.Count*GameBoard.Count(); 
       if (boardRowPosition < 0 || boardRowPosition >= totalSize) 
        throw new ArgumentOutOfRangeException("boardRowPosition", boardRowPosition, "Invalid boardRowPosition index"); 
       if (boardColumnPosition < 0 || boardColumnPosition >= totalSize) 
        throw new ArgumentOutOfRangeException("boardColumnPosition", boardColumnPosition, "Invalid boardColumnPosition index"); 
       return 
        GameBoard[boardRowPosition/GameBoard.Count][boardColumnPosition/GameBoard.Count][ 
         boardRowPosition%GameBoard.Count, boardColumnPosition%GameBoard.Count]; 
      } 
     } 



     public Box this[int boardRowPosition, int boardColumnPosition, bool b] 
     { 
      get 
      { 
       int totalSize = GameBoard.Count * GameBoard.Count(); 
       if (boardRowPosition < 0 || boardRowPosition >= totalSize) 
        throw new ArgumentOutOfRangeException("boardRowPosition", boardRowPosition, "Invalid boardRowPosition index"); 
       if (boardColumnPosition < 0 || boardColumnPosition >= totalSize) 
        throw new ArgumentOutOfRangeException("boardColumnPosition", boardColumnPosition, "Invalid boardColumnPosition index"); 
       return 
        GameBoard[boardRowPosition/GameBoard.Count][boardColumnPosition/GameBoard.Count]; 
      } 
     } 
} 

Wielkie dzięki za pomoc,

+1

Twoje pytanie jest niepełne. Musimy dowiedzieć się więcej o istniejącym kodzie (tj. O definicji klasy dla jednostki i komórki oraz o tym, jak kandydaci są obsługiwani itd.). W przeciwnym razie jest to logiczna łamigłówka, a właściwie nie jest to pytanie programistyczne. –

+0

Pewnie Joel. Mam nadzieję, że mój fragment kodu pomaga. Dzięki – Houman

+0

hehe ahhhh cóż, programowanie będzie wyzwaniem, o) – Houman

Odpowiedz

1

Algorytm Psuedo; moje C jest trochę zardzewiałe.

Polecam znalezienie wszystkich możliwych kombinacji trzech liczb z wartości kandydujących. Może istnieć od 6 do 504 kombinacji, w zależności od tego, ilu kandydatów posiadasz (podane przez n!/(3! * (N-3)!)).

Dla każdej z nich przejdź przez wszystkie komórki w jednostce i sprawdź, czy pasują do warunku, że nie mają żadnych liczb, które nie znajdują się w Twojej kombinacji. Jeśli określona kombinacja ma trzy lub więcej, możesz ją zastosować.

combos = (array containing 3-long combination of candidates) 
for each combo in combos     # iterate through every combo 
    matches = new array     # initialize a blank array 
    for each cell in unit 
    if (cell does not contain candidates other than the ones in your current combo) 
     matches.add(cell)     # this is a match! 
    end 
    end 

    if matches.size >= 3     # naked triple found! (three matches for given combo) 
    for each cell in unit 
     if (cell is not in matches) 
     (delete every candidate in current combo in this cell) 
     end 
    end 
    end 
    delete matches       # clear up memory 
end 

Mam nadzieję, że to pomoże! Będę C-ify ten kod, jeśli potrzebujesz; W każdym razie zamierzałem odświeżyć moje C.

Ponadto, jeśli jeszcze tego nie wiesz, istnieje znacznie prostszy sposób rozwiązywania zagadek sudoku z użyciem komputerów, które nie wymagają ręcznego programowania w żadnej logice. Ale myślę, że sposób, w jaki próbujesz to zrobić, jest całkiem szlachetny.


Generowanie tablicę wszystkich możliwych posunięć

Istnieje wiele sposobów, aby to zrobić, i nie może być najlepszy; Nie zrobiłem sam tego poważnego badania. Polecam google: combination algorithm ... Sam znalazłem one solution in C.

Pamiętaj, aby dołączyć czek, aby upewnić się, że liczba kandydatów jest odpowiednia. W przypadku n = 3 istnieje tylko jedna możliwa kombinacja kandydatów, a Twój algorytm powinien ją znaleźć. Dla n = 1 i n = 2, Nagie Trójki nawet się nie odnoszą.

+0

Dziękuję bardzo za ten znakomity kod pseudo. Ma sens i pomógł mi zrozumieć. Szczególnie użycie Factorial jest świetne. Nadal mam problemy, aby zrozumieć ten krok: combos = (tablica zawierająca 3-długą kombinację kandydatów) Nie znam jeszcze skutecznego sposobu, aby to zrobić. Czy możesz rozwinąć nieco więcej na ten temat? Wielkie dzięki – Houman

+0

Odnośnie tego c!/(C-3) !, czy ma to zastosowanie do wszystkich możliwych kandydatów w ramach Jednostki, prawda? Ale co to jest c w tym przypadku? Największa liczba kandydatów? Nie rozumiem tego ... – Houman

+0

c!/(C-3)! jest * liczbą * możliwych kombinacji kandydatów, biorąc pod uwagę n możliwych kandydatów. Tak więc, przy 6 możliwych kandydatach, masz 6!/3! = 120. Zauważ, że znacznie skuteczniejszym sposobem obliczenia tego byłoby n * (n-1) * (n-2), co jest równoważne i tańsze. Będę edytować mój post, aby uwzględnić jedną z wielu metod generowania tablicy combosów, ponieważ trudno byłoby sformatować ją w tym polu. –