DarthGizka icon

CodeReview_Rainfall.cs

DarthGizka | PRO | 08/21/16 11:45:43 AM UTC | 0 ⭐ | 477 👁️ | Never ⏰ | []
C# |

2.48 KB

|

None

|

0 👍

/

0 👎

// CodeReview_Rainfall.cs
// 2016-08-21
//
// see http://codereview.stackexchange.com/questions/38500/rainfall-challenge
 
#if !LINQPAD
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
#endif
 
class Rainfall
{
    const string TEST_FILE = "d:/dev/cpp/cc/LINQPad/queries/CodeReview/rainfall/"
        + /**/ "sample-3-input.txt" /*/ "rainfall-example-4.txt" /**/;
 
    static void Main (string[] args)
    {
        var filename = args != null && args.Length > 0 ? args[0] : TEST_FILE;
 
        using (var sr = new StreamReader(filename))
            process_file(sr);
    }
 
    static void process_file (StreamReader sr)
    {
        var s = sr.ReadLine().Trim().Split().Select(int.Parse).ToArray();
        int row_count = s[0], col_count = s.Length > 1 ? s[1] : row_count;
        var dsf = Enumerable.Repeat(-1, row_count * col_count).ToArray();
        var dummy = Enumerable.Repeat(ushort.MaxValue, 1 + row_count + 1).ToArray();
        ushort[] prev_row = dummy, curr_row = dummy;
 
        for (int row = 0; row <= row_count; ++row)
        {
            var next_row = dummy;
 
            if (row < row_count)
                next_row = ("65535 " + sr.ReadLine().Trim() + " 65535").Split()
                    .Select(ushort.Parse)
                    .ToArray();
 
            if (row > 0)
            {
                for (int col = 1; col <= col_count; ++col)
                {
                    var n_w = Math.Min(prev_row[col], curr_row[col - 1]);
                    var s_e = Math.Min(next_row[col], curr_row[col + 1]);
                    var min = Math.Min(n_w, s_e);
 
                    if (curr_row[col] > min)
                    {
                        int curr = (row - 1) * col_count + (col - 1), sink = curr;
 
                        if (min == prev_row[col])
                            sink -= col_count;
                        else if (min == next_row[col])
                            sink += col_count;
                        else if (min == curr_row[col - 1])
                            sink -= 1;
                        else
                            sink += 1;
 
                        join(dsf, curr, sink);
                    }
                }
            }
 
            prev_row = curr_row;
            curr_row = next_row;
        }
 
        var basins = new HashSet<int>(Enumerable.Range(0, dsf.Length).Select(i => root(dsf, i)));
        var counts = basins.Select(sink => -dsf[sink]).OrderBy(x => -x);
 
        Console.WriteLine(string.Join(" ", counts));        
    }
 
    static int root (int[] a, int i)
    {
        int j = a[i];
 
        if (j >= 0)
            for (int k; (k = a[i = j]) >= 0; j = k)
                a[i] = k;
 
        return i;
    }
 
    static void join (int[] a, int i, int j)
    {
        if ((i = root(a, i)) != (j = root(a, j)))
        {
            if (a[i] <= a[j])  // |set(i)| >= |set(j)| (membership counts are negative)
            {
                a[i] += a[j];
                a[j] = i;
            }
            else
            {
                a[j] += a[i];
                a[i] = j;
            }
        }
    }
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎