Advertisement
jules0707

Anagrams

Feb 27th, 2017
279
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 6.20 KB | None | 0 0
  1. package forcomp
  2.  
  3. import com.sun.org.apache.xerces.internal.impl.xs.models.XSDFACM.Occurence
  4.  
  5. object Anagrams {
  6.  
  7.   /** A word is simply a `String`. */
  8.   type Word = String
  9.  
  10.   /** A sentence is a `List` of words. */
  11.   type Sentence = List[Word]
  12.  
  13.   /**
  14.    * `Occurrences` is a `List` of pairs of characters and positive integers saying
  15.    *  how often the character appears.
  16.    *  This list is sorted alphabetically w.r.t. to the character in each pair.
  17.    *  All characters in the occurrence list are lowercase.
  18.    *
  19.    *  Any list of pairs of lowercase characters and their frequency which is not sorted
  20.    *  is **not** an occurrence list.
  21.    *
  22.    *  Note: If the frequency of some character is zero, then that character should not be
  23.    *  in the list.
  24.    */
  25.   type Occurrences = List[(Char, Int)]
  26.  
  27.   /**
  28.    * The dictionary is simply a sequence of words.
  29.    *  It is predefined and obtained as a sequence using the utility method `loadDictionary`.
  30.    */
  31.   val dictionary: List[Word] = loadDictionary
  32.  
  33.   /**
  34.    * Converts the word into its character occurrence list.
  35.    *
  36.    *  Note: the uppercase and lowercase version of the character are treated as the
  37.    *  same character, and are represented as a lowercase character in the occurrence list.
  38.    *
  39.    *  Note: you must use `groupBy` to implement this method!
  40.    */
  41.   def wordOccurrences(w: Word): Occurrences = {
  42.     for { (c, l) <- w.groupBy(c => c.toLower) }
  43.       yield (c, l.length)
  44.   }.toList.sorted
  45.  
  46.   /** Converts a sentence into its character occurrence list. */
  47.   def sentenceOccurrences(s: Sentence): Occurrences = wordOccurrences(s.mkString)
  48.  
  49.   /**
  50.    * The `dictionaryByOccurrences` is a `Map` from different occurrences to a sequence of all
  51.    *  the words that have that occurrence count.
  52.    *  This map serves as an easy way to obtain all the anagrams of a word given its occurrence list.
  53.    *
  54.    *  For example, the word "eat" has the following character occurrence list:
  55.    *
  56.    *     `List(('a', 1), ('e', 1), ('t', 1))`
  57.    *
  58.    *  Incidentally, so do the words "ate" and "tea".
  59.    *
  60.    *  This means that the `dictionaryByOccurrences` map will contain an entry:
  61.    *
  62.    *    List(('a', 1), ('e', 1), ('t', 1)) -> Seq("ate", "eat", "tea")
  63.    *
  64.    */
  65.   lazy val dictionaryByOccurrences: Map[Occurrences, List[Word]] =
  66.     dictionary.groupBy { w => wordOccurrences(w) }
  67.  
  68.   /** Returns all the anagrams of a given word. */
  69.   def wordAnagrams(word: Word): List[Word] = dictionaryByOccurrences(wordOccurrences(word))
  70.  
  71.   /**
  72.    * Returns the list of all subsets of the occurrence list.
  73.    *  This includes the occurrence itself, i.e. `List(('k', 1), ('o', 1))`
  74.    *  is a subset of `List(('k', 1), ('o', 1))`.
  75.    *  It also include the empty subset `List()`.
  76.    *
  77.    *  Example: the subsets of the occurrence list `List(('a', 2), ('b', 2))` are:
  78.    * List(
  79.    *      List(),
  80.    *      List(('a', 1)),
  81.    *      List(('a', 2)),
  82.    *      List(('b', 1)),
  83.    *      List(('a', 1), ('b', 1)),
  84.    *      List(('a', 2), ('b', 1)),
  85.    *      List(('b', 2)),
  86.    *      List(('a', 1), ('b', 2)),
  87.    *      List(('a', 2), ('b', 2))
  88.    *    )
  89.    */
  90.  
  91.   /**
  92.    *  Note that the order of the occurrence list subsets does not matter -- the subsets
  93.    *  in the example above could have been displayed in some other order.
  94.    */
  95.   def combinations(occurrences: Occurrences): List[Occurrences] = {
  96.  
  97.     def combine(l1: List[Occurrences], l2: List[Occurrences]): List[Occurrences] = {
  98.       for {
  99.         e1 <- l1
  100.         e2 <- l2
  101.         p1 <- e1
  102.         p2 <- e2
  103.       } yield p1 :: (p2 :: List(Nil).flatten)
  104.     }
  105.  
  106.     def eclate(pair: (Char, Int)): List[(Char, Int)] = {
  107.       for { occ <- 1 to pair._2 }
  108.         yield (pair._1, occ)
  109.     }.toList
  110.  
  111.     occurrences match {
  112.       case Nil => List(Nil)
  113.       case head :: tail =>
  114.         combine(List(eclate(head._1, head._2)), combinations(tail))
  115.  
  116.     }
  117.   }
  118.  
  119.   /**
  120.    * Subtracts occurrence list `y` from occurrence list `x`.
  121.    *
  122.    *  The precondition is that the occurrence list `y` is a subset of
  123.    *  the occurrence list `x` -- any character appearing in `y` must
  124.    *  appear in `x`, and its frequency in `y` must be smaller or equal
  125.    *  than its frequency in `x`.
  126.    *
  127.    *  Note: the resulting value is an occurrence - meaning it is sorted
  128.    *  and has no zero-entries.
  129.    */
  130.   def subtract(x: Occurrences, y: Occurrences): Occurrences = ???
  131.  
  132.   /**
  133.    * Returns a list of all anagram sentences of the given sentence.
  134.    *
  135.    *  An anagram of a sentence is formed by taking the occurrences of all the characters of
  136.    *  all the words in the sentence, and producing all possible combinations of words with those characters,
  137.    *  such that the words have to be from the dictionary.
  138.    *
  139.    *  The number of words in the sentence and its anagrams does not have to correspond.
  140.    *  For example, the sentence `List("I", "love", "you")` is an anagram of the sentence `List("You", "olive")`.
  141.    *
  142.    *  Also, two sentences with the same words but in a different order are considered two different anagrams.
  143.    *  For example, sentences `List("You", "olive")` and `List("olive", "you")` are different anagrams of
  144.    *  `List("I", "love", "you")`.
  145.    *
  146.    *  Here is a full example of a sentence `List("Yes", "man")` and its anagrams for our dictionary:
  147.    *
  148.    *    List(
  149.    *      List(en, as, my),
  150.    *      List(en, my, as),
  151.    *      List(man, yes),
  152.    *      List(men, say),
  153.    *      List(as, en, my),
  154.    *      List(as, my, en),
  155.    *      List(sane, my),
  156.    *      List(Sean, my),
  157.    *      List(my, en, as),
  158.    *      List(my, as, en),
  159.    *      List(my, sane),
  160.    *      List(my, Sean),
  161.    *      List(say, men),
  162.    *      List(yes, man)
  163.    *    )
  164.    *
  165.    *  The different sentences do not have to be output in the order shown above - any order is fine as long as
  166.    *  all the anagrams are there. Every returned word has to exist in the dictionary.
  167.    *
  168.    *  Note: in case that the words of the sentence are in the dictionary, then the sentence is the anagram of itself,
  169.    *  so it has to be returned in this list.
  170.    *
  171.    *  Note: There is only one anagram of an empty sentence.
  172.    */
  173.   def sentenceAnagrams(sentence: Sentence): List[Sentence] = ???
  174. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement