Beispiel #1
22
 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;
 }
Beispiel #2
5
 static ICrossBoard GenerateFirstCrossWord(ICrossBoard board, ICrossDictionary dictionary)
 {
     var gen = new CrossGenerator(dictionary, board);
     board.Preprocess(dictionary);
     return gen.Generate().FirstOrDefault();
 }
Beispiel #3
0
 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);
 }
Beispiel #4
0
        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 !);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        static ICrossBoard GenerateFirstCrossWord(ICrossBoard board, ICrossDictionary dictionary)
        {
            var gen = new CrossGenerator(dictionary, board);

            board.Preprocess(dictionary);
            return(gen.Generate().FirstOrDefault());
        }
Beispiel #7
0
        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;
        }
Beispiel #8
0
 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));
 }
Beispiel #9
0
        private static string GetDescription(ICrossDictionary dictionary, string word)
        {
            string description;

            if (!dictionary.TryGetDescription(word, out description))
            {
                description = "[PUZZLE]";
            }

            return(description);
        }
Beispiel #10
0
        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();
        }
Beispiel #11
0
        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));
            }
        }
Beispiel #12
0
        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;
 }
Beispiel #14
0
    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}");
        }
    }
Beispiel #15
0
        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));
            }
        }
Beispiel #16
0
 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);
     }
 }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        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);
        }
Beispiel #19
0
 public CrossTransformation TryFill(string dictWord, ReadOnlySpan <char> word, ICrossDictionary dict)
 {
     return(TryFill(dictWord, word, dict, false));
 }
Beispiel #20
0
 public CrossGenerator(ICrossDictionary aDict, ICrossBoard aBoard)
 {
     _dict = aDict;
     _board = aBoard;
 }
Beispiel #21
0
    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);
        }
    }
Beispiel #22
0
        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);
                }
            }
        }
Beispiel #23
0
 public CrossGenerator(ICrossDictionary aDict, ICrossBoard aBoard)
 {
     _dict  = aDict;
     _board = aBoard;
 }
Beispiel #24
0
        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);
                }
            }
        }
Beispiel #25
0
 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;
 }
Beispiel #26
0
        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;
        }
Beispiel #27
0
 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);
 }
Beispiel #28
0
 public CrossTransformation TryFill(string word, ICrossDictionary dict)
 {
     return TryFill(word, dict, false);
 }
Beispiel #29
0
        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;
            }
        }