diff options
Diffstat (limited to 'Scala/forcomp/src/main')
| -rw-r--r-- | Scala/forcomp/src/main/scala/forcomp/Anagrams.scala | 52 | 
1 files changed, 45 insertions, 7 deletions
| diff --git a/Scala/forcomp/src/main/scala/forcomp/Anagrams.scala b/Scala/forcomp/src/main/scala/forcomp/Anagrams.scala index 33852d7..cd08b47 100644 --- a/Scala/forcomp/src/main/scala/forcomp/Anagrams.scala +++ b/Scala/forcomp/src/main/scala/forcomp/Anagrams.scala @@ -33,10 +33,13 @@ object Anagrams {     *  Note: the uppercase and lowercase version of the character are treated as the     *  same character, and are represented as a lowercase character in the occurrence list.     */ -  def wordOccurrences(w: Word): Occurrences = ??? +  def wordOccurrences(w: Word): Occurrences = +    w.toLowerCase.groupBy((element: Char) => element).toList.sortWith(_._1 < _._1).map( x => (x._1, x._2.length)) +                                                         // .sorted               .map{ case (x,y) => (x, y.length) }    /** Converts a sentence into its character occurrence list. */ -  def sentenceOccurrences(s: Sentence): Occurrences = ??? +  def sentenceOccurrences(s: Sentence): Occurrences = wordOccurrences(s.mkString) +                                                                   // s.foldLeft("")(_.concat(_))    /** The `dictionaryByOccurrences` is a `Map` from different occurrences to a sequence of all     *  the words that have that occurrence count. @@ -53,10 +56,10 @@ object Anagrams {     *    List(('a', 1), ('e', 1), ('t', 1)) -> Seq("ate", "eat", "tea")     *     */ -  lazy val dictionaryByOccurrences: Map[Occurrences, List[Word]] = ??? +  lazy val dictionaryByOccurrences: Map[Occurrences, List[Word]] = dictionary groupBy((element: Word) => wordOccurrences(element))    /** Returns all the anagrams of a given word. */ -  def wordAnagrams(word: Word): List[Word] = ??? +  def wordAnagrams(word: Word): List[Word] = dictionaryByOccurrences(wordOccurrences(word))    /** Returns the list of all subsets of the occurrence list.     *  This includes the occurrence itself, i.e. `List(('k', 1), ('o', 1))` @@ -80,7 +83,17 @@ object Anagrams {     *  Note that the order of the occurrence list subsets does not matter -- the subsets     *  in the example above could have been displayed in some other order.     */ -  def combinations(occurrences: Occurrences): List[Occurrences] = ??? +  def combinations(occurrences: Occurrences): List[Occurrences] = occurrences match { +      case Nil => List(List()) +      case head :: tail => { +        val combs = combinations(tail) +        /* keep previous combination untouched */ +        combs ::: ( for { +            comb <- combs +            i <- 1 to head._2 +          } yield (head._1, i)  :: comb) // combine each Pair with each element cons in comb +      } +    }    /** Subtracts occurrence list `y` from occurrence list `x`.     *  @@ -92,7 +105,14 @@ object Anagrams {     *  Note: the resulting value is an occurrence - meaning it is sorted     *  and has no zero-entries.     */ -  def subtract(x: Occurrences, y: Occurrences): Occurrences = ??? +  def subtract(x: Occurrences, y: Occurrences): Occurrences = { +    (y.toMap.foldLeft(x.toMap) ((map, tuple) => { +        val newFreq = map(tuple._1) - tuple._2  // freq diff with the corresponding Occurence in map +        if (newFreq <= 0) map - tuple._1        // remove Occurence +        else map.updated(tuple._1, newFreq)     // reduce Occurence count +      }) +    ).toList.sorted +  }    /** Returns a list of all anagram sentences of the given sentence.     *   @@ -134,6 +154,24 @@ object Anagrams {     *     *  Note: There is only one anagram of an empty sentence.     */ -  def sentenceAnagrams(sentence: Sentence): List[Sentence] = ??? +  def sentenceAnagrams(sentence: Sentence): List[Sentence] = { +    def iter(occurrences: Occurrences): List[Sentence] = { +      if (occurrences.isEmpty) List(List()) +      else +        for { +          // for each combination of the occurences +          comb <- combinations(occurrences) +          // for each word that exists in the dictionary +          word <- dictionaryByOccurrences.getOrElse(comb, List()) +          // take all the sentences that come from subtracting from the occurrences +          // the occurrence list of the word +          sentence <- iter(subtract(occurrences, wordOccurrences(word))) +          if !comb.isEmpty +          // and yield the concatenation of the word with the sentence +          // preserving the invariant of the occurrence list +        } yield word :: sentence +    } +    iter(sentenceOccurrences(sentence)) +  }  } | 
