HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Check consistency of statements, with fuzzy rhyme matching (Kattis "Mårten's Theorem" challenge)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
challengewithstatementsrhymemårtenconsistencytheoremkattischeckmatching

Problem

I wrote a review for Check consistency of a list of statements, with fuzzy rhyme matching, which basically required me to try writing my own solution to fully understand the challenge. So, I thought that I should put my solution up for review.

I'll paraphrase the "Mårten's Theorem" challenge on Kattis:


Given up to 100000 statements of the form X is Y or X not Y, determine whether the statements are consistent (in which case output yes) or inconsistent (in which case output wait what?). X and Y are words, up to 20 characters long. For example, the two statements ulf is lukas and ulf not lukas contradict each other. The three statements ulf is lukas and lukas is ulf and ulf is bjorn, however, could be consistent.


The catch is that every word that rhymes with X in any provided statement is said to be equivalent to X. Here, two words X and Y are said to "rhyme" if the last min(3, |X|, |Y|) characters are the same.


Some examples:

4
herp is derp
derp is herp
herp is herp
derp is derp




Output to the input above should be yes.



3
oskar not lukas
oskar is poptart
lukas is smart




… should output wait what?, because:



  • you could infer that lukas is poptart (due to rhyming equivalence between poptart and smart)



  • you could also infer that lukas is oskar (since lukas is poptart and oskar is poptart)



  • that contradicts oskar not lukas.






1
moo not foo




… should output yes



2
moo not foo
oo is blah




… should output wait what?, because the appearance of the word oo anywhere means that the first statement moo not foo could be equivalent to oo not oo, which is a self-contradiction.

I wrote a solution in Python 3, but I believe it also works in Python 2. I've attempted to address all of the issues I pointed out in this review.

```
import fileinput
from itertools import chain
import re

def read_rules(line_iter, word

Solution

There's a bug if I understood the rules. This is now a "yes" even though it should be a "wait what?":

2
aaa not aa
a is aa


This happens because rhyme_map does not necessarily map each word to the shortest possible rhyme. The fix is simply to change short_words from set to list and add a break to the loop that iterates over it. There is no reason for it to be a set anyway as it is only accessed by iteration.

Also, rhyme_map would seem simpler to me if, instead of testing different short words with ends_with, we would look up every suffix of every word:

def rhyme_map(rules, word_suffix_len=3):
    words = set(chain.from_iterable(chain.from_iterable(rules.values())))
    abbreviations = {}
    for word in words:
        for suffix_len in range(1, len(word)):
            suffix = word[-suffix_len:]
            if suffix in words:
                 abbreviations[word] = suffix
                 break
    return abbreviations

Code Snippets

2
aaa not aa
a is aa
def rhyme_map(rules, word_suffix_len=3):
    words = set(chain.from_iterable(chain.from_iterable(rules.values())))
    abbreviations = {}
    for word in words:
        for suffix_len in range(1, len(word)):
            suffix = word[-suffix_len:]
            if suffix in words:
                 abbreviations[word] = suffix
                 break
    return abbreviations

Context

StackExchange Code Review Q#156880, answer score: 6

Revisions (0)

No revisions yet.