Edward
Edward

Reputation: 1000

random values with uneven distribution

Implementing Hangman. I want to randomly select the length of the word, taking into account how many words of a given length are in the wordlist - ie. 12-letter words should be chosen less frequently than 5-letter ones, because there are fewer of the former.

It doesn't look like the random module will do that easily.

I could hack something semi-ugly together, but am looking for suggestions of a tidy way to do it.

UPDATE to remove some confusion:

This is a cheating version of hangman: it specifies a word-length at the beginning, but doesn't actually pick the word until it absolutely has to.

Here's the full problem description (from Chapter 8 of the book Think Like a Programmer):

Write a program that will be Player 1 in a text-based version of hangman (that is, you don't actually have to draw a hanged man—just keep track of the number of incorrect guesses). Player 2 will set the difficulty of the game by specifying the length of the word to guess as well as the number of incorrect guesses that will lose the game. The twist is that the program will cheat. Rather than actually picking a word at the beginning of the game, the program may avoid picking a word, so long as when Player 2 loses, the program can display a word that matches all the information given to Player 2. The correctly guessed letters must appear in their correct positions, and none of the incorrectly guessed letters can appear in the word at all. When the game ends, Player 1 (the program) will tell Player 2 the word that was chosen. Therefore, Player 2 can never prove that the game is cheating; it's just that the likelihood of Player 2 winning is small.

Upvotes: 0

Views: 866

Answers (2)

Chad Kennedy
Chad Kennedy

Reputation: 1736

# rel_dist holds the relative weight you want for each word length
# here, words of length 3 have weight 9, length 4 have weight 8, etc
# make sure you cover all word lengths
rel_dist = [0, 0, 0, 9, 8, 7, 6, 5, 4, 3]
random.choice(sum([[word]*rel_dist[len(word)]) for word in words], []))

Upvotes: 0

David Wolever
David Wolever

Reputation: 154464

If you have your words in a list words, random.choice(words) will uniformly randomly select a word from the list.

If you only have word lengths, I'd store the lengths and counts in a list:

len_counts = [
    (1, 24), # 24 1-length words
    (2, 39), # 39 2-length words
    ...
]

And use the algorithm in this answer to uniformly select a length: https://stackoverflow.com/a/4322940/71522

Upvotes: 3

Related Questions