while loop in line 36 won't exit despite fulfilling condition - python

The outer while loop should exit when current_digit and powers[digit_of_powers] both equal 26 but the while-loop doesn't exit as it should.
As a proof of what I'm claiming, see for yourself, the last line never executes. The program is stuck in the stopped while loop.
I'm new to programming so I may do daft mistakes
#enter a number in base 10 and find how it's written in choosen base... or at least thats what it should do
import math
def find_powers(num, base, start_num): #stackoverflow experts, this function is not important for my problem
power = 1 # power starts as a '1' each iteration
while start_num + power <= num:
power *= base
if start_num != num:
power /= base
powers.append(round(math.log(power, base)))
find_powers(num, base, start_num + power)
num = 7892 #enter choosen number in base 10 here
base = 10 #enter choosen base here. I put ten because its much easier to check the program with a base I'm familiar with
powers = []
find_powers(num, base, 0)
print(powers)
print('')
check = 0 #this script is not necessary, it's just a way for me to check if it can find the input of the def find_powers function from its output.
for i in powers: # It if it does then the function still work
check += base**i
print(check)
print('')
string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
digits = []
# Two things to check here
# 1. if powers[i] misses a digit or not.
# If it does, digits.append(0)
# 2. How many times the same power comes (it'll always be in row)
digit_of_powers = 0
while digit_of_powers != len(powers):
digit_of_powers += 1
print('digits_of_powers = ' + str(digit_of_powers))
current_digit = powers[digit_of_powers]
print('current_digit = ' + str(current_digit))
print('powers[digit_of_powers] = ' + str(powers[digit_of_powers]))
print('')
digit_thatll_go_in_digits = 1
while current_digit == powers[digit_of_powers]:
digit_thatll_go_in_digits += 1
digit_of_powers += 1
print('digit_thatll_go_in_digits = ' + str(digit_thatll_go_in_digits))
print('digits_of_powers = ' + str(digit_of_powers))
print(digits)
print('while ' + str(digit_of_powers) + ' != ' + str(len(powers)))
print('while ' + str(current_digit) + ' == ' + str(powers[digit_of_powers]))
print('')
digits.append(digit_thatll_go_in_digits)
print('fin du while')
print('')
print('this last line never executes for some reason')

You are increasing (conditionally) digit_of_powers twice, but condition is exact value while digit_of_powers != len(powers): (not equal)
It means that your code can jump over this condition and run further.
For example, if len(powers) == 10, digit_of_powers + 1 + 1 will increase from 9 to 11 and can be never the same.
Try this:
while digit_of_powers <= len(powers): (if it starts with 1)
or
while digit_of_powers < len(powers): (if it starts with 0)

Related

How to remove a certain string before printing?

answer = input('Enter a number: ')
x = 10**(len(answer) - 1)
print(answer, end = ' = ')
for i in answer:
if '0' in i:
x = x//10
continue
else:
print('(' + i + ' * ' + str(x) + ')' , end = '')
x = x//10
print(' + ', end = '')
so i have this problem, when i enter any number, everything is great but at the end there is an extra ' + ' that i do not want. Now normally this wouldnt be an issue with lists and .remove function, however i am not allowed to use these for this problem. I cannot come up with any sort of solution that does not involve functions
I tried matching the length but it didnt work because of '0'
you can insert an extra condition in the else block:
else:
print('(' + i + ' * ' + str(x) + ')' , end = '')
x = x//10
if x:
print(' + ', end = '')
this will help not to insert the last plus when it is not needed
The error is that there is an extra '+' at the end of the output. This can be fixed by adding an 'if' statement to the end of the code that checks if the last character in the output is a '+' and, if so, removes it.
Well Valery's answer is the best just add one more condition in case the answer was a 10 multiple
if x and int(answer)%10 != 0:
This kind of problem is best solved using the str.join() method.
answer = input("Enter a number: ")
x = 10**(len(answer) - 1)
terms = []
for i in answer:
if i == "0":
x = x//10
continue
else:
terms.append(f"({i} * {x})")
x = x//10
print(f"{answer} =", " + ".join(terms))
Sample interaction:
Enter a number: 1025
1025 = (1 * 1000) + (2 * 10) + (5 * 1)
Notes
We build up the terms by appending them into the list terms
At the end of the for loop, given 1025 as the input, the terms looks like this
['(1 * 1000)', '(2 * 10)', '(5 * 1)']
Update
Here is a patch of your original solution:
answer = input('Enter a number: ')
x = 10**(len(answer) - 1)
print(answer, end = ' = ')
for i in answer:
if '0' in i:
x = x//10
continue
else:
print('(' + i + ' * ' + str(x) + ')' , end = '')
x = x//10
if x == 0:
print()
else:
print(' + ', end = '')
The difference is in the last 4 lines where x (poor name, by the way), reaches 0, we know that we should not add any more plus signs.
answer = input('Enter a number: ')
#finds length of answer
length = 0
for n in answer:
length += 1
loop_counter = 0
##
zero_counter = 0
multiple_of_ten = 10
#finds if answer is multiple of 10 and if so by what magnitude
while True:
if int(answer) % multiple_of_ten == 0:
#counts the zeroes aka multiple of 10
zero_counter += 1
multiple_of_ten = multiple_of_ten*10
else:
break
#finds the multiple of 10 needed for print output
x = 10**(length - 1)
print(answer, end = ' = ')
for i in answer:
# if its a 0 it will skip
if '0' in i:
x = x//10
#still divises x by 10 for the next loop
pass
else:
print('(' + i + ' * ' + str(x) + ')' , end = '')
x = x//10
#if position in loop and zeroes remaining plus one is equal to
#the length of the integer provided, it means all the reamining
#digits are 0
if loop_counter + zero_counter + 1 == length:
break
else:
#adds ' + ' between strings
print(' + ', end = '')
# keeps track of position in loop
loop_counter += 1
ended up implementing a counter to see how many zeroes there are, and a counter to see where we are in the for loop and stop the loop when its the same as amount of zeroes remaining
I tested this code and it worked fine
if x and int(answer)%10 != 0:
Enter a number: 25
25 = (2 * 10) + (5 * 1)
Enter a number: 1000
1000 = (1 * 1000)
Enter a number: 117
117 = (1 * 100) + (1 * 10) + (7 * 1)

Draw a centered triforce surrounded by hyphens using Python

I want to draw a triangle of asterisks from a given n which is an odd number and at least equal to 3. So far I did the following:
def main():
num = 5
for i in range(num):
if i == 0:
print('-' * num + '*' * (i + 1) + '-' * num)
elif i % 2 == 0:
print('-' * (num-i+1) + '*' * (i + 1) + '-' * (num-i+1))
else:
continue
if __name__ == "__main__":
main()
And got this as the result:
-----*-----
----***----
--*****--
But how do I edit the code so the number of hyphens corresponds to the desirable result:
-----*-----
----***----
---*****---
--*-----*--
-***---***-
*****-*****
There's probably a better way but this seems to work:
def triangle(n):
assert n % 2 != 0 # make sure n is an odd number
hyphens = n
output = []
for stars in range(1, n+1, 2):
h = '-'*hyphens
s = '*'*stars
output.append(h + s + h)
hyphens -= 1
pad = n // 2
mid = n
for stars in range(1, n+1, 2):
fix = '-'*pad
mh = '-'*mid
s = '*'*stars
output.append(fix + s + mh + s + fix)
pad -= 1
mid -= 2
print(*output, sep='\n')
triangle(5)
Output:
-----*-----
----***----
---*****---
--*-----*--
-***---***-
*****-*****
Think about what it is you're iterating over and what you're doing with your loop. Currently you're iterating up to the maximum number of hyphens you want, and you seem to be treating this as the number of asterisks to print, but if you look at the edge of your triforce, the number of hyphens is decreasing by 1 each line, from 5 to 0. To me, this would imply you need to print num-i hyphens each iteration, iterating over line number rather than the max number of hyphens/asterisks (these are close in value, but the distinction is important).
I'd recommend trying to make one large solid triangle first, i.e.
-----*-----
----***----
---*****---
--*******--
-*********-
***********
since this is a simpler problem to solve and is just one modification away from what you're trying to do (this is where the distinction between number of asterisks and line number will be important, as your pattern changes dependent on what line you're on).
I'll help get you started; for any odd n, the number of lines you need to print is going to be (n+1). If you modify your range to be over this value, you should be able to figure out how many hyphens and asterisks to print on each line to make a large triangle, and then you can just modify it to cut out the centre.

I no longer have an alignment issue, however, when I print out my X's and O's there will be a 0 next to them. Does anyone know a different solution?

This is what I have so far, if you have any ideas please let me know. It would mean a lot to me.
a_list = list(range(1, squared_input + 1))
turn = 0
Symbol_1 = "X"
Symbol_2 = "O"
while turn <= 9:
X = 1
while X < squared_input + 1 :
print(str(a_list[X - 1]).zfill(2), end= "")
if X%board_size == 0 :
print("")
print(("--+" * (board_size - 1)), end="")
print("--")
else:
print("|", end="")
X = X + 1
turn = turn + 1
Symbol_1, Symbol_2 = Symbol_2, Symbol_1
print("You are user " + Symbol_1 + ".")
user_input = input("Please pick a slot on the game board (using numbers 1 - " + str(squared_input) + "): ")
a_list[int(user_input) - 1] = Symbol_1
The zeros come from your call to zfill which explicitly pads a string with 0 to a requested size. You call zfill(2) with a string that contains a single character. So the function pads that to length two by adding a 0.
To pad with blanks you can for example use the format() function or just something like
'%2d' % a_list[X-1]
which will pad each number to length 2 from the left with blanks, or
'%-2d' % a_list[X-1]
which will pad each number to length 2 from the right with blanks.

getting into infinite loop when using a while loop

I am using this code to use a dataframe lookup for every single record in the first dataframe.
for i in range(len(a1)):
title_derived = []
k = 100000
print(i)
for j in range(len(b1)):
print(j)
while j < (k + 6):
#print(b1.iloc[i][10], a1.iloc[j][3])
if b1.iloc[j][10] == a1.iloc[i][3]:
print(j,k)
print('1st if ' + str(j))
print (b1.iloc[j][1], a1.iloc[i][11], b1.iloc[j][5])
if (((pd.to_datetime(b1.iloc[j][1]) <= pd.to_datetime(a1.iloc[i][11]) <= pd.to_datetime(b1.iloc[j][5]))) or ((pd.to_datetime(b1.iloc[j][1]) <= pd.to_datetime(a1.iloc[i][8]) <= pd.to_datetime(b1.iloc[j][5])))) :
print('2nd if' + str(j))
title_derived.append(b1.iloc[j][15])
print('inserted ' + b1.iloc[j][15] + ' in ' + str(i) + ' th record ')
a1.iat[i,65] = title_derived
It prints,
0
0
and then goes into a an infinite loop.
May be it is because you are length of "b1" in lesser than value of "k + 6". And in that case you will never get out of while loop and in the last it will throw and error.
In this case you should first check the least possible length of "b1" and then decide your wile condition.

Python IndexError: list index out of range with long string

My code seems to work with shorter strings, but inexplicably to me gets stuck on others. The function of this is to replace characters with digits, and I have it print out the new string after each part is replaced. Any help you can give me is appreciated, thanks!
By the way, I did look at the similar questions on this and they did not answer my particular question, please don't remove my question.
possibleChars = ['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','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','1','2','3','4','5','6','7','8','9','0',' ',',','.','?','!','/','\\','[',']','{','}',
'|','<','>',';',':','+','=','-','_','(',')','#','#','$','%','^','&','*','~','`'] #0-92
possibleCharsToDigit = ['1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3',
'4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8',
'9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3',
'4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3'] #0-92
password = "How is your day today?"
def passwordToDigit(passToConvert):
passLen = len(passToConvert) #puts the length of the password in a variable
i = 0 #i is the selected character in the password
j = 0 #j is the selected possible char, i.e. '0' is 'A' in possibleChars or '1' in possibleCharsToDigit
while i < passLen:
if passToConvert[i] == possibleChars[j]:
passToConvert = passToConvert[0:i] + possibleCharsToDigit[j] + passToConvert[i + 1:]
i += 1
print passToConvert
else:
j += 1
print passToConvert
passwordToDigit(password)
When you are incrementing j variable inside the while loop, notice that when j gets bigger than the length of possibleCharsToDigit list then you are trying to access its element with index out of bounds.
you should set j = 0 in the if passToConvert[i] == possibleChars[j] clause:
def passwordToDigit(passToConvert):
passLen = len(passToConvert) #puts the length of the password in a variable
i = 0 #i is the selected character in the password
j = 0 #j is the selected possible char, i.e. '0' is 'A' in possibleChars or '1' in possibleCharsToDigit
while i < passLen:
if passToConvert[i] == possibleChars[j]:
passToConvert = passToConvert[0:i] + possibleCharsToDigit[j] + passToConvert[i + 1:]
i += 1
j = 0
print passToConvert
else:
j += 1
print passToConvert
As you increment j within your while loop, without ever resetting it, each time you successfully match a character and move onto the next one. This will cause your code to fail as soon as you have a character earlier in possibleChars than a previous one.
To illustrate:
passwordToDigit('ABCDEFGHIJKLMNOP') #will work correctly
passwordToDigit('BA') #will fail with IndexError
Quick Solution
The quickest solution would be to reset the j index when you find a match.
ie
# ...
if passToConvert[i] == possibleChars[j]:
passToConvert = passToConvert[0:i] + possibleCharsToDigit[j] + passToConvert[i + 1:]
i += 1
print passToConvert
j = 0 #Reset tje j index to start searching from beginning
else:
#...
Dict Solution
You could also spend some time refactoring your code to use a dict to map characters to digits as in:
import string
charopts = string.ascii_uppercase + string.ascii_lowercase + string.digits[1:] + r'0 ,.?!/\[]{}|<>;:+=-_()##$%^&*~`'
char2dig = dict((k,str((i+1)%10)) for i,k in enumerate(charopts))
def passwordToDigitDic(passToConvert):
newpass = ''
for c in passToConvert:
newpass += char2dig[c]
print(newpass + passToConvert[len(newpass):])
passwordToDigitDic('ABCDEFGH')
passwordToDigitDic('HGEFBCA')
Note, if you are ever interested in doing the translation in one go as opposed to step by step with prints, look into the string.translate function.
When i=passLen-1, then you are trying to access passToConvert[i+1], which is out of the range of passToConvert. Hence you are getting this error. Try this:
if passToConvert[i] == possibleChars[j]:
if i<passLen-1:
passToConvert = passToConvert[0:i] + possibleCharsToDigit[j] + passToConvert[i + 1:]
else:
passToConvert = passToConvert[0:i] + possibleCharsToDigit[j]
i += 1
print passToConvert

Categories

Resources