Advertisement
DarthGizka

CodeReview_Rainfall.cs

Aug 21st, 2016
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 2.48 KB | None | 0 0
  1. // CodeReview_Rainfall.cs
  2. // 2016-08-21
  3. //
  4. // see http://codereview.stackexchange.com/questions/38500/rainfall-challenge
  5.  
  6. #if !LINQPAD
  7. using System;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Linq;
  11. #endif
  12.  
  13. class Rainfall
  14. {
  15.     const string TEST_FILE = "d:/dev/cpp/cc/LINQPad/queries/CodeReview/rainfall/"
  16.         + /**/ "sample-3-input.txt" /*/ "rainfall-example-4.txt" /**/;
  17.  
  18.     static void Main (string[] args)
  19.     {
  20.         var filename = args != null && args.Length > 0 ? args[0] : TEST_FILE;
  21.  
  22.         using (var sr = new StreamReader(filename))
  23.             process_file(sr);
  24.     }
  25.  
  26.     static void process_file (StreamReader sr)
  27.     {
  28.         var s = sr.ReadLine().Trim().Split().Select(int.Parse).ToArray();
  29.         int row_count = s[0], col_count = s.Length > 1 ? s[1] : row_count;
  30.         var dsf = Enumerable.Repeat(-1, row_count * col_count).ToArray();
  31.         var dummy = Enumerable.Repeat(ushort.MaxValue, 1 + row_count + 1).ToArray();
  32.         ushort[] prev_row = dummy, curr_row = dummy;
  33.  
  34.         for (int row = 0; row <= row_count; ++row)
  35.         {
  36.             var next_row = dummy;
  37.  
  38.             if (row < row_count)
  39.                 next_row = ("65535 " + sr.ReadLine().Trim() + " 65535").Split()
  40.                     .Select(ushort.Parse)
  41.                     .ToArray();
  42.  
  43.             if (row > 0)
  44.             {
  45.                 for (int col = 1; col <= col_count; ++col)
  46.                 {
  47.                     var n_w = Math.Min(prev_row[col], curr_row[col - 1]);
  48.                     var s_e = Math.Min(next_row[col], curr_row[col + 1]);
  49.                     var min = Math.Min(n_w, s_e);
  50.  
  51.                     if (curr_row[col] > min)
  52.                     {
  53.                         int curr = (row - 1) * col_count + (col - 1), sink = curr;
  54.  
  55.                         if (min == prev_row[col])
  56.                             sink -= col_count;
  57.                         else if (min == next_row[col])
  58.                             sink += col_count;
  59.                         else if (min == curr_row[col - 1])
  60.                             sink -= 1;
  61.                         else
  62.                             sink += 1;
  63.  
  64.                         join(dsf, curr, sink);
  65.                     }
  66.                 }
  67.             }
  68.  
  69.             prev_row = curr_row;
  70.             curr_row = next_row;
  71.         }
  72.  
  73.         var basins = new HashSet<int>(Enumerable.Range(0, dsf.Length).Select(i => root(dsf, i)));
  74.         var counts = basins.Select(sink => -dsf[sink]).OrderBy(x => -x);
  75.  
  76.         Console.WriteLine(string.Join(" ", counts));       
  77.     }
  78.  
  79.     static int root (int[] a, int i)
  80.     {
  81.         int j = a[i];
  82.  
  83.         if (j >= 0)
  84.             for (int k; (k = a[i = j]) >= 0; j = k)
  85.                 a[i] = k;
  86.  
  87.         return i;
  88.     }
  89.  
  90.     static void join (int[] a, int i, int j)
  91.     {
  92.         if ((i = root(a, i)) != (j = root(a, j)))
  93.         {
  94.             if (a[i] <= a[j])  // |set(i)| >= |set(j)| (membership counts are negative)
  95.             {
  96.                 a[i] += a[j];
  97.                 a[j] = i;
  98.             }
  99.             else
  100.             {
  101.                 a[j] += a[i];
  102.                 a[i] = j;
  103.             }
  104.         }
  105.     }
  106. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement