234 lines
5.0 KiB
Plaintext
234 lines
5.0 KiB
Plaintext
|
<Query Kind="Program" />
|
||
|
|
||
|
class Rail
|
||
|
{
|
||
|
public int X,Y;
|
||
|
public Rail N,E,S,W;
|
||
|
}
|
||
|
class Cart
|
||
|
{
|
||
|
public bool C=false;
|
||
|
public Dir D;
|
||
|
public Rail R;
|
||
|
public int Mem = 0;
|
||
|
}
|
||
|
enum Dir { N = 0, E = 1, S = 2, W = 3 }
|
||
|
|
||
|
void Main()
|
||
|
{
|
||
|
(List<Rail> rails, List<Cart> carts) = Parse(File.ReadAllLines(Path.Combine(Path.GetDirectoryName(Util.CurrentQueryPath), @"13_input.txt")));
|
||
|
|
||
|
int cc = carts.Count;
|
||
|
for (int gen = 0; ; gen++)
|
||
|
{
|
||
|
foreach (var c in carts.OrderBy(c => c.R.Y * 10000 + c.R.X))
|
||
|
{
|
||
|
if (c.C)continue;
|
||
|
switch (c.D)
|
||
|
{
|
||
|
case Dir.S:
|
||
|
Move(c, new[] { (Dir.E, c.R.E), (Dir.S, c.R.S), (Dir.W, c.R.W) });
|
||
|
break;
|
||
|
case Dir.W:
|
||
|
Move(c, new[] { (Dir.S, c.R.S), (Dir.W, c.R.W), (Dir.N, c.R.N) });
|
||
|
break;
|
||
|
case Dir.N:
|
||
|
Move(c, new[] { (Dir.W, c.R.W), (Dir.N, c.R.N), (Dir.E, c.R.E) });
|
||
|
break;
|
||
|
case Dir.E:
|
||
|
Move(c, new[] { (Dir.N, c.R.N), (Dir.E, c.R.E), (Dir.S, c.R.S) });
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
var dc = carts.FirstOrDefault(oc => oc != c && oc.R == c.R && !oc.C);
|
||
|
if (dc != null) { c.C = dc.C = true; cc-=2; }
|
||
|
if (cc == 1) { $"{carts.Single(p => !p.C).R.X},{carts.Single(p => !p.C).R.Y} after {gen}".Dump(); return; }
|
||
|
|
||
|
}
|
||
|
//foreach (var c in carts) $"{c.R.X}|{c.R.Y}|{c.D}".Dump();"------".Dump();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void Move(Cart c, IEnumerable<(Dir, Rail)> options)
|
||
|
{
|
||
|
var outs = options.Where(p => p.Item2 != null).ToList();
|
||
|
if (outs.Count == 1)
|
||
|
{
|
||
|
c.R = outs[0].Item2;
|
||
|
c.D = outs[0].Item1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
c.R = outs[c.Mem % 3].Item2;
|
||
|
c.D = outs[c.Mem % 3].Item1;
|
||
|
c.Mem++;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void Dump(List<Rail> rails, List<Cart> carts)
|
||
|
{
|
||
|
int maxx = rails.Max(r => r.X) + 1;
|
||
|
int maxy = rails.Max(r => r.Y) + 1;
|
||
|
|
||
|
var b = new StringBuilder();
|
||
|
for (int yy = 0; yy < maxy; yy++)
|
||
|
{
|
||
|
for (int xx = 0; xx < maxx; xx++)
|
||
|
{
|
||
|
var cc = carts.FirstOrDefault(c => c.R.X == xx && c.R.Y == yy);
|
||
|
if (cc != null)
|
||
|
{
|
||
|
if (cc.D == Dir.N) b.Append('^');
|
||
|
if (cc.D == Dir.E) b.Append('>');
|
||
|
if (cc.D == Dir.S) b.Append('v');
|
||
|
if (cc.D == Dir.W) b.Append('<');
|
||
|
}
|
||
|
else if (rails.Any(r => r.X == xx && r.Y == yy))
|
||
|
{
|
||
|
b.Append('.');
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
b.Append(' ');
|
||
|
}
|
||
|
}
|
||
|
b.AppendLine();
|
||
|
}
|
||
|
b.ToString().Dump();
|
||
|
"".Dump();
|
||
|
}
|
||
|
|
||
|
(List<Rail>, List<Cart>) Parse(string[] line)
|
||
|
{
|
||
|
var rails = new Dictionary<(int, int), Rail>();
|
||
|
var carts = new List<Cart>();
|
||
|
|
||
|
Rail get(int x, int y) { if (rails.TryGetValue((x, y), out var v)) return v; Rail r = new Rail { X = x, Y = y }; rails.Add((x, y), r); return r; }
|
||
|
|
||
|
char last = ' ';
|
||
|
for (int y = 0; y < line.Length; y++)
|
||
|
{
|
||
|
last = ' ';
|
||
|
for (int x = 0; x < line[y].Length; x++)
|
||
|
{
|
||
|
char c = line[y][x];
|
||
|
if (c == ' ') continue;
|
||
|
|
||
|
switch (c)
|
||
|
{
|
||
|
case '-':
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x - 1, y);
|
||
|
var rb = get(x + 1, y);
|
||
|
rr.W = ra; ra.E = rr;
|
||
|
rr.E = rb; rb.W = rr;
|
||
|
}
|
||
|
break;
|
||
|
case '|':
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x, y - 1);
|
||
|
var rb = get(x, y + 1);
|
||
|
rr.N = ra; ra.S = rr;
|
||
|
rr.S = rb; rb.N = rr;
|
||
|
}
|
||
|
break;
|
||
|
case '+':
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x, y - 1);
|
||
|
var rb = get(x + 1, y);
|
||
|
var rc = get(x, y + 1);
|
||
|
var rd = get(x - 1, y);
|
||
|
rr.N = ra; ra.S = rr;
|
||
|
rr.E = rb; rb.W = rr;
|
||
|
rr.S = rc; rc.N = rr;
|
||
|
rr.W = rd; rd.E = rr;
|
||
|
}
|
||
|
break;
|
||
|
case '/':
|
||
|
if (last == '-' || last == '+')
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x - 1, y);
|
||
|
var rb = get(x, y - 1);
|
||
|
rr.W = ra; ra.E = rr;
|
||
|
rr.N = rb; rb.S = rr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x + 1, y);
|
||
|
var rb = get(x, y + 1);
|
||
|
rr.E = ra; ra.W = rr;
|
||
|
rr.S = rb; rb.N = rr;
|
||
|
}
|
||
|
break;
|
||
|
case '\\':
|
||
|
if (last == '-' || last == '+')
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x - 1, y);
|
||
|
var rb = get(x, y + 1);
|
||
|
rr.W = ra; ra.E = rr;
|
||
|
rr.S = rb; rb.N = rr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x + 1, y);
|
||
|
var rb = get(x, y - 1);
|
||
|
rr.E = ra; ra.W = rr;
|
||
|
rr.N = rb; rb.S = rr;
|
||
|
}
|
||
|
break;
|
||
|
case '^':
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x, y - 1);
|
||
|
var rb = get(x, y + 1);
|
||
|
rr.N = ra; ra.S = rr;
|
||
|
rr.S = rb; rb.N = rr;
|
||
|
carts.Add(new Cart { D = Dir.N, R = rr, });
|
||
|
}
|
||
|
break;
|
||
|
case 'v':
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x, y - 1);
|
||
|
var rb = get(x, y + 1);
|
||
|
rr.N = ra; ra.S = rr;
|
||
|
rr.S = rb; rb.N = rr;
|
||
|
carts.Add(new Cart { D = Dir.S, R = rr, });
|
||
|
}
|
||
|
break;
|
||
|
case '>':
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x - 1, y);
|
||
|
var rb = get(x + 1, y);
|
||
|
rr.W = ra; ra.E = rr;
|
||
|
rr.E = rb; rb.W = rr;
|
||
|
carts.Add(new Cart { D = Dir.E, R = rr, });
|
||
|
}
|
||
|
break;
|
||
|
case '<':
|
||
|
{
|
||
|
var rr = get(x, y);
|
||
|
var ra = get(x - 1, y);
|
||
|
var rb = get(x + 1, y);
|
||
|
rr.W = ra; ra.E = rr;
|
||
|
rr.E = rb; rb.W = rr;
|
||
|
carts.Add(new Cart { D = Dir.W, R = rr, });
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
last = c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (rails.Select(p => p.Value).ToList(), carts);
|
||
|
}
|