Exemple #1
0
        public bool Check(Soup soup, WordEntry entry)
        {
            var boundaries = new BoundariesManager(NullLogger <BoundariesManager> .Instance);

            boundaries.Soup = soup;
            return(boundaries.Check(entry));
        }
Exemple #2
0
        private (Range left, Range right, bool hasCommon) FindCommonLetters(WordEntry a, WordEntry b)
        {
            int    minLength = Math.Min(a.Name.Length, b.Name.Length);
            string nameA     = a.Direction.IsReverse() ? Reverse(a.Name) : a.Name;
            string nameB     = b.Direction.IsReverse() ? Reverse(b.Name) : b.Name;

            for (int i = 1; i < minLength; i++)
            {
                string e = nameA.Substring(nameA.Length - i);
                string c = nameB.Substring(0, i);
                if (e == c)
                {
                    int leftInit  = a.Direction.IsReverse() ? 0 : nameA.Length - i;
                    int rightInit = b.Direction.IsReverse() ? nameB.Length - i : 0;
                    return(left : new Range {
                        Init = leftInit, Length = i
                    },
                           right : new Range {
                        Init = rightInit, Length = i
                    },
                           hasCommon : true
                           );
                }
            }
            return(left : null, right : null, hasCommon : false);
        }
Exemple #3
0
        /// <summary>
        /// Computes the necessary delta to move the <see cref="WordEntry"/> inside the boundaries
        /// </summary>
        /// <param name="entry"><see cref="WordEntry"/> to test</param>
        /// <returns>Delta</returns>
        public Point GetDelta(WordEntry entry)
        {
            var size   = new Point(Soup.Matrix.GetUpperBound(0), Soup.Matrix.GetUpperBound(1));
            var origin = entry.Origin;
            var ending = entry.EndingCoordinate();
            var result = new Point();

            if (origin.X < 0)
            {
                result.X = origin.X * -1;
            }
            if (origin.Y < 0)
            {
                result.Y = origin.Y * -1;
            }
            if (ending.X > size.X)
            {
                result.X = size.X - ending.X;
            }
            if (ending.Y > size.Y)
            {
                result.Y = size.Y - ending.Y;
            }

            return(result);
        }
Exemple #4
0
        public bool Check(WordEntry entry)
        {
            var  size   = new Point(Soup.Matrix.GetUpperBound(0), Soup.Matrix.GetUpperBound(1));
            var  origin = entry.AbsoluteOrigin();
            var  ending = entry.AbsoluteEnding();
            bool haveHorizontalSpace = origin.X >= 0 && ending.X <= size.X;
            bool haveVerticalSpace   = origin.Y >= 0 && ending.Y <= size.Y;

            return(haveHorizontalSpace && haveVerticalSpace);
        }
Exemple #5
0
 /// <summary>
 /// Returns <c>true</c> if the <see cref="Candidate"/> entry intersects with other entries besides the <see cref="Existing"/>
 /// </summary>
 /// <param name="candidate">Candidate word to check with existing entries</param>
 /// <param name="entries">List of entries already set up in the <see cref="Soup"/></param>
 public bool IntersectsWithOthers(WordEntry candidate, IEnumerable <WordEntry> entries)
 {
     foreach (WordEntry entry in entries)
     {
         if (entry.Name != Existing.Name && entry.IntersectWith(candidate))
         {
             Logger.LogDebug($"Also intersects with {entry}");
             return(true);
         }
     }
     return(false);
 }
Exemple #6
0
 /// <summary>
 /// Initialize the words to check if have intersection
 /// </summary>
 /// <param name="existing"><see cref="WordEntry"/> already set in the <see cref="Soup"/></param>
 /// <param name="candidate"><see cref="WordEntry"/> to test if can be set in the <see cref="Soup"/></param>
 public void Check(WordEntry existing, WordEntry candidate)
 {
     if (Soup == null)
     {
         throw new InvalidOperationException($"{nameof(Soup)} must be initialized");
     }
     Existing  = existing ?? throw new ArgumentNullException(nameof(existing));
     Candidate = candidate ?? throw new ArgumentNullException(nameof(candidate));
     if (Logger.IsEnabled(LogLevel.Trace))
     {
         Logger.LogDebug($"Comparing to ({Existing})");
     }
     GetIntersection();
 }
Exemple #7
0
        /// <summary>
        /// Fill the alphabet soup with random words in random coordinates and directions
        /// </summary>
        /// <returns>The reated <see cref="Soup"/></returns>
        public Soup Create()
        {
            Logger.LogInformation("==Starting generation==");
            int total = 0;

            for (int i = 0; i < Options.NumWords; i++)
            {
                bool      failed    = false;
                WordEntry wordEntry = null;
                do
                {
                    failed    = false;
                    wordEntry = NextEntry();
                    Logger.LogInformation($"Trying {wordEntry}");
                    foreach (WordEntry existing in Soup.UsedWords.Values)
                    {
                        IntersectionManager.Check(existing, wordEntry);
                        if (IntersectionManager.Intersects)
                        {
                            wordEntry = IntersectionManager.RepositionEntry();
                            if (wordEntry == null)
                            {
                                failed = true;
                            }
                        }
                        if (failed)
                        {
                            break;
                        }
                    }
                    if (!failed)
                    {
                        foreach (IRule rule in Rules)
                        {
                            if (!rule.Check(Soup, wordEntry))
                            {
                                Logger.LogWarning($"Word {wordEntry.Name} doesn't match '{rule.Name}' rule.");
                                failed = true;
                                break;
                            }
                        }
                    }
                    total++;
                } while (failed);
                System.Diagnostics.Debug.Assert(wordEntry != null);
                AddWord(wordEntry);
            }
            Logger.LogInformation($"==Finishing generation ({Options.NumWords}/{total})==");
            return(Soup);
        }
Exemple #8
0
 /// <summary>
 /// Returns <c>true</c> if the <see cref="WordEntry"/> intersects in any point with <paramref name="other"/>
 /// </summary>
 /// <param name="other">The <see cref="WordEntry"/> to test</param>
 public bool IntersectWith(WordEntry other)
 {
     for (int i = 0; i < Name.Length; i++)
     {
         for (int j = 0; j < other.Name.Length; j++)
         {
             if (Coordinate(i) == other.Coordinate(j))
             {
                 return(true);
             }
         }
     }
     return(false);
 }
Exemple #9
0
        private bool IsOverlapped(WordEntry bigWord, WordEntry smallWord)
        {
            var  big      = bigWord.AbsoluteOrigin();
            var  small    = smallWord.AbsoluteOrigin();
            bool overlapp = false;

            if (bigWord.Direction.MovesHorizontal())
            {
                overlapp = small.X >= big.X && small.X + smallWord.Name.Length <= big.X + bigWord.Name.Length;
            }
            if (!overlapp && bigWord.Direction.MovesVertical())
            {
                overlapp = small.Y >= big.Y && small.Y + smallWord.Name.Length <= big.Y + bigWord.Name.Length;
            }
            return(overlapp);
        }
Exemple #10
0
 private void AddWord(WordEntry wordEntry)
 {
     for (int i = 0; i < wordEntry.Name.Length; i++)
     {
         char  c  = wordEntry.Name[i];
         Point pt = wordEntry.Coordinate(i);
         try {
             Soup.Matrix[pt.X, pt.Y]       = c;
             Soup.ShadowMatrix[pt.X, pt.Y] = true;
         } catch (Exception ex) {
             System.Diagnostics.Debug.Print($"{ex.Message} at ({pt.X}, {pt.Y}) with entry: {wordEntry}");
             throw;
         }
     }
     Soup.UsedWords.Add(wordEntry.Name, wordEntry);
 }
Exemple #11
0
        /// <summary>
        /// Compute and set the new <see cref="WordEntry.Origin"/> of the <see cref="Candidate"/> entry, so this entry intersects in the common letter
        /// </summary>
        /// <exception cref="InvalidOperationException">If both entries do not intersect or do not have common letters</exception>
        public WordEntry RepositionEntry()
        {
            if (!Intersects)
            {
                throw new InvalidOperationException("Can't reposition an entry that do not intersects with others");
            }
            if (!GetCommonLetters())
            {
                Logger.LogWarning($"Words {Existing} and {Candidate} intersect but don't have common letters");
                return(null);
            }
            bool      reposition       = false;
            WordEntry repositionedWord = null;

            if (Overlaps)
            {
                Logger.LogInformation($"Words {Existing} and {Candidate} overlap {Count} common letters");
                Point target    = Existing.Coordinate(ExistingRange.Init);
                int   increment = Candidate.Direction.IsReverse() ? 1 : 0;
                Point delta     = target.Delta(Candidate.Coordinate(CandidateRange.Init + increment));
                repositionedWord = Candidate.Translate(delta);
                bool insideBoundaries = CheckBoundaries(repositionedWord.Origin);
                reposition = insideBoundaries && !IntersectsWithOthers(repositionedWord, Soup.UsedWords.Values);
            }
            else
            {
                int  i = 0;
                bool insideBoundaries = false;
                Logger.LogInformation($"Candidate intersects at ({this[0]}) with ({Existing})");
                do
                {
                    Point target = Existing.Coordinate(CommonLetters[i].ExistingPos);
                    Point delta  = target.Delta(Candidate.Coordinate(CommonLetters[i].CandidatePos));
                    repositionedWord = Candidate.Translate(delta);
                    Logger.LogDebug($"Try to reposition to: {repositionedWord}");
                    insideBoundaries = CheckBoundaries(repositionedWord.Origin);
                    i++;
                } while (!insideBoundaries && i < CommonLetters.Count);
                reposition = insideBoundaries && !IntersectsWithOthers(repositionedWord, Soup.UsedWords.Values);
            }
            if (reposition)
            {
                Logger.LogWarning($"Candidate repositioned: {repositionedWord}");
                return(repositionedWord);
            }
            return(null);
        }
Exemple #12
0
 public bool Check(Soup soup, WordEntry entry)
 {
     foreach (WordEntry item in soup.UsedWords.Values)
     {
         if (item.Direction.SameDirection(entry.Direction))
         {
             if (item.Name.Length >= entry.Name.Length)
             {
                 if (IsOverlapped(item, entry))
                 {
                     return(false);
                 }
             }
             else
             {
                 if (IsOverlapped(entry, item))
                 {
                     return(false);
                 }
             }
         }
     }
     return(true);
 }
Exemple #13
0
 public bool Check(Soup soup, WordEntry entry)
 {
     return(entry.Name.Length >= _min && entry.Name.Length <= _max);
 }
Exemple #14
0
 public bool Check(Soup soup, WordEntry entry)
 {
     return(!soup.UsedWords.Keys.Contains(entry.Name));
 }