Skip to content

Commit

Permalink
1.2.0: Added optional maxResults parameter to Rhymer.getRhymingWords().
Browse files Browse the repository at this point in the history
Added optional `maxResults` parameter to `Rhymer.getRhymingWords()` to limit the number of results returned. By default, all results are returned, which is new behavior. Previously, "last-syllable" matches were ommitted completely if better rhymes were available (strict or "last-two-syllables").
  • Loading branch information
caarmen committed Feb 11, 2017
1 parent a151e0e commit a29343b
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 23 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Change Log
==========

1.2.0 *(2017-02-11)*
--------------------
* Added optional `maxResults` parameter to `Rhymer.getRhymingWords()` to limit the number of results returned. By default, all results are returned, which is new behavior. Previously, "last-syllable" matches were ommitted completely if better rhymes were available (strict or "last-two-syllables").

1.1.2 *(2016-10-29)*
--------------------
* New behavior if there are too many "last-syllable" matches: Now we will omit all "last-syllable" matches if either "strict" or "last-two-syllable" matches are present. Previously, we omitted all one-syllable matches if "last-two-syllable" matches were present.

1.1.1 *(2016-10-21)*
--------------------
* Filter out empty rhyme results.

1.1.0 *(2016-02-25)*
--------------------
* Added "strict" rhyming matches (words match from the last stressed syllable to the end of the word).

1.0.0 *(2016-02-14)*
--------------------
* First version.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ To test out the library on the command-line:

```
./gradlew clean cliJar
java -jar example/build/libs/example-all-1.1.2.jar <word to rhyme>
java -jar example/build/libs/example-all-1.2.0.jar <word to rhyme>
```

The library is available on jcenter. To include it in your project:
Expand All @@ -18,14 +18,14 @@ maven:
<dependency>
<groupId>ca.rmen</groupId>
<artifactId>rhymer</artifactId>
<version>1.1.2</version>
<version>1.2.0</version>
</dependency>
```

gradle:

```
compile 'ca.rmen:rhymer:1.1.2'
compile 'ca.rmen:rhymer:1.2.0'
```


2 changes: 1 addition & 1 deletion example/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group 'ca.rmen'
version '1.1.2'
version '1.2.0'

apply plugin: 'java'

Expand Down
2 changes: 1 addition & 1 deletion library/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group 'ca.rmen'
version '1.1.2'
version '1.2.0'

apply plugin: 'java'
apply plugin: 'maven'
Expand Down
51 changes: 33 additions & 18 deletions library/src/main/java/ca/rmen/rhymer/Rhymer.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,31 @@
package ca.rmen.rhymer;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

public abstract class Rhymer {
private static final int THRESHOLD_TOO_MANY_RHYMES = 500;

/**
* @param word the word for which we want to find rhymes.
* @return a list of RhymeResults. Most words will have one RhymeResult. Words with multiple possible
* pronunciations (word variants) will have one RhymeResult per variant.
*/
public List<RhymeResult> getRhymingWords(String word) {
return getRhymingWords(word, -1);
}

/**
* @param word the word for which we want to find rhymes.
* @param maxResults return at most this many results per rhyme type. For no limit, pass -1.
* @return a list of RhymeResults. Most words will have one RhymeResult. Words with multiple possible
* pronunciations (word variants) will have one RhymeResult per variant.
*/
public List<RhymeResult> getRhymingWords(String word, int maxResults) {
List<RhymeResult> results = new ArrayList<>();
String lookupWord = word.toLowerCase(Locale.US);

Expand All @@ -45,10 +55,10 @@ public List<RhymeResult> getRhymingWords(String word) {
// One RhymeResult per word variant (pronunciation)
for (WordVariant wordVariant : wordVariants) {

Set<String> matches0 = getWordsWithLastStressSyllable(wordVariant.lastStressRhymingSyllables);
Set<String> matches1 = getWordsWithLastSyllable(wordVariant.lastRhymingSyllable);
Set<String> matches2 = new TreeSet<>();
Set<String> matches3 = new TreeSet<>();
SortedSet<String> matches0 = getWordsWithLastStressSyllable(wordVariant.lastStressRhymingSyllables);
SortedSet<String> matches1 = getWordsWithLastSyllable(wordVariant.lastRhymingSyllable);
SortedSet<String> matches2 = new TreeSet<>();
SortedSet<String> matches3 = new TreeSet<>();

if (wordVariant.lastTwoRhymingSyllables != null) {
matches2 = getWordsWithLastTwoSyllables(wordVariant.lastTwoRhymingSyllables);
Expand All @@ -69,30 +79,35 @@ public List<RhymeResult> getRhymingWords(String word) {
matches2.removeAll(matches0);
matches3.removeAll(matches0);

// Some words, like "puppy", match way too many words.... any word
// ending with an "ee" sound (IY0 phone). If we end up in this situation,
// completely ignore all the one-syllable matches, and only return
// strict, 2 and 3 syllable matches.
// TODO maybe there is a better way to solve this problem.
if (matches1.size() > THRESHOLD_TOO_MANY_RHYMES && (matches0.size() > 0 || matches2.size() > 0)) {
matches1.clear();
}

if (!matches0.isEmpty()
|| !matches1.isEmpty()
|| !matches2.isEmpty()
|| !matches3.isEmpty()) {
RhymeResult result = new RhymeResult(wordVariant.variantNumber,
matches0.toArray(new String[matches0.size()]),
matches1.toArray(new String[matches1.size()]),
matches2.toArray(new String[matches2.size()]),
matches3.toArray(new String[matches3.size()]));
toArray(matches0, maxResults),
toArray(matches1, maxResults),
toArray(matches2, maxResults),
toArray(matches3, maxResults));
results.add(result);
}
}
return results;
}

private static String[] toArray(Set<String> set, int limit) {
// Some words, like "puppy", match way too many words.... any word
// ending with an "ee" sound (IY0 phone).
// TODO maybe there is a better way to solve this problem.

if (limit < 0) return set.toArray(new String[set.size()]);
String[] result = new String[Math.min(set.size(), limit)];
int index = 0;
for (Iterator<String> iterator = set.iterator(); iterator.hasNext() && index < limit; index++) {
result[index] = iterator.next();
}
return result;
}

protected abstract List<WordVariant> getWordVariants(String word);
protected abstract SortedSet<String> getWordsWithLastStressSyllable(String lastStressSyllable);
protected abstract SortedSet<String> getWordsWithLastSyllable(String lastSyllable);
Expand Down

0 comments on commit a29343b

Please sign in to comment.