Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

HOW CAN I GET THE CORRECT OUTPUT? \"BumpRoe, Cartoon, Forthis, Fovenay, Gaylton,

ID: 3594549 • Letter: H

Question

HOW CAN I GET THE CORRECT OUTPUT?  "BumpRoe, Cartoon, Forthis, Fovenay, Gaylton, Haneram, Hansoro, Madiela, Ninasoo, Relayle, Ronburd, and Wanhumo."

Introduction.

In this assignment, you will write a Python program that is given example words, and generates random words that resemble them. For example, after being given the last names of all U.S. presidents, the program generated the names BumpRoe, Cartoon, Forthis, Fovenay, Gaylton, Haneram, Hansoro, Madiela, Ninasoo, Relayle, Ronburd, and Wanhumo. Perhaps these will be the names of future presidents. It is claimed that the names of some companies and commercial products were produced by programs similar to this one.

1. Theory.

For this project, you need an algorithm that generates random integers. You also need an algorithm that records example words, and another algorithm that uses the random integers and example words to generate random words.

Random integers. No algorithm can generate truly random integers, but it can generate pseudo-randomintegers that seem random, even though they’re not. Python has its own random number generator, but for this project you must implement your own.
      The Park-Miller algorithm (named for its inventors) is a simple way to generate a sequence of pseudo-random integers. It works like this. Let N be an integer called the seed. The seed is the first term of the sequence, and must be between 1 and 2³¹ 2. Starting from N, later terms N, N ..., are produced by the following equation.

Nk+1 = (75 Nk) % (231 1)

Here 7 is 16807, and 2³¹ is 2147483648. The operator multiplies two integers, and the operator % returns the remainder after dividing one integer by another. You will always get the same sequence of integers for a given seed. For example, if you start with the seed 101, then you get a sequence whose first few terms are 1697507, 612712738, 678900201, 695061696, 1738368639, 246698238, 1613847356, and 1214050682.
      Some of these integers are large, but you can make them smaller by using the % operator again. If N is an integer from the sequence, then N % M gives you an integer between 0 and M 1. For example, if you need a pseudo-random integer from 0 to 9, then you write N % 10. You can use this to choose a random element from a sequence. If S is a sequence, then the Python expression S[N % len(S)] returns a randomly-chosen element of S.

Recording example words. Here’s how to record example words. A letter is a single-character string, 'A'–'Z' and 'a'–'z'. Suppose that first is a string of letters, and is initially empty. As its name suggests, first will hold the first letter of each example word. Also suppose that follow is a dictionary, also initially empty, whose keys are letters, and whose values are strings of letters. The dictionary follow will hold strings of letters that can follow other letters.
      If you’re given the example word 'Trump', then you add 'T' to first, because 'T' is the first letter of the word. You also add 'r' to the string in follow that is the value of the key 'T', because 'r' follows 'T'. Similarly, you add 'u' to the string that is the value of the key 'r', because 'u' follows 'r'. You add 'm' to the string that is the value of the key 'u', because 'm'follows 'u'. Finally, you add 'p' to the string that is the value of the key 'm' because 'p' follows 'm'.
      After many example words, first will record the first letters of each one, and follow will record how letters follow one another in the example words. Letters may appear more than once in the string first, and in the strings from follow.

Generating random words. Here’s how to use first and follow to generate a random word, one letter at a time. You get the first letter of the word by randomly choosing it from first. Next, you look up the first letter in follow, obtaining a string of possible letters. You get the second letter by randomly choosing it from that string. Then, you look up the second letter in follow, obtaining another string. You get the third letter by randomly choosing it from that string. You continue like this, choosing letters from strings, and concatenating them together, until you’ve constructed the entire word.
      The number of times a letter appears in a string records how often that letter appeared in the example words. As a result, if you choose a letter at random from a string, then it is more likely to be chosen if it appeared often. Also, follow records how letters followed other letters in the example words. This lets you generate words that are roughly similar to the ones that were given as examples.
      One potential problem remains. While you’re generating a random word, you may find that there is no string in follow for some letter. If this happens, then you choose a letter at random from first instead, and continue generating the word as before. The Python-2 expression follow.has_key(l) tests if there is a string in follow for the letter l. The Python-3 equivalent is l in follow.

2. Implementation.

You must write two Python classes. The first class must be called Random, and it must implement the Park-Miller random number generator discussed in section 1. The class Random must have the following methods.

__init__(self, seed)

(5 points.) Initialize an instance of Random with the integer seed. Assume that seed is in the proper range for the Park-Miller algorithm to work.

next(self, range)

(5 points.) Generate the next random number in the sequence. Use it to return a nonnegative integer greater than or equal to 0, but strictly less than the integer range. Return that random number. Assume that range is an integer greater than 0.

choose(self, characters)

(5 points.) Choose a character from the string characters at random, using an index obtained by calling next. Return that character. You may assume that characters is not empty.

The second class must be called Words, and it must implement the random word generation algorithm discussed in section 1. The class Words must have the following methods.

__init__(self, seed)

(5 points.) Create private variables first, follow, and random. The variable first must be an empty string. The variable follow must be an empty dictionary. The variablerandom must be an instance of Random, whose seed is the integer seed. You may assume that seed is in the proper range for the Park-Miller algorithm to work.

add(self, word)

(10 points.) Add the string word as a new example, using first and follow as described in section 1. You may assume that word is made up entirely of letters, and that it has at least one letter. Return None.

make(self, size)

(10 points.) Create a new example word using first, follow, and random as described in section 1. The word must be a string with exactly size letters. Return that string. You may assume that size is an integer greater than or equal to 0.

For efficiency, first must be a string, and the keys and values of follow must also be strings. You will receive ZERO POINTS for this project if you use lists or tuples instead of strings!
      My code for Random is about half a page of code, and its methods have one to three lines each. My code for Words is about one page. Python can be very concise! If you find yourself writing much more code than this, then you do not understand this assignment, and you should ask for help.

3. Example.

The random names from part 0 were generated by the following fragment of Python code. First, a new instance of the class Words is created, called prez. Then prez is given the last names of all U.S. presidents. Some names appear more than once because a president served for two non-consecutive terms, or because two presidents had the same last name.

prez = Words(101)  
prez.add('Washington')  
prez.add('Adams')  
prez.add('Jefferson')  
prez.add('Madison')  
prez.add('Monroe')  
prez.add('Adams')  
prez.add('Jackson')  
prez.add('Vanburen')  
prez.add('Harrison')  
prez.add('Tyler')  
prez.add('Polk')  
prez.add('Taylor')  
prez.add('Fillmore')  
prez.add('Pierce')  
prez.add('Buchanan')  
prez.add('Lincoln')  
prez.add('Johnson')  
prez.add('Grant')  
prez.add('Hayes')  
prez.add('Garfield')  
prez.add('Arthur')  
prez.add('Cleveland')  
prez.add('Harrison')  
prez.add('Cleveland')  
prez.add('Mckinley')  
prez.add('Roosevelt')  
prez.add('Taft')  
prez.add('Wilson')  
prez.add('Harding')  
prez.add('Coolidge')  
prez.add('Hoover')  
prez.add('Roosevelt')  
prez.add('Truman')  
prez.add('Eisenhower')  
prez.add('Kennedy')  
prez.add('Johnson')  
prez.add('Nixon')  
prez.add('Ford')  
prez.add('Carter')  
prez.add('Reagan')  
prez.add('Bush')  
prez.add('Clinton')  
prez.add('Bush')  
prez.add('Obama')  
prez.add('Trump')

After this, each call to prez.make(7) returns a new seven-letter word, roughly similar to the names that prez was given. Some look more like English words than others. The longer the words, the less they look like English.

Explanation / Answer

class Random:
# Constructor
def __init__(self, seed):
self.seed = seed
self.sequence = seed

# It returns next sequence generated by the algorithm
def next(self, range):
self.sequence = (16807 * self.sequence) % (2147483648 - 1)
return self.sequence % range # Taking % to bring the random integer in the range

# It returns the next letter from the characters from the random location
def choose(self, characters):
return characters[self.next(len(characters))]


# This Words class implementing add and make methods.
# It generates the word as per the algorithm.
class Words:

# Initializing private variables in the constructor
def __init__(self, seed):
self.__first = ""
self.__follow = {}
self.__random = Random(seed)

# Add words
def add(self, word):
self.__first = self.__first + word[0]
for i in range(len(word)):
if (i + 1) < len(word):
if self.__follow.has_key(word[i]):
self.__follow[word[i]] = self.__follow[word[i]] + word[i + 1]
else:
self.__follow[word[i]] = word[i + 1]

# Generates the word as per the algorithm
def make(self, size):
character = self.__random.choose(self.__first)
word = character
for i in range(size - 1):
if self.__follow.has_key(character):
character = self.__random.choose(self.__follow[character])
else:
character = self.__random.choose(self.__first)
word = word + character

return word

# Main method
def main():
prez = Words(101)
prez.add('Washington')
prez.add('Adams')
prez.add('Jefferson')
prez.add('Madison')
prez.add('Monroe')
prez.add('Adams')
prez.add('Jackson')
prez.add('Vanburen')
prez.add('Harrison')
prez.add('Tyler')
prez.add('Polk')
prez.add('Taylor')
prez.add('Fillmore')
prez.add('Pierce')
prez.add('Buchanan')
prez.add('Lincoln')
prez.add('Johnson')
prez.add('Grant')
prez.add('Hayes')
prez.add('Garfield')
prez.add('Arthur')
prez.add('Cleveland')
prez.add('Harrison')
prez.add('Cleveland')
prez.add('Mckinley')
prez.add('Roosevelt')
prez.add('Taft')
prez.add('Wilson')
prez.add('Harding')
prez.add('Coolidge')
prez.add('Hoover')
prez.add('Roosevelt')
prez.add('Truman')
prez.add('Eisenhower')
prez.add('Kennedy')
prez.add('Johnson')
prez.add('Nixon')
prez.add('Ford')
prez.add('Carter')
prez.add('Reagan')
prez.add('Bush')
prez.add('Clinton')
prez.add('Bush')
prez.add('Obama')
prez.add('Trump')
  
for i in range(100):
print(prez.make(7))

# to call main method
if __name__ == "__main__":
main()

I generated list till 100 such names and found what you were looking for.
I don't think your output will ever be in the sequence given. You can do simple calculation by just considering first letter of all president and seed 101 and you will find that first letter will be G and not B

Grurumo
Jonsone
Hansoro
Cldisoe
Fovenay
Fisooos
Clnnhin
Taruson
Tayeylo
Adgeama
Madiela
Roshnbu
Obayeay
Ponhuso
Monconc

Mcecopy pstable version: https://paste.ee/p/sJySCsens

Haringe
Cosovel
Lingten
Jarrixo
Jonarfi
Adinhum
Ponlele
Polnlel
Ninasoo
Clannga
Relayle
HampCan
Jonhuse
Kesolin
Jolkiso
Linnrso
Einanel
Gruceve
Jendgto
Jenchix
Busonar
Tantonb
Gaylton
Foondga
Pisoels
Adannge
Coshndi
Haneram
Jantoel
Keltons
Adiench
Forthis
Hangted
Aroverf
Monelto
Jonbant
Molelen
Trcerum
Einsoes
Cllixor
Adinbar
Jontera
Gaylkin
HampKey
Grtonda
Hamshnh
Jorfish
Burdada
Winsenr
Vaylkie
Harcksh
Poowela
BumpRoe
Moonera
Obamant
Rensoso
Eiserur
Pielthn
Wanhumo
Tylonth
Cackiso
Tarurso
Burieli
Pineven
Kevevev
Treltoo
Buchnbu
Folearu
Ronburd
Ganbump
Hangady
Cartoon
Tanleln
Adyliev
Tangtoo
Jedylso
Hosedgt
Adisong
Kevevev
Trenhnc
Einbama
Tylsorf
Hashnto
Triseyl

Here is my code to verify that all such names are present

class Random:
# Constructor
def __init__(self, seed):
self.seed = seed
self.sequence = seed

# It returns next sequence generated by the algorithm
def next(self, range):
self.sequence = (16807 * self.sequence) % (2147483648 - 1)
return self.sequence % range # Taking % to bring the random integer in the range

# It returns the next letter from the characters from the random location
def choose(self, characters):
return characters[self.next(len(characters))]


# This Words class implementing add and make methods.
# It generates the word as per the algorithm.
class Words:

# Initializing private variables in the constructor
def __init__(self, seed):
self.__first = ""
self.__follow = {}
self.__random = Random(seed)

# Add words
def add(self, word):
self.__first = self.__first + word[0]
for i in range(len(word)):
if (i + 1) < len(word):
if self.__follow.has_key(word[i]):
self.__follow[word[i]] = self.__follow[word[i]] + word[i + 1]
else:
self.__follow[word[i]] = word[i + 1]

# Generates the word as per the algorithm
def make(self, size):
character = self.__random.choose(self.__first)
word = character
for i in range(size - 1):
if self.__follow.has_key(character):
character = self.__random.choose(self.__follow[character])
else:
character = self.__random.choose(self.__first)
word = word + character

return word

# Main method
def main():
prez = Words(101)
prez.add('Washington')
prez.add('Adams')
prez.add('Jefferson')
prez.add('Madison')
prez.add('Monroe')
prez.add('Adams')
prez.add('Jackson')
prez.add('Vanburen')
prez.add('Harrison')
prez.add('Tyler')
prez.add('Polk')
prez.add('Taylor')
prez.add('Fillmore')
prez.add('Pierce')
prez.add('Buchanan')
prez.add('Lincoln')
prez.add('Johnson')
prez.add('Grant')
prez.add('Hayes')
prez.add('Garfield')
prez.add('Arthur')
prez.add('Cleveland')
prez.add('Harrison')
prez.add('Cleveland')
prez.add('Mckinley')
prez.add('Roosevelt')
prez.add('Taft')
prez.add('Wilson')
prez.add('Harding')
prez.add('Coolidge')
prez.add('Hoover')
prez.add('Roosevelt')
prez.add('Truman')
prez.add('Eisenhower')
prez.add('Kennedy')
prez.add('Johnson')
prez.add('Nixon')
prez.add('Ford')
prez.add('Carter')
prez.add('Reagan')
prez.add('Bush')
prez.add('Clinton')
prez.add('Bush')
prez.add('Obama')
prez.add('Trump')
l = ["BumpRoe", "Cartoon", "Forthis", "Fovenay", "Gaylton", "Haneram", "Hansoro", "Madiela", "Ninasoo", "Relayle", "Ronburd", "Wanhumo"]
count = 0
for i in range(100):
name = prez.make(7)
if name in l:
print(name)
count += 1
print(count)
print(len(l))

# to call main method
if __name__ == "__main__":
main()

# code link: https://paste.ee/p/nZo61