检测邻居词

时间:2014-08-11 09:57:40

标签: python python-3.x

基本上我需要创建一个python文件,它接受一些随机单词的输入并打印出临床单词和非临床单词。临床词是每个字母在单词中具有相邻字母的单词。 E.G铁匠是邻近的,因为每个字母至少有一个相邻的字母,所以这里是程序需要起作用的东西:

Line: The blacksmith fights in the tower
Vicinals: blacksmith fights
Non-vicinals: The in the tower
Line: The baker fights in the street
Vicinals: fights
Non-vicinals: The in the
Line: The butcher flees from the scene
Non-vicinals: The from the scene
Line: 

到目前为止我有这个,基本上我还没有把它放到一个循环中但似乎我的ord比较不起作用,并且由于某种原因我得到了可怕的输出。

line = input('Line: ').lower().split()
for item in line:
  listy = []
  nonvicinals = []
  yesvicinals = []
  vicinal = True
  for letter in item:
    listy.append(ord(letter))
  for num in listy:
    if int(num) != 97 or int(num) != 122:
      # because if it is a or z (97, 122) the number can wrap around
      if (num + 1) in listy or (num - 1) in listy:
        vicinal = True
      else:
        vicinal = False
    else:
      if int(num) == 97:
        if (num + 1) in listy or 122 in listy:
          vicinal = True
        else:
          vicinal = False
      else:
        if (num - 1) in listy or 97 in listy:
          vicinal = True
        else:
          vicinal = False
    if vicinal == False:
      nonvicinals.append(item) 
      break
  if vicinal == True:
    yesvicinals.append(item)

if yesvicinals:
  print('vicinals: {}'.format(' '.join(yesvicinals)))
if nonvicinals:
  print('Non-vicinals: {}'.format(' '.join(nonvicinals)))

现在,当我输入第一个例子时,我得到了输出:

Line: The blacksmith fights in the tower
Non-vicinals: tower

我做错了什么,为什么我得不到想要的输出? 我的代码也很坦率,非常长而且非常丑陋。是否有更快的方式使用一些lambdas / comprehensions等?

感谢任何帮助,这一直困扰着我好几个小时! 谢谢, Itechmatrix

4 个答案:

答案 0 :(得分:4)

这在(至少)两个功能中会容易得多:

def process(line):
    vicinals = []
    non_vicinals = []
    for word in line.split():
        if is_vicinal(word):
            vicinals.append(word)
        else:
            non_vicinals.append(word)
    if vicinals:
        print('vicinals: {}'.format(' '.join(vicinals)))
    if non_vicinals:
        print('Non-vicinals: {}'.format(' '.join(non_vicinals)))

def is_vicinal(word):
    raise NotImplementedError()

line = input('Line: ').lower()
process(line)

现在我们可以开发和测试is_vicinal,而无需担心任何显示或输入内容。


接下来,请注意您只想处理唯一字符而不关心word中的订单(建议set),并且您要查看相邻的字符(建议排序):

>>> sorted(set("blacksmith"))
['a', 'b', 'c', 'h', 'i', 'k', 'l', 'm', 's', 't']

现在我们要group这些字符(我会将此实现留给您),以便:

>>> group(['a', 'b', 'c', 'h', 'i', 'k', 'l', 'm', 's', 't'])
[['a', 'b', 'c'], ['h', 'i'], ['k', 'l', 'm'], ['s', 't']]

现在我们的is_vicinal功能变得简单了:

>>> def is_vicinal(word)
    letters = sorted(set(word))
    return all(len(l) > 1 for l in group(letters))

>>> is_vicinal("blacksmith")
True
>>> is_vicinal("tower")
False

现在您需要做的就是为'a''z'添加额外的逻辑!您可以将其放在groupis_vicinal中 - 进行实验并查看它最适合的位置。


请注意,至少根据definition in Wikipedia,非邻近并不像not is_vicinal那么简单,因此您可能需要编写另一个函数def is_non_vicinal(word):来处理接着就,随即。这与is_vicinal函数非常相似,仍然可以使用group(这就是打破单独函数的原因)。

>>> is_non_vicinal("tower")
True
>>> is_vicinal("almanac")
False
>>> is_non_vicinal("almanac")
False

这也需要对process稍作修改。

答案 1 :(得分:3)

这是一个来自当前NCSS Challenge(高级)的编程竞赛的问题。请不要为他/她做user24492的工作。

user24492 / Itechmatrix,有一些论坛和导师可供您使用。请改用它们。

答案 2 :(得分:2)

一些提示:

创建一个函数:

def is_vicinal(word):
    letters = [ord(l) for l in word]
    for letter in letters:
        if letter - 1 not in letters and letter + 1 not in letters:
            if letter == 97 and 122 in letters:
                continue
            elif letter == 122 and 97 in letters:
                continue
            else:
                return False
    return True

现在你已经将主要循环中的邻近逻辑分开了。然后,您可以独立测试该功能,并确保它能够执行您想要的功能。

然后你可以简单地在每个单词上调用它。

vicinals = [w for w in line.split() if is_vicinal(w)]
non_vicinials = [w for w in line.split() if not is_vicinal(w)]
例如

你可以将两者结合起来,这样你每个单词只运行一次is_vicinal函数:

words_tested = [w, is_vicinal(w) for w in line.split()]

然后会给出一个列表:

[('word',False)] ... 

注意:

我上面的is_vicinal函数可能不完全正确。但我相信,这是正确的方向。 : - )

答案 3 :(得分:0)

忽略字符重复,可以实现每个字O(N),其中N是单词的长度:

LINES = ["The blacksmith fights the Gazh in the tower",
     "The almanac has a dictionary"]
ABC = [False for _ in range(0, ord('z')-ord('a')+1)]
LEN = len(ABC)


def is_vicinal(arr, abc):
    vicinal = True
    index = 0
    while vicinal and index < len(arr):
        c = arr[index]
        vicinal = vicinal and (abc[(c-1) % LEN] or abc[(c+1) % LEN])
        index += 1
    return vicinal


def is_non_vicinal(arr, abc):
    non_vicinal = True
    index = 0
    while non_vicinal and index < len(arr):
        c = arr[index]
        isolated = (not(abc[(c-1) % LEN])) and (not(abc[(c+1) % LEN]))
        non_vicinal = non_vicinal and isolated
        index += 1
    return non_vicinal


for line in LINES:
    vicinals = []
    non_vicinals = []
    neithers = []

    for word in line.split():
        arr = [ord(c.lower()) - ord('a') for c in word]
        abc = ABC[:]
        for c in arr:
            abc[c] = True

        if is_vicinal(arr, abc):
            vicinals.append(word)
        elif is_non_vicinal(arr, abc):
            non_vicinals.append(word)
        else:
            neithers.append(word)

    print(line)
    print("\tvicinal: " + str(vicinals))
    print("\tnon_vicinal: " + str(non_vicinals))
    print("\tneither: " + str(neithers))
    print('\n')

请注意,非本地人不仅不是(邻近的);参加http://en.wikipedia.org/wiki/Vicinal_(logology)

输出:

The blacksmith fights the Gazh in the tower
    vicinal: ['blacksmith', 'fights', 'Gazh']
    non_vicinal: ['The', 'the', 'in', 'the', 'tower']
    neither: []


The almanac has a dictionary
    vicinal: []
    non_vicinal: ['The', 'has', 'a']
    neither: ['almanac', 'dictionary']