The code is supposed to take a 5 digit zip code input and convert it to bar codes as the output. The bar code for each digit is:
{1:'...!!',2:'..!.!',3:'..!!.',4:'.!..!',5:'.!.!.',6:'.!!..',7:'!...!',8:'!..!.',9:'!.!..',0:'!!...'}
For example, the zip code 95014 is supposed to produce:
!!.!.. .!.!. !!... ...!! .!..! ...!!!
There is an extra ! at the start and end, that is used to determine where the bar code starts and stops. Notice that at the end of the bar code is an extra ...!! which is an 1. This is the check digit and you get the check digit by:
Adding up all the digits in the zipcode to make the sum Z
Choosing the check digit C so that Z + C is a multiple of 10
For example, the zipcode 95014 has a sum of Z = 9 + 5 + 0 + 1 + 4 = 19, so the check digit C is 1 to make the total sum Z + C equal to 20, which is a multiple of 10.
def printDigit(digit):
digit_dict = {1:'...!!',2:'..!.!',3:'..!!.',4:'.!..!',5:'.!.!.',6:'.!!..',7:'!...!',8:'!..!.',9:'!.!..',0:'!!...'}
return digit_dict[digit]
def printBarCode(zip_code):
sum_digits=0
num=zip_code
while num!=0:
sum_digits+=(num%10)
num/=10
rem = 20-(sum_digits%20)
answer=[]
for i in str(zip_code):
answer.append(printDigit(int(i)))
final='!'+' '.join(answer)+'!'
return final
print printBarCode(95014)
The code I currently have produces an output of
!!.!.. .!.!. !!... ...!! .!..!!
for the zip code 95014 which is missing the check digit. Is there something missing in my code that is causing the code not to output the check digit? Also, what to include in my code to have it ask the user for the zip code input?
Your code computes rem based on the sum of the digits, but you never use it to add the check-digit bars to the output (answer and final). You need to add code to do that in order to get the right answer. I suspect you're also not computing rem correctly, since you're using %20 rather than %10.
I'd replace the last few lines of your function with:
rem = (10 - sum_digits) % 10 # correct computation for the check digit
answer=[]
for i in str(zip_code):
answer.append(printDigit(int(i)))
answer.append(printDigit(rem)) # add the check digit to the answer!
final='!'+' '.join(answer)+'!'
return final
Interesting problem. I noticed that you solved the problem as a C-style programmer. I'm guessing your background is in C/C++. I's like to offer a more Pythonic way:
def printBarCode(zip_code):
digit_dict = {1:'...!!',2:'..!.!',3:'..!!.',4:'.!..!',5:'.!.!.',
6:'.!!..',7:'!...!',8:'!..!.',9:'!.!..',0:'!!...'}
zip_code_list = [int(num) for num in str(zip_code)]
bar_code = ' '.join([digit_dict[num] for num in zip_code_list])
check_code = digit_dict[10 - sum(zip_code_list) % 10]
return '!{} {}!'.format(bar_code, check_code)
print printBarCode(95014)
I used list comprehension to work with each digit rather than to iterate. I could have used the map() function to make it more readable, but list comprehension is more Pythonic. Also, I used the Python 3.x format for string formatting. Here is the output:
!!.!.. .!.!. !!... ...!! .!..! ...!!!
>>>
Related
Below is my work. I did the printline function before, and this question required to call the function printline above for printing each line. I try to print 3 lines, each line has 4 symbols, but I only can get 2 lines, each line comes with 12 symbols. Can someone help me correct my code?
def printline(num,sym):
for i in range(num):
a = (num*sym)
return a
a = printline(5,'*')
print(a)
def printrectangle(num,height,sym):
for i in range(height):
a = printline(num,sym)*height
print(a)
return a
c = printrectangle(3,4,'*')
print(c)
A few things here:
Your printline function works, but overcomplicates the problem.
In other programming languages, in order to repeat the same string multiple times it is common to create a loop of the form:
String s = "";
for(int i = 0; i < num; i++)
s += sym;
return s;
Since this is equivalent to just concatenating the same string num times, in python there is a simpler way to do this:
s = sym*num
Your solution works because you are overwriting the value in the variable a for num times before returning it.
You misinterpreted your testcase.
You said printrectangle(3, 4, '*') should print 3 lines with 4 symbols. But as you wrote it, the first variable num=3, and the second variable height=4.
The output here is in fact:
***
***
***
***
Your code does not currently do that, but let's not get ahead of ourselves.
Indentation error
The return statement in the printrectangle function is inside the loop. This means that during the first iteration of the loop, the function will return a value.
Easy fix, just backspace until the indentation of the return lines up with that of the loop.
Actually solving the problem.
From part 1, I introduced here that in python to concatenate the same string multiple times you may simply multiply the string by the number of times you want it to show up.
Here we want the string printline(num, sym) to show up height times with an enter key after each time.
The enter key sends the command of \n. In other words, a string such as 'a\nb' is printed as:
a
b
For our purposes, we can concatenate the string printline(num, sym) with \n first, and then multiply the resulting string by height to get the result of printrectangle(num, height, sym)
def printrectangle(num, height, sym):
a = (printline(num, sym)+'\n')*height
return a
Though this code will give you what you are looking for, I still doubt by mistake you swapped num and height values in the call printrectangle(3,4,'*') itself
def printline(h,sym):
a = h*sym # removed unnessary loop
return a
def printrectangle(num,height,sym):
for i in range(num): # swap height with num in your code
a = printline(height,sym) #swap num with height in your code
yield a
for row in printrectangle(3,4,'*'):
print(row)
I am using python 2.7. I wrote a code to generate passwords. For doing this, I used the random module to generate how many characters of different types(uppercase, lowercase, special and numbers) to be used to generate a password of a given length. When a wrote a function for this, it was supposed to return a tuple, but it returns None. Why is it happening?
I tried the casual debugging method of putting print statements in between and figuring out where it went wrong. Everything works just fine, except it returns None.
def passlen(a):
"""Gives length of different characters to be put into passwords"""
uplen=random.randrange(0, a)
lwlen=random.randrange(0, a)
speclen=random.randrange(0, a)
nmbrlen=random.randrange(0, a)
if uplen+lwlen+speclen+nmbrlen==a:
print (uplen, lwlen, speclen, nmbrlen)
return(uplen, lwlen, speclen, nmbrlen)
else:
passlen(a)
x=input("how many characters in the password?")
print(passlen(x))
Expected results are 4-tuples, but it gives None instead.
So you want four random numbers that add to a? Of course you can try choosing four random numbers until you find a set that adds up to a, but that might take a while for large values of a (and you definitely don't want to do this recursively).
Much better to choose three split points between 0 and a:
def passlen(a):
splits = sorted([random.randrange(0,a) for _ in range(3)])
uplen = splits[0]
lwlen = splits[1] - uplen
speclen = splits[2] - uplen - lwlen
nmbrlen = a - uplen - lwlen - speclen
return uplen, lwlen, speclen, nmbrlen
Thanks to Kamiccolo for trying to help out.
The function should look like this:
def passlen(a):
"""Gives length of different characters to be put into passwords"""
uplen=int(random.randrange(0, a))
lwlen=int(random.randrange(0, a))
speclen=int(random.randrange(0, a))
nmbrlen=int(random.randrange(0, a))
bab=(uplen, lwlen, speclen, nmbrlen)
if uplen+lwlen+speclen+nmbrlen==a:
return bab
else:
return passlen(a)
A duplicate thread also helped me in this.
I'm making a method that takes a string, and it outputs parts of the strings on separate line according to a window.
For example:
I want to output every 3 letters of my string on separate line.
Input : "Advantage"
Output:
Adv
ant
age
Input2: "23141515"
Output:
231
141
515
My code:
def print_method(input):
mywindow = 3
start_index = input[0]
if(start_index == input[len(input)-1]):
exit()
print(input[1:mywindow])
printmethod(input[mywindow:])
However I get a runtime error.... Can someone help?
I think this is what you're trying to get. Here's what I changed:
Renamed input to input_str. input is a keyword in Python, so it's not good to use for a variable name.
Added the missing _ in the recursive call to print_method
Print from 0:mywindow instead of 1:mywindow (which would skip the first character). When you start at 0, you can also just say :mywindow to get the same result.
Change the exit statement (was that sys.exit?) to be a return instead (probably what is wanted) and change the if condition to be to return once an empty string is given as the input. The last string printed might not be of length 3; if you want this, you could use instead if len(input_str) < 3: return
def print_method(input_str):
mywindow = 3
if not input_str: # or you could do if len(input_str) == 0
return
print(input_str[:mywindow])
print_method(input_str[mywindow:])
edit sry missed the title: if that is not a learning example for recursion you shouldn't use recursion cause it is less efficient and slices the list more often.
def chunked_print (string,window=3):
for i in range(0,len(string) // window + 1): print(string[i*window:(i+1)*window])
This will work if the window size doesn't divide the string length, but print an empty line if it does. You can modify that according to your needs
New to programming and currently working with python. I am trying to take a user inputted string (containing letters, numbers and special characters), I then need to split it multiple times at different points to reform new strings. I have done research on the splitting of strings (and lists) and feel I understand it but I still know there must be a better way to do this than I can think of.
This is what I currently have
ass=input("Enter Assembly Number: ")
#Sample Input 1 - BF90UQ70321-14
#Sample Input 2 - BS73OA91136-43
ass0=ass[0]
ass1=ass[1]
ass2=ass[2]
ass3=ass[3]
ass4=ass[4]
ass5=ass[5]
ass6=ass[6]
ass7=ass[7]
ass8=ass[8]
ass9=ass[9]
ass10=ass[10]
ass11=ass[11]
ass12=ass[12]
ass13=ass[13]
code1=ass0+ass2+ass3+ass4+ass5+ass6+ass13
code2=ass0+ass2+ass3+ass4+ass5+ass6+ass9
code3=ass1+ass4+ass6+ass7+ass12+ass6+ass13
code4=ass1+ass2+ass4+ass5+ass6+ass9+ass12
# require 21 different code variations
Please tell me that there is a better way to do this.
Thank you
Give a look to this code and Google "python string slicing" (a nice tutorial for beginners is at https://www.youtube.com/watch?v=EqAgMUPRh7U).
String (and list) slicing is used a lot in Python. Be sure to learn it well. The upper index could be not so intuitive, but it becomes second nature.
ass="ABCDEFGHIJKLMN"
code1 = ass[0] + ass[2:7] + ass[13] # ass[2:7] is to extract 5 chars starting from index 2 (7 is excluded)
code2 = ass[0] + ass[3:7] + ass[9]
code3 = ass[1] + ass[4] + ass[6:8] + ass[12] + ass[6] + ass[13]
code4 = ass[1:3] + ass[4:7] + ass[9] + ass[12]
PS: You probably need also to check if the string length is 14 before working with it.
EDIT: Second solution
Here is another solution, perhaps it is easier to follow:
def extract_chars(mask):
chars = ""
for i in mask:
chars += ass[i]
return chars
mask = [0,2,3,4,5,6,13]
print extract_chars(mask)
Here you define a mask of indexes of the chars you want to extract.
You can try something like this,
input1 = 'BF90UQ70321-14'
code = lambda anum, pos: ''.join(anum[p] for p in pos)
code4 = code(input1, (1,2,4,5,6,9,12))
I'm trying to create a code that counts how many G's and C's there are in a "strand of DNA" and calculate the percentage of the G's + C's in that strand, e.g.
gcContent('CGGTCCAATAGATTCGAA')
44.4444444444
There are 18 letters in that string and 8 G's + C's together.
I am struggling so far to even count the letter of G's in a strand in my code, this is what I have so far:
def gcContent(dnaMolecule):
count = 0
for g in dnaMolecule:
dnaMolecule.count('g')
count += 1
return count
and when I type it into the interactive python shell the result is this:
In [1]: gcContent('a')
Out[1]: 1.0
It's not counting the amount of G's so far and it says one no matter what if I type in 1 character inside the brackets after gcContent.
You can use the count method that every string has.
def gcContent(dnaMolecule):
dnaMolecule = dnaMolecule.lower()
count = dnaMolecule.count('g') + dnaMolecule.count('c')
return count / len(dnaMolecule)
For Python 2.x and getting a value between 0 - 100 instead of 0 - 1:
def gcContent(dnaMolecule):
dnaMolecule = dnaMolecule.lower()
count = dnaMolecule.count('g') + dnaMolecule.count('c')
return 100.0 * count / len(dnaMolecule)
If you can make use of Biopython, there is already a predefined function GC which calculates the GC content of a given sequence:
from Bio.SeqUtils import GC
print(GC('CGGTCCAATAGATTCGAA'))
That gives the desired output:
44.44444444444444
Depending on what additional things you want to do with your sequence, I highly recommend to use the predefined functions rather than writing your own ones.
EDIT:
As this is discussed below #TammoHeeren's answer, GC also takes care of the lower/upper case issue:
print(GC('CGGGggg'))
gives
100.0