Created
May 7, 2018 21:31
-
-
Save ygra/4d054235179ead26bea49ac65f1b8675 to your computer and use it in GitHub Desktop.
Rullo solver (https://www.kongregate.com/games/Crescentyr/rullo)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 6 | |
8 8 8 2 8 8 | |
2 5 4 2 9 7 | |
6 2 7 3 5 4 | |
4 6 6 1 7 1 | |
8 2 7 3 3 6 | |
7 3 2 3 7 3 | |
3 2 2 8 1 7 | |
30 21 32 15 36 21 | |
32 18 20 24 24 22 15 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
namespace Rullo | |
{ | |
class Grid | |
{ | |
private int[,] _data; | |
private bool[,] _mask; | |
private int[] _rowSums; | |
private int[] _colSums; | |
private int[] currentRowSums; | |
private int[] currentColSums; | |
private (int, int) _size; | |
private int _columns; | |
public Grid(int rows, int columns) | |
{ | |
Size = (rows, columns); | |
currentRowSums = new int[rows]; | |
currentColSums = new int[columns]; | |
} | |
public (int rows, int columns) Size | |
{ | |
get => _size; | |
set | |
{ | |
_size = value; | |
_data = new int[value.rows, value.columns]; | |
_mask = new bool[value.rows, value.columns]; | |
_rowSums = new int[value.rows]; | |
_colSums = new int[value.columns]; | |
} | |
} | |
public int this[int row, int column] | |
{ | |
get => _data[row, column]; | |
set => _data[row, column] = value; | |
} | |
public void SetMask((int row, int column) tuple, bool value) | |
{ | |
var oldValue = _mask[tuple.row, tuple.column]; | |
_mask[tuple.row, tuple.column] = value; | |
var gridCell = this[tuple.row, tuple.column]; | |
if (!oldValue && value) | |
{ | |
currentColSums[tuple.column] += gridCell; | |
currentRowSums[tuple.row] += gridCell; | |
} | |
if (oldValue && !value) | |
{ | |
currentColSums[tuple.column] -= gridCell; | |
currentRowSums[tuple.row] -= gridCell; | |
} | |
} | |
public int[] CurrentRowSums { get => currentRowSums; } | |
public int[] CurrentColumnSums { get => currentColSums; } | |
public void Display() | |
{ | |
Console.ForegroundColor = ConsoleColor.Red; | |
Console.Write(" "); | |
for (int i = 0; i < Size.columns; i++) | |
{ | |
Console.Write(" {0,2}/{1,2}", CurrentColumnSums[i], _colSums[i]); | |
} | |
Console.WriteLine(); | |
for (int row = 0; row < Size.rows; row++) | |
{ | |
Console.ForegroundColor = ConsoleColor.Red; | |
Console.Write("{0,2}/{1,2} ", CurrentRowSums[row], _rowSums[row]); | |
for (int col = 0; col < Size.columns; col++) | |
{ | |
Console.ForegroundColor = _mask[row, col] ? ConsoleColor.White : ConsoleColor.DarkGray; | |
Console.Write(_mask[row, col] ? " {0,-3}" : " ({0})", this[row, col]); | |
} | |
Console.WriteLine(); | |
} | |
} | |
public bool IsSolved | |
{ | |
get | |
{ | |
for (int i = 0; i < Size.rows; i++) | |
{ | |
if (CurrentRowSums[i] != _rowSums[i]) | |
{ | |
return false; | |
} | |
} | |
for (int i = 0; i < Size.columns; i++) | |
{ | |
if (CurrentColumnSums[i] != _colSums[i]) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
} | |
private IEnumerable<(int row, int column)> GetPositions((int row, int column) tuple) | |
{ | |
for (int r = tuple.row; r < Size.rows; r++) | |
{ | |
for (int c = r == tuple.row ? tuple.column : 0; c < Size.columns; c++) | |
{ | |
yield return (r, c); | |
} | |
} | |
} | |
public bool IsInvalid | |
{ | |
get | |
{ | |
for (int i = 0; i < Size.rows; i++) | |
{ | |
if (CurrentRowSums[i] < _rowSums[i]) | |
{ | |
return true; | |
} | |
} | |
for (int i = 0; i < Size.columns; i++) | |
{ | |
if (CurrentColumnSums[i] < _colSums[i]) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
} | |
public void Solve() | |
{ | |
foreach (var tuple in GetPositions((0, 0))) | |
{ | |
SetMask(tuple, true); | |
} | |
foreach (var tuple in GetPositions((0, 0))) | |
{ | |
if (Solve(tuple)) | |
{ | |
break; | |
} | |
} | |
} | |
private bool Solve((int row, int column) tuple) | |
{ | |
SetMask(tuple, false); | |
if (IsInvalid) | |
{ | |
SetMask(tuple, true); | |
return false; | |
} | |
if (IsSolved) | |
{ | |
return true; | |
} | |
foreach (var next in GetPositions(tuple).Skip(1)) | |
{ | |
var result = Solve(next); | |
if (result) | |
{ | |
return result; | |
} | |
} | |
SetMask(tuple, true); | |
return false; | |
} | |
public static Grid Load(string file) | |
{ | |
var input = File.ReadAllLines(file); | |
var sizes = input[0].Split().Select(int.Parse).ToArray(); | |
var rows = sizes[0]; | |
var columns = sizes.Length > 1 ? sizes[1] : sizes[0]; | |
var grid = new Grid(rows, columns); | |
string[] line; | |
for (var row = 0; row < rows; row++) | |
{ | |
line = input[row + 1].Split(); | |
for (var col = 0; col < columns; col++) | |
{ | |
int v = int.Parse(line[col]); | |
grid[row, col] = v; | |
} | |
} | |
foreach (var tuple in grid.GetPositions((0, 0))) | |
{ | |
grid.SetMask(tuple, true); | |
} | |
line = input[rows + 1].Split(); | |
for (var x = 0; x < columns; x++) | |
{ | |
grid._colSums[x] = int.Parse(line[x]); | |
} | |
line = input[rows + 2].Split(); | |
for (var x = 0; x < rows; x++) | |
{ | |
grid._rowSums[x] = int.Parse(line[x]); | |
} | |
return grid; | |
} | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
if (args.Length < 1) | |
{ | |
return; | |
} | |
var grid = Grid.Load(args[0]); | |
grid.Solve(); | |
grid.Display(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment