Adding if condition based on value [Python] - python

So basically, I have to add one more condition to my if statement depending on the length of the list. Here's the sample code:
for index in indices:
if len(phrase.split(" ")) == 1:
if path in rang:
rang[path] += 1
else:
rang[path] = 1
elif len(phrase.split(" ")) == 2:
if phrase.split(" ")[1] == parser.words[index + 1]:
if path in rang:
rang[path] += 1
else:
rang[path] = 1
elif len(phrase.split(" ")) == 3:
if phrase.split(" ")[1] == parser.words[index + 1] and phrase.split(" ")[2] == parser.words[index + 2]:
if path in rang:
rang[path] += 1
else:
rang[path] = 1
else:
if phrase.split(" ")[1] == parser.words[index + 1] and phrase.split(" ")[2] == parser.words[index + 2] and phrase.split(" ")[3] == parser.words[index + 3]:
if path in rang:
rang[path] += 1
else:
rang[path] = 1

So basically you are trying this?
all(p==q for p, q in zip(phrase.split(" ")[1:], parser.words[index+1:]))
That should replace all the if/elif-statements.
zip returns a tuple of two elements, one from each list; we are then iterating this list of tuples and checking for equality of both elements; just like in your code, but without knowing/restricting about the length of the lists
You can replace your code by:
for index in indices:
if len(phrase.split(" "))==1 or all(p==q for p, q in zip(phrase.split(" ")[1:], parser.words[index+1:])):
if path in rang:
rang[path] += 1
else:
rang[path] = 1

Related

Why I cannot change index inside the while loop?

I want to implement basic calculator only includes numbers, '+' and '-' in Python. But I found that I cannot change index i inside the while loop.
def basicCalculator(expression):
res = 0
sign = 1
i = 0
while i < len(expression): # using while loop here
if expression[i] == '+':
sign = 1
elif expression[i] == '-':
sign = -1
elif '0' <= expression[i] <= '9':
temp = int(expression[i])
while i + 1 < len(expression) and '0' <= expression[i + 1] <= '9':
i += 1 # want to increase i, but failed
temp = temp * 10 + int(expression[i])
res += sign * temp
return res
s = "2+3-999"
print(basicCalculator(s)) # ouput should be -994, but infinite
Then I tried another way: using for loop instead of while loop, get incorrect answer.
def basicCalculator(expression):
res = 0
sign = 1
for i in range(len(expression)): # using for loop
if expression[i] == '+':
sign = 1
elif expression[i] == '-':
sign = -1
elif '0' <= expression[i] <= '9':
temp = int(expression[i])
while i + 1 < len(expression) and '0' <= expression[i + 1] <= '9':
i += 1 # increase i
temp = temp * 10 + int(expression[i])
res += sign * temp
return res
s = "2+3-999"
print(basicCalculator(s)) # ouput should be -994, but got -1102
I don't know why I cannot change the index inside the while loop or for loop. It is not a good idea to change i in for loop. What is the best way to fix the bug?
(I wrote the same code in Java using approach 2, everything is good, any difference?)
Rather than incrementing the index in a loop within the loop, I suggest just accumulating the current number in the main loop so you have less to keep track of:
def basicCalculator(expression):
res = 0
sign = 1
num = ""
for c in expression:
if c.isdecimal():
num += c
continue
res += int(num) * sign
num = ""
if c == "+":
sign = 1
elif c == "-":
sign = -1
else:
raise ValueError(f"Invalid operator {c}")
return res + int(num) * sign
print(basicCalculator("2+3-999")) # -994

Is there a way such that I can refresh a board on the screen instead of having it pile on and on in the console?

I've just completed a Connect Four game and now I'm wondering how I can keep the board in one place without having it refresh over and over again in the console. I've searched far and wide on the web for any solutions but couldn't find anything.
Below is my full code. Feel free to run it on your IDEs. Any help would be greatly appreciated!
import random
import ast
def winner(board):
"""This function accepts the Connect Four board as a parameter.
If there is no winner, the function will return the empty string "".
If the user has won, it will return 'X', and if the computer has
won it will return 'O'."""
row = 0
while row <= len(board) - 1:
count = 0
last = ''
col = 0
while col <= len(board[0]) - 1:
row_win = board[row][col]
if row_win == " ":
count = 0
col += 1
continue
if row_win == last:
count += 1
else:
count = 1
if count >= 4:
return row_win
last = row_win
col += 1
row += 1
col = 0
while col <= len(board[0]) - 1:
count = 0
last = ''
row = 0
while row <= len(board) - 1:
col_win = board[row][col]
if col_win == " ":
count = 0
row += 1
continue
if col_win == last:
count += 1
else:
count = 1
if count >= 4:
return col_win
last = col_win
row += 1
col += 1
row = 0
while row <= len(board) - 1:
col = 0
while col <= len(board[0]) - 1:
try:
if (board[row][col] == board[row + 1][col + 1] and board[row + 1][col + 1] == board[row + 2][
col + 2] and
board[row + 2][col + 2] == board[row + 3][col + 3]) and (
board[row][col] != " " or board[row + 1][col + 1] != " " or board[row + 2][col + 2] != " " or
board[row + 3][col + 3] != " "):
return board[row][col]
except:
IndexError
col += 1
row += 1
row = 0
while row <= len(board) - 1:
col = 0
while col <= len(board[0]) - 1:
try:
if (board[row][col] == board[row + 1][col - 1] and board[row + 1][col - 1] == board[row + 2][
col - 2] and
board[row + 2][col - 2] == board[row + 3][col - 3]) and (
board[row][col] != " " or board[row + 1][col - 1] != " " or board[row + 2][col - 2] != " " or
board[row + 3][col - 3] != " "):
return board[row][col]
except:
IndexError
col += 1
row += 1
# No winner: return the empty string
return ""
def display_board(board):
"""This function accepts the Connect Four board as a parameter.
It will print the Connect Four board grid (using ASCII characters)
and show the positions of any X's and O's. It also displays
the column numbers on top of the board to help
the user figure out the coordinates of their next move.
This function does not return anything."""
header = " "
i = 1
while i < len(board[0]):
header = header + str(i) + " "
i += 1
header = header + str(i)
print(header)
separator = "+---+"
i = 1
while i < len(board[0]):
separator = separator + "---+"
i += 1
print(separator)
for row in board:
print(" ", " | ".join(row))
separator = "+---+"
i = 1
while i < len(board[0]):
separator = separator + "---+"
i += 1
print(separator)
print()
def make_user_move(board):
"""This function accepts the Connect Four board as a parameter.
It will ask the user for a row and column. If the row and
column are each within the range of 1 and 7, and that square
is not already occupied, then it will place an 'X' in that square."""
valid_move = False
while not valid_move:
try:
col_num = "What col would you like to move to (1 - " + str(len(board[0])) + ")? "
col = int(input(col_num))
if board[0][col - 1] != ' ':
print("Sorry, that column is full. Please try again!\n")
else:
col = col - 1
for row in range(len(board) - 1, -1, -1):
if board[row][col] == ' ' and not valid_move:
board[row][col] = 'X'
valid_move = True
except:
ValueError
print("Please enter a valid option! ")
return board
def make_computer_move(board):
"""This function accepts the Connect Four board as a parameter.
It will randomly pick row and column values between 0 and 6.
If that square is not already occupied it will place an 'O'
in that square. Otherwise, another random row and column
will be generated."""
computer_valid_move = False
while not computer_valid_move:
col = random.randint(0, len(board) - 1)
if board[0][col] != ' ':
print("Sorry, that column is full. Please try again!\n")
else:
for row in range(len(board) - 1, -1, -1):
if board[row][col] == ' ' and not computer_valid_move:
board[row][col] = 'O'
computer_valid_move = True
return board
def main():
"""The Main Game Loop:"""
cf_board = []
row = int(input("How many rows do you want your game to have? "))
col = int(input("How many columns do you want your game to have? "))
move_order = input("Would you like to move first? (y/n) ")
while move_order.lower() != "y" and move_order.lower() != "n":
print("Invalid input! Please choose y (yes) or n (no) - case insensitive. ")
move_order = input("Would you like to move first? (y/n) ")
if move_order.lower() == "y":
users_turn = True
elif move_order.lower() == "n":
users_turn = False
free_cells = col * row
row_str = "\" \""
board_str = "\" \""
i = 0
j = 0
while i < col - 1:
row_str = row_str + "," + "\" \""
i += 1
board_list = [row_str]
while j < row - 1:
board_list.append(row_str)
j += 1
cf_board = [list(ast.literal_eval(x)) for x in board_list]
# for i in range(row-1):
# cf_board.append(row_str)
while not winner(cf_board) and (free_cells > 0):
display_board(cf_board)
if users_turn:
cf_board = make_user_move(cf_board)
users_turn = not users_turn
else:
cf_board = make_computer_move(cf_board)
users_turn = not users_turn
free_cells -= 1
display_board(cf_board)
if (winner(cf_board) == 'X'):
print("Y O U W O N !")
elif (winner(cf_board) == 'O'):
print("T H E C O M P U T E R W O N !")
elif free_cells == 0:
print("S T A L E M A T E !")
print("\n*** GAME OVER ***\n")
# Start the game!
main()
I guess the idea you want to implement is similar to make a terminal based progress bar;
For example on unix/linux systems you can update a progress bar or a simple sentence in one place with "\r" character instead of "\n" which used on print() function by default:
from sys import stdout
from time import sleep
def realtime_sentence():
name = 0
while name <= 100:
stdout.write("\r My name is {}".format(name))
name += 1
sleep(0.2)
def realtime_progress_bar():
progress = 0
while progress <= 100:
stdout.write("\r Progress: {} {}%".format(progress*"#", progress))
progress += 1
sleep(0.2)
realtime_sentence()
realtime_progress_bar()
Also check this question:
Rewrite multiple lines in the console

Getting a 'list index out of range' error

The goal of this code is to find the number of 'sh', 'th', 'wh', and 'ch' digraphs there are in any given sentence. The function keeps returning a 'list index out of range' error, when it seems like everything should be running properly.
exsentence = input("Enter a sentence to scan: ")
slist = list(exsentence.lower())
ch = 0
sh = 0
th = 0
wh = 0
i = 0
'''muppets = slist[i] + slist[i+1]'''
while i < len(slist):
if slist[i] + slist[i+1] == "sh":
sh += 1
elif slist[i] + slist[i+1] == "ch":
ch += 1
elif slist[i] + slist[i+1] == "th":
th += 1
else:
if slist[i] + slist[i+1] == "wh":
wh += 1
i+=1
print("Has {} 'ch' {} 'sh' {} 'th' {} 'wh'".format(ch,sh,th,wh))
Any help is very appriceciated. Thank you.
i+1 will be out of slist bounds. You need to iterate until slist size - 1
while i < len(slist) - 1:
As a side note, for seems to be more appropriate here. Remove i = 0 and i+=1
for i in range(len(slist) - 1):
Use a for loop with range instead:
exsentence = input("Enter a sentence to scan: ")
slist = list(exsentence.lower())
ch = 0
sh = 0
th = 0
wh = 0
i = 0
'''muppets = slist[i] + slist[i+1]'''
for i in range(1,len(slist)):
if slist[i-1] + slist[i] == "sh":
sh += 1
elif slist[i-1] + slist[i] == "ch":
ch += 1
elif slist[i-1] + slist[i] == "th":
th += 1
elif slist[i-1] + slist[i] == "wh":
wh += 1
print(f"Has {ch} 'ch' {sh} 'sh' {th} 'th' {wh} 'wh'")
start the range at 1 and check i-1 against i this way you wont go out of index range
You are checking one position ahead of the current one. Thus you are getting the error of being out of range.
Basically, you are iterating over each position of the array, but you are checking for the nth position against the nth + 1 position. What does happen when you reach the last position? You check it with the next position, which is not defined (otherwise it would not be the last position), and thus get the out of range error.
My suggestion is to not perform the check on the last item against the next one, as there will not be any sequence anymore.
while i < len(slist) - 1:
if slist[i] + slist[i+1] == "sh":
sh += 1
elif slist[i] + slist[i+1] == "ch":
ch += 1
elif slist[i] + slist[i+1] == "th":
th += 1
else:
if slist[i] + slist[i+1] == "wh":
wh += 1
i+=1

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

Binary Subtraction - Python

I want to make a binary calculator and I have a problem with the subtraction part. Here is my code (I have tried to adapt one for sum that I've found on this website).
maxlen = max(len(s1), len(s2))
s1 = s1.zfill(maxlen)
s2 = s2.zfill(maxlen)
result = ''
carry = 0
i = maxlen - 1
while(i >= 0):
s = int(s1[i]) - int(s2[i])
if s <= 0:
if carry == 0 and s != 0:
carry = 1
result = result + "1"
else:
result = result + "0"
else:
if carry == 1:
result = result + "0"
carry = 0
else:
result = result + "1"
i = i - 1
if carry>0:
result = result + "1"
return result[::-1]
The program works fine with some binaries subtraction but it fails with others.
Can someone please help me because I can't find the mistake? Thanks a lot.
Short answer: Your code is wrong for the case when s1[i] == s2[i] and carry == 1.
Longer answer: You should restructure your code to have three separate cases for s==-1, s==0, and s==1, and then branch on the value of carry within each case:
if s == -1: # 0-1
if carry == 0:
...
else:
...
elif s == 0: # 1-1 or 0-0
if carry == 0:
...
else:
...
else: # 1-0
if carry == 0:
...
else:
...
This way you have a separate block for each possibility, so there is no chance of overlooking a case like you did on your first attempt.
I hope the answer below it helps.
def binarySubstration(str1,str2):
if len(str1) == 0:
return
if len(str2) == 0:
return
str1,str2 = normaliseString(str1,str2)
startIdx = 0
endIdx = len(str1) - 1
carry = [0] * len(str1)
result = ''
while endIdx >= startIdx:
x = int(str1[endIdx])
y = int(str2[endIdx])
sub = (carry[endIdx] + x) - y
if sub == -1:
result += '1'
carry[endIdx-1] = -1
elif sub == 1:
result += '1'
elif sub == 0:
result += '0'
else:
raise Exception('Error')
endIdx -= 1
return result[::-1]
normalising the strings
def normaliseString(str1,str2):
diff = abs((len(str1) - len(str2)))
if diff != 0:
if len(str1) < len(str2):
str1 = ('0' * diff) + str1
else:
str2 = ('0' * diff) + str2
return [str1,str2]

Categories

Resources