wordfinder.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. # Natural Language Toolkit: Word Finder
  2. #
  3. # Copyright (C) 2001-2020 NLTK Project
  4. # Author: Steven Bird <stevenbird1@gmail.com>
  5. # URL: <http://nltk.org/>
  6. # For license information, see LICENSE.TXT
  7. # Simplified from PHP version by Robert Klein <brathna@gmail.com>
  8. # http://fswordfinder.sourceforge.net/
  9. import random
  10. # reverse a word with probability 0.5
  11. def revword(word):
  12. if random.randint(1, 2) == 1:
  13. return word[::-1]
  14. return word
  15. # try to insert word at position x,y; direction encoded in xf,yf
  16. def step(word, x, xf, y, yf, grid):
  17. for i in range(len(word)):
  18. if grid[xf(i)][yf(i)] != "" and grid[xf(i)][yf(i)] != word[i]:
  19. return False
  20. for i in range(len(word)):
  21. grid[xf(i)][yf(i)] = word[i]
  22. return True
  23. # try to insert word at position x,y, in direction dir
  24. def check(word, dir, x, y, grid, rows, cols):
  25. if dir == 1:
  26. if x - len(word) < 0 or y - len(word) < 0:
  27. return False
  28. return step(word, x, lambda i: x - i, y, lambda i: y - i, grid)
  29. elif dir == 2:
  30. if x - len(word) < 0:
  31. return False
  32. return step(word, x, lambda i: x - i, y, lambda i: y, grid)
  33. elif dir == 3:
  34. if x - len(word) < 0 or y + (len(word) - 1) >= cols:
  35. return False
  36. return step(word, x, lambda i: x - i, y, lambda i: y + i, grid)
  37. elif dir == 4:
  38. if y - len(word) < 0:
  39. return False
  40. return step(word, x, lambda i: x, y, lambda i: y - i, grid)
  41. def wordfinder(words, rows=20, cols=20, attempts=50, alph="ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
  42. """
  43. Attempt to arrange words into a letter-grid with the specified
  44. number of rows and columns. Try each word in several positions
  45. and directions, until it can be fitted into the grid, or the
  46. maximum number of allowable attempts is exceeded. Returns a tuple
  47. consisting of the grid and the words that were successfully
  48. placed.
  49. :param words: the list of words to be put into the grid
  50. :type words: list
  51. :param rows: the number of rows in the grid
  52. :type rows: int
  53. :param cols: the number of columns in the grid
  54. :type cols: int
  55. :param attempts: the number of times to attempt placing a word
  56. :type attempts: int
  57. :param alph: the alphabet, to be used for filling blank cells
  58. :type alph: list
  59. :rtype: tuple
  60. """
  61. # place longer words first
  62. words = sorted(words, key=len, reverse=True)
  63. grid = [] # the letter grid
  64. used = [] # the words we used
  65. # initialize the grid
  66. for i in range(rows):
  67. grid.append([""] * cols)
  68. # try to place each word
  69. for word in words:
  70. word = word.strip().upper() # normalize
  71. save = word # keep a record of the word
  72. word = revword(word)
  73. for attempt in range(attempts):
  74. r = random.randint(0, len(word))
  75. dir = random.choice([1, 2, 3, 4])
  76. x = random.randint(0, rows)
  77. y = random.randint(0, cols)
  78. if dir == 1:
  79. x += r
  80. y += r
  81. elif dir == 2:
  82. x += r
  83. elif dir == 3:
  84. x += r
  85. y -= r
  86. elif dir == 4:
  87. y += r
  88. if 0 <= x < rows and 0 <= y < cols:
  89. if check(word, dir, x, y, grid, rows, cols):
  90. # used.append((save, dir, x, y, word))
  91. used.append(save)
  92. break
  93. # Fill up the remaining spaces
  94. for i in range(rows):
  95. for j in range(cols):
  96. if grid[i][j] == "":
  97. grid[i][j] = random.choice(alph)
  98. return grid, used
  99. def word_finder():
  100. from nltk.corpus import words
  101. wordlist = words.words()
  102. random.shuffle(wordlist)
  103. wordlist = wordlist[:200]
  104. wordlist = [w for w in wordlist if 3 <= len(w) <= 12]
  105. grid, used = wordfinder(wordlist)
  106. print("Word Finder\n")
  107. for i in range(len(grid)):
  108. for j in range(len(grid[i])):
  109. print(grid[i][j], end=" ")
  110. print()
  111. print()
  112. for i in range(len(used)):
  113. print("%d:" % (i + 1), used[i])
  114. if __name__ == "__main__":
  115. word_finder()