private static IEnumerable <WordWithValue> CreateWords(IEnumerable <IList <Arrangement> > arrangements) { var arrangementsList = arrangements.ToList(); var alphabetSize = arrangementsList.Count; var language = CreateBaseLanguage(alphabetSize); var tilesInArrangements = arrangementsList.Select(a => a.Max(b => b.TotalValue)).ToList(); foreach (var word in language) { var sumOfTiles = word.Sum(c => tilesInArrangements[c]); if (sumOfTiles <= 14 && sumOfTiles >= 5) { var analyzer = new ArrangementAnalyzer(); foreach (var character in word) { analyzer.AddSetOfArrangements(arrangementsList[character]); } var shanten = analyzer.CalculateShanten(); if (shanten < 9) { yield return(new WordWithValue(word, shanten + 1)); } } } }
private Dictionary <string, string> CreateRedundantArrangements(string workingDirectory) { var fileName = Path.Combine(workingDirectory, "replacements.txt"); if (File.Exists(fileName)) { var redundanciesLines = File.ReadAllLines(fileName); return(redundanciesLines.ToDictionary( line => line.Substring(0, line.IndexOf('>')), line => line.Substring(line.IndexOf('>') + 1))); } var arrangements = GetAllArrangements().ToList(); var alphabetSize = arrangements.Count; var tilesInArrangements = arrangements.Select(a => a.Max(b => b.TotalValue)).ToList(); var replacements = new Dictionary <string, string>(); var foundRedundancy = true; while (foundRedundancy) { foundRedundancy = false; for (var i = 0; i < arrangements.Count; ++i) { // If there is only a single arrangement, it can't have any redundancies. // Still need to keep those in the list for their interactions with others. var arrangement = arrangements[i]; if (arrangement.Count < 2) { continue; } // Check for each arrangement in the current group if it is redundant. for (var j = 0; j < arrangement.Count; ++j) { var isRedundant = true; // Create words for all possible combinations of arrangement groups. var language = CreateBaseLanguage(alphabetSize); foreach (var word in language) { // If the current group of arrangements is not part of the word, skip the word. if (word.All(c => c != i)) { continue; } // Pick the arrangements that correspond to the word and sum their tile counts. var sumOfTiles = word.Sum(c => tilesInArrangements[c]); if (sumOfTiles > 14) { continue; } // It's impossible to have less than 5 usable tiles in a hand. if (sumOfTiles < 5) { continue; } // Calculate the shanten for the word. var analyzer = new ArrangementAnalyzer(); foreach (var character in word) { analyzer.AddSetOfArrangements(arrangements[character]); } var shanten = analyzer.CalculateShanten(); if (shanten >= 9) { continue; } // Calculate the shanten with one arrangement from the current arrangement group removed. var replacement = arrangement.Where((t, index) => index != j).ToList(); var analyzer2 = new ArrangementAnalyzer(); foreach (var character in word) { analyzer2.AddSetOfArrangements(character == i ? replacement : arrangements[character]); } var shanten2 = analyzer2.CalculateShanten(); // If for any word that contains the current arrangement group there is difference in shanten, // the arrangement that was removed above is not redundant. if (shanten != shanten2) { isRedundant = false; break; } } if (isRedundant) { var current = string.Join("", arrangements[i]); arrangements[i].RemoveAt(j); var compacted = string.Join("", arrangements[i]); if (!replacements.ContainsKey(current) || replacements[current] != compacted) { replacements.Add(current, compacted); } foundRedundancy = true; break; } } if (foundRedundancy) { break; } } } var lines = replacements.Select(r => r.Key + ">" + r.Value); File.WriteAllLines(fileName, lines); return(replacements); }