using AdventOfCode.Core; using System.Linq; using System.Text.RegularExpressions; namespace AdventOfCode.Solutions._2023 { public partial class Day12(InputReader reader) : IChallange { private InputReader _inputReader = reader; public async Task GetSolutionPart1() { long total = 0; await foreach(string line in _inputReader.ReadAsStringLine()) { string[] splitted = line.Split(' '); int[] groups = splitted[1].Split(',').Select(int.Parse).ToArray(); Console.Write(splitted[0]); long possiblies = Possibilities2(splitted[0], groups, 0, 0); Console.WriteLine($": {possiblies}"); total += possiblies; //total += Possibilities(splitted[0], groups); } return total.ToString(); } public async Task GetSolutionPart2() { long total = 0; await foreach (string line in _inputReader.ReadAsStringLine()) { string[] splitted = line.Split(' '); var joinedLine = string.Join("?", new[] { splitted[0], splitted[0], splitted[0], splitted[0], splitted[0] }); int[] groups = splitted[1].Split(',').Select(int.Parse).ToArray(); int[] groupsTotal = groups.Concat(groups).Concat(groups).Concat(groups).Concat(groups).ToArray(); //total += Possibilities(splitted[0], groups); Console.Write(joinedLine + " " + string.Join(",", new[] { splitted[1], splitted[1], splitted[1], splitted[1], splitted[1] })); long possiblies = Possibilities2(joinedLine, groupsTotal, 0, 0); Console.WriteLine($": {possiblies}"); total += possiblies; } return total.ToString(); } private long Possibilities(string lineToValidate, int[] groups) { long total = 0; if (lineToValidate.Contains('?')) { var regex = new Regex(Regex.Escape("?")); total += Possibilities(regex.Replace(lineToValidate, ".", 1), groups); total += Possibilities(regex.Replace(lineToValidate, "#", 1), groups); return total; } MatchCollection matches = GroupMatch().Matches(lineToValidate); if (matches.Count == groups.Length && groups.Where((g, i) => matches[i].Length == g).Count() == groups.Length) { //Console.WriteLine($"{lineToValidate} is valid"); return 1; } else return 0; } private long Possibilities2(string lineToValidate, int[] groups, int readIndex, int captureSize) { // if group index is 0 there are no captures and not captures running if (readIndex < lineToValidate.Length) { int[] splitGroups = lineToValidate[..readIndex].Split('.', StringSplitOptions.RemoveEmptyEntries).Select(s => s.Length).ToArray(); if (groups.Length < splitGroups.Length) { // we have more groups than expected return 0; } if (lineToValidate.Length - readIndex < groups.Skip(splitGroups.Length).Sum() + groups.Length - splitGroups.Length - 1) { // there is not enough space to even fit the groups so reject return 0; } // validate everything, including fixed groups for (int i = 0; i < splitGroups.Length - 1; i++) { // all except the last must match if (splitGroups[i] != groups[i]) { return 0; // group lengths do not match, reject } } // the last one is allowed to be smaller than the expected groups size if (splitGroups.Any() && splitGroups[^1] > groups[splitGroups.Length - 1]) { // if the last group is larger than allowed the line is invalid return 0; } } if (!lineToValidate.Contains('?')) // no more variations { int[] splitGroups = lineToValidate.Split('.', StringSplitOptions.RemoveEmptyEntries).Select(s => s.Length).ToArray(); if (splitGroups.Length != groups.Length) { // group amount does not match return 0; } for (int i = 0; i < groups.Length; i++) { if (splitGroups[i] != groups[i]) { return 0; // group lengths do not match, reject } } // valid combos so valid return 1; } long total = 0; //go search for # or ? for (int charIndex = readIndex; charIndex < lineToValidate.Length; charIndex++) { if (lineToValidate[charIndex] == '.') { captureSize = 0; readIndex++; continue; } if (lineToValidate[charIndex] == '#') { captureSize++; readIndex++; continue; } if (lineToValidate[charIndex] == '?') { var regex = new Regex(Regex.Escape("?")); total += Possibilities2(regex.Replace(lineToValidate, "#", 1), groups, readIndex + 1, captureSize + 1); total += Possibilities2(regex.Replace(lineToValidate, ".", 1), groups, readIndex + 1, captureSize); return total; } } return Possibilities2(lineToValidate, groups, readIndex + 1, captureSize); } [GeneratedRegex("#+")] private static partial Regex GroupMatch(); } }