My function isn't printing anything other than "None" - python

I'm doing an assignment for school that's due tonight and I can't figure out why it isn't working. I'm really new to programming in general but I just don't understand why it doesn't work.
The program is supposed to convert from decimal to binary and, depending on how big the number is, print it in either 8 bits or 16 bits.
def dec2bin(värde, antal_bitar):
while bitvärde == (2 ** (antal_bitar - 1)):
if värde >= bitvärde:
return str("1")
värde= värde - bitvärde
else:
return str("0")
antal_bitar = antal_bitar - 1
invärde_ok = False
invärde = 0
while invärde_ok == False:
invärde=(int(input("Ange ett decimalt värde: ")))
if (invärde > 65536):
print("Fel. Kan inte hantera stora tal. Försök igen.")
else:
if invärde < 0:
print("Fel. Kan bara hantera positiva tal. Försök igen.")
else:
invärde_ok = True
if invärde < 256:
bitvärde=8
print("Talet", invärde , "ryms i en byte och blir binärt:")
print(dec2bin(invärde,bitvärde))
else:
bitvärde=16
print("Talet", invärde , "ryms i 16 bitar och blir binärt:")
print(dec2bin(invärde,bitvärde))
Sorry for the Swedish parts.

The problem is, instead of giving bitvarde a new value in each iteration in your dec2bin function, you're checking if it equals a certain value - which it does not. Instead, you should use a For loop,
for i in range(y-1,-1,-1):
which will give i a different value each iteration.
range(y-1,-1,-1) simply means that i will get values starting from y-1, changing by -1 every turn, and ending before -1, ie at 0.
In the loop, just add the following:
bitvarde = 2**i
Remove the y=y-1 from the end.
Also, when you use return in the function, that ends the function's execution. You want it to add a 1 or a 0 to the end of the final string.
For that, define an empty string, result = "", in the beginning (before the for loop).
instead of
return str("1"), use result += "1", which simply means result = result + "1".
at the end of the function, after the loop, put:
return result
That should do it! Of course, you can rename result as something else in Swedish.
Here's what the final code should look like:
def dec2bin(värde, antal_bitar):
result = ""
for i in range(antal_bitar-1,-1,-1):
bitvärde = 2**(i)
if värde>=bitvärde:
result += "1"
värde=värde-bitvärde
else:
result += "0"
return result
Hopefully this matches the pseudocode you were given.

Related

how to code in python with the following logic for the roman numeral to integer conversion

I am trying to convert the given roman numerals to just numerals for programming practice, with the following logic (I dont want to change this logic unless its falsely thought of)
Here,
M - 1000, C-100, X-10, V-5, I-1
example :
Input - MCMXCVI
Expected Result - 1996
logic - 1000 + (1000-100) + (100-10) + 5 + 1
index- 1 + (3-2) + (5-4) + 6 + 7
Here i am searching next value from the current value subtracting it if its not greater we are adding it normally.
Here is what i have tried, i could't code it correctly, having spent lot of time, thought to ask out for help.
def roman_numeral(num):
"""
Write a Python class to convert an roman numeral to a integer.
Logic: https://www.rapidtables.com/convert/number/how-roman-numerals-to-number.html
"""
# Input the string
# Map of roman numerals and the corresponding values in a dictionary.
NUMERALS = {1000:'M', 900:'CM', 500:'D', 400:'CD', 100:'C', 90:'XC',
50:'L', 40:'XL', 10:'X', 9:'IX', 5:'V', 4:'IV', 1:'I'}
retval=[]
#Check if each char matches with the dictionary and take the numerical value of the inputed roman
for k in range(len(num)):
for i,j in NUMERALS.items():
if(j==num[k]):
retval.append(i)
elm_count = len(retval)
result=0
result_less=0
result_more=0
ind_tracker=0
#Check if next char from the position of current char if that numerical value is greater then current numerical value.
#If it is greater subtract the current numeric value, if not greater then add it.
for ind,i in enumerate(retval):
print('ind= ',ind,'i= ', i)
#Using this below condition to skip if we have already subtracted the current value from previous value.
if( ind_tracker>ind):
continue
if((ind+1 < elm_count)):
if(i<retval[ind+1]):
#print('result=',result,'retval[ind]=',retval[ind],'retval[ind+1]=', retval[ind+1])
result_less=retval[ind+1]-retval[ind]
print('result_less=',result_less)
ind_tracker=ind+1
else:
result_more+=retval[ind]+result_less
print('result_more=',result_more)
result=result_more
print('final result= ',result)
return result
roman_numeral('MCMXCVI')
The output im getting is
3185
I expect to get
1996
You can change the basic concept. If you reverse the roman numbers and basically start from the right side of the string the whole thing get really simple.
The idea is that if you start from the right, if the next number is bigger or equal to the current number you add the number to the total, if the next number is smaller than the previous one then it is substraced from the total.
roman = "MCMXCVI"
NUMERALS = {1000:'M', 900:'CM', 500:'D', 400:'CD', 100:'C', 90:'XC',
50:'L', 40:'XL', 10:'X', 9:'IX', 5:'V', 4:'IV', 1:'I'}
# reverse roman number letters (basically start from the end
roman_reversed = list(reversed(roman))
#invert the dictionary because we want to translate the letter to numbers not the other way around
inverse_NUMERALS = {v: k for k, v in NUMERALS.items()}
# get the number for each character on its own:
lst_numbers = [inverse_NUMERALS.get(x) for x in roman_reversed]
# loop through the list of numbers
total = 0
previous = 0
for numb in lst_numbers:
if numb >= previous:
total += numb
else:
total -= numb
previous = numb
print(total)
#Out[21]: 1996
You could use (self-implemented):
class RomanToDecimal:
conversion = {'M': 1000, 'CM': 900, 'D': 500, 'CD': 400, 'C': 100, 'XC': 90, 'L': 50, 'XL': 40, 'X': 10, 'IX': 9,
'V': 5, 'IV': 4, 'I': 1}
def convert(self, roman):
total = 0
while len(roman):
before = len(roman)
for key in self.conversion:
if roman.startswith(key):
total += self.conversion[key]
roman = roman[len(key):]
after = len(roman)
if before == after:
raise ValueError("Not a Roman numeral.")
return total
try:
rtd = RomanToDecimal()
assert rtd.convert('M') == 1000
assert rtd.convert('XXXVI') == 36
assert rtd.convert('MMXII') == 2012
assert rtd.convert('MMXX') == 2020
except ValueError as error:
print(error)
I made some minor changes to your existing code!
I added a variable "flag" set to False on default and when result_less, I set it to true
To check we subtracted or not, I used this flag, when the flag is true, i made it false and skipped an iternation.
added a new if statement to check for last number
on result_more, result+=retval[ind], did not used result_less value
on result_less, result+=retval[ind+1]-retval[ind]. in both cases i changed the result value rather than changing more and less values for simplicity.
and BTW, I got rid of those result_more and result_less variables but kept the print statements.
here is your code, modified:
def roman_numeral(num):
"""
Write a Python class to convert an roman numeral to a integer.
Logic: https://www.rapidtables.com/convert/number/how-roman-numerals-to-number.html
"""
# Input the string
# Map of roman numerals and the corresponding values in a dictionary.
NUMERALS = {1000:'M', 900:'CM', 500:'D', 400:'CD', 100:'C', 90:'XC',
50:'L', 40:'XL', 10:'X', 9:'IX', 5:'V', 4:'IV', 1:'I'}
retval=[]
#Check if each char matches with the dictionary and take the numerical value of the inputed roman
for k in range(len(num)):
for i,j in NUMERALS.items():
if(j==num[k]):
retval.append(i)
elm_count = len(retval)
result=0
result_less=0
result_more=0
# ind_tracker=0
flag = False
#Check if next char from the position of current char if that numerical value is greater then current numerical value.
#If it is greater subtract the current numeric value, if not greater then add it.
for ind,i in enumerate(retval):
print('ind= ',ind,'i= ', i)
#Using this below condition to skip if we have already subtracted the current value from previous value.
# if( ind_tracker>ind):
# continue
if(flag):
print("Skipped! Already Subracted!")
flag=False
continue
if((ind+1 == elm_count)):
# if last digit is greater than it's previous, the flag will skip this iteration
print('last digit=',retval[ind])
result+=retval[ind]
if((ind+1 < elm_count)):
if(i<retval[ind+1]):
#print('result=',result,'retval[ind]=',retval[ind],'retval[ind+1]=', retval[ind+1])
# result_less=retval[ind+1]-retval[ind]
result+=retval[ind+1]-retval[ind]
print('result_less=',retval[ind+1]-retval[ind])
# ind_tracker=ind+1
flag = True
else:
# result_more+=retval[ind]+result_less
result+=retval[ind]
print('result_more=',retval[ind])
# result=result_more
print('final result= ',result)
return result
roman_numeral('MCMXCVI')

Need Help On Code, All Results Are Coming Back False, when 2 should be true

So basically, I need to write a code for the luhn algorithm, but i need to have at least 5 functions
I have written a code to do this, yet I am receiving False results where they should be true. For example, I know that the second and the fourth data pieces in the data file are true for this algorithm, yet all of my outputs are false. Can you help me figure out where I've gone wrong?
This is the code:
def CheckLength(numb):
if len(numb)>12 and len(numb)<17:
return True
else:
return False
def CheckType(numb):
if numb[0]=='4':
return 'Visa'
elif numb[0]=='5':
return 'MasterCard'
elif numb[0]=='6':
return 'Discover'
elif numb[0:2]=='37':
return 'American Express'
else:
return 'Invalid Entry'
def Step1(numb):
total1=0
total2=0
length=len(numb)
for i in range(length-2,-1,-2):
double=eval(numb[i])*2
if double>9:
doublex=str(double)
doubleY=int(doublex[0])+int(doublex[1])
total1+=doubleY
else:
total2+=double
total=total1+total2
return total
def Step2(numb):
total=0
length=len(numb)
for i in range(length-1,-2,-2):
total+=i
return total
def Step3(num1,num2):
total=num1+num2
if total%10==0:
return True
else:
return False
def main():
inFile=open('pa7.cards','r')
cardNum=inFile.readline().strip()
while cardNum!='99999':
step1=Step1(cardNum)
step2=Step2(cardNum)
step3=Step3(step1,step2)
print(step1)
print(step2)
print(step3)
cardNum=inFile.readline().strip()
inFile.close()
main()
This is the data file:
4388576018402626
4388576018410707
37271983
5190828258102121
99999
This is the output i am getting when printing all 3 steps
4
63
False
0
63
False
7
15
False
4
63
False
(My comments as an answer, including suggestions and corrections from #DavidZemens' comments)
In terms of bugs, I think you have:
Step 1 has the return statement inside the loop, so the loop only happens once, then it stops.
def Step1(numb):
for i in range(length-2,-1,-2):
return total
^ -- ^ -- move this left, to where 'for' is
Step 2 is adding up the counter, not the credit card digits, and it's stepping through every other digit instead of every digit:
def Step2(numb):
total=0
length=len(numb)
for i in range(length-1,-1,-1):
total += int(numb[i])
return total
In general code comments, this kind of test:
if len(numb)>12 and len(numb)<17:
return True
else:
return False
is a bit redundant. If (truth test) return True else return False can become return (truth test):
return 12 < len(numb) < 17
and later:
total = num1 + num2
if total%10==0:
return True
else:
return False
can be:
return (num1 + num2) % 10 == 0
This calculation:
double=eval(numb[i])*2
if double>9:
doublex=str(double)
doubleY=int(doublex[0])+int(doublex[1])
total1 += doubleY
is a bit awkward turning the number into text, taking text characters, turning them back into numbers, then adding them up.
What it does is take the number of tens (integer divide by 10) and the remainder (modulo 10), so you could keep it all as numbers with:
double = int(numb[i]) * 2
if double > 9:
total1 += (double // 10) + (double % 10)
eval() is a bad practice, it gives any input complete access to the Python interpreter with no safeguards. In your code, you could use int() instead
Your file loop could be clearer:
def main():
with open('pa7.cards') as inFile:
for cardNum in inFile:
cardNum = cardNum.strip()
step1=Step1(cardNum)
step2=Step2(cardNum)
step3=Step3(step1,step2)
print(step1)
print(step2)
print(step3)
And you might get some benefit by converting the cardNum into a list of numbers once and then working with that, instead of calling int() all over the place.
You can also optimize the two unused functions (assuming you use them elsewhere in the code):
def CheckLength(numb):
return 12 < len(numb) < 17
def CheckType(numb):
"""
returns the type of credit card, based on the first digit or 2 digits
numb; passed as string
"""
n = numb[0] if not numb[0] == '3' else numb[:1]
d = {4:'Visa',
5:'Mastercard',
6:'Discover',
37:'American Express'}
return d.get(int(n), 'Invalid Entry')

Python recursive function not recursing

I'm trying to solve a puzzle, which is to reverse engineer this code, to get a list of possible passwords, and from those there should be one that 'stands out', and should work
function checkPass(password) {
var total = 0;
var charlist = "abcdefghijklmnopqrstuvwxyz";
for (var i = 0; i < password.length; i++) {
var countone = password.charAt(i);
var counttwo = (charlist.indexOf(countone));
counttwo++;
total *= 17;
total += counttwo;
}
if (total == 248410397744610) {
//success//
} else {...
I wrote something in python that I think should work, I reverse engineered the order of which it adds and multiplies, and has it try every character to see if it properly divides into an even number.
from random import shuffle
def shuffle_string(word):
word = list(word)
shuffle(word)
return ''.join(word)
charlist = "abcdefghijklmnopqrstuvwxyz"
total = 248410397744610
temp = total
password = ''
runtime = 20
def runlist():
global charlist
global total
global temp
global password
global runtime
for i in range(25):
if (temp - (i+1)) % 17 == 0:
password += charlist[i]
temp -= i+1
temp = temp /17
if temp == 0:
print password
password = ''
temp = total
runtime += 1
charlist = shuffle_string(charlist)
if runtime < 21:
runlist()
else:
runlist()
But when I try to run it I only get
deisx
Process finished with exit code 0
I'm wondering why my function isn't recursing properly, because it looks like it should from what I see. try and run it yourself, and see what happens.
There should be multiple solutions for this puzzle (I think?), and I was planning on making it be able repeat until it gets all solutions, but I'm a little lost on why it just runs through every letter once, then dies.
EDIT:
Revised code to actually recurse, but now I get no output, and still finish with exit code 0.
EDIT 2:
Revised code again to fix a mistake
Afraid I don't know much about python, but I can probably help you with the algorithm.
The encoding process repeats the following:
multiply the current total by 17
add a value (a = 1, b = 2, ..., z = 26) for the next letter to the
total
So at any point, the total is a multiple of 17 plus the value of the final letter. So each step in the recursive solver must remove the final letter then divide the result by 17.
However, because the multiplier is 17 and there are 26 characters in the alphabet, some of the remainder values may be produced by more than one letter - this is where many passwords may give rise to the same solution.
For example:
encoding "a" gives a total of 1, and 1 % 17 = 1
encoding "r" gives a total of 18, and 18 % 17 = 1
So if the current remainder is 1, then the encoded letter may be either "a" or "r". I think in your solution you only ever look for the first of these cases, and miss the second.
In pseudo code, my function to solve this would look something like:
function decodePassword(total, password)
if total == 0
print password
return
end if
var rem = total / 17 # integer division - truncate
var char1 = total % 17 # potential first character
var char2 = char1 + 17 # potential second character
# char1 values 1-16 map to letters a-p
if char1 >= 1
decodePassword(rem, charlist.charAt(char1 - 1) + password)
end if
# char2 values 17-26 map to letters q-z
if rem > 0 && char2 <= 26
decodePassword(rem - 1, charlist.charAt(char2 - 1) + password)
end if
end function
If it helps, the answer you are looking for is 12 chars long, and probably not printable in this forum!
HTH
Your code is neither repeating nor recursing because:
The runlist function is only called once
The runlist function does not fit the pattern for recursion which is:
Check for end of processing condition and if met return final result
Otherwise return the results so far plus of calling youself

Find one occurence of substring using suffix array

I'm trying to figure out how to binary search in suffix array for one occurence of pattern.
Let's have a text: petertomasjohnerrnoerror.
I try to find er.
SA is a suffix array of this text: 8,14,19,3,1,12,10,7,13,17,18,11,6,22,0,23,16,21,15,20,4,9,2,5
Now, I want to find any index of suffix array, which value pointing at one 'er'. So the output would be index in SA pointing at 3,14 or 19 so it would return 1,2 or 3
I'm trying to use a binary search but I can't figure out how.
def findOneOccurence(text,SA,p):
high = len(text)-1 # The last index
low = 0 # the lowest index
while True:
check = (high-low)/2 # find a middle
if p in text[SA[check]:SA[check]+len(p)]:
return check
else:
if text[SA[check]:SA[check]+len(p)]<p:
low = check
else:
high = check
if high<=low:
return None
This returns 11. But text[SA[11]:SA[11]+2] is 'oh' instad of 'er'.
Where could be the problem?
This function would work on huge texts about millions of chars.
EDIT: I've found a mistake. Instead of if text[SA[check]:SA[check+len(p)]]<p: should be text[SA[check]:SA[check]+len(p)]<p: but it's still wrong. It returns None instead of 'er'
EDIT II: Another mistake: if high>=low changed to high<=low, now, it returns 2 which is good.
EDIT III: Now it works, but on some inputs it gets to the loop and never ends.
Borrowing and editing https://hg.python.org/cpython/file/2.7/Lib/bisect.py
>>> text= 'petertomasjohnerrnoerror'
>>> SA = 8,14,19,3,1,12,10,7,13,17,18,11,6,22,0,23,16,21,15,20,4,9,2,5
>>> def bisect_left(a, x, text, lo=0, hi=None):
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if text[a[mid]:] < x: lo = mid+1
else: hi = mid
if not text[a[lo]:].startswith(x):
# i suppose text[a[lo]:a[lo]+len(x)] == x could be a faster check
raise IndexError('not found')
return a[lo]
>>> bisect_left(SA, 'er', text)
14

variable within a nested loop in python

I'm trying to figure what the values of xcoord_orig and ycoord_orig are when the last conditional statement is true i.e. when board[xcoordT][ycoordT] == computer. I feel that as I have it right now, I'm simply printing their values if the conditional statement is true. But what I really want are the values of xcoord_orig and ycoord_orig under the first loop at the point where the last conditional statement is true. I'm not sure if this is clear but I thought I would ask.
for num in range(8):
for i in range(len(valid_list)):
xcoord_orig = valid_list[i][0]
ycoord_orig = valid_list[i][1]
xcoord1 = valid_list[i][0] + num_list[num]
ycoord1 = valid_list[i][1] + num_list2[num]
if 0 <= xcoord1 <= 7 and 0 <= ycoord1 <= 7:
piece = board[xcoord1][ycoord1]
if piece == player:
move_list = []
for i in range(2,8):
xcoordT = xcoord_orig
ycoordT = ycoord_orig - i
print(xcoord_orig, ycoord_orig)
if board[xcoordT][ycoordT] == computer:
move_list.append([xcoordT, ycoordT])
print(xcoord_orig, ycoord_orig)
This
for i in range(len(valid_list)):
...
for i in range(2,8):
Is epic fail. It can't be correct.

Categories