Example #1
0
 public void Undo(CrossPattern aCrossPattern)
 {
     //Console.WriteLine("Undo: {0}", new String(aCrossPattern.Pattern));
     for (int i = 0; i < _changes.Count; i += 3)
     {
         var    adjIdx = _changes[i];
         var    pos    = _changes[i + 1];
         char[] pattern;
         if (adjIdx == -1)
         {
             pattern = aCrossPattern.Pattern;
         }
         else
         {
             pattern = aCrossPattern.AdjacentPatterns[adjIdx].Pattern;
         }
         pattern[pos] = '.';
     }
     for (int i = 0; i < _instChanges.Count; i += 3)
     {
         var adjIdx = _instChanges[i];
         var old    = _instChanges[i + 1];
         if (adjIdx != -1)
         {
             aCrossPattern.AdjacentPatterns[adjIdx].InstantiationCount = old;
         }
         else
         {
             aCrossPattern.InstantiationCount = old;
         }
     }
 }
Example #2
0
 public void Transform(CrossPattern aCrossPattern)
 {
     for (int i = 0; i < _changes.Count; i += 3)
     {
         var    adjIdx  = _changes[i];
         var    pos     = _changes[i + 1];
         var    newChar = (char)_changes[i + 2];
         char[] pattern;
         if (adjIdx == -1)
         {
             pattern = aCrossPattern.Pattern;
         }
         else
         {
             pattern = aCrossPattern.AdjacentPatterns[adjIdx].Pattern;
         }
         pattern[pos] = newChar;
     }
     for (int i = 0; i < _instChanges.Count; i += 3)
     {
         var adjIdx  = _instChanges[i];
         var newInst = _instChanges[i + 2];
         if (adjIdx != -1)
         {
             aCrossPattern.AdjacentPatterns[adjIdx].InstantiationCount = newInst;
         }
         else
         {
             aCrossPattern.InstantiationCount = newInst;
         }
     }
     //Console.WriteLine("Transform: {0}", new String(aCrossPattern.Pattern));
 }
Example #3
0
        CrossPattern BackTrack(List <int> history, List <List <CrossTransformation> > historyTrans, HashSet <string> usedWords)
        {
            CrossPattern crossPatternToContinueWith = null;

            while (history.Count > 0)
            {
                int last      = history.Count - 1;
                int item      = history[last];
                var succTrans = historyTrans[last];
                var trans     = succTrans[item];
                trans.Undo(trans.Pattern);
                usedWords.Remove(trans.Word);
                item++;
                if (item < succTrans.Count)
                {
                    var nextTrans = succTrans[item];
                    usedWords.Add(nextTrans.Word);
                    nextTrans.Transform(nextTrans.Pattern);
                    history[last] = item;
                    crossPatternToContinueWith = _board.GetMostConstrainedPattern(_dict);
                    break;
                }
                history.RemoveAt(last);
                historyTrans.RemoveAt(last);
            }
            return(crossPatternToContinueWith);
        }
Example #4
0
 public object Clone()
 {
     var result = new CrossPattern(_startX, _startY, _length, _isHorizontal);
     result._instantiationCount = _instantiationCount;
     result._pattern = new char[_pattern.Length];
     Array.Copy(_pattern, result._pattern, _pattern.Length);
     return result;
 }
Example #5
0
 public CrossPattern(int startX, int startY, int length, bool isHorizontal)
 {
     _startX          = startX;
     _startY          = startY;
     _length          = length;
     AdjacentPatterns = new CrossPattern[_length];
     _isHorizontal    = isHorizontal;
     _pattern         = Enumerable.Repeat('.', length).ToArray();
 }
Example #6
0
        public object Clone()
        {
            var result = new CrossPattern(_startX, _startY, _length, _isHorizontal);

            result._instantiationCount = _instantiationCount;
            result._pattern            = new char[_pattern.Length];
            Array.Copy(_pattern, result._pattern, _pattern.Length);
            return(result);
        }
Example #7
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);
        }
Example #8
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);
        }
Example #9
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);
                }
            }
        }
Example #10
0
        /*
         * 1. Choosing which pattern to fill (i.e. which variable to solve for).
         * 2. Picking a suitable word (i.e. which value to select).
         * 3. Choosing where to backtrack to when we reach an impasse.
         */

        public IEnumerable <ICrossBoard> Generate()
        {
            var          history       = new List <int>();
            var          historyTrans  = new List <List <CrossTransformation> >();
            var          matchingWords = new List <string>();
            var          usedWords     = new HashSet <string>();
            CrossPattern pattern       = _board.GetMostConstrainedPattern(_dict);

            Random rnd = new Random();

            while (true)
            {
                DoCommands();
                if (pattern != null)
                {
                    matchingWords.Clear();
                    _dict.GetMatch(pattern.Pattern, matchingWords);
                    var succTrans = new List <CrossTransformation>();
                    foreach (string t in matchingWords)
                    {
                        if (usedWords.Count > 0 && usedWords.Contains(t))
                        {
                            continue;
                        }

                        // checking if there exist words in the dictionary matching each of the adjacent patterns
                        var trans = pattern.TryFill(t, t.AsSpan(), _dict);
                        if (trans != null)
                        {
                            succTrans.Add(trans);
                            trans.Pattern = pattern;
                        }
                    }

                    if (succTrans.Count > 0)
                    {
                        succTrans.Sort(new CrossTransformationComparer()); // using the successfull transform with most ?!

                        // always use the first index (i.e. the one with the most possible adjacent hits)
                        var trans = succTrans[0];
                        history.Add(0);

                        // don't always use the "best" match to randomize the crossword better
                        // var lowestIndexToUse = 0;
                        // var highestIndexToUse = succTrans.Count > 10 ? 10 : succTrans.Count;
                        // int index = rnd.Next(lowestIndexToUse, highestIndexToUse);
                        // var trans = succTrans[index];
                        // history.Add(index);

                        usedWords.Add(trans.Word);
                        trans.Transform(pattern);
                        historyTrans.Add(succTrans);

                        pattern = _board.GetMostConstrainedPattern(_dict);
                    }
                    else
                    {
                        pattern = BackTrack(history, historyTrans, usedWords);
                        if (pattern == null)
                        {
                            yield break;
                        }
                    }
                }
                else
                {
                    yield return(_board.Clone());

                    pattern = BackTrack(history, historyTrans, usedWords);
                    if (pattern == null)
                    {
                        yield break;
                    }
                }
            }
        }
Example #11
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);
            }
        }