4
\$\begingroup\$

WiKi and GitHub.

Sudoku rules are being checked with the following tests:

    [TestMethod]
    public void Be_Valid()
    {
        var data = new int?[,]
        {
            { 5, 3, null },
            { 6, null, null },
            { null, 9, 8 }
        };

        var board = new Board(data);
        Assert.IsTrue(board.Valid);
    }

And:

    [TestMethod]
    public void Be_Invalid()
    {
        var data = new int?[,]
        {
            { 5, 3, 8 },
            { 6, null, null },
            { null, 9, 8 }
        };

        var board = new Board(data);
        Assert.IsFalse(board.Valid);
    }

Where actual implementation looks like:

public class Board
{
    public Board(int?[,] cells)
    {
        Cells = cells ?? throw new ArgumentNullException(nameof(cells));
        if(Cells.GetLength(0) != Cells.GetLength(1))
            throw new ArgumentNullException(nameof(cells), "Square board required.");
        if (Cells.GetLength(0) % 3 != 0)
            throw new ArgumentNullException(nameof(cells), "Board size should be multiple of 3.");
    }

    int? [,] Cells { get; }
    int N => Cells.GetLength(0);

    public bool Valid => ColumnsValid && RowsValid && GridsValid;

    bool RowsValid => Rows.All(AreUnique);
    bool ColumnsValid => Columns.All(AreUnique);
    bool GridsValid => Grids.All(AreUnique);

    IEnumerable<IEnumerable<int>> Rows => 
        Range(0, N).Select(r => Numbers(0, N - 1, r, r));
    IEnumerable<IEnumerable<int>> Columns => 
        Range(0, N).Select(c => Numbers(c, c, 0, N - 1));
    IEnumerable<IEnumerable<int>> Grids => 
        from r in Range(0, N / 3)
        from c in Range(0, N / 3)
        select Numbers(
            c * 3, c * 3 + 2, r * 3, r * 3 + 2);

    bool AreUnique(IEnumerable<int> numbers) =>
        numbers.Distinct().Count() == numbers.Count();

    IEnumerable<int> Numbers(int left, int right, int top, int bottom) =>
        from r in Range(top, bottom - top + 1)
        from c in Range(left, right - left + 1)
        where Cells[r, c].HasValue
        select Cells[r, c].Value;
}
\$\endgroup\$
  • \$\begingroup\$ Where does Range come from? Did you mean Enumerable.Range? \$\endgroup\$ – tinstaafl Nov 8 at 4:05
  • 1
    \$\begingroup\$ @tinstaafl yes, exactly. You could see all the code by clicking the github link on above. \$\endgroup\$ – Dmitry Nogin Nov 8 at 4:08
  • \$\begingroup\$ @DmitryNogin: Please post all relevant code, don't hide it behind a link. Links can decay, potentially rendering the question unintelligible for posterity's sake. \$\endgroup\$ – Flater Nov 8 at 10:19
  • \$\begingroup\$ Without correct compilable code being shown in your post,not referenced through a link, your post is off topic. \$\endgroup\$ – tinstaafl Nov 8 at 12:05
  • \$\begingroup\$ @tinstaafl @Flater It is correct and compilable. And no one ever being posting required using directives here. I bet you need to declare off topic all the C# related content. I wish you a good luck in that :) \$\endgroup\$ – Dmitry Nogin Nov 8 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.