Using binary search and user input - python

I'm trying to figure out how to use binary search on a list that was already sorted so I can have the user search for a name that was entered by the user and have it display the name if it's there or tell the user if it's not.
I cannot use built-in sort functions.
I have the bubble search setup to sort the list of names entered by the user, which is the code below:
def names():
members = []
done = False
while done != True:
mem = input("Enter a name, enter 'done' when finished: ")
if mem == "done":
done = True
else:
members.append(mem)
print(members)
index = len(members) - 1
sort = False
while not sort:
sort = True
for j in range(0, index):
if members[j] > members[j + 1]:
sort = False
members[j], members[j + 1] = members[j + 1], members[j]
#Here is the output for the first code:
Enter a name, enter 'done' when finished: Bob
['Bob']
Enter a name, enter 'done' when finished: George
['Bob', 'George']
Enter a name, enter 'done' when finished: Mike
['Bob', 'George', 'Mike']
Enter a name, enter 'done' when finished: Zed
['Bob', 'George', 'Mike', 'Zed']
Enter a name, enter 'done' when finished: Vorp
['Bob', 'George', 'Mike', 'Zed', 'Vorp']
Enter a name, enter 'done' when finished: done
['Bob', 'George', 'Mike', 'Vorp', 'Zed']
I created another function for searching the sorted list and this is where I'm stuck. I've attempted to take the sorted list and place it in my main() function but it's not printing anything.
def main(members):
name_search = input("Please enter the name you're looking for: ")
print(name_search)
begin_index = 0
end_index = len(members) -1
while begin_index <= end_index:
midpoint = begin_index + (end_index - begin_index) // 2
midpoint_value = members[midpoint]
if midpoint_value == members:
return midpoint
elif members < midpoint_value:
end_index = midpoint - 1
else:
begin_index = midpoint + 1
print(members)
return None
names()
Does anyone mind helping?

It's basically the same algorithm for regular binary search, simply replace the number list with the name list:
def binary(lst, sml, bg, x):
if bg >= sml:
mid = (bg + sml) // 2
if lst[mid] == x:
return mid
elif lst[mid] > x:
return binary(lst, sml, mid - 1, x)
else:
return binary(lst, mid + 1, bg, x)
else:
return -1
lst = ['Bob', 'George', 'Mike', 'Vorp', 'Zed']
x = input('Input the name: ')
index = binary(lst, 0, len(lst)-1, x)
if index != -1:
print(index)
else:
print("Not in list.")
Input:
Input the name: Mike
Output:
2

You are comparing the midpoint_value against the whole list instead of name_search. Try with this:
if midpoint_value == name_search:
return midpoint
elif name_search < midpoint_value:
end_index = midpoint - 1
else:
begin_index = midpoint + 1
Also for your future questions, make sure you provide a minimal reproducible example, e.g.:
def search(name_search, members):
begin_index = 0
end_index = len(members) -1
while begin_index <= end_index:
midpoint = begin_index + (end_index - begin_index) // 2
midpoint_value = members[midpoint]
if midpoint_value == name_search :
return midpoint
elif name_search < midpoint_value:
end_index = midpoint - 1
else:
begin_index = midpoint + 1
return None
members = ['Bob', 'George', 'Mike', 'Vorp', 'Zed']
name_search = 'George'
print(search(name_search, members))

Related

Vieux garcon game - Problem with execution

how would I solve this problem? The program is supposed to remove all pairs from your hand at the beginning but it is not working. This is what it outputs at the moment:
Hello. I am Robot and I distribute the cards.
Your hand is:
2♠ 5♡ Q♠ Q♡ 4♡ J♢ 2♣ J♠ K♢ 8♢ 10♠ A♣ 5♣ 3♣ 6♣ 4♢ 7♣ 9♢ 2♢ J♡ A♢ 8♠ 10♣ 6♢ 10♡
Don't worry, I cannot see your cards or their order.
Now discard all pairs in your hand. I will do it too.
Press Enter to continue.
************************************************************
Your turn.
Your hand is:
9♢ J♡ 3♣ K♢ 10♠ 2♢ 10♣ 10♡ 7♣
There is not supposed to be two 10s in your hand. This is the code:
# vieux garcon card game.
import random
def wait_for_player():
try:
input("Press Enter to continue. ")
except SyntaxError:
pass
def prepare_pack():
pack = []
colors = ['♠', '♡', '♢', '♣']
value = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
for val in value:
for color in colors:
pack.append(val + color)
pack.remove('J♣')
return pack
def shuffle_pack(p):
random.shuffle(p)
def give_cards(p):
giver = []
other = []
loop = 0
for i in p:
if (loop % 2) == 0:
giver.append(i)
else:
other.append(i)
loop += 1
return (giver, other)
def remove_pairs(l):
colors = ['♠', '♡', '♢', '♣']
result = []
for crt in l:
if crt[1] + crt[0] == '10':
nbr = '10'
else:
nbr = crt[0]
for i in colors:
find = False
if nbr + i in result:
find = True
result.remove(nbr + i)
break
if find == False:
result.append(crt)
random.shuffle(result)
return result
def show_cards(p):
for i in p:
print(i, end = " ")
print()
def enter_valid_position(n):
enter = int(input('Please enter a number from 1 to'+ str(n) +": ")) - 1
while enter not in range(0, n):
enter = int(input('Invalid position. Please enter a number from 1 to ' + str(n) +": ")) - 1
return enter
def play():
p = prepare_pack()
shuffle_pack(p)
tmp = give_cards(p)
giver = tmp[0]
human = tmp[1]
print("Hello. I am Robot and I distribute the cards.")
print("Your hand is:")
show_cards(human)
print("Don't worry, I cannot see your cards or their order.")
print(
"Now discard all pairs in your hand. I will do it too."
)
wait_for_player()
giver = remove_pairs(giver)
human = remove_pairs(human)
#Instance = 1, human's turn, instance = 2, robot's turn
instance = 1
while instance in range(1,2):
if instance == 1:
print('*' * 60)
print('Your turn.')
print('Your hand is: ')
show_cards(human)
print("I have ", len(giver), "cards. If 1 is the position of my first card and ")
print(len(giver), "is the position of my last card, which card do you want?")
entry = enter_valid_position(len(giver))
print("You asked for my card number ", entry+1, ".")
print("There it is. It is a ", giver[entry])
print("With ", giver[entry]," added, your hand is:")
human.append(giver[entry])
giver.remove(giver[entry])
show_cards(human)
human=remove_pairs(human)
if len(human) == 0:
print("I finished all the cards.")
win = True
break
print("After discarding all pairs and shuffling the cards, your hand is:")
show_cards(human)
wait_for_player()
instance = 2
pass
if instance == 2:
print('*' * 60)
print('My turn.')
take_card = random.randint(0, len(human) - 1)
giver.append(human[take_card])
human.remove(human[take_card])
print("I took your card number ", take_card+1,".")
giver=remove_pairs(giver)
if len(giver)==0:
print("I finished all the cards.")
win = False
break
wait_for_player()
instance = 1
pass
if win == True:
print("Congratulations! You, Human, have won.")
else:
print("You lost! Me, Robot, have won.")
# main
play()
What should I do? My program does remove pairs later on in the game, but not at the beginning.
I found my error.
for crt in l:
if crt[1] + crt[0] == '10':
nbr = '10'
I flipped the positions of the 1 and 0. it was checking for 01 and not 10. It was supposed to be:
for crt in l:
if crt[0] + crt[1] == '10':
nbr = '10'
Sorry for the inconvience.

Last paragraph of code is running when it does not need to

I am working on a username generator in Python, and everything is going well but one thing: the "IF" statement at the very end of the code is malfunctioning. The first part of the code works, but the last paragraph kicks in, even when I have typed in a supposedly valid choice.
The code:
[import random, tkinter
#variables that make up the name. the "1" symbolises the first part and the "2" symbolises the last part of the username
general1 = \["noob","baby","dude","soldier","discount"\]
general2 = \["kid","plant","painter","officer","conscience"\]
animal1 = \["frantic","fiesty","quick","quiet","loud"\]
animal2 = \["ferret","dog","hampster","cat","rabbit"\]
food1 = \["delicious","disgusting","stinky","fried","bitter"\]
food2 = \["pickle","chocolate","rice","water","lemonade"\]
name1 = \["dylan","eve","chris","simon","adele"\]
name2 = \["christopher","sharp","smith","james","baker"\]
#the main part
category = str(input("**USERNAME GENERATOR**\n\nWhat category do you want?\n1 for general\n2 for animals\n3 for food\n4 for human names\n\n"))
if category == "1":
output1 = random.choice((general1))
output2 = random.choice((general2))
endNumber = random.randint(0, 100)
print("\nYour random username is: ",output1,output2,endNumber)
if category == "2":
output1 = random.choice((animal1))
output2 = random.choice((animal2))
endNumber = random.randint(0, 100)
print("\nYour random username is: ",output1,output2,endNumber)
if category == "3":
output1 = random.choice((food1))
output2 = random.choice((food2))
endNumber = random.randint(0, 100)
print("\nYour random username is: ",output1,output2,endNumber)
if category == "4":
output1 = random.choice((name1))
output2 = random.choice((name2))
endNumber = random.randint(0, 100)
print("\nYour random username is: ",output1,output2,endNumber)
if category != ("1","2","3","4"):
print("\nPlease enter a valid option:")
category = str(input("What category do you want?\n1 for general\n2 for animals\n3 for food\n4 for human names\n\n"))][1]
if category != ("1","2","3","4"):
This only checks if category is equal to the tuple ("1","2","3","4"). You want to check if category is equal to any value of the tuple. Do that by changing that line to this:
if category not in ("1","2","3","4"):
After an if statement ends, the next line is executed.
In your case, the next line is the next if paragraph.
And after that the next one and so on.
e.g.:
if a:
do_action_a()
if b:
do_action_b()
if c:
do_action_c()
if not(a or b or c):
do_action_all_others()
Here you will always execute each paragraph independently of the previous one(s).
To avoid this, you can put each of the following statements in the
else of the previous if statement:
if a:
do_action_a()
else:
if b:
do_action_b()
else:
if c:
do_action_c()
else:
do_action_all_others()
However, there is an idiom for this: elif
so the pythonic is to use:
if a:
do_action_a()
elif b:
do_action_b()
elif c:
do_action_c()
else:
do_action_all_others()
Change the last conditional statement to
if category not in ('1', '2', '3', '4'):
print('\nPlease enter a valid option:')
category = str(input('. . .'))
My Refined Implementation of your code
import random
general_first = ['noob', 'baby', 'dude', 'soldier', 'discount']
general_last = ['kid', 'plant', 'painter', 'officer', 'conscience']
animal_first = ['frantic', 'fiesta', 'quick', 'quiet', 'loud']
animal_last = ['ferret', 'dog', 'hamster', 'cat', 'rabbit']
food_first = ['delicious', 'disgusting', 'stinky', 'fried', 'bitter']
food_last = ['pickle', 'chocolate', 'rice', 'water', 'lemonade']
name_first = ['dylan', 'eve', 'chris', 'simon', 'adele']
name_last = ['christopher', 'sharp', 'smith', 'james', 'baker']
def endNumber(): return str(random.randint(0, 100))
def firstName(values): return random.choice(values)
def lastName(values): return random.choice(values)
def generate_usernames(category):
if category == 1:
return firstName(general_first) + lastName(general_last) + endNumber()
elif category == 2:
return firstName(animal_first) + lastName(animal_last) + endNumber()
elif category == 3:
return firstName(food_first) + lastName(food_last) + endNumber()
elif category == 4:
return firstName(name_first) + lastName(name_last) + endNumber()
else:
return None
input_prompt = "What category do you want?" \
"\n'1' for general" \
"\n'2' for animals" \
"\n'3' for food" \
"\n'4' for human names" \
"\n\nCHOICE : "
invalid_prompt = "\nPlease enter a valid option"
print('\tUSERNAME GENERATOR')
while True:
input_category = int(input(input_prompt))
username = generate_usernames(input_category)
if username is not None:
print(f'Your Random Username is : {username}')
break
else:
print(invalid_prompt)

Budget tracker program not working in Linux

I am trying to improve this program. I am working with Linux. I want to add a menu function where the user can pick an option and based on the option call the respective function, but the program is not working, when I run it in the Terminal it doesn't do anything and doesn't show any errors. Please, I need help to solve the problem and make the program works. Thanks!
Here's what I have so far, still there are some functions that need to develop:
#! /usr/bin/python3
import sys
def menu(self):
print ("""
1. Add an Expense
2. Remove an Expense
3. Add revenue
4. Remove Revenue
5. Exit
""")
option = input ("What would you like to do [Number Only]?")
if option == "1":
self.add_expense()
elif option == "2":
self.remove_expense()
elif option == "3":
self.add_revenue()
elif option == "4":
self.remove_revenue()
else:
self.reset_program()
self.close_program()
return option
def add_expense(self):
def __init__(self):
self.month_balance = 0
self.expenses = 0
self.expense_list = []
self.expense_name = []
self.month_balance_name = []
self.month_balance_list = []
self.prompt_income()
def month_balance_ask(self):
add_month_balance = input('Add monthly balance? [y/n]: ')
return add_month_balance
def month_balance_sum(self):
self.month_balance = sum(self.month_balance_list)
def expense_ask(self):
add_expense = input('Add expense? [y/n]: ')
return add_expense
def expense_sum(self):
self.expenses = sum(self.expense_list)
def month_balance_check(self):
if not self.month_balance_list:
print('Please enter at least one monthly balance. ')
self.prompt_month_balance()
def expense_check(self):
if not self.expense_list:
print('Please enter at least one expense. ')
self.prompt_expense()
def prompt_month_balance(self):
x = False
while not x:
result = self.month_balance_ask()
if result == 'y':
month_balance_input = int(input('Enter monthly balance. [Numbers Only]: '))
self.month_balance_list.append(month_balance_input)
month_balance_name = input('Enter monthly balance name. [Name Only]: ')
self.month_balance_name.append(month_balance_name)
else:
self.month_balance_check()
x = True
self.month_balance_sum()
name = [name for name in self.month_balance_name]
month_balance = [month_balance for month_balance in self.month_balance_list]
month_balancedict = dict(zip(name, month_balance))
for k in incomedict:
print(k + ': ', '$' + str(month_balancedict[k]))
print('Total user monthly balance: ', '$' + str(self.month_balance))
self.prompt_expense()
def prompt_expense(self):
x = False
while not x:
result = self.expense_ask()
if result == 'y':
expense_input = int(input('Enter expense amount. [Numbers Only]: '))
self.expense_list.append(expense_input)
expense_name = input('Enter expense name. [Name Only]: ')
self.expense_name.append(expense_name)
else:
self.expense_check()
x = True
self.expense_sum()
name = [name for name in self.expense_name]
expense = [income for income in self.expense_list]
expensedict = dict(zip(name, expense))
for k in expensedict:
print(k + ': ', '$' + str(expensedict[k]))
print('Total user expenses: ', '$' + str(self.expenses))
self.added_expense()
def added_expense(self):
expenseadded = self.month_balance - self.expenses
if expenseadded < 0:
print('You are in the negative, you have a deficit of ' + '$' + str(expenseadded))
if expenseadded == 0:
print('You have broken even, you are spending exactly as much as you make.')
if expenseadded > 0:
print('You are in the positive, you have a surplus of ' + '$' + str(expenseadded))
another = input('Would you like to run another analysis? [y/n]: ')
if another == 'y':
self.menu()
else:
self.reset_program()
self.close_program()
def remove_expense(self):
print("code goes here")
def add_revenue(self):
print("code goes here")
def remove_revenue(self):
print("code goes here")
def reset_program(self):
self.month_balance = 0
self.expenses = 0
del self.expense_list[0:]
del self.expense_name[0:]
del self.month_balance_name[0:]
del self.month_balance_list[0:]
self.prompt_month_balance()
def close_program(self):
print('Exiting Program.')
sys.exit(0)

Flight seating: Python (reset seating problem)

I'm working on an assignment that books seats on a flight, the code I have so far works for everything besides the part for resetting all the seats to available when the flight is fully booked.
NUM_ROWS = 2
NUM_COLS = 1
AVAIL = '-'
BOOKED = 'X'
seatTable = []
for i in range(NUM_ROWS):
column = []
for j in range(NUM_COLS):
column.append(AVAIL)
seatTable.append(column)
def resetTable(seats): ##<--need to fix
seatTable = []
for i in range(NUM_ROWS):
column = []
for j in range(NUM_COLS):
column.append(AVAIL)
seatTable.append(column)
resetTable(printTable(seatTable)) ##<-- not correct
print()
def printTable(seats):
i=1
alpha = 'abcdefghijklmnopqrstuvwxyz'
print('Row', end=' ')
for num in range(NUM_COLS):
print(f'{alpha[num]:2s}'.format(alpha),end='')
print()
for num in seats:
print(f'{str(i):3s}'.format(str(i)), end=' ')
i+=1
for j in num:
print(j,end=' ')
print()
def full(seats):
for row in seats:
for seat in row:
if seat == AVAIL:
return False
return True
def getRes():
alpha = 'abcdefghijklmnopqrstuvwxyz'
while True:
try:
rowNum = input(f'Enter a row number (1 to {NUM_ROWS}): ')
seatLetter = input(f'Enter a seat letter (A to {(alpha[NUM_COLS-1]).upper()}): ')
reserve(seatTable,rowNum,seatLetter)
break
except:
pass
print('Error, Please choose another seat')
print(f'Seat {rowNum}{seatLetter.upper()} has been booked\n')
def reserve(seats,resR,resC):
alpha = 'abcdefghijklmnopqrstuvwxyz'
column = 0
p = 0
for i in alpha:
if i.lower() == resC.lower():
column = p
p+=1
row = int(resR)-1
seats[row][column] = BOOKED
def main():
printTable(seatTable)
while not full(seatTable):
getRes()
printTable(seatTable)
print('Plane is booked')
next = input('\nWould you like to check the next flight? (Y/N): ')
if next == 'y': ##<---problem
resetTable(printTable(seatTable))
return main()
else:
exit()
main()
When I run the code to check for the "next flight" the seats reset, but then gets stuck on an infinite loop, followed by an error:
line 23, in resetTable
resetTable(printTable(seatTable)) ##<-- not correct
[Previous line repeated 992 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object
How can I fix the resetTable() function to work?
Try this
NUM_ROWS = 2
NUM_COLS = 1
AVAIL = '-'
BOOKED = 'X'
seatTable = []
for i in range(NUM_ROWS):
column = []
for j in range(NUM_COLS):
column.append(AVAIL)
seatTable.append(column)
def resetTable(seats):
for i in range(NUM_ROWS):
column = []
for j in range(NUM_COLS):
seatTable[i][j] = AVAIL
def printTable(seats):
i=1
alpha = 'abcdefghijklmnopqrstuvwxyz'
print('Row', end=' ')
for num in range(NUM_COLS):
print(f'{alpha[num]:2s}'.format(alpha),end='')
print()
for num in seats:
print(f'{str(i):3s}'.format(str(i)), end=' ')
i+=1
for j in num:
print(j,end=' ')
print()
def full(seats):
for row in seats:
for seat in row:
if seat == AVAIL:
return False
return True
def getRes():
alpha = 'abcdefghijklmnopqrstuvwxyz'
while True:
try:
rowNum = input(f'Enter a row number (1 to {NUM_ROWS}): ')
seatLetter = input(f'Enter a seat letter (A to {(alpha[NUM_COLS-1]).upper()}): ')
reserve(seatTable,rowNum,seatLetter)
break
except:
pass
print('Error, Please choose another seat')
print(f'Seat {rowNum}{seatLetter.upper()} has been booked\n')
def reserve(seats,resR,resC):
alpha = 'abcdefghijklmnopqrstuvwxyz'
column = 0
p = 0
for i in alpha:
if i.lower() == resC.lower():
column = p
p+=1
row = int(resR)-1
seats[row][column] = BOOKED
def main():
printTable(seatTable)
while not full(seatTable):
getRes()
printTable(seatTable)
print('Plane is booked')
next = input('\nWould you like to check the next flight? (Y/N): ')
if next == 'y':
resetTable(seatTable)
return main()
else:
exit()
main()

How do I run a binary search for words that start with a certain letter?

I am asked to binary search a list of names and if these names start with a particular letter, for example A, then I am to print that name.
I can complete this task by doing much more simple code such as
for i in list:
if i[0] == "A":
print(i)
but instead I am asked to use a binary search and I'm struggling to understand the process behind it. We are given base code which can output the position a given string. My problem is not knowing what to edit so that I can achieve the desired outcome
name_list = ["Adolphus of Helborne", "Aldric Foxe", "Amanita Maleficant", "Aphra the Vicious", "Arachne the Gruesome", "Astarte Hellebore", "Brutus the Gruesome", "Cain of Avernus"]
def bin_search(list, item):
low_b = 0
up_b = len(list) - 1
found = False
while low_b <= up_b and found == False:
midPos = ((low_b + up_b) // 2)
if list[midPos] < item:
low_b = midPos + 1
elif list[midPos] > item:
up_b = midPos - 1
else:
found = True
if found:
print("The name is at positon " + str(midPos))
return midPos
else:
print("The name was not in the list.")
Desired outcome
bin_search(name_list,"A")
Prints all the names starting with A (Adolphus of HelBorne, Aldric Foxe .... etc)
EDIT:
I was just doing some guess and check and found out how to do it. This is the solution code
def bin_search(list, item):
low_b = 0
up_b = len(list) - 1
true_list = []
count = 100
while low_b <= up_b and count > 0:
midPos = ((low_b + up_b) // 2)
if list[midPos][0] == item:
true_list.append(list[midPos])
list.remove(list[midPos])
count -= 1
elif list[midPos] < item:
low_b = midPos + 1
count -= 1
else:
up_b = midPos - 1
count -= 1
print(true_list)
Not too sure if this is what you want as it seems inefficient... as you mention it seems a lot more intuitive to just iterate over the entire list but using binary search i found here i have:
def binary_search(seq, t):
min = 0
max = len(seq) - 1
while True:
if max < min:
return -1
m = (min + max) // 2
if seq[m][0] < t:
min = m + 1
elif seq[m][0] > t:
max = m - 1
else:
return m
index=0
while True:
index=binary_search(name_list,"A")
if index!=-1:
print(name_list[index])
else:
break
del name_list[index]
Output i get:
Aphra the Vicious
Arachne the Gruesome
Amanita Maleficant
Astarte Hellebore
Aldric Foxe
Adolphus of Helborne
You just need to found one item starting with the letter, then you need to identify the range. This approach should be fast and memory efficient.
def binary_search(list,item):
low_b = 0
up_b = len(list) - 1
found = False
midPos = ((low_b + up_b) // 2)
if list[low_b][0]==item:
midPos=low_b
found=True
elif list[up_b][0]==item:
midPos = up_b
found=True
while True:
if found:
break;
if list[low_b][0]>item:
break
if list[up_b][0]<item:
break
if up_b<low_b:
break;
midPos = ((low_b + up_b) // 2)
if list[midPos][0] < item:
low_b = midPos + 1
elif list[midPos] > item:
up_b = midPos - 1
else:
found = True
break
if found:
while True:
if midPos>0:
if list[midPos][0]==item:
midPos=midPos-1
continue
break;
while True:
if midPos<len(list):
if list[midPos][0]==item:
print list[midPos]
midPos=midPos+1
continue
break
else:
print("The name was not in the list.")
the output is
>>> binary_search(name_list,"A")
Adolphus of Helborne
Aldric Foxe
Amanita Maleficant
Aphra the Vicious
Arachne the Gruesome
Astarte Hellebore

Categories

Resources