HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Rainfall Challenge (August 2016 Community Challenge)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
rainfallaugustchallengecommunity2016

Problem

My solution for the Rainfall Challenge (August 2016 Community Challenge).

Error handling was intentionally ignored.

Cell.cs

public class Cell
{
    private readonly int myRowIndex;
    private readonly int myColIndex;
    private readonly int myValue;

    public Cell(int value, int rowIndex, int colIndex)
    {
        myRowIndex = rowIndex;
        myColIndex = colIndex;
        myValue = value;
    }

    public int RowIndex => myRowIndex;
    public int ColIndex => myColIndex;
    public int Value => myValue;
    public bool IsSink { get; set; }
    public Cell Top { get; set; }
    public Cell Right { get; set; }
    public Cell Bottom { get; set; }
    public Cell Left { get; set; }
    public Cell Next { get; set; }
}


Program.cs

Main

static void Main(string[] args)
{
    var data = ReadData();

    var cells = CreateCells(data).ToArray();

    ConnectCells(cells, data.GetLength(0));

    SetIsSink(cells);

    SetNext(cells);

    var basins = GetBasins(cells);

    Console.WriteLine(string.Join(" ", basins));
}


ReadData

private static int[,] ReadData()
{
    var size = int.Parse(Console.ReadLine());
    var result = new int[size, size];
    for (int row = 0; row < size; row++)
    {
        var rowData = Console.ReadLine().Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries).ToArray();
        for (int col = 0; col < size; col++)
            result[row, col] = int.Parse(rowData[col]);
    }
    return result;
}


CreateCells

private static IEnumerable CreateCells(int[,] data)
{
    for (int row = 0; row < data.GetLength(0); row++)
        for (int col = 0; col < data.GetLength(1); col++)
            yield return new Cell(data[row, col], row, col);
}


ConnectCells

```
private static void ConnectCells(Cell[] cells, int size)
{
foreach (var cell in cells)
{
var indexLeft = GetIndexLeft(cell, size);
var indexRight = GetIndexRight(cell, size);
var indexTop = GetIndexTop(cell, size);

Solution

The most obvious changes are to put most of those static methods into the Cell class.

If you thought little bit more carefully you could Tell that IsSink and Next could be calculated properties, removing the need for the methods GetNext, SetNext and SetIsSink.

public Cell Next {
    get
    {
        var cells = new[] { Left, Right, Top, Bottom };
        return cells.Where(c => c != null)
                    .OrderBy(c => c.Value)
                    .First();
    } 
}

public bool IsSink { 
    get {
        return (Left == null || Left.Value > Value) &&
                (Right == null || Right.Value > Value) &&
                (Top == null || Top.Value > Value) &&
                (Bottom == null || Bottom.Value > Value);
    } 
}


The same goes for ConnectCell and all help methods used there.

private void ConnectCell(Cell[,] cells)
{
    Left = ColIndex > 0 ? cells[RowIndex, ColIndex - 1] : null;
    Right = ColIndex  0 ? cells[RowIndex - 1, ColIndex] : null;
    Bottom = RowIndex < cells.GetLength(0) -1 ? cells[RowIndex + 1, ColIndex] : null;
}


You don't need to create explicit backfields for the properties RowIndex, ColIndex and Value. Instead create private setters. Example for Value

public int Value{ get; private set; }


It's also worth mentioning that the prefix my is not adding any information to the name. In C# it's common the use of _ as a field prefix instead.

If you are willing to use jagged arrays, you can change ReadData to use more Linq.

private static int[][] ReadData()
{
    var size = int.Parse(Console.ReadLine());
    var result = new int[size][];
    for (int row = 0; row  int.Parse(s))
            .ToArray();
        result[row] = rowData;
    }
    return result;
}

Code Snippets

public Cell Next {
    get
    {
        var cells = new[] { Left, Right, Top, Bottom };
        return cells.Where(c => c != null)
                    .OrderBy(c => c.Value)
                    .First();
    } 
}

public bool IsSink { 
    get {
        return (Left == null || Left.Value > Value) &&
                (Right == null || Right.Value > Value) &&
                (Top == null || Top.Value > Value) &&
                (Bottom == null || Bottom.Value > Value);
    } 
}
private void ConnectCell(Cell[,] cells)
{
    Left = ColIndex > 0 ? cells[RowIndex, ColIndex - 1] : null;
    Right = ColIndex < cells.GetLength(1) -1 ? cells[RowIndex, ColIndex - 1] : null;
    Top = RowIndex > 0 ? cells[RowIndex - 1, ColIndex] : null;
    Bottom = RowIndex < cells.GetLength(0) -1 ? cells[RowIndex + 1, ColIndex] : null;
}
public int Value{ get; private set; }
private static int[][] ReadData()
{
    var size = int.Parse(Console.ReadLine());
    var result = new int[size][];
    for (int row = 0; row < size; row++)
    {
        var rowData = Console.ReadLine()
            .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
            .ToArray()
            .Select(s => int.Parse(s))
            .ToArray();
        result[row] = rowData;
    }
    return result;
}

Context

StackExchange Code Review Q#136786, answer score: 6

Revisions (0)

No revisions yet.