|
|
@@ -1,6 +1,7 @@
|
|
|
using Accord.Video.FFMPEG;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
+using System.Diagnostics;
|
|
|
using System.Drawing;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
@@ -26,7 +27,7 @@ namespace D17.Bonus
|
|
|
var reg = new Regex(@"[xy]=(\d+), [xy]=(\d+)[.][.](\d+)");
|
|
|
|
|
|
var map = new Dictionary<(int x, int y), EnumType>();
|
|
|
- var rwater = new Dictionary<(int x, int y), (int x, int y)>();
|
|
|
+ var rwater = new Accord.Collections.OrderedDictionary<(int x, int y), (int x, int y)>();
|
|
|
|
|
|
int MAXY = 0;
|
|
|
int MINX = int.MaxValue;
|
|
|
@@ -43,11 +44,13 @@ namespace D17.Bonus
|
|
|
CreateMap(map, ref MAXY, ref MINX, ref MINY, ref MAXX, line, result);
|
|
|
|
|
|
} while (true);
|
|
|
+ file.Close();
|
|
|
|
|
|
// Start with river
|
|
|
rwater.Add((500, 0), (500, 0));
|
|
|
map.Add((500, 0), EnumType.RunningWater);
|
|
|
|
|
|
+ Console.SetOut(TextWriter.Null);
|
|
|
VideoFileWriter writer = new VideoFileWriter();
|
|
|
|
|
|
var width = MAXX - MINX + 2;
|
|
|
@@ -58,10 +61,11 @@ namespace D17.Bonus
|
|
|
|
|
|
writer.Open("out.avi", width, height);
|
|
|
|
|
|
+ int rr = 0;
|
|
|
while (rwater.Count > 0)
|
|
|
{
|
|
|
+ rr++;
|
|
|
if (rwater.Any(r => r.Key.y > panY + tpy)) panY++;
|
|
|
- PrintMap(map, writer, MINX, MAXX, MAXY, width, height);
|
|
|
|
|
|
var enumer = rwater.FirstOrDefault();
|
|
|
var water = enumer.Key;
|
|
|
@@ -73,14 +77,17 @@ namespace D17.Bonus
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ bool renderMap = false;
|
|
|
if (map.ContainsKey((water.x, water.y + 1)) == false || map[(water.x, water.y + 1)] == EnumType.RunningWater)
|
|
|
{
|
|
|
RaindropsOnRoses(map, rwater, water);
|
|
|
+ renderMap = true;
|
|
|
}
|
|
|
|
|
|
else
|
|
|
{
|
|
|
ExpandToBothSides(map, rwater, water, source);
|
|
|
+ renderMap = true;
|
|
|
|
|
|
int maxX, minX;
|
|
|
bool canConvert = CanConvertToStillWater(map, rwater, water, source, out maxX, out minX);
|
|
|
@@ -90,12 +97,29 @@ namespace D17.Bonus
|
|
|
else
|
|
|
rwater.Remove(water);
|
|
|
}
|
|
|
+
|
|
|
+ if (renderMap)
|
|
|
+ {
|
|
|
+ if (rr < rwater.Count) continue;
|
|
|
+ RenderMap(map, writer, MINX, MAXY, width, height);
|
|
|
+ rr = 1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- PrintMap(map, writer, MINX, MAXX, MAXY, width, height);
|
|
|
+ var lastBitmap = RenderMap(map, writer, MINX, MAXY, width, height);
|
|
|
+
|
|
|
+ var countEx1 = map.Count(m => (m.Key.y >= MINY && m.Key.y <= MAXY) && (m.Value == EnumType.RunningWater || m.Value == EnumType.StillWater));
|
|
|
+ var countEx2 = map.Count(m => (m.Key.y >= MINY && m.Key.y <= MAXY) && (m.Value == EnumType.StillWater));
|
|
|
+ var answer = $"The answer is {countEx1}m3 flooded,\n and {countEx2}m3 still water ☺";
|
|
|
+ using (var gd = Graphics.FromImage(lastBitmap))
|
|
|
+ using (var font = new Font(FontFamily.GenericSerif, 12, FontStyle.Regular))
|
|
|
+ {
|
|
|
+ gd.DrawString(answer, font, Brushes.IndianRed, 10, tpy + 10);
|
|
|
+ writer.WriteVideoFrame(lastBitmap);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private static void RaindropsOnRoses(Dictionary<(int x, int y), EnumType> map, Dictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water)
|
|
|
+ private static void RaindropsOnRoses(Dictionary<(int x, int y), EnumType> map, IDictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water)
|
|
|
{
|
|
|
rwater.Remove(water);
|
|
|
|
|
|
@@ -104,7 +128,7 @@ namespace D17.Bonus
|
|
|
map[drop] = EnumType.RunningWater;
|
|
|
}
|
|
|
|
|
|
- private static void ConvertToStillWater(Dictionary<(int x, int y), EnumType> map, Dictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source, int maxX, int minX)
|
|
|
+ private static void ConvertToStillWater(Dictionary<(int x, int y), EnumType> map, IDictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source, int maxX, int minX)
|
|
|
{
|
|
|
for (var x = minX; x <= maxX; ++x)
|
|
|
{
|
|
|
@@ -120,7 +144,7 @@ namespace D17.Bonus
|
|
|
if (!rwater.ContainsKey(source)) rwater.Add(source, (source.x, source.y - 1));
|
|
|
}
|
|
|
|
|
|
- private static bool CanConvertToStillWater(Dictionary<(int x, int y), EnumType> map, Dictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source, out int maxX, out int minX)
|
|
|
+ private static bool CanConvertToStillWater(Dictionary<(int x, int y), EnumType> map, IDictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source, out int maxX, out int minX)
|
|
|
{
|
|
|
bool canConvert = true;
|
|
|
maxX = 0;
|
|
|
@@ -132,7 +156,7 @@ namespace D17.Bonus
|
|
|
if (res == false)
|
|
|
{
|
|
|
canConvert = false;
|
|
|
- //rwater.TryAdd((x - 1, water.y), source);
|
|
|
+ if (!rwater.ContainsKey((x - 1, water.y))) rwater.Add((x - 1, water.y), source);
|
|
|
}
|
|
|
else if (type == EnumType.Clay) break;
|
|
|
}
|
|
|
@@ -143,7 +167,7 @@ namespace D17.Bonus
|
|
|
if (res == false)
|
|
|
{
|
|
|
canConvert = false;
|
|
|
- //rwater.TryAdd((x + 1, water.y), source);
|
|
|
+ if (!rwater.ContainsKey((x + 1, water.y))) rwater.Add((x + 1, water.y), source);
|
|
|
}
|
|
|
else if (type == EnumType.Clay) break;
|
|
|
}
|
|
|
@@ -151,7 +175,7 @@ namespace D17.Bonus
|
|
|
return canConvert;
|
|
|
}
|
|
|
|
|
|
- private static void ExpandToBothSides(Dictionary<(int x, int y), EnumType> map, Dictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source)
|
|
|
+ private static void ExpandToBothSides(Dictionary<(int x, int y), EnumType> map, IDictionary<(int x, int y), (int x, int y)> rwater, (int x, int y) water, (int x, int y) source)
|
|
|
{
|
|
|
var next = water;
|
|
|
|
|
|
@@ -192,7 +216,7 @@ namespace D17.Bonus
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static void CreateMap(Dictionary<(int x, int y), EnumType> map, ref int MAXY, ref int MINX, ref int MINY, ref int MAXX, string line, Match result)
|
|
|
+ private static void CreateMap(IDictionary<(int x, int y), EnumType> map, ref int MAXY, ref int MINX, ref int MINY, ref int MAXX, string line, Match result)
|
|
|
{
|
|
|
var c1 = int.Parse(result.Groups[1].Value);
|
|
|
var rmin = int.Parse(result.Groups[2].Value);
|
|
|
@@ -227,25 +251,35 @@ namespace D17.Bonus
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static void PrintMap(Dictionary<(int x, int y), EnumType> map, VideoFileWriter writer, int MINX, int MAXX, int MAXY, int width, int height)
|
|
|
+ static Bitmap _REFBMP = null;
|
|
|
+ private static Bitmap RenderMap(Dictionary<(int x, int y), EnumType> map, VideoFileWriter writer, int MINX, int MAXY, int width, int height)
|
|
|
{
|
|
|
- var bmp = new Bitmap(width, height);
|
|
|
+ if (_REFBMP == null)
|
|
|
+ {
|
|
|
+ _REFBMP = new Bitmap(width, height);
|
|
|
+ for (int x = 0; x < width; ++x)
|
|
|
+ for (int y = 0; y < height; ++y)
|
|
|
+ _REFBMP.SetPixel(x, y, Color.FloralWhite);
|
|
|
+ }
|
|
|
+
|
|
|
+ var bmp = new Bitmap(_REFBMP);
|
|
|
|
|
|
- for (int y = panY; y < height + panY; ++y)
|
|
|
+ var hh = Math.Min(height + panY, MAXY);
|
|
|
+ var sortedMap = map.OrderBy(m => m.Key.y).Where(m => m.Key.y > panY && m.Key.y <= hh);
|
|
|
+
|
|
|
+ foreach (var res in sortedMap)
|
|
|
{
|
|
|
- int px = 0;
|
|
|
- int py = y - panY;
|
|
|
- for (int x = MINX - 1; x < MAXX + 1; ++x)
|
|
|
- {
|
|
|
- var res = map.TryGetValue((x, y), out var type);
|
|
|
- if (res == false) bmp.SetPixel(px, py, Color.White);
|
|
|
- else if (type == EnumType.Clay) bmp.SetPixel(px, py, Color.Maroon);
|
|
|
- else if (type == EnumType.RunningWater) bmp.SetPixel(px, py, Color.Aqua);
|
|
|
- else if (type == EnumType.StillWater) bmp.SetPixel(px, py, Color.Aquamarine);
|
|
|
- px++;
|
|
|
- }
|
|
|
+ var type = res.Value;
|
|
|
+ var px = res.Key.x - MINX + 1;
|
|
|
+ var py = res.Key.y - panY - 1;
|
|
|
+
|
|
|
+ if (type == EnumType.Clay) bmp.SetPixel(px, py, Color.Maroon);
|
|
|
+ else if (type == EnumType.RunningWater) bmp.SetPixel(px, py, Color.Aqua);
|
|
|
+ else if (type == EnumType.StillWater) bmp.SetPixel(px, py, Color.Aquamarine);
|
|
|
}
|
|
|
+
|
|
|
writer.WriteVideoFrame(bmp);
|
|
|
+ return bmp;
|
|
|
}
|
|
|
}
|
|
|
}
|