Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
103
Task/Sudoku/C-sharp/sudoku-1.cs
Normal file
103
Task/Sudoku/C-sharp/sudoku-1.cs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
using System;
|
||||
|
||||
class SudokuSolver
|
||||
{
|
||||
private int[] grid;
|
||||
|
||||
public SudokuSolver(String s)
|
||||
{
|
||||
grid = new int[81];
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
grid[i] = int.Parse(s[i].ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void solve()
|
||||
{
|
||||
try
|
||||
{
|
||||
placeNumber(0);
|
||||
Console.WriteLine("Unsolvable!");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
Console.WriteLine(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void placeNumber(int pos)
|
||||
{
|
||||
if (pos == 81)
|
||||
{
|
||||
throw new Exception("Finished!");
|
||||
}
|
||||
if (grid[pos] > 0)
|
||||
{
|
||||
placeNumber(pos + 1);
|
||||
return;
|
||||
}
|
||||
for (int n = 1; n <= 9; n++)
|
||||
{
|
||||
if (checkValidity(n, pos % 9, pos / 9))
|
||||
{
|
||||
grid[pos] = n;
|
||||
placeNumber(pos + 1);
|
||||
grid[pos] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool checkValidity(int val, int x, int y)
|
||||
{
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
if (grid[y * 9 + i] == val || grid[i * 9 + x] == val)
|
||||
return false;
|
||||
}
|
||||
int startX = (x / 3) * 3;
|
||||
int startY = (y / 3) * 3;
|
||||
for (int i = startY; i < startY + 3; i++)
|
||||
{
|
||||
for (int j = startX; j < startX + 3; j++)
|
||||
{
|
||||
if (grid[i * 9 + j] == val)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string sb = "";
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
for (int j = 0; j < 9; j++)
|
||||
{
|
||||
sb += (grid[i * 9 + j] + " ");
|
||||
if (j == 2 || j == 5)
|
||||
sb += ("| ");
|
||||
}
|
||||
sb += ('\n');
|
||||
if (i == 2 || i == 5)
|
||||
sb += ("------+-------+------\n");
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
new SudokuSolver("850002400" +
|
||||
"720000009" +
|
||||
"004000000" +
|
||||
"000107002" +
|
||||
"305000900" +
|
||||
"040000000" +
|
||||
"000080070" +
|
||||
"017000000" +
|
||||
"000036040").solve();
|
||||
Console.Read();
|
||||
}
|
||||
}
|
||||
77
Task/Sudoku/C-sharp/sudoku-2.cs
Normal file
77
Task/Sudoku/C-sharp/sudoku-2.cs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
using System.Linq;
|
||||
using static System.Linq.Enumerable;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace SodukoFastMemoBFS {
|
||||
internal readonly record struct Square (int Row, int Col);
|
||||
internal record Constraints (IEnumerable<int> ConstrainedRange, Square Square);
|
||||
internal class Cache : Dictionary<Square, Constraints> { };
|
||||
internal record CacheGrid (int[][] Grid, Cache Cache);
|
||||
|
||||
internal static class SudokuFastMemoBFS {
|
||||
internal static U Fwd<T, U>(this T data, Func<T, U> f) => f(data);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static int RowCol(int rc) => rc <= 2 ? 0 : rc <= 5 ? 3 : 6;
|
||||
|
||||
private static bool Solve(this CacheGrid cg, Constraints constraints, int finished) {
|
||||
var (row, col) = constraints.Square;
|
||||
foreach (var i in constraints.ConstrainedRange) {
|
||||
cg.Grid[row][col] = i;
|
||||
if (cg.Cache.Count == finished || cg.Solve(cg.Next(constraints.Square), finished))
|
||||
return true;
|
||||
}
|
||||
cg.Grid[row][col] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static readonly int[] domain = Range(0, 9).ToArray();
|
||||
private static readonly int[] range = Range(1, 9).ToArray();
|
||||
|
||||
private static bool Valid(this int[][] grid, int row, int col, int val) {
|
||||
for (var i = 0; i < 9; i++)
|
||||
if (grid[row][i] == val || grid[i][col] == val)
|
||||
return false;
|
||||
for (var r = RowCol(row); r < RowCol(row) + 3; r++)
|
||||
for (var c = RowCol(col); c < RowCol(col) + 3; c++)
|
||||
if (grid[r][c] == val)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static IEnumerable<int> Constraints(this int[][] grid, int row, int col) =>
|
||||
range.Where(val => grid.Valid(row, col, val));
|
||||
|
||||
private static Constraints Next(this CacheGrid cg, Square square) =>
|
||||
cg.Cache.ContainsKey(square)
|
||||
? cg.Cache[square]
|
||||
: cg.Cache[square]=cg.Grid.SortedCells();
|
||||
|
||||
private static Constraints SortedCells(this int[][] grid) =>
|
||||
(from row in domain
|
||||
from col in domain
|
||||
where grid[row][col] == 0
|
||||
let cell = new Constraints(grid.Constraints(row, col), new Square(row, col))
|
||||
orderby cell.ConstrainedRange.Count() ascending
|
||||
select cell).First();
|
||||
|
||||
private static CacheGrid Parse(string input) =>
|
||||
input
|
||||
.Select((c, i) => (index: i, val: int.Parse(c.ToString())))
|
||||
.GroupBy(id => id.index / 9)
|
||||
.Select(grp => grp.Select(id => id.val).ToArray())
|
||||
.ToArray()
|
||||
.Fwd(grid => new CacheGrid(grid, new Cache()));
|
||||
|
||||
public static string AsString(this int[][] grid) =>
|
||||
string.Join('\n', grid.Select(row => string.Concat(row)));
|
||||
|
||||
public static int[][] Run(string input) {
|
||||
var cg = Parse(input);
|
||||
var marked = cg.Grid.SelectMany(row => row.Where(c => c > 0)).Count();
|
||||
return cg.Solve(cg.Grid.SortedCells(), 80 - marked) ? cg.Grid : new int[][] { Array.Empty<int>() };
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Task/Sudoku/C-sharp/sudoku-3.cs
Normal file
36
Task/Sudoku/C-sharp/sudoku-3.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using System.Linq;
|
||||
using static System.Linq.Enumerable;
|
||||
using static System.Console;
|
||||
using System.IO;
|
||||
|
||||
namespace SodukoFastMemoBFS {
|
||||
static class Program {
|
||||
|
||||
static void Main(string[] args) {
|
||||
var num = int.Parse(args[0]);
|
||||
var puzzles = File.ReadLines(@"sudoku17.txt").Take(num);
|
||||
var single = puzzles.First();
|
||||
|
||||
var watch = new System.Diagnostics.Stopwatch();
|
||||
watch.Start();
|
||||
WriteLine(SudokuFastMemoBFS.Run(single).AsString());
|
||||
watch.Stop();
|
||||
WriteLine($"{single}: {watch.ElapsedMilliseconds} ms");
|
||||
|
||||
WriteLine($"Doing {num} puzzles");
|
||||
var total = 0.0;
|
||||
watch.Start();
|
||||
foreach (var puzzle in puzzles) {
|
||||
watch.Reset();
|
||||
watch.Start();
|
||||
SudokuFastMemoBFS.Run(puzzle);
|
||||
watch.Stop();
|
||||
total += watch.ElapsedMilliseconds;
|
||||
Write(".");
|
||||
}
|
||||
watch.Stop();
|
||||
WriteLine($"\nPuzzles:{num}, Total:{total} ms, Average:{total / num:0.00} ms");
|
||||
ReadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
73
Task/Sudoku/C-sharp/sudoku-4.cs
Normal file
73
Task/Sudoku/C-sharp/sudoku-4.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
using Microsoft.SolverFoundation.Solvers;
|
||||
|
||||
namespace Sudoku
|
||||
{
|
||||
class Program
|
||||
{
|
||||
private static int[,] B = new int[,] {{9,7,0, 3,0,0, 0,6,0},
|
||||
{0,6,0, 7,5,0, 0,0,0},
|
||||
{0,0,0, 0,0,8, 0,5,0},
|
||||
|
||||
{0,0,0, 0,0,0, 6,7,0},
|
||||
{0,0,0, 0,3,0, 0,0,0},
|
||||
{0,5,3, 9,0,0, 2,0,0},
|
||||
|
||||
{7,0,0, 0,2,5, 0,0,0},
|
||||
{0,0,2, 0,1,0, 0,0,8},
|
||||
{0,4,0, 0,0,7, 3,0,0}};
|
||||
|
||||
private static CspTerm[] GetSlice(CspTerm[][] sudoku, int Ra, int Rb, int Ca, int Cb)
|
||||
{
|
||||
CspTerm[] slice = new CspTerm[9];
|
||||
int i = 0;
|
||||
for (int row = Ra; row < Rb + 1; row++)
|
||||
for (int col = Ca; col < Cb + 1; col++)
|
||||
{
|
||||
{
|
||||
slice[i++] = sudoku[row][col];
|
||||
}
|
||||
}
|
||||
return slice;
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
ConstraintSystem S = ConstraintSystem.CreateSolver();
|
||||
CspDomain Z = S.CreateIntegerInterval(1, 9);
|
||||
CspTerm[][] sudoku = S.CreateVariableArray(Z, "cell", 9, 9);
|
||||
for (int row = 0; row < 9; row++)
|
||||
{
|
||||
for (int col = 0; col < 9; col++)
|
||||
{
|
||||
if (B[row, col] > 0)
|
||||
{
|
||||
S.AddConstraints(S.Equal(B[row, col], sudoku[row][col]));
|
||||
}
|
||||
}
|
||||
S.AddConstraints(S.Unequal(GetSlice(sudoku, row, row, 0, 8)));
|
||||
}
|
||||
for (int col = 0; col < 9; col++)
|
||||
{
|
||||
S.AddConstraints(S.Unequal(GetSlice(sudoku, 0, 8, col, col)));
|
||||
}
|
||||
for (int a = 0; a < 3; a++)
|
||||
{
|
||||
for (int b = 0; b < 3; b++)
|
||||
{
|
||||
S.AddConstraints(S.Unequal(GetSlice(sudoku, a * 3, a * 3 + 2, b * 3, b * 3 + 2)));
|
||||
}
|
||||
}
|
||||
ConstraintSolverSolution soln = S.Solve();
|
||||
object[] h = new object[9];
|
||||
for (int row = 0; row < 9; row++)
|
||||
{
|
||||
if ((row % 3) == 0) System.Console.WriteLine();
|
||||
for (int col = 0; col < 9; col++)
|
||||
{
|
||||
soln.TryGetValue(sudoku[row][col], out h [col]);
|
||||
}
|
||||
System.Console.WriteLine("{0}{1}{2} {3}{4}{5} {6}{7}{8}", h[0],h[1],h[2],h[3],h[4],h[5],h[6],h[7],h[8]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
279
Task/Sudoku/C-sharp/sudoku-5.cs
Normal file
279
Task/Sudoku/C-sharp/sudoku-5.cs
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using static System.Linq.Enumerable;
|
||||
|
||||
public class Sudoku
|
||||
{
|
||||
public static void Main2() {
|
||||
string puzzle = "....7.94.....9...53....5.7...74..1..463...........7.8.8........7......28.5.26....";
|
||||
string solution = new Sudoku().Solutions(puzzle).FirstOrDefault() ?? puzzle;
|
||||
Print(puzzle, solution);
|
||||
}
|
||||
|
||||
private DLX dlx;
|
||||
|
||||
public void Build() {
|
||||
const int rows = 9 * 9 * 9, columns = 4 * 9 * 9;
|
||||
dlx = new DLX(rows, columns);
|
||||
for (int i = 0; i < columns; i++) dlx.AddHeader();
|
||||
|
||||
for (int cell = 0, row = 0; row < 9; row++) {
|
||||
for (int column = 0; column < 9; column++) {
|
||||
int box = row / 3 * 3 + column / 3;
|
||||
for (int digit = 0; digit < 9; digit++) {
|
||||
dlx.AddRow(cell, 81 + row * 9 + digit, 2 * 81 + column * 9 + digit, 3 * 81 + box * 9 + digit);
|
||||
}
|
||||
cell++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> Solutions(string puzzle) {
|
||||
if (puzzle == null) throw new ArgumentNullException(nameof(puzzle));
|
||||
if (puzzle.Length != 81) throw new ArgumentException("The input is not of the correct length.");
|
||||
if (dlx == null) Build();
|
||||
|
||||
for (int i = 0; i < puzzle.Length; i++) {
|
||||
if (puzzle[i] == '0' || puzzle[i] == '.') continue;
|
||||
if (puzzle[i] < '1' && puzzle[i] > '9') throw new ArgumentException($"Input contains an invalid character: ({puzzle[i]})");
|
||||
int digit = puzzle[i] - '0' - 1;
|
||||
dlx.Give(i * 9 + digit);
|
||||
}
|
||||
return Iterator();
|
||||
|
||||
IEnumerable<string> Iterator() {
|
||||
var sb = new StringBuilder(new string('.', 81));
|
||||
foreach (int[] rows in dlx.Solutions()) {
|
||||
foreach (int r in rows) {
|
||||
sb[r / 81 * 9 + r / 9 % 9] = (char)(r % 9 + '1');
|
||||
}
|
||||
yield return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Print(string left, string right) {
|
||||
foreach (string line in GetPrintLines(left).Zip(GetPrintLines(right), (l, r) => l + "\t" + r)) {
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
|
||||
IEnumerable<string> GetPrintLines(string s) {
|
||||
int r = 0;
|
||||
foreach (string row in s.Cut(9)) {
|
||||
yield return r == 0
|
||||
? "╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗"
|
||||
: r % 3 == 0
|
||||
? "╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣"
|
||||
: "╟───┼───┼───╫───┼───┼───╫───┼───┼───╢";
|
||||
yield return "║ " + row.Cut(3).Select(segment => segment.DelimitWith(" │ ")).DelimitWith(" ║ ") + " ║";
|
||||
r++;
|
||||
}
|
||||
yield return "╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class DLX //Some functionality elided
|
||||
{
|
||||
private readonly Header root = new Header(null, null) { Size = int.MaxValue };
|
||||
private readonly List<Header> columns;
|
||||
private readonly List<Node> rows;
|
||||
private readonly Stack<Node> solutionNodes = new Stack<Node>();
|
||||
private int initial = 0;
|
||||
|
||||
public DLX(int rowCapacity, int columnCapacity) {
|
||||
columns = new List<Header>(columnCapacity);
|
||||
rows = new List<Node>(rowCapacity);
|
||||
}
|
||||
|
||||
public void AddHeader() {
|
||||
Header h = new Header(root.Left, root);
|
||||
h.AttachLeftRight();
|
||||
columns.Add(h);
|
||||
}
|
||||
|
||||
public void AddRow(params int[] newRow) {
|
||||
Node first = null;
|
||||
if (newRow != null) {
|
||||
for (int i = 0; i < newRow.Length; i++) {
|
||||
if (newRow[i] < 0) continue;
|
||||
if (first == null) first = AddNode(rows.Count, newRow[i]);
|
||||
else AddNode(first, newRow[i]);
|
||||
}
|
||||
}
|
||||
rows.Add(first);
|
||||
}
|
||||
|
||||
private Node AddNode(int row, int column) {
|
||||
Node n = new Node(null, null, columns[column].Up, columns[column], columns[column], row);
|
||||
n.AttachUpDown();
|
||||
n.Head.Size++;
|
||||
return n;
|
||||
}
|
||||
|
||||
private void AddNode(Node firstNode, int column) {
|
||||
Node n = new Node(firstNode.Left, firstNode, columns[column].Up, columns[column], columns[column], firstNode.Row);
|
||||
n.AttachLeftRight();
|
||||
n.AttachUpDown();
|
||||
n.Head.Size++;
|
||||
}
|
||||
|
||||
public void Give(int row) {
|
||||
solutionNodes.Push(rows[row]);
|
||||
CoverMatrix(rows[row]);
|
||||
initial++;
|
||||
}
|
||||
|
||||
public IEnumerable<int[]> Solutions() {
|
||||
try {
|
||||
Node node = ChooseSmallestColumn().Down;
|
||||
do {
|
||||
if (node == node.Head) {
|
||||
if (node == root) {
|
||||
yield return solutionNodes.Select(n => n.Row).ToArray();
|
||||
}
|
||||
if (solutionNodes.Count > initial) {
|
||||
node = solutionNodes.Pop();
|
||||
UncoverMatrix(node);
|
||||
node = node.Down;
|
||||
}
|
||||
} else {
|
||||
solutionNodes.Push(node);
|
||||
CoverMatrix(node);
|
||||
node = ChooseSmallestColumn().Down;
|
||||
}
|
||||
} while(solutionNodes.Count > initial || node != node.Head);
|
||||
} finally {
|
||||
Restore();
|
||||
}
|
||||
}
|
||||
|
||||
private void Restore() {
|
||||
while (solutionNodes.Count > 0) UncoverMatrix(solutionNodes.Pop());
|
||||
initial = 0;
|
||||
}
|
||||
|
||||
private Header ChooseSmallestColumn() {
|
||||
Header traveller = root, choice = root;
|
||||
do {
|
||||
traveller = (Header)traveller.Right;
|
||||
if (traveller.Size < choice.Size) choice = traveller;
|
||||
} while (traveller != root && choice.Size > 0);
|
||||
return choice;
|
||||
}
|
||||
|
||||
private void CoverRow(Node row) {
|
||||
Node traveller = row.Right;
|
||||
while (traveller != row) {
|
||||
traveller.DetachUpDown();
|
||||
traveller.Head.Size--;
|
||||
traveller = traveller.Right;
|
||||
}
|
||||
}
|
||||
|
||||
private void UncoverRow(Node row) {
|
||||
Node traveller = row.Left;
|
||||
while (traveller != row) {
|
||||
traveller.AttachUpDown();
|
||||
traveller.Head.Size++;
|
||||
traveller = traveller.Left;
|
||||
}
|
||||
}
|
||||
|
||||
private void CoverColumn(Header column) {
|
||||
column.DetachLeftRight();
|
||||
Node traveller = column.Down;
|
||||
while (traveller != column) {
|
||||
CoverRow(traveller);
|
||||
traveller = traveller.Down;
|
||||
}
|
||||
}
|
||||
|
||||
private void UncoverColumn(Header column) {
|
||||
Node traveller = column.Up;
|
||||
while (traveller != column) {
|
||||
UncoverRow(traveller);
|
||||
traveller = traveller.Up;
|
||||
}
|
||||
column.AttachLeftRight();
|
||||
}
|
||||
|
||||
private void CoverMatrix(Node node) {
|
||||
Node traveller = node;
|
||||
do {
|
||||
CoverColumn(traveller.Head);
|
||||
traveller = traveller.Right;
|
||||
} while (traveller != node);
|
||||
}
|
||||
|
||||
private void UncoverMatrix(Node node) {
|
||||
Node traveller = node;
|
||||
do {
|
||||
traveller = traveller.Left;
|
||||
UncoverColumn(traveller.Head);
|
||||
} while (traveller != node);
|
||||
}
|
||||
|
||||
private class Node
|
||||
{
|
||||
public Node(Node left, Node right, Node up, Node down, Header head, int row) {
|
||||
Left = left ?? this;
|
||||
Right = right ?? this;
|
||||
Up = up ?? this;
|
||||
Down = down ?? this;
|
||||
Head = head ?? this as Header;
|
||||
Row = row;
|
||||
}
|
||||
|
||||
public Node Left { get; set; }
|
||||
public Node Right { get; set; }
|
||||
public Node Up { get; set; }
|
||||
public Node Down { get; set; }
|
||||
public Header Head { get; }
|
||||
public int Row { get; }
|
||||
|
||||
public void AttachLeftRight() {
|
||||
this.Left.Right = this;
|
||||
this.Right.Left = this;
|
||||
}
|
||||
|
||||
public void AttachUpDown() {
|
||||
this.Up.Down = this;
|
||||
this.Down.Up = this;
|
||||
}
|
||||
|
||||
public void DetachLeftRight() {
|
||||
this.Left.Right = this.Right;
|
||||
this.Right.Left = this.Left;
|
||||
}
|
||||
|
||||
public void DetachUpDown() {
|
||||
this.Up.Down = this.Down;
|
||||
this.Down.Up = this.Up;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class Header : Node
|
||||
{
|
||||
public Header(Node left, Node right) : base(left, right, null, null, null, -1) { }
|
||||
|
||||
public int Size { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class Extensions
|
||||
{
|
||||
public static IEnumerable<string> Cut(this string input, int length)
|
||||
{
|
||||
for (int cursor = 0; cursor < input.Length; cursor += length) {
|
||||
if (cursor + length > input.Length) yield return input.Substring(cursor);
|
||||
else yield return input.Substring(cursor, length);
|
||||
}
|
||||
}
|
||||
|
||||
public static string DelimitWith<T>(this IEnumerable<T> source, string separator) => string.Join(separator, source);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue