void Main1() { var lines = File.ReadAllLines(Path.Join("..", "..", "05a.txt")).Select(l => l.Trim()).ToList(); if (lines.Last() == "") lines.RemoveAt(lines.Count - 1); List rules = new(); foreach (var line in lines.TakeWhile(l => !string.IsNullOrWhiteSpace(l))) { var parts = line.Split('|'); rules.Add(new( int.Parse(parts[0]), int.Parse(parts[1]) )); } List collections = new(); foreach (var line in lines.SkipWhile(l => !string.IsNullOrWhiteSpace(l)).Skip(1)) { var parts = line.Split(',').Select(int.Parse); collections.Add(new(parts)); } int total = 0; foreach (var collection in collections.Where(c => rules.All(r => c.TestRule(r)))) { total += collection.Middle(); } Console.WriteLine(total); } void Main2() { var lines = File.ReadAllLines(Path.Join("..", "..", "05a.txt")).Select(l => l.Trim()).ToList(); if (lines.Last() == "") lines.RemoveAt(lines.Count - 1); List rules = new(); RuleList rulelist = new(); foreach (var line in lines.TakeWhile(l => !string.IsNullOrWhiteSpace(l))) { var parts = line.Split('|'); Rule rule = new( int.Parse(parts[0]), int.Parse(parts[1]) ); rulelist.Add(rule); rules.Add(rule); } List collections = new(); foreach (var line in lines.SkipWhile(l => !string.IsNullOrWhiteSpace(l)).Skip(1)) { var parts = line.Split(',').Select(int.Parse); collections.Add(new(parts)); } var total = 0; var count = 0; foreach (var collection in collections) { var r = collection.Pairs() .Select(p => rulelist.ExtractRule(p.Item1, p.Item2)) .Where(r => r is not null) .Select(r => (Rule)r) .ToList(); if (!rules.All(collection.TestRule)) { collection.Pages.Sort(rulelist.Compare); total += collection.Pages[collection.Pages.Count / 2]; count++; } } Console.WriteLine($"Collections: {collections.Count}"); Console.WriteLine($"With errors: {count}"); Console.WriteLine($"Solution: {total}"); } Main2(); record struct Rule(int First, int Second); class RuleList { Dictionary<(int,int), bool> Rules = new(); public RuleList() { } public void Add(Rule rule) { bool ordered = rule.First < rule.Second; var pair = ordered ? (rule.First, rule.Second) : (rule.Second, rule.First); Rules.Add(pair, ordered); } //true if correct order, null if no rule public bool? Check(int a, int b) { bool ordered = a < b; var pair = ordered ? (a, b) : (b, a); bool result; return Rules.TryGetValue(pair, out result) ? result ^ ordered : null; } public int Compare(int a, int b) { var check = Check(a, b); if (check is bool _check) return _check ? -1 : 1; return 0; } public Rule? ExtractRule(int a, int b) { var check = Check(a, b); if (check is bool _check) return _check ? new(a, b) : new(b, a); return null; } } class Collection { public readonly List Pages; public Collection(IEnumerable pages) { Pages = pages.ToList(); } public bool TestRule(Rule rule) { bool foundFirst = false; bool foundSecond = false; foreach (var page in Pages) { if (page == rule.First) { if (foundSecond) return false; foundFirst = true; } if (page == rule.Second) { if (foundFirst) return true; foundSecond = true; } } return true; } public int Middle() { return Pages[Pages.Count / 2]; } public List<(int,int)> Pairs() { List<(int,int)> pairs = new(); for (int i = 0; i < Pages.Count-1; i++) { for (int j = i+1; j < Pages.Count; j++) { pairs.Add((Pages[i], Pages[j])); } } return pairs; } }