How to add running total using complex if statement in Python - python

I have the following data in a text file.
Intium II,2.8,24,128
Celerisc I,1.6,32,256
Ethloan III,2.6,32,128
Powerup II,1.9,64,512
Mitduo III,3.1,24,128
I am doing the following:
Allocating points to each processor
Points will be awarded to each processor as follows:
Clock speed is less than 2 GHz, award 10 points.
Clock speed is between 2 GHz and 3 GHz inclusive, award 20 points.
Clock speed is greater than 3 GHz, award 30 points.
Data Bus Points
1 point for each line on the data bus e.g. 24 bit data bus, award 24 points.
Cache Size Points
1 point for each whole 10 Kb of cache e.g. 128Kb cache, award 12 points.
(128/10 = 12ยท8, which should be rounded down to 12)
The output from the program should be similar to the following:
John Doe your order code is JD3f
Processor Points
Intium II 56
Celerisc I 67
Ethloan III 64
Powerup II 125
Mitduo III 66
Here is my code
import random
import string
def getDetails():
forename = input("Enter first name: ")
surname = input("Enter last name: ")
number = random.randint(0,9)
character = random.choice(string.ascii_letters).lower()
code = (forename[:1] + str(surname[:1]) + str(number) + str(character))
return forename, surname, code
def readProcessorDetails():
processorName = []*5
clockSpeed = []*5
dataBusWidth = []*5
cacheSize = []*5
file = open("processors.txt","r")
for line in file:
data = line.split(",")
processorName.append(data[0])
clockSpeed.append(float(data[1]))
dataBusWidth.append(data[2])
cacheSize.append(data[3])
input("file read successfully.. Press any key to continue")
return processorName, clockSpeed, dataBusWidth, cacheSize
def allocatePoints(clockSpeed, dataBusWidth, cacheSize):
proPoints = 0.0
processorPoints = []
for counter in range(len(clockSpeed)):
if clockSpeed[counter] < 2.0 or dataBusWidth[counter] == 24 or dataBusWidth[counter] == 128:
proPoints = proPoints + 10 + 24 + 12
processorPoints.append(proPoints)
elif clockSpeed[counter] > 2.0 or clockSpeed[counter] <= 3.0 or dataBusWidth[counter] == 24 or dataBusWidth[counter] == 128:
proPoints = proPoints + 20 + 24 + 12
processorPoints.append(proPoints)
elif clockSpeed[counter] > 3.0 or dataBusWidth[counter] == 24 or dataBusWidth[counter] == 128:
proPoints = proPoints + 30 + 24 + 12
processorPoints.append(proPoints)
return processorPoints
def display(processorName, processorPoints):
print(f"Processor \t Points")
for counter in range(len(processorPoints)):
print(f"{processorName[counter]}\t {processorPoints[counter]}\n")
def main():
forename, surname, code = getDetails()
processorName, clockSpeed, dataBusWidth, cacheSize = readProcessorDetails()
processorPoints = allocatePoints(clockSpeed, dataBusWidth, cacheSize)
print()
print(forename + " " + surname + " your order code is " + code)
print()
display(processorName, processorPoints)
main()
Here is my code output
Enter first name: John
Enter last name: Doe
file read successfully.. Press any key to continue
John Doe your order code is JD8z
Processor Points
Intium II 56.0
Celerisc I 102.0
Ethloan III 158.0
Powerup II 204.0
Mitduo III 260.0
I am not sure what I am doing wrong in my allocatePoints() function where I have used complex if statements and running total to add processor points.

Consider keeping all of the data in one list, rather than trying to coordinate multiple lists. This lets you avoid the unPythonic "for x in range(len(x))" construct, and iterate through the list directly.
I also fixed your root problem, which is that you weren't resetting the points to zero for every new processor.
import random
import string
def getDetails():
forename = input("Enter first name: ")
surname = input("Enter last name: ")
number = random.randint(0,9)
character = random.choice(string.ascii_letters).lower()
code = (forename[:1] + str(surname[:1]) + str(number) + str(character))
return forename, surname, code
def readProcessorDetails():
pdata = []
for line in open("processors.txt"):
data = line.split(",")
pdata.append( [data[0], float(data[1]), int(data[2]), int(data[3])] )
return pdata
def allocatePoints(pdata):
for row in pdata:
points = 0
if row[1] < 2.0:
points += 10
elif row[1] <= 3.0:
points += 20
else:
points += 30
points += row[2]
points += row[3] // 10
row.append( points )
def display(pdata):
print("Processor\tPoints")
for row in pdata:
print(f"{row[0]}\t{row[-1]}")
def main():
forename, surname, code = getDetails()
processorData = readProcessorDetails()
allocatePoints(processorData)
print()
print(forename + " " + surname + " your order code is " + code)
print()
display(processorData)
main()

Related

Using 'For Loop' to write data to a file

I am trying to use 'for loop' to write to a file in python dynamically, but I do not know how to calculate to write dynamically. I would appreciate if I get some help on this.
def earnings(name, age, salary):
AnnualRate = 0.05
outFile = open('yearly_earnings.txt', 'w')
outFile.write('Prepared by: Amornchot Singh')
outFile.write('Age Salary Total')
n = 26
for n in range(66):
ageLimit = 65
i = 26
totalEarned = 0
for i in range(ageLimit+1):
totalEarned += salary * (1+AnnualRate)
print('summary for ' + name)
print('Starting salary at age ' + age + ' was ' + salary)
print('Salary increases were 5.0% per year')
print('Total accumulated earnings by age 65 is {:,.2f}'.format(totalEarned))
print("To view yearly data go to 'yearly_earnings.txt'")
print("'Thank you for using the earnings() function.'")
First of all remove all redundant lines of code
Call the function
Don't forget to close the file after writing something, otherwise it
will not save the data in your file
Python don't allow to add integer with string so convert the integer
into str before concatenating
print('Starting salary at age ' + str(age) + ' was ' + str(salary))
Here is full code
def earnings(name, age, salary):
AnnualRate = 0.05
outFile = open('yearly_earnings.txt', 'w')
outFile.write('Prepared by: Amornchot Singh')
outFile.write('Age Salary Total')
ageLimit = 65
i = 26
totalEarned = 0
for i in range(ageLimit+1):
totalEarned += salary * (1+AnnualRate)
outFile.close()
print('summary for ' + name)
print('Starting salary at age ' + str(age) + ' was ' + str(salary))
print('Salary increases were 5.0% per year')
print('Total accumulated earnings by age 65 is {:,.2f}'.format(totalEarned))
print("To view yearly data go to 'yearly_earnings.txt'")
print("'Thank you for using the earnings() function.'")
earnings("Tariq", 20, 500000)

Algebraic pyramid python challenge- more efficient way?

I'm doing a python challenge where you have to create an upside-down algebraic pyramid based on a list. Each level (going down) needs to be the sum of the numbers above it.
I created the code to do this for 4 layers.
The challenge part 2 was to do it for any length of list, so I added the len(list) code to accommodate. You can see my code below.
I just wondered if there was a more efficient way to do this for long lists, or would I just need to type out more code for the remaining layers.
Also, I wondered how the return statement is meant to fit into it (you're given the hint written in the code below to update the return statement).
def drawPyramid(list):
layer = ""
layer2 = " "
layer3 = " "
layer4 = " "
for i in range(len(list)):
layer = layer + " " + str(list[i])
for i in range(len(list)-1):
layer2 = layer2 + " " + str(list[i]+list[i+1])
for i in range(len(list)-2):
layer3 = layer3 + " " + str(list[i]+(list[i+1]*2)+list[i+2])
for i in range(len(list)-3):
layer4 = layer4 + " " + str(list[i]+(list[i+1]*3)+(list[i+2]*3)+list[i+3])
print(layer)
print(layer2)
print(layer3)
print(layer4)
#Update this code to generate all 4 layers of the pyramid
#Update this return statement to return the value of the single brick on the last layer of the pyramid
return 0
#Main code starts here
list = [30,12,10,22]
drawPyramid(list)
Here this function will calculate your pyramid using list:
def calcul_pyramid(base):
pyramid = [base]
for i in range(len(base) - 1):
actual_layer = []
last_layer = pyramid[i]
for j in range(len(last_layer) - 1):
actual_layer.append(last_layer[j] + last_layer[j + 1])
pyramid.append(actual_layer)
return pyramid
This function will get your pyramid as string:
def print_pyramid(pyramid):
lines = []
for layer in pyramid:
line = ""
for brick in layer:
line += str(brick)
line += " "
lines.append(line)
pyramid_len = max([len(layer) for layer in lines])
txt = ""
for line in lines:
diff = (pyramid_len - len(line)) / 2
txt += " " * int(diff + 0.5)
txt += line
txt += " " * int(diff - 0.5)
txt += "\n"
print(txt)
Now you can enter every base you want, it will work
print_pyramid(calcul_pyramid([30,12,10,22])))
You can use zip to add up the values, then it's just a question of formatting:
def pyramid(A):
indent = ""
width = len(str(sum(A)))
while A:
print(indent,*(f"{a:{width}}" for a in A))
A = [a+b for a,b in zip(A,A[1:])]
indent += " "*max(1,width-1)
output:
L = [30,12,10,22]
pyramid(L)
30 12 10 22
42 22 32
64 54
118
L = [30,12,10,22,23,43]
pyramid(L)
30 12 10 22 23 43
42 22 32 45 66
64 54 77 111
118 131 188
249 319
568

How to count file in function of their age in Python?

I'm trying to count how many file are very young, young, old and very old in a directory passed by command line. I have some struggle counting the number of file in the directory and then to change the counter in function of the age of the file.
Here is what I did yet:
import sys
import os, os.path
import time
x = 7
file_count = 0
DIR = sys.argv[1]
age = 0
age_sum = 0
nb_vy = 0
nb_y = 0
nb_o = 0
nb_vo = 0
now = time.time()
for root, subFolders, files in os.walk(DIR):
for file in (files):
try:
file_count += 1
# here I want to do some if to add 1 in the counter nb_vy/nb_y/nb_o/nb_vo but I don't know how
age=now - os.stat(os.path.join(root,file)).st_mtime
age_sum+=age
if now-timedelta(hours=24) <= age <= now :
nb_vy += 1
elif now-timedelta(days=7) <= age :
nb_y += 1
elif now-timedelta(days=30) <= age :
nb_o += 1
else:
nb_vo += 1
except Exception:
pass
print("Filecount = %s" % file_count)
print("--------------------------------------------------------------------\n")
print("Scanned: "+ str(file_count) +" files\n")
print("Average age: "+ str(age/age_sum) + "\n")
print("--------------------------------------------------------------------\n")
print("Very young files (<= 1 day) | "+ str(nb_vy/file_count) +"% (" + str(nb_vy) + ")\n")
print("Young files (<= 1 week) | "+ str(nb_y/file_count) +"% (" + str(nb_v) + ")\n")
print("Old files (<= 30 days) | "+ str(nb_o/file_count) +"% (" + str(nb_o) + ")\n")
print("Very old files (> 30 days | "+ str(nb_vo/file_count) +"% (" + str(nb_vo) + ")\n")
print("--------------------------------------------------------------------\n")
How can I manage the if cascade to increment the right counter ?
You had the sides of the comparison swapped and the unneeded now - was still there. Once those are fixed and the timedelta converted to a duration of seconds for comparison:
if age <= timedelta(hours=24).total_seconds():
nb_vy += 1
elif age <= timedelta(days=7).total_seconds():
nb_y += 1
elif age <= timedelta(days=30).total_seconds():
nb_o += 1
else:
nb_vo += 1
You should be using age < max_age_for_group as the condition. age is already now - mtime. age is in seconds.
Also except Exception: pass will harm debugging. If you must have it at least use:
except Exception:
logging.exception('')
This will eat the exception but still print it. And then you can turn the printing off by changing the level on the root logger.
You correctly calculate the age of the file with calculating the difference in time using:
now = time.time()
mt = os.stat(os.path.join(root,file)).st_mtime
age = now - mt
All of the above variable are stored as float and represent the time in seconds ellapsed since January 1st 1970. So the difference age is a time difference in seconds!
In order to categorize into the intervals specified, you need to convert this time difference to days, e.g. with:
# import datetime
td = datetime.timedelta(0, age)
print(td.days) # Prints the time delta in days (integer)
I think, this is exactly what you need for you comparison, as if the time difference is, e.g. 72000 seconds (=20 hours), td.days will be evalutated to 0.

How to input a readable text file into my Python code and have it run properly

def main():
infile = open("studentinfo.txt", "rt")
data = infile.read()
fName, lName, ID, year = data.split(",")
year = int(year)
# Prompt the user for three test scores
grades = eval(input("Enter the three test scores separated by a coma: "))
# Prompt create a username
uName = (lName[:4] + fName[:2] + str(year)).lower()
converted_id = ID[:3] + "-" + ID[3:5] + "-" + ID[5:]
grade_1, grade_2, grade_3 = grades
# Convert the grades to strings so they can be written to a new file
[grade_1, grade_2, grade_3] = [str(grade_1), str(grade_2), str(grade_3)]
# Calculate the average
average =(float(grade_1) + float(grade_2)+ float(grade_3))/3.0
# Convert the average to a string
average = str(average)
# Write the information to the file
outfile = open("studentreport.txt", "w")
outfile.write("*******Student Report*******\nStudent Name:" + fName + " " + lName)
outfile.write("\nStudent ID: " + converted_id + "\n" + "Username: " + uName + "\n\n")
outfile.write("Grade 1: " + str(grade_1) + "\n" "Grade 2: " + str(grade_2) + "\n" + "Grade 3: " + str(grade_3) + "\n" + "Average: " + str(average))
infile.close()
outfile.close()
main()
How to make it run properly using a readable text file
this is all I get when I run the program help?
Enter the three test scores separated by a coma: 80,78,90,
>>> 80,78,90,
(80, 78, 90)
>>> main()
Enter the three test scores separated by a coma: 87,86,90
>>>
There may be some syntax issues, but I cannot test it since I do not have your files, but this may be inline with what you are thinking:
def get_grades(student_name):
grades = raw_input("Enter the three test scores for {0} separated by a coma: ".format(student_name)).split(',')
if len(grades) != 3:
print "must enter three grades"
return get_grades(student_name)
return float(grades[0]), float(grades[1]), float(grades[2])
with open("studentreport.txt", "w") as outfile:
outfile.write("*******Student Report*******\n")
with open("studentinfo.txt", "r") as infile:
for student in infile:
fName, lName, ID, year = student.split(",")
year = int(year)
uName = "{0}{1}{2}".format(lName[:4], fName[:2], str(year)).lower()
converted_id = "{0}-{1}-{2}".format(ID[:3], ID[3:5], ID[5:])
# Prompt the user for three test scores
grade_1, grade_2, grade_3 = get_grades("{0} {1}".format(fName, lName))
average = sum([grade_1, grade_2, grade_3])/3
outfile.write("Student Name:{0} {1}\n".format(fName, lName))
outfile.write("Student ID: {0}\nUsername: {1}\n\n".format(converted_id, uName))
outfile.write("Grade 1: {0}\nGrade 2: {1}\nGrade 3: {2}\nAverage: {3}\n\n".format(grade_1, grade_2, grade_3,average))
tested with input:
sam, snead, kghasjkdfiuaski21, 2006
john, doe, 9792345678872, 2009
garth, nroken, 097892364, 2006
which outputs:
*******Student Report*******
Student Name:sam snead
Student ID: kg-ha-sjkdfiuaski21
Username: snesa2006
Grade 1: 56.0
Grade 2: 67.0
Grade 3: 78.0
Average: 67.0
Student Name:john doe
Student ID: 97-92-345678872
Username: doejo2009
Grade 1: 67.0
Grade 2: 89.0
Grade 3: 78.0
Average: 78.0
Student Name:garth nroken
Student ID: 09-78-92364
Username: nroga2006
Grade 1: 45.0
Grade 2: 67.0
Grade 3: 89.0
Average: 67.0
And remember: Eval is Evil

Python Separating String into Words and Recursion

I'm trying to create a code that will take in an input (example below)
Input:
BHK158 VEHICLE 11
OIUGHH MOTORCYCLE 34.46
BHK158 VEHICLE 12.000
TRIR TRUCK 2.0
BLAS215 MOTORCYCLE 0.001
END
and produce an output where each license plate number is listed and the total cost is listed beside (example below)
Corresponding output:
OIUGHH: 5.8582
BHK158: 5.75
TRIR: 2.666
BLAS215: 0.00017
The vehicle license plates are charged $0.25 per kilometer (the kilometers are the number values in the input list), trucks are charged $1.333 per kilometer, and motorcycles $0.17 per kilometer. The output is listed in descending order.
Here is my code thus far:
fileinput = input('Input: \n')
split_by_space = fileinput.split(' ')
vehicles = {}
if split_by_space[1] == 'VEHICLE':
split_by_space[2] = (float(split_by_space[2]) * 0.25)
elif split_by_space[1] == 'TRUCK':
split_by_space[2] = float(split_by_space[2]) * 1.333
elif split_by_space[1] == 'MOTORCYCLE':
split_by_space[2] = float(split_by_space[2]) * 0.17
if split_by_space[0] in vehicles:
previousAmount = vehicles[split_by_space[0]]
vehicles[split_by_space[0]] = previousAmount + split_by_space[2]
else:
vehicles[split_by_space[0]] = split_by_space[2]
Thanks, any help/hints would be greatly appreciated.
Going through your code I noticed a few things, list indicies in python start at 0, not 1 so you were get a bunch of out of bounds errors. Secondly, input only takes the first line of the input so it was never going past the first line. .split() splits text by \n by default, you have to specify if you want to split by something else, like a space.
test.txt contents:
BHK158 VEHICLE 11
OIUGHH MOTORCYCLE 34.46
BHK158 VEHICLE 12.000
TRIR TRUCK 2.0
BLAS215 MOTORCYCLE 0.001
python code:
fileinput = open('test.txt', 'r')
lines = fileinput.readlines()
vehicles = {}
for line in lines:
split_by_space = line.split(' ')
if split_by_space[1] == "VEHICLE":
split_by_space[2] = (float(split_by_space[2]) * 0.25)
elif split_by_space[1] == "TRUCK":
split_by_space[2] = float(split_by_space[2]) * 1.333
elif split_by_space[1] == "MOTORCYCLE":
split_by_space[2] = float(split_by_space[2]) * 0.17
if split_by_space[0] in vehicles:
previousAmount = vehicles[split_by_space[0]]
vehicles[split_by_space[0]] = previousAmount + split_by_space[2]
else:
vehicles[split_by_space[0]] = split_by_space[2]
output:
{'BLAS215': 0.00017, 'OIUGHH': 5.858200000000001, 'TRIR': 2.666, 'BHK158': 5.75}

Categories

Resources