static ICrossBoard GenerateFirstCrossWord(ICrossBoard board, ICrossDictionary dictionary, string puzzle) { var placer = new PuzzlePlacer(board, puzzle); var cts = new CancellationTokenSource(); var mre = new ManualResetEvent(false); ICrossBoard successFullBoard = null; foreach (var boardWithPuzzle in placer.GetAllPossiblePlacements(dictionary)) { //boardWithPuzzle.WriteTo(new StreamWriter(Console.OpenStandardOutput(), Console.OutputEncoding) { AutoFlush = true }); var gen = new CrossGenerator(dictionary, boardWithPuzzle); var t = Task.Factory.StartNew(() => { foreach (var solution in gen.Generate()) { successFullBoard = solution; cts.Cancel(); mre.Set(); break; //interested in the first one } }, cts.Token); if (cts.IsCancellationRequested) break; } mre.WaitOne(); return successFullBoard; }
static ICrossBoard GenerateFirstCrossWord(ICrossBoard board, ICrossDictionary dictionary) { var gen = new CrossGenerator(dictionary, board); board.Preprocess(dictionary); return gen.Generate().FirstOrDefault(); }
static void SaveResultToFile(string outputFile, ICrossBoard resultBoard, ICrossDictionary dictionary) { Console.WriteLine("Solution has been found:"); using var writer = new StreamWriter(new FileStream(outputFile, FileMode.Create)); resultBoard.WriteTo(writer); resultBoard.WritePatternsTo(writer, dictionary); }
static ICrossBoard GenerateFirstCrossWord(ICrossBoard board, ICrossDictionary dictionary, string puzzle) { var placer = new PuzzlePlacer(board, puzzle); var cts = new CancellationTokenSource(); var mre = new ManualResetEvent(false); ICrossBoard?successFullBoard = null; foreach (var boardWithPuzzle in placer.GetAllPossiblePlacements(dictionary)) { //boardWithPuzzle.WriteTo(new StreamWriter(Console.OpenStandardOutput(), Console.OutputEncoding) { AutoFlush = true }); var gen = new CrossGenerator(dictionary, boardWithPuzzle); var t = Task.Factory.StartNew(() => { foreach (var solution in gen.Generate()) { successFullBoard = solution; cts.Cancel(); mre.Set(); break; //interested in the first one } }, cts.Token); if (cts.IsCancellationRequested) { break; } } mre.WaitOne(); return(successFullBoard !); }
public CrossPattern GetMostConstrainedPattern(ICrossDictionary aDict) { var min = (int)Constants.Unbounded; CrossPattern result = null; foreach (var p in _horizontalPatterns) { if (p.InstantiationCount >= min) { continue; } result = p; min = p.InstantiationCount; } foreach (var p in _verticalPatterns) { if (p.InstantiationCount >= min) { continue; } result = p; min = p.InstantiationCount; } return(result); }
static ICrossBoard GenerateFirstCrossWord(ICrossBoard board, ICrossDictionary dictionary) { var gen = new CrossGenerator(dictionary, board); board.Preprocess(dictionary); return(gen.Generate().FirstOrDefault()); }
public IEnumerable<ICrossBoard> GetAllPossiblePlacements(ICrossDictionary dictionary) { var puzzle = NormalizePuzzle(_puzzle); var board = (ICrossBoard)_board.Clone(); board.Preprocess(dictionary); var patterns = new List<CrossPattern>(); for (int i = 0; i < board.GetPatternCount(); i++) patterns.Add(board.GetCrossPattern(i)); patterns.Sort((a, b) => -1 * a.Length.CompareTo(b.Length)); if (patterns.Count == 0) yield break; var restPuzzleLength = puzzle.Length; var stack = new List<int>(); var appliedTransformations = new List<CrossTransformation>(); int idx = 0; while (true) { continueOuterLoop: for (; idx < patterns.Count; idx++) { var patt = patterns[idx]; if (restPuzzleLength < patt.Length) continue; if (restPuzzleLength - patt.Length == 1) continue; var trans = patt.TryFillPuzzle(puzzle.Substring(puzzle.Length - restPuzzleLength, patt.Length), dictionary); if (trans != null) { trans.Transform(patt); if (restPuzzleLength == patt.Length) { var cloned = (ICrossBoard)board.Clone(); trans.Undo(patt); yield return cloned; continue; } stack.Add(idx + 1); trans.Pattern = patt; appliedTransformations.Add(trans); restPuzzleLength -= patt.Length; idx = 0; goto continueOuterLoop; } } if (stack.Count == 0) break; idx = stack.Back(); stack.Pop(); var appTr = appliedTransformations.Back(); appliedTransformations.Pop(); appTr.Undo(appTr.Pattern); restPuzzleLength += appTr.Pattern.Length; } yield break; }
public CrossTransformation TryFillPuzzle(ReadOnlySpan <char> word, ICrossDictionary dict) { for (int i = 0; i < word.Length; i++) { if (_pattern[i] != '.') { return(null); } } return(TryFill(null, word, dict, true)); }
private static string GetDescription(ICrossDictionary dictionary, string word) { string description; if (!dictionary.TryGetDescription(word, out description)) { description = "[PUZZLE]"; } return(description); }
public static async Task GenerateCrosswordsAsync(ICrossBoard board, ICrossDictionary dictionary, string puzzle, CancellationToken cancellationToken) { // Keep trying to until we can start HubConnection hubConnection = null; while (true) { hubConnection = new HubConnectionBuilder() .WithUrl("http://localhost:8000/crosswordsignalrhub") .ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Information); logging.AddConsole(); }) .Build(); try { await hubConnection.StartAsync(); break; } catch (Exception) { await Task.Delay(1000); } } try { var generated = GenerateCrossWords(board, dictionary, puzzle, cancellationToken); int generatedCount = 0; foreach (var curCrossword in generated) { generatedCount++; var cb = curCrossword as CrossBoard; var crossWordModel = cb.ToCrossWordModel(dictionary); crossWordModel.Title = "Generated crossword number " + generatedCount; await hubConnection.InvokeAsync("SendCrossword", "Client", crossWordModel, cancellationToken); // await Task.Delay(100); // this makes the generation slower, can be removed break; } } catch (OperationCanceledException) { // Cancel and timeout logic } await hubConnection.DisposeAsync(); }
public void WritePatternsTo(StreamWriter writer, ICrossDictionary dictionary) { writer.WriteLine("Patterns: "); int cnt = GetPatternCount(); for (int i = 0; i < cnt; i++) { var pattern = GetCrossPattern(i); var word = pattern.GetWord(); var description = GetDescription(dictionary, word); writer.WriteLine(string.Format("{0},{1}", pattern, description)); } }
CrossTransformation TryFill(string dictWord, ReadOnlySpan <char> word, ICrossDictionary dict, bool puzzle) { var trans = new CrossTransformation(dictWord); int instSum = 0; for (int i = 0; i < word.Length; i++) { if (_pattern[i] == '.') { if (AdjacentPatterns[i] != null) { int adjIndex; if (_isHorizontal) { adjIndex = _startY - AdjacentPatterns[i].StartY; } else { adjIndex = _startX - AdjacentPatterns[i].StartX; } char c = AdjacentPatterns[i].Pattern[adjIndex]; if (c == '.') { char[] adjacent = AdjacentPatterns[i].Pattern; adjacent[adjIndex] = word[i]; int newInstCount = dict.GetMatchCount(adjacent); adjacent[adjIndex] = '.'; // clear the adj index if (newInstCount == 0) { return(null); } instSum += newInstCount; trans.AddChangeInst(i, AdjacentPatterns[i].InstantiationCount, newInstCount); trans.AddChange(i, adjIndex, word[i]); } else if (puzzle || c != word[i]) { return(null); } } trans.AddChange(-1, i, word[i]); } } trans.AddChangeInst(-1, _instantiationCount, (int)Constants.Unbounded); trans.SumInst = instSum; // set the sum instantiation count return(trans); }
public CrossWordController(IConfiguration config, UserManager <ApplicationUser> userManager, WordHintDbContext db, ICrossDictionary dictionary, IBackgroundTaskQueue queue, ILogger <CrossWordController> logger, IServiceScopeFactory serviceScopeFactory) { this.config = config; this.userManager = userManager; this.db = db; this.dictionary = dictionary; this.logger = logger; this.Queue = queue; this.serviceScopeFactory = serviceScopeFactory; }
public void WritePatternsTo(StreamWriter writer, ICrossDictionary dictionary) { writer.WriteLine("Patterns: "); int cnt = GetPatternCount(); for (int i = 0; i < cnt; i++) { var pattern = GetCrossPattern(i); var word = pattern.GetWord(); if (!dictionary.TryGetDescription(word, out var description)) { description = "[PUZZLE]"; } writer.WriteLine($"{pattern},{description}"); } }
public void WritePatternsTo(StreamWriter writer, ICrossDictionary dictionary) { writer.WriteLine("Patterns: "); int cnt = GetPatternCount(); for (int i = 0; i < cnt; i++) { var pattern = GetCrossPattern(i); var word = pattern.GetWord(); string description; if (!dictionary.TryGetDescription(word, out description)) { description = "[PUZZLE]"; } writer.WriteLine(string.Format("{0},{1}", pattern, description)); } }
static void SaveResultToFile(string outputFile, ICrossBoard resultBoard, ICrossDictionary dictionary) { Console.WriteLine("Solution has been found:"); using (var writer = new StreamWriter(new FileStream(outputFile, FileMode.Create))) { resultBoard.WriteTo(writer); resultBoard.WritePatternsTo(writer, dictionary); } }
public CrossWordGuardian ToCrossWordModelGuardian(ICrossDictionary dictionary) { var model = new CrossWordGuardian(); var clueList = new List <IClue>(); var patterns = new List <CrossPattern>(); // across = horizontal foreach (var p in _horizontalPatterns) { patterns.Add(p); } // down = vertical foreach (var p in _verticalPatterns) { patterns.Add(p); } var sortedPatterns = patterns.OrderBy(s => s.StartY).ThenBy(s => s.StartX); int gridNumber = 0; CrossPattern lastPattern = null; var coordinateMap = new Dictionary <CrossPattern, Coordinate>(); // when using a database - read in all descriptions once dictionary.AddAllDescriptions(patterns.Select(a => a.GetWord()).ToList()); foreach (var p in sortedPatterns) { if (lastPattern != null && lastPattern.StartX == p.StartX && lastPattern.StartY == p.StartY) { // patterns starts at same index } else { // pattern start at new index, increment gridNumber++; } // store grid number as a part of the coordinate coordinateMap.Add(p, new Coordinate(p.StartX, p.StartY, gridNumber)); // and store the clues var word = p.GetWord(); var description = p.IsPuzzle ? "[PUZZLE]" : GetDescription(dictionary, word); var clue = new IClue(); clue.Id = string.Format("{0}-{1}", gridNumber, p.IsHorizontal ? "across" : "down"); clue.Number = gridNumber; clue.HumanNumber = gridNumber.ToString(); clue.Clue = string.Format("{0} ({1})", description, p.Length); clue.Direction = p.IsHorizontal ? Direction.Across : Direction.Down; clue.Length = p.Length; clue.Group = new string[] { clue.Id }; clue.Position = new IPosition() { X = p.StartX, Y = p.StartY }; clue.Solution = word; clue.SeparatorLocations = new SeparatorLocations(); clueList.Add(clue); // save last pattern to compare with lastPattern = p; } model.Id = null; model.Name = "Generated Crossword"; model.Creator = new ICreator() { Name = "the amazing crossword generator", WebUrl = "" }; model.Entries = clueList.ToArray(); model.Dimensions = new IDimensions { Cols = _sizeX, Rows = _sizeY }; model.CrosswordType = CrosswordType.Quick; model.SolutionAvailable = true; model.Pdf = null; model.Instructions = null; model.Date = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); model.DateSolutionAvailable = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); return(model); }
public CrossWordTimes ToCrossWordModel(ICrossDictionary dictionary) { var model = new CrossWordTimes(); var board = new char[_sizeX, _sizeY]; foreach (var sw in _startWords) { board[sw.StartX, sw.StartY] = '-'; } var patterns = new List <CrossPattern>(); var stringWriter = new StringWriter(); // across = horizontal foreach (var p in _horizontalPatterns) { patterns.Add(p); for (int x = p.StartX; x < p.StartX + p.Length; x++) { if (p.Pattern != null) { board[x, p.StartY] = p.Pattern[x - p.StartX]; } else { board[x, p.StartY] = '.'; } } // stringWriter.WriteLine("{0}<br>", p); } // down = vertical foreach (var p in _verticalPatterns) { patterns.Add(p); for (int y = p.StartY; y < p.StartY + p.Length; y++) { if (p.Pattern != null) { var c = p.Pattern[y - p.StartY]; if (c != '.') { board[p.StartX, y] = c; } } } // stringWriter.WriteLine("{0}<br>", p); } // calculate grid numbers and build answer and clues lists var acrossAnswerList = new List <String>(); var downAnswerList = new List <String>(); var acrossClueList = new List <String>(); var downClueList = new List <String>(); model.Gridnums = new long[_sizeX * _sizeY]; model.Circles = new long[_sizeX * _sizeY]; var sortedPatterns = patterns.OrderBy(s => s.StartY).ThenBy(s => s.StartX); int gridNumber = 0; CrossPattern lastPattern = null; var coordinateMap = new Dictionary <CrossPattern, Coordinate>(); // when using a database - read in all descriptions once dictionary.AddAllDescriptions(patterns.Select(a => a.GetWord()).ToList()); foreach (var p in sortedPatterns) { if (lastPattern != null && lastPattern.StartX == p.StartX && lastPattern.StartY == p.StartY) { // patterns starts at same index } else { // pattern start at new index, increment gridNumber++; } // store grid number as a part of the coordinate coordinateMap.Add(p, new Coordinate(p.StartX, p.StartY, gridNumber)); // and store the clues var word = p.GetWord(); var description = p.IsPuzzle ? "[PUZZLE]" : GetDescription(dictionary, word); string clue = string.Format("{0}. {1}", gridNumber, description); if (p.IsHorizontal) { acrossAnswerList.Add(word); acrossClueList.Add(clue); } else { downAnswerList.Add(word); downClueList.Add(clue); } // save last pattern to compare with lastPattern = p; } // build output var grid = new List <String>(); for (int y = 0; y < _sizeY; y++) { string row = ""; for (int x = 0; x < _sizeX; x++) { row += board[x, y] + " "; // set grid but replace - with . grid.Add(board[x, y].ToString().Replace('-', '.')); if (board[x, y] != '-') { var coordinate = new Coordinate(x, y); if (coordinateMap.ContainsValue(coordinate)) { Coordinate foundCoordinate = null; var coordinates = coordinateMap.Where(v => v.Value == coordinate); if (coordinates.Count(a => a.Key.IsPuzzle) > 0) { var hit = coordinates.Where(a => a.Key.IsPuzzle).First(); var IsHorizontal = hit.Key.IsHorizontal; var letterCount = hit.Key.Length; // highlight all cells covered by the word foundCoordinate = hit.Value; if (IsHorizontal) { for (int i = 0; i < letterCount; i++) { model.Circles[(y * _sizeX) + x + i] = 1; } } else { for (int i = 0; i < letterCount; i++) { model.Circles[((y * _sizeX) + x) + (i * _sizeX)] = 1; } } } else { foundCoordinate = coordinates.First().Value; } model.Gridnums[(y * _sizeX) + x] = foundCoordinate.GridNumber; } } } // stringWriter.WriteLine("{0:00}: {1} <br>", y, row); } model.Title = "Generated Crossword"; model.Author = "the amazing crossword generator"; model.Copyright = "Crossword Generator"; model.Size = new Size { Cols = _sizeX, Rows = _sizeY }; // model.Notepad = "<br>" + stringWriter.ToString(); model.Grid = grid.ToArray(); model.Clues = new Answers() { Across = acrossClueList.ToArray(), Down = downClueList.ToArray() }; model.Answers = new Answers() { Across = acrossAnswerList.ToArray(), Down = downAnswerList.ToArray() }; model.Shadecircles = false; return(model); }
public CrossTransformation TryFill(string dictWord, ReadOnlySpan <char> word, ICrossDictionary dict) { return(TryFill(dictWord, word, dict, false)); }
public CrossGenerator(ICrossDictionary aDict, ICrossBoard aBoard) { _dict = aDict; _board = aBoard; }
public void Preprocess(ICrossDictionary aDict) { _horizontalPatterns.Clear(); _startWords.Sort(new YXStartWordComparer()); //first create horizontal patterns int wordIdx = 0; for (int y = 0; y < _sizeY; y++) { int nextX = 0; while (wordIdx < _startWords.Count) { var sw = _startWords[wordIdx]; //Console.WriteLine("StartWord x:{0} y:{1} idx:{2}/cnt:{3}",sw.StartX,sw.StartY,wordIdx,_startWords.Count); if (sw.StartY == y) { if (sw.StartX - nextX >= MinPatternLength) { var cp = new CrossPattern(nextX, y, sw.StartX - nextX, true); //Console.WriteLine("SW pattern startX: {0} startY: {1} len: {2}",cp.StartX, cp.StartY, cp.Length); _horizontalPatterns.Add(cp); } nextX = sw.StartX + 1; wordIdx++; } else { break; } } if (_sizeX - nextX >= MinPatternLength) { var cp = new CrossPattern(nextX, y, _sizeX - nextX, true); //Console.WriteLine("EL pattern startX: {0} startY: {1} len: {2}",cp.StartX, cp.StartY, cp.Length); _horizontalPatterns.Add(cp); } } _verticalPatterns.Clear(); _startWords.Sort(new XYStartWordComparer()); //first create horizontal patterns wordIdx = 0; for (int x = 0; x < _sizeX; x++) { int nextY = 0; while (wordIdx < _startWords.Count) { var sw = _startWords[wordIdx]; //Console.WriteLine("StartWord x:{0} y:{1} idx:{2}/cnt:{3}",sw.StartX,sw.StartY,wordIdx,_startWords.Count); if (sw.StartX == x) { if (sw.StartY - nextY >= MinPatternLength) { var cp = new CrossPattern(x, nextY, sw.StartY - nextY, false); //Console.WriteLine("SW patternY startX: {0} startY: {1} len: {2}",cp.StartX, cp.StartY, cp.Length); _verticalPatterns.Add(cp); } nextY = sw.StartY + 1; wordIdx++; } else { break; } } if (_sizeY - nextY >= MinPatternLength) { var cp = new CrossPattern(x, nextY, _sizeY - nextY, false); //Console.WriteLine("EL patternY startX: {0} startY: {1} len: {2}",cp.StartX, cp.StartY, cp.Length); _verticalPatterns.Add(cp); } } BindAdjacentPatterns(); //set instantiation count int patternCount = GetPatternCount(); for (int i = 0; i < patternCount; i++) { var pattern = GetCrossPattern(i); pattern.InstantiationCount = aDict.GetWordOfLengthCount(pattern.Length); } }
public void Preprocess(ICrossDictionary aDict) { _horizontalPatterns = new List <CrossPattern>(); _startWords.Sort(new YXStartWordComparer()); // first create horizontal patterns int wordIdx = 0; for (int y = 0; y < _sizeY; y++) { int nextX = 0; while (wordIdx < _startWords.Count) { var sw = _startWords[wordIdx]; // Console.WriteLine("StartWord x:{0} y:{1} idx:{2}/cnt:{3}",sw.StartX,sw.StartY,wordIdx,_startWords.Count); if (sw.StartY == y) { if (sw.StartX - nextX >= MinPatternLength) { var cp = new CrossPattern(nextX, y, sw.StartX - nextX, true); // Console.WriteLine("SW pattern startX: {0} startY: {1} len: {2}",cp.StartX, cp.StartY, cp.Length); _horizontalPatterns.Add(cp); } nextX = sw.StartX + 1; wordIdx++; } else { break; } } if (_sizeX - nextX >= MinPatternLength) { var cp = new CrossPattern(nextX, y, _sizeX - nextX, true); // Console.WriteLine("EL pattern startX: {0} startY: {1} len: {2}",cp.StartX, cp.StartY, cp.Length); _horizontalPatterns.Add(cp); } } _verticalPatterns = new List <CrossPattern>(); _startWords.Sort(new XYStartWordComparer()); // then create vertical patterns wordIdx = 0; for (int x = 0; x < _sizeX; x++) { int nextY = 0; while (wordIdx < _startWords.Count) { var sw = _startWords[wordIdx]; // Console.WriteLine("StartWord x:{0} y:{1} idx:{2}/cnt:{3}",sw.StartX,sw.StartY,wordIdx,_startWords.Count); if (sw.StartX == x) { if (sw.StartY - nextY >= MinPatternLength) { var cp = new CrossPattern(x, nextY, sw.StartY - nextY, false); // Console.WriteLine("SW patternY startX: {0} startY: {1} len: {2}",cp.StartX, cp.StartY, cp.Length); _verticalPatterns.Add(cp); } nextY = sw.StartY + 1; wordIdx++; } else { break; } } if (_sizeY - nextY >= MinPatternLength) { var cp = new CrossPattern(x, nextY, _sizeY - nextY, false); // Console.WriteLine("EL patternY startX: {0} startY: {1} len: {2}",cp.StartX, cp.StartY, cp.Length); _verticalPatterns.Add(cp); } } BindAdjacentPatterns(); // calculate instantiation count var wordLengthCount = new int[aDict.MaxWordLength + 1]; for (int i = 1; i <= aDict.MaxWordLength; i++) { wordLengthCount[i] = aDict.GetWordOfLengthCount(i); } int patternCount = GetPatternCount(); for (int i = 0; i < patternCount; i++) { var pattern = GetCrossPattern(i); if (pattern.Pattern == null) { // empty pattern.InstantiationCount = wordLengthCount[pattern.Length]; pattern.Pattern = Enumerable.Repeat('.', pattern.Length).ToArray(); } else { // already set some letters pattern.InstantiationCount = aDict.GetMatchCount(pattern.Pattern); } } }
public CrossGenerator(ICrossDictionary aDict, ICrossBoard aBoard) { _dict = aDict; _board = aBoard; }
private static IEnumerable <ICrossBoard> GenerateCrossWords(ICrossBoard board, ICrossDictionary dictionary, string puzzle, CancellationToken cancellationToken) { if (puzzle != null) { var placer = new PuzzlePlacer(board, puzzle); foreach (var boardWithPuzzle in placer.GetAllPossiblePlacements(dictionary)) { cancellationToken.ThrowIfCancellationRequested(); var gen = new CrossGenerator(dictionary, boardWithPuzzle); // limit int generatedCount = 0; var generated = gen.Generate(); foreach (var solution in generated) { cancellationToken.ThrowIfCancellationRequested(); generatedCount++; if (generatedCount >= MAX_GENERATOR_COUNT) { break; } yield return(solution); } } } else { var gen = new CrossGenerator(dictionary, board); board.Preprocess(dictionary); var crosswords = gen.Generate(); // limit int generatedCount = 0; foreach (var resultBoard in crosswords) { cancellationToken.ThrowIfCancellationRequested(); generatedCount++; if (generatedCount >= MAX_GENERATOR_COUNT) { break; } yield return(resultBoard); } } }
CrossTransformation TryFill(string word, ICrossDictionary dict, bool puzzle) { var trans = new CrossTransformation(word); int instSum = 0; for (int i = 0; i < word.Length; i++) { if (_pattern[i] == '.') { if (AdjacentPatterns[i] != null) { int adjIndex; if (_isHorizontal) adjIndex = _startY - AdjacentPatterns[i].StartY; else adjIndex = _startX - AdjacentPatterns[i].StartX; char c = AdjacentPatterns[i].Pattern[adjIndex]; if (c == '.') { char[] adjacent = AdjacentPatterns[i].Pattern; adjacent[adjIndex] = word[i]; int newInstCount = dict.GetMatchCount(adjacent); adjacent[adjIndex] = '.'; if (newInstCount == 0) return null; instSum += newInstCount; trans.AddChangeInst(i, AdjacentPatterns[i].InstantiationCount, newInstCount); trans.AddChange(i, adjIndex, word[i]); } else if (puzzle || c != word[i]) { return null; } } trans.AddChange(-1, i, word[i]); } } trans.AddChangeInst(-1, _instantiationCount, (int)Constants.Unbounded); trans.SumInst = instSum; return trans; }
public IEnumerable <ICrossBoard> GetAllPossiblePlacements(ICrossDictionary dictionary) { var puzzle = NormalizePuzzle(_puzzle); // used to be .AsSpan() but throwing exception: Instance of type 'ReadOnlySpan<char>' cannot be used inside a nested function, query expression, iterator block or async method var board = _board.Clone(); board.Preprocess(dictionary); var patterns = new List <CrossPattern>(); for (int i = 0; i < board.GetPatternCount(); i++) { patterns.Add(board.GetCrossPattern(i)); } // sort by word length patterns.Sort((a, b) => - 1 * a.Length.CompareTo(b.Length)); if (patterns.Count == 0) { yield break; } var restPuzzleLength = puzzle.Length; var stack = new List <int>(); var appliedTransformations = new List <CrossTransformation>(); int idx = 0; while (true) { continueOuterLoop: for (; idx < patterns.Count; idx++) { var pattern = patterns[idx]; if (restPuzzleLength < pattern.Length) { continue; } if (restPuzzleLength - pattern.Length == 1) { break; // PIN: this was a continue statement - which seems like a bug } var trans = pattern.TryFillPuzzle(puzzle.AsSpan(puzzle.Length - restPuzzleLength, pattern.Length), dictionary); if (trans != null) { trans.Transform(pattern); if (restPuzzleLength == pattern.Length) { // ensure only one pattern is marked as a puzzle patterns.All(c => { c.IsPuzzle = false; return(true); }); // set the current pattern as puzzle pattern.IsPuzzle = true; var cloned = (ICrossBoard)board.Clone(); // clone before we revert the puzzle pattern trans.Undo(pattern); yield return(cloned); continue; } stack.Add(idx + 1); trans.Pattern = pattern; appliedTransformations.Add(trans); restPuzzleLength -= pattern.Length; idx = 0; goto continueOuterLoop; } } if (stack.Count == 0) { break; } idx = stack.Back(); stack.Pop(); var appTr = appliedTransformations.Back(); appliedTransformations.Pop(); appTr.Undo(appTr.Pattern); restPuzzleLength += appTr.Pattern.Length; } yield break; }
public CrossTransformation TryFillPuzzle(string word, ICrossDictionary dict) { for (int i = 0; i < word.Length; i++ ) if (_pattern[i] != '.') return null; return TryFill(word, dict, true); }
public CrossTransformation TryFill(string word, ICrossDictionary dict) { return TryFill(word, dict, false); }
public IEnumerable <ICrossBoard> GetAllPossiblePlacements(ICrossDictionary dictionary) { var puzzle = NormalizePuzzle(_puzzle).AsMemory(); var board = _board.Clone(); board.Preprocess(dictionary); var patterns = new List <CrossPattern>(); for (int i = 0; i < board.GetPatternCount(); i++) { patterns.Add(board.GetCrossPattern(i)); } patterns.Sort((a, b) => - 1 * a.Length.CompareTo(b.Length)); if (patterns.Count == 0) { yield break; } var restPuzzleLength = puzzle.Length; var stack = new List <int>(); var appliedTransformations = new List <CrossTransformation>(); int idx = 0; while (true) { continueOuterLoop: for (; idx < patterns.Count; idx++) { var pattern = patterns[idx]; if (restPuzzleLength < pattern.Length) { continue; } if (restPuzzleLength - pattern.Length == 1) { continue; } var trans = pattern.TryFillPuzzle(puzzle.Slice(puzzle.Length - restPuzzleLength, pattern.Length).Span, dictionary); if (trans != null) { trans.Transform(pattern); if (restPuzzleLength == pattern.Length) { var cloned = board.Clone(); trans.Undo(pattern); yield return(cloned); continue; } stack.Add(idx + 1); trans.Pattern = pattern; appliedTransformations.Add(trans); restPuzzleLength -= pattern.Length; idx = 0; goto continueOuterLoop; } } if (stack.Count == 0) { break; } idx = stack.Back(); stack.Pop(); var appTr = appliedTransformations.Back(); appliedTransformations.Pop(); appTr.Undo(appTr.Pattern); restPuzzleLength += appTr.Pattern.Length; } }