using Accord.Video.FFMPEG; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; namespace D13._3 { class Track : Dictionary<(int x, int y), char> { }; class Carts : List<(int x, int y, int vx, int vy, int t, Color c)> { }; class Program { static void Main(string[] args) { if (args.Length < 1) return; if (File.Exists(args[0]) == false) return; var file = File.OpenText(args[0]); var track = new Track(); var carts = new Carts(); FillTrack(file, track, carts); int width = track.Max(c => c.Key.x) + 1; int height = track.Max(c => c.Key.y) + 1; VideoFileWriter writer = new VideoFileWriter(); writer.Open("out.avi", width, height); int? last = null; do { Bitmap image = new Bitmap(width, height); foreach (var t in track) image.SetPixel(t.Key.x, t.Key.y, Color.White); foreach (var t in carts) image.SetPixel(t.x, t.y, t.c); writer.WriteVideoFrame(image); carts.Sort((a, b) => { if (a.y == b.y) return a.x - b.x; return a.y - b.y; }); last = lastCart(carts); if (last == null) tick(track, carts); } while (last == null) ; writer.Close(); } private static void FillTrack(StreamReader file, Track track, Carts carts) { int y = 0; do { var line = file.ReadLine(); if (line == null) break; for (int x = 0; x < line.Length; ++x) { char c = line[x]; if (c == ' ') continue; if (isCart(c)) { carts.Add(getCart(c, x, y)); c = c == '>' || c == '<' ? '-' : '|'; } track[(x, y)] = c; } y++; } while (true); } private static void tick(Track track, Carts carts) { for (var i = 0; i < carts.Count; ++i) { var cart = carts[i]; if (cart == default) continue; cart.x += cart.vx; cart.y += cart.vy; if (inter(carts, cart, i)) continue; var c = track[(cart.x, cart.y)]; var ncart = getCart(c, cart); carts[i] = ncart; } } static int? lastCart(Carts carts) { int count = 0; int? cart = null; for (var i = 0; i < carts.Count; ++i) { if (carts[i] == default) continue; cart = i; count++; } return count == 1 ? cart : null; } static bool inter(Carts carts, (int x, int y, int vx, int vy, int t, Color c) cj, int skip) { for (var i = 0; i < carts.Count; ++i) { if (i == skip) continue; var ci = carts[i]; if (ci == default) continue; if (ci.x == cj.x && ci.y == cj.y) { carts[i] = default; carts[skip] = default; return true; } } return false; } static bool isCart(char c) { return c == '>' || c == '<' || c == '^' || c == 'v'; } static (int x, int y, int vx, int vy, int t, Color c) getCart(char c, int x, int y) { var r = new Random(DateTime.Now.Millisecond); var cl = Color.FromArgb(255, r.Next(0, 255), r.Next(0, 255), r.Next(0, 255)); switch (c) { case '>': return (x, y, +1, +0, 0, cl); case '<': return (x, y, -1, +0, 0, cl); case '^': return (x, y, +0, -1, 0, cl); case 'v': return (x, y, +0, +1, 0, cl); } return default; } static (int x, int y, int vx, int vy, int t, Color c) getCart(char c, (int x, int y, int vx, int vy, int t, Color c) cart) { if (c == '|' || c == '-') return cart; if (c == '+' && cart.t == 1) { cart.t++; return cart; } switch (cart) { case var t when t.vx == 1 && t.vy == 0: if (c == '/') return (cart.x, cart.y, +0, -1, cart.t, cart.c); if (c == '\\') return (cart.x, cart.y, +0, +1, cart.t, cart.c); if (c == '+' && cart.t == 0) return (cart.x, cart.y, +0, -1, 1, cart.c); if (c == '+' && cart.t == 2) return (cart.x, cart.y, +0, +1, 0, cart.c); return default; case var t when t.vx == -1 && t.vy == 0: if (c == '/') return (cart.x, cart.y, +0, +1, cart.t, cart.c); if (c == '\\') return (cart.x, cart.y, +0, -1, cart.t, cart.c); if (c == '+' && cart.t == 0) return (cart.x, cart.y, +0, +1, 1, cart.c); if (c == '+' && cart.t == 2) return (cart.x, cart.y, +0, -1, 0, cart.c); return default; case var t when t.vx == 0 && t.vy == 1: if (c == '/') return (cart.x, cart.y, -1, +0, cart.t, cart.c); if (c == '\\') return (cart.x, cart.y, +1, +0, cart.t, cart.c); if (c == '+' && cart.t == 0) return (cart.x, cart.y, +1, +0, 1, cart.c); if (c == '+' && cart.t == 2) return (cart.x, cart.y, -1, +0, 0, cart.c); return default; case var t when t.vx == 0 && t.vy == -1: if (c == '/') return (cart.x, cart.y, +1, +0, cart.t, cart.c); if (c == '\\') return (cart.x, cart.y, -1, +0, cart.t, cart.c); if (c == '+' && cart.t == 0) return (cart.x, cart.y, -1, +0, 1, cart.c); if (c == '+' && cart.t == 2) return (cart.x, cart.y, +1, +0, 0, cart.c); return default; } return default; } } }