|
|
@@ -0,0 +1,165 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Drawing;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+
|
|
|
+namespace D6.Bonus
|
|
|
+{
|
|
|
+ class Program
|
|
|
+ {
|
|
|
+ static void Main(string[] args)
|
|
|
+ {
|
|
|
+ if (args.Length < 2) return;
|
|
|
+ if (File.Exists(args[0]) == false) return;
|
|
|
+ if (int.TryParse(args[1], out int ceil) == false) return;
|
|
|
+
|
|
|
+ var coordinates = new List<((uint x, uint y) coord, bool isInfinite)>();
|
|
|
+ var file = File.OpenText(args[0]);
|
|
|
+
|
|
|
+ uint minXY = int.MaxValue;
|
|
|
+ uint maxXY = 0;
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ var line = file.ReadLine();
|
|
|
+ if (line == null) break;
|
|
|
+
|
|
|
+ var cl = line.Split(", ");
|
|
|
+ (uint x, uint y) xy = (uint.Parse(cl[0]), uint.Parse(cl[1]));
|
|
|
+
|
|
|
+ if (xy.x < minXY) minXY = xy.x;
|
|
|
+ if (xy.y < minXY) minXY = xy.y;
|
|
|
+ if (xy.x > maxXY) maxXY = xy.x;
|
|
|
+ if (xy.y > maxXY) maxXY = xy.y;
|
|
|
+
|
|
|
+ coordinates.Add((xy, false));
|
|
|
+ } while (true);
|
|
|
+
|
|
|
+ uint size = minXY + maxXY;
|
|
|
+
|
|
|
+ var area = new (int closest, int total)[size, size];
|
|
|
+
|
|
|
+ fillMapArea(size, coordinates, area);
|
|
|
+
|
|
|
+ flagPointOnEdges(size, coordinates);
|
|
|
+
|
|
|
+ GenerateBitMap(ceil, coordinates, size, area);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void GenerateBitMap(int ceil, List<((uint x, uint y) coord, bool isInfinite)> coordinates, uint size, (int closest, int total)[,] area)
|
|
|
+ {
|
|
|
+ var bmp = new Bitmap((int)size, (int)size);
|
|
|
+ Random r = new Random();
|
|
|
+ Dictionary<int, Color> Colors = new Dictionary<int, Color>();
|
|
|
+
|
|
|
+ for (var x = 0; x < size; x++)
|
|
|
+ {
|
|
|
+ for (var y = 0; y < size; y++)
|
|
|
+ {
|
|
|
+ var id = area[x, y].closest;
|
|
|
+ var total = area[x, y].total;
|
|
|
+
|
|
|
+ if (Colors.ContainsKey(id) == false)
|
|
|
+ Colors.Add(id, Color.FromArgb(coordinates.ElementAt(id).isInfinite ? 20 : 255, r.Next(0, 256), r.Next(0, 256), r.Next(0, 256)));
|
|
|
+
|
|
|
+ if (coordinates.ElementAt(id).isInfinite && (x + y % 2) % 3 == 0) continue;
|
|
|
+
|
|
|
+ bmp.SetPixel(x, y, Colors[id]);
|
|
|
+
|
|
|
+ var c = bmp.GetPixel(x, y);
|
|
|
+ if (total < ceil) bmp.SetPixel(x, y, Color.FromArgb((int)((c.R + 127) / 1.5), (int)((c.G + 127) / 1.5), (int)((c.B + 127) / 1.5)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var coord in coordinates)
|
|
|
+ {
|
|
|
+ int x = (int)coord.coord.x;
|
|
|
+ int y = (int)coord.coord.y;
|
|
|
+ bmp.SetPixel(x, y, Color.Red);
|
|
|
+ bmp.SetPixel(x - 1, y, Color.Red);
|
|
|
+ bmp.SetPixel(x + 1, y, Color.Red);
|
|
|
+ bmp.SetPixel(x, y - 1, Color.Red);
|
|
|
+ bmp.SetPixel(x, y + 1, Color.Red);
|
|
|
+
|
|
|
+ bmp.SetPixel(x - 1, y - 1, Color.DarkRed);
|
|
|
+ bmp.SetPixel(x + 1, y - 1, Color.DarkRed);
|
|
|
+ bmp.SetPixel(x - 1, y + 1, Color.DarkRed);
|
|
|
+ bmp.SetPixel(x + 1, y + 1, Color.DarkRed);
|
|
|
+ }
|
|
|
+
|
|
|
+ bmp = new Bitmap(bmp, new Size((int)(size * 2), (int)(size * 2)));
|
|
|
+
|
|
|
+ bmp.Save("result.bmp");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static int findMaxCoveredArea(List<((uint x, uint y) coord, bool isInfinite)> coordinates, int[] area)
|
|
|
+ {
|
|
|
+ int maxArea = 0;
|
|
|
+ for (int i = 0; i < area.Length; ++i)
|
|
|
+ {
|
|
|
+ if (coordinates.ElementAt(i).isInfinite) continue;
|
|
|
+
|
|
|
+ if (area[i] > maxArea) maxArea = area[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ return maxArea;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void flagPointOnEdges(uint size, List<((uint x, uint y) coord, bool isInfinite)> coordinates)
|
|
|
+ {
|
|
|
+ for (uint i = 0; i < size; ++i)
|
|
|
+ {
|
|
|
+ var x0yi = GetClosest(coordinates, (0, i));
|
|
|
+ MarkInfinite(coordinates, x0yi.closest);
|
|
|
+
|
|
|
+ var xiy0 = GetClosest(coordinates, (i, 0));
|
|
|
+ MarkInfinite(coordinates, xiy0.closest);
|
|
|
+
|
|
|
+ var xsizeyi = GetClosest(coordinates, (size, i));
|
|
|
+ MarkInfinite(coordinates, xsizeyi.closest);
|
|
|
+
|
|
|
+ var xiysize = GetClosest(coordinates, (i, size));
|
|
|
+ MarkInfinite(coordinates, xiysize.closest);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void fillMapArea(uint size, List<((uint x, uint y) coord, bool isInfinite)> coordinates, (int closest, int total)[,] area)
|
|
|
+ {
|
|
|
+ for (uint x = 0; x < size; x++)
|
|
|
+ {
|
|
|
+ for (uint y = 0; y < size; y++)
|
|
|
+ {
|
|
|
+ var closest = GetClosest(coordinates, (x, y));
|
|
|
+ area[x,y] = closest;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static (int closest, int total) GetClosest(List<((uint x, uint y) coord, bool isInfinite)> coordinates, (uint x, uint y) point)
|
|
|
+ {
|
|
|
+ int total = 0;
|
|
|
+ int lowest = int.MaxValue;
|
|
|
+ int lowestId = 0;
|
|
|
+ for (int i = 0; i < coordinates.Count; i++)
|
|
|
+ {
|
|
|
+ var (x, y) = coordinates[i].coord;
|
|
|
+ var manhattan = Math.Abs((int)point.x - (int)x) + Math.Abs((int)point.y - (int)y);
|
|
|
+ if (manhattan < lowest)
|
|
|
+ {
|
|
|
+ lowest = manhattan;
|
|
|
+ lowestId = i;
|
|
|
+ }
|
|
|
+ total += manhattan;
|
|
|
+ }
|
|
|
+ return (lowestId, total);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void MarkInfinite(List<((uint x, uint y) coord, bool isInfinite)> coordinates, int id)
|
|
|
+ {
|
|
|
+ var coord = coordinates[id];
|
|
|
+ coord.isInfinite = true;
|
|
|
+ coordinates[id] = coord;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|