I need to find words in a list of lists (a somewhat matrix), by entering a given direction to search.
so for example, if I need to search all words that are horizontal from right to left - I will do that by manipulating the indexes that run over the columns.
the_matrix = [['a', 'p', 'p', 'l', 'e'],
['a', 'g', 'o', 'd', 'o'],
['n', 'n', 'e', 'r', 't'],
['g', 'a', 'T', 'A', 'C'],
['m', 'i', 'c', 's', 'r'],
['P', 'o', 'P', 'o', 'P']]
the_word_list = ['ert','PoP']
def find_words_in_matrix(directions):
good_list = []
for col in range(len(the_matrix[0])):
for row in range(len(the_matrix)):
for word in the_word_list:
for i in range(len(word)):
found_word = True
#a = word[i]
if col + i > len(the_matrix[0])-1:
break
#b = the_matrix[row][col+i]
if word[i] != the_matrix[row][col+i]:
found_word=False
break
if found_word is True:
good_list.append(word)
return good_list
Im getting the output:
['PoP', 'ert', 'PoP', 'ert', 'PoP']
instead of:
['PoP', 'ert', 'PoP']
*pop shows up twich at the bottom line, not three times. and ert only once.
that is my problem
thanks for the help!
You are getting stray matches when the break terminates the loop early before the whole word has matched. To eliminate this, you can keep track of the match length:
def find_words_in_matrix(directions):
good_list = []
for col in range(len(the_matrix[0])):
for row in range(len(the_matrix)):
for word in the_word_list:
match_len = 0
for i in range(len(word)):
found_word = True
#a = word[i]
if col + i > len(the_matrix[0])-1:
break
#b = the_matrix[row][col+i]
if word[i] != the_matrix[row][col+i]:
found_word=False
break
match_len += 1
if (match_len == len(word)) and (found_word is True):
good_list.append(word)
return good_list
Related
inp = (input("Paste in the encoded message (over 100 words):\n")).lower()
inp_list = list(inp)
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
letter_counter = 26
new_list = []
number_of_es = []
def shift_list(lista):
for item in lista:
if item in letters:
if (letters.index(item) - 1) < 0:
position = (letters.index(item) - 1) + 26
else:
position = (letters.index(item) - 1)
new_list.append(letters[position])
else:
new_list.append(item)
return new_list
while letter_counter > 0:
number_of_es.append(inp_list.count("e"))
print(number_of_es)
letter_counter -= 1
inp_list = shift_list(inp_list)
print(inp_list)
print(letter_counter)
(https://i.stack.imgur.com/fuGrp.png)(https://i.stack.imgur.com/j6oE4.png)
I am a beginner in python but have started trying to write some code that I find interesting. I am trying to make a program that cycles each letter in a line of text through the alphabet, counting the incidences of the letter 'e'.
The problem I am having is that the while loop seems to break after one iteration and I can't see where the problem is.
Python provides two keywords that terminate a loop iteration prematurely:
The Python break statement immediately terminates a loop entirely. Program execution proceeds to the first statement following the loop body.
The Python continue statement immediately terminates the current loop iteration. Execution jumps to the top of the loop, and the controlling expression is re-evaluated to determine whether the loop will execute again or terminate.
Initializing the new_list within the function shift_list() should fix the problem.
Thus a new empty list is created and filled for each function call.
Otherwise the list is always extended because it was a global variable.
inp = (input("Paste in the encoded message (over 100 words):\n")).lower()
inp_list = list(inp)
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
letter_counter = 26
number_of_es = []
def shift_list(lista):
new_list = []
for item in lista:
if item in letters:
if (letters.index(item) - 1) < 0:
position = (letters.index(item) - 1) + 26
else:
position = (letters.index(item) - 1)
new_list.append(letters[position])
else:
new_list.append(item)
return new_list
while letter_counter > 0:
number_of_es.append(inp_list.count("e"))
print(number_of_es)
letter_counter -= 1
inp_list = shift_list(inp_list)
print(inp_list)
print(letter_counter)
I am completely new to computer science and am not sure on how to collect the results and return them to the user as an 8 character string.
This is the code I made to give the user 8 random consonants or vowels based on what the user asks for.
count = 2
while count < 10:
char = input("v or c")
if char == "v":
vow = ['a', 'e', 'i', 'o', 'u']
v = random.choice(vow)
print(v)
count = count + 1
if char == "c":
con = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's',
't', 'v', 'w', 'x',
'y', 'z']
c = random.choice(con)
print(c)
count = count + 1`
Just collect the random choices in a list or a string:
vowels = 'aeiou' # random.choice can choose from any type of sequence
consonants = 'bcdfghjklmnpqrstvwxyz'
chars = [] # collects the choices
for _ in range(8): # for loop if iteration count is known beforehand
select_char = input("Please enter either v for a vowel or c for a consonant: ")
if select_char == "v":
chars.append(random.choice(vowels))
else:
chars.append(random.choice(consonants))
print(''.join(chars))
So I am supposed to make a script that asks user to make a sentence then discard all characters but lower case and print the lower case letters like this ['m', 'y', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd'].
My script:
#!/usr/bin/python3
sentence = input("Enter a sentence: ")
for letter in sentence:
if letter.islower():
print(letter)
and this is the output:
o
e
s
h
i
s
w
r
k
Seems like you want to produce a list, you have list comprehensions to make life easy:
l = ['P', 'm', 'y', 'H', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd']
out = [i for i in l if i.islower()]
print(out)
# ['m', 'y', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd']
Which is equivalent to:
out = []
for i in l:
if i.islower():
out.append(i)
print(out)
# ['m', 'y', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd']
You might be looking for end = ",":
sentence = input("Enter a sentence: ")
for letter in sentence:
if letter.islower():
print(letter, end=",")
# ^^^
Your program is almost OK, only instead of printing every lowercase character, append it to a list, and finally print only that list:
sentence = input("Enter a sentence: ")
lowercases = [] # prepare an empty list
for letter in sentence:
if letter.islower():
lowercases.append(letter)
print(lowercases) # print the filled list
Test:
Enter a sentence: The End of Universe.
['h', 'e', 'n', 'd', 'o', 'f', 'n', 'i', 'v', 'e', 'r', 's', 'e']
I am doing a Python exercise to search a word from a given sorted wordlist, containing more than 100,000 words.
When using bisect_left from the Python bisect module, it is very efficient, but using the binary method created by myself is very inefficient. Could anyone please clarify why?
This is the searching method using the Python bisect module:
def in_bisect(word_list, word):
"""Checks whether a word is in a list using bisection search.
Precondition: the words in the list are sorted
word_list: list of strings
word: string
"""
i = bisect_left(word_list, word)
if i != len(word_list) and word_list[i] == word:
return True
else:
return False
My implementation is really very inefficient (don't know why):
def my_bisect(wordlist,word):
"""search the given word in a wordlist using
bisection search, also known as binary search
"""
if len(wordlist) == 0:
return False
if len(wordlist) == 1:
if wordlist[0] == word:
return True
else:
return False
if word in wordlist[len(wordlist)/2:]:
return True
return my_bisect(wordlist[len(wordlist)/2:],word)
if word in wordlist[len(wordlist)/2:]
will make Python search through half of your wordlist, which is kinda defeating the purpose of writing a binary search in the first place. Also, you are not splitting the list in half correctly. The strategy for binary search is to cut the search space in half each step, and then only apply the same strategy to the half which your word could be in. In order to know which half is the right one to search, it is critical that the wordlist is sorted. Here's a sample implementation which keeps track of the number of calls needed to verify whether a word is in wordlist.
import random
numcalls = 0
def bs(wordlist, word):
# increment numcalls
print('wordlist',wordlist)
global numcalls
numcalls += 1
# base cases
if not wordlist:
return False
length = len(wordlist)
if length == 1:
return wordlist[0] == word
# split the list in half
mid = int(length/2) # mid index
leftlist = wordlist[:mid]
rightlist = wordlist[mid:]
print('leftlist',leftlist)
print('rightlist',rightlist)
print()
# recursion
if word < rightlist[0]:
return bs(leftlist, word) # word can only be in left list
return bs(rightlist, word) # word can only be in right list
alphabet = 'abcdefghijklmnopqrstuvwxyz'
wl = sorted(random.sample(alphabet, 10))
print(bs(wl, 'm'))
print(numcalls)
I included some print statements so you can see what is going on. Here are two sample outputs. First: word is in the wordlist:
wordlist ['b', 'c', 'g', 'i', 'l', 'm', 'n', 'r', 's', 'v']
leftlist ['b', 'c', 'g', 'i', 'l']
rightlist ['m', 'n', 'r', 's', 'v']
wordlist ['m', 'n', 'r', 's', 'v']
leftlist ['m', 'n']
rightlist ['r', 's', 'v']
wordlist ['m', 'n']
leftlist ['m']
rightlist ['n']
wordlist ['m']
True
4
Second: word is not in the wordlist:
wordlist ['a', 'c', 'd', 'e', 'g', 'l', 'o', 'q', 't', 'x']
leftlist ['a', 'c', 'd', 'e', 'g']
rightlist ['l', 'o', 'q', 't', 'x']
wordlist ['l', 'o', 'q', 't', 'x']
leftlist ['l', 'o']
rightlist ['q', 't', 'x']
wordlist ['l', 'o']
leftlist ['l']
rightlist ['o']
wordlist ['l']
False
4
Note that if you double the size of the wordlist, i.e. use
wl = sorted(random.sample(alphabet, 20))
numcalls on average will be only one higher than for a wordlist of length 10, because wordlist has to be split in half only once more.
to search if a word is in a wordlist simply (python 2.7):
def bisect_fun(listfromfile, wordtosearch):
bi = bisect.bisect_left(listfromfile, wordtosearch)
if listfromfile[bi] == wordtosearch:
return listfromfile[bi], bi
I'm trying to write a method that takes a key and an alphabet and creates a playfair cipher box. For those of you that don't know what that is, It takes the key and puts it in a 5 x 5 grid of letters, spilling onto the next line if neccessary, and then adds the rest of the letters of the alphabet. Each letter is only supposed to appear in the box once. I'm trying to do this with a list with 5 internal lists, each with 5 items. the only problem is that where the method is supposed to skip letters, it isn't. Here is the method and the output, can anyone help me?
def makePlayFair(key, alpha):
box = []
#join the key and alphabet string so that you only have to itterate over one string
keyAlpha = ""
keyAlpha = keyAlpha.join([key, alpha])
ind = 0
for lines in range(5):
line = []
while len(line) < 5:
if isIn(keyAlpha[ind], box) or isIn(keyAlpha[ind], line):
print(isIn(keyAlpha[ind],box))
ind += 1
continue
else:
line.append(keyAlpha[ind])
ind += 1
box.append(line)
return box
def isIn(item, block):
there = None
for each_item in block:
if type(each_item) == type([]):
for nested_item in each_item:
if item == nested_item:
there = True
break
else:
there = False
else:
if item == each_item:
there = True
break
else:
there = False
return there
>>> makePlayFair("hello", alphabet) #alphabet is a string with all the letters in it
> `[['h', 'e', 'l', 'o', 'a'], ['b', 'c', 'd', 'f', 'g'], ['h', 'i', 'j', 'k', 'l'], ['m', 'n', 'o', 'p', 'q'], ['r', 's', 't', 'u', 'v']]`
Thanks for your help in advance!
cheers, brad
Your problem is in isIn:
Your break statement only breaks out of the inner for loop. The code then continues to iterate over the second for loop. This means that only the last one is considered. You have to make sure that you exit out of both loops for this to work correctly.
The entire process can be made simpler by doing something like:
def makePlayFair(key, alpha):
letters = []
for letter in key + alpha:
if letter not in letters:
letters.append(letter)
box = []
for line_number in range(5):
box.append( letters[line_number * 5: (line_number+1) * 5])
Make the list of letters first, then break them up into the 5x5 grid:
def takeNatATime(n, seq):
its = [iter(seq)]*n
return zip(*its)
def makePlayfair(s):
keystr = []
for c in s + "abcdefghijklmnopqrstuvwxyz":
if c not in keystr:
keystr.append(c)
return list(takeNatATime(5, keystr))
print makePlayfair("hello")
Prints:
[('h', 'e', 'l', 'o', 'a'), ('b', 'c', 'd', 'f', 'g'), ('i', 'j', 'k', 'm', 'n'), ('p', 'q', 'r', 's', 't'), ('u', 'v', 'w', 'x', 'y')]
Here's my attempt:
#!/usr/bin/env python
from string import ascii_uppercase
import re
def boxify(key):
cipher = []
key = re.sub('[^A-Z]', '', key.upper())[:25]
for i in range(max(25 - len(key), 0)):
for letter in ascii_uppercase:
if letter not in key:
key += letter
break
for i in range(0, 25, 5):
cipher.append(list(key[i:i+5]))
return cipher
if __name__ == "__main__":
print boxify("This is more than twenty-five letters, i'm afraid.")
print boxify("But this isn't!")