Blekinge Institude of Technology
Kmom01Kursmoment01: Get Started with Python
Introduction
You must now create a program that asks the user to enter one of the following values:
- Speed (km/h)
- Price
The program should then ask which value the user wants to convert to:
- P: Price, where the value is adjusted with a fixed discount (10 SEK) and then increased by VAT (20%).
- S: Speed, where the value is interpreted as km/h and converted to mph (miles per hour).
1 kilometer equals 0.62137 miles.
Finally, print the converted value with a maximum of two decimal places.
It is important that your program follows the instructions in the requirements; otherwise, the tests will not work and your submission will not be graded.
value_str = input().strip()
if not value_str.replace(".", "", 1).lstrip("-").isdigit():
print("Invalid value")
exit()
value = float(value_str)
converter = input().strip().upper()
# Skriv ut det ursprungliga värdet formaterat
print(f"{value:.1f} ")
if converter == "S":
mph = value * 0.62137
print(f"{mph:.2f} ")
elif converter == "P":
discount = 10
tax = 0.2
price_after_discount = value - discount
final_price = price_after_discount * (1 + tax)
print(f"{final_price:.1f} ")
# felaktig konvertering
else:
print("Invalid converter")
exit()
Kmom02Kursmoment02: Loop
Marvin - steg 1
Programming and problem-solving in Python, where you will build a chatbot called Marvin that can answer “all” your questions.
from collections import Counter
"""
Marvin, vännen i terminal
"""
print(r"""
.<'"'=,,_
//__ -_"(XX,
(y") \_ ) "X
( \ r )_| X______
) | (_//"/\__ \
Y_<_ /_/ /\ \ \
|__\ \/ x\ \ \
/_--\ \x / \ \
( \ \ \/ | \_
|\ \ "' \ fu''_]
| \ \ | | r""
\__\ | \ ||
,x"| | ',"'
x" | |\_.-"_>-.
x' | |[_.-" \
|\ | |/ |
_|_| | |
fl"Ol] _/ /
|,U""-. / \_.-"|
|| /" | |
"' / | |
/ / | |
/ / | /_
| .' \ \
| \ \ |
| | '._-\
| | ". \
| / \ \
|__| _\ \
f""l ( _ ]
I | "" ""
I |
__l |
( _ ]
""" ""
""")
print("Hej, Här har du Marvin, hjälpsamma robot som hjälper dig 🦾")
while True: # main loop som visar upp menyn å kontrollerar user's val
print("\nMeny")
print("1. Skriv ditt namn")
print("2. Change Temperature Celsius → Fahrenheit")
print("3. Poäng till betyg")
print("4. Jämför tal: ")
print("5. Skriv in personnummer")
print("6. Rovarspråket")
print("q. Avsluta")
val = input("Välja ett alternativ: ")
if val == "q":
print(f"{GREEN}Hejdå från roboten 👋{RESET}")
break # avslutar programmet
--------------------------------------------------------------------------------
elif val == "1":
print(f"{GREEN}Hej Ali heter jag, å Robot hälsar dig tillbaka 🤚{RESET}")
--------------------------------------------------------------------------------
elif val == "2":
celcius = float(input(f"{GREEN}Skriv temperaturen i Celcius: {RESET}"))
fahrenheit = round((celcius * 9 / 5) + 32, 2) # runda decimalen till 2
print(f"{celcius} °C Celcius motsvarar {fahrenheit: 2} °F Fahrenheit")
--------------------------------------------------------------------------------
elif val == "3":
max_poang = float(input("Ange Max poang: ")) # example 169
din_poang = float(input("Ange dina poang: ")) # example 59
procent = (din_poang / max_poang) * 100 # 59/169 = 0.349 * 100 = 34.9
GRADE_A = 90
GRADE_B = 80
GRADE_C = 70
GRADE_D = 60
GRADE_E = 50
if procent >= GRADE_A:
betyg = "A"
elif procent >= GRADE_B:
betyg = "B"
elif procent >= GRADE_C:
betyg = "C"
elif procent >= GRADE_D:
betyg = "D"
elif procent >= GRADE_E:
betyg = "E"
else:
betyg = "F"
print(f"{GREEN}score: {betyg}{RESET}")
--------------------------------------------------------------------------------
elif val == "4":
old_value = None
while True:
# tar en input från användaren
value = input(
f"{GREEN}skriv ett tal eller (skriv done för att avsluta): {RESET}"
)
if value == "done":
break;
try:
# Konvertera till int för strikt jämförelse
tal = int(value)
if old_value is None:
old_value = tal
continue # försätt
if tal > old_value:
print("larger!")
elif tal < old_value:
print("smaller!")
else:
print("same!")
old_value = tal
except ValueError: # s124❌ dfhdf❌ 4124✅
print("not a number!")
--------------------------------------------------------------------------------
elif val == "5":
personnummer = input(f"{GREEN}Skriv in personnummer: {RESET}").replace("-", "")
LENGHT_PERSONNUMMER = 10
if not personnummer.isdigit() or len(personnummer) != LENGHT_PERSONNUMMER:
RED = "\033[31m"
RESET = "\033[0m"
print(f"{RED}Not valid{RESET}")
continue # försätt till nästa iteration
total = 0 # summering variabel enligt Luhn algorithm
# gå genom varje siffra i personnummer i å värdet är digit
for i, digit in enumerate(personnummer):
tal_n = int(digit) # omvandla siffran från sträng till heltal
if i % 2 == 0: # varje siffra som är jämna index bearbetas
tal_n = tal_n * 2 # multipliceras siffran med 2
LUHN = 9 # if result greater than 9, addera ihop siffror
if tal_n > LUHN:
tal_n = tal_n // 10 + tal_n % 10
total = total + tal_n # lägger siffran till den totala summan
if total % 10 == 0: # kontroll om siffran är modulus 10
print(f"{GREEN}Valid{RESET}")
else:
print(f"{RED}Not valid{RESET}")
--------------------------------------------------------------------------------
elif val == "6":
word = input("Skriv ett ord: ") # ber skriva skrva nåt
vowels = "AEIOUÅÄÖaeiouyåäö"
resultat = ""
for s in word:
if s.isalpha() and s not in vowels:
resultat += s + "o" + s
else:
resultat += s
print(f"{GREEN}{resultat}{RESET}")
--------------------------------------------------------------------------------
elif val == "7": # nytt alternativ: jämför två strängar, för extra uppgifter
string_one = input("Skriv din första strängen: ").lower()
string_two = input("Skriv din andra strängen: ").lower()
count_str_one = Counter(string_one)
count_str_two = Counter(string_two)
match = True
for letter, antal in count_str_two.items():
if count_str_one[letter] < antal:
match = False
break
if match:
print(f"{GREEN}Matching ...{letter} finns med i första strängen{RESET}")
else:
print(f"{RED}Not Matching.{RESET}")
--------------------------------------------------------------------------------
else:
RED = "\033[31m"
RESET = "\033[0m"
print(f"{RED}Alternativet {val} finns ej med i listen..!{RESET}")
Kmom03Kursmoment03: Functions & Modules
Marvin - steg 2
Programming and problem-solving in Python. Structure the code using your own functions.
main.py
import marvin1
import marvin2
def main():
"""Startar Marvin och visar menyn."""
while True:
print("\n==== Marvin Menu ====")
print("1. Greet")
print("2. Celsius to Fahrenheit")
print("3. Points to Grade")
print("4. Compare Numbers")
print("5. Validate SSN")
print("6. Robber Language")
print("7. Create SSN")
print("8. Randomize String")
print("q. Quit")
choice = input("Your choice: ")
if choice == "q":
print("Goodbye!")
break
if choice == "1":
marvin1.greet()
elif choice == "2":
marvin1.celsius_to_fahrenheit()
elif choice == "3":
marvin1.points_to_grade()
elif choice == "4":
marvin1.compare_numbers()
elif choice == "5":
marvin1.validate_ssn()
elif choice == "6":
marvin1.robber_language()
elif choice == "7":
birth = input("Enter birth date (YYMMDD): ")
print(marvin2.create_ssn(birth))
elif choice == "8":
text = input("Enter a string to randomize: ")
print(f"{text} --> {marvin2.randomize_string(text)}")
else:
print("Invalid choice.")
if __name__ == "__main__":
main()
marvin1.py
VOWELS = "aeiouyåäöAEIOUYÅÄÖ"
GRADE_F_LIMIT = 50
GRADE_E_LIMIT = 60
GRADE_D_LIMIT = 70
GRADE_C_LIMIT = 80
GRADE_B_LIMIT = 90
SSN_LEN = 10
LUHN_NBR = 9
def greet():
"""Menyval 1: Hälsa på användaren."""
name = input("What is your name? ")
print("\nMarvin says:\n")
print(f"Hello {name} - your awesomeness!")
print("What can I do you for?!")
--------------------------------------------------------------------------------
def celsius_to_fahrenheit():
"""Menyval 2: Omvandla Celsius till Fahrenheit."""
celsius = float(input("Enter temperature in Celsius: "))
fahrenheit = celsius * 9 / 5 + 32
print(f"{celsius}°C is {fahrenheit}°F")
--------------------------------------------------------------------------------
def get_grade(points):
"""Returnerar betyg beroende på poäng."""
if points < GRADE_F_LIMIT:
return "F"
elif points < GRADE_E_LIMIT:
return "E"
elif points < GRADE_D_LIMIT:
return "D"
elif points < GRADE_C_LIMIT:
return "C"
elif points < GRADE_B_LIMIT:
return "B"
return "A"
--------------------------------------------------------------------------------
def points_to_grade():
"""Menyval 3: Räkna ut betyg från poäng."""
while True:
try:
value = input("Enter your points (0–100 or 'done'): ")
except (EOFError, StopIteration):
break
if value is None or value.lower() == "done":
break
try:
points = int(value)
except ValueError:
continue
grade = get_grade(points)
print(f"score: {grade}")
--------------------------------------------------------------------------------
def compare_numbers():
"""Menyval 4: Jämför flera tal tills 'done' skrivs."""
prev = None
while True:
value = input("Enter a number (or 'done'): ")
if value.lower() == "done":
break
num = float(value)
if prev is not None:
if num > prev:
print("larger!")
elif num < prev:
print("smaller!")
else:
print("same!")
prev = num
--------------------------------------------------------------------------------
def validate_ssn():
"""Menyval 5: Kontrollera giltigt personnummer."""
ssn = input("Enter a full SSN (YYMMDD-NNNN): ")
# Ta bara siffror
digits = ""
for ch in ssn:
if ch.isdigit():
digits += ch
if len(digits) != SSN_LEN:
print("Invalid SSN (must have 10 digits)")
return
# Räkna ut Luhn-summan
total = calculate_luhn_sum(digits)
# Om summan är delbar med 10 → giltigt SSN
if total % 10 == 0:
print("Valid SSN")
else:
print("Invalid SSN")
--------------------------------------------------------------------------------
def calculate_luhn_sum(digits):
"""Räknar ut Luhn-summan (för svenska personnummer, från vänster)."""
total = 0
for i, ch in enumerate(digits):
n = int(ch)
if i % 2 == 0: # varannan siffra från vänster
n *= 2
if n > LUHN_NBR:
n -= LUHN_NBR
total += n
return total
--------------------------------------------------------------------------------
def robber_language():
"""Menyval 6: Översätt till rövarspråket."""
text = input("Enter text: ")
result = ""
for ch in text:
if ch.lower() not in VOWELS and ch.isalpha():
result += ch + "o" + ch.lower()
else:
result += ch
print(result)
marvin2.py
import random
from marvin1 import calculate_luhn_sum
# Konstant för antal slumpade siffror i personnummer
RANDOM_DIGIT_COUNT = 3
def calculate_luhna_sum(ssn):
"""Wrapper för testet som använder felstavat funktionsnamn."""
return calculate_luhn_sum(ssn)
--------------------------------------------------------------------------------
def create_ssn(birth):
"""Menyval 7: Skapa ett giltigt personnummer med slumpade siffror."""
random_digits = ""
count = 0
while count < RANDOM_DIGIT_COUNT:
random_digits += str(random.randint(0, 9))
count += 1
digits = birth + random_digits # utan bindestreck!
total = calculate_luhn_sum(digits)
last_digit = (10 - (total % 10)) % 10
ssn = f"{birth}-{random_digits}{last_digit}"
return ssn
--------------------------------------------------------------------------------
def randomize_string(text):
"""Menyval 8: Slumpa om bokstäver i en text (utan listor)."""
result = ""
original = text
# Slumpa bort bokstäver en i taget
while len(text) > 0:
index = random.randint(0, len(text) - 1)
result += text[index]
text = text[:index] + text[index + 1 :]
# Om slumpningen blev identisk, kör om
if result == original and len(original) > 1:
return randomize_string(original)
return result
Kmom04Kursmoment04: Lists
Marvin - steg 3
Programming and problem-solving in Python. Continue working with Marvin and implement new functionality using lists.
inventory.py
# Funktion för att lägga till föremål i ryggsäcken
def pick(bagpack, item, position=None):
try:
# Om ingen position anges, lägg sist
if position is None:
bagpack.append(item)
print(f"Du lade till '{item}' i ryggsäcken (sist).")
--------------------------------------------------------------------------------
else:
position = int(position) # Gör om till heltal
if position < 0 or position > len(bagpack):
print(f"Error: position {position} finns inte.")
return bagpack
# Lägg till på specifik position
bagpack.insert(position, item)
print(f"Du lade till '{item}' på position {position}.")
# Fel om position inte är ett nummer
except ValueError:
print(f"Error ogiltig position '{position}'.")
return bagpack
--------------------------------------------------------------------------------
# Funktion för att slänga föremål från ryggsäcken
def drop(bagpack, item):
try:
# Försök ta bort föremålet
bagpack.remove(item)
print(f"Du slängde '{item}'.")
except ValueError:
print(f"Error '{item}' finns inte i ryggsäcken.")
return bagpack
def swap(bagpack, first, second):
if len(bagpack) == 0:
# Lägg till första föremålet om ryggsäcken är tom
print(f"Error: föremålen '{first}' och '{second}' finns inte i ryggsäcken.")
return bagpack
try:
i1 = bagpack.index(first)
i2 = bagpack.index(second)
bagpack[i1], bagpack[i2] = bagpack[i2], bagpack[i1]
print(f"Bytte plats på '{first}' och '{second}'.")
except ValueError:
missing_items = []
if first not in bagpack:
missing_items.append(first)
if second not in bagpack:
missing_items.append(second)
print(f"Error: föremålen {', '.join(missing_items)} finns inte i ryggsäcken.")
return bagpack
--------------------------------------------------------------------------------
# Funktion för att visa innehåll i ryggsäcken
def inventory(bagpack):
# Om ryggsäcken är tom
if not bagpack:
print("Ryggsäcken är tom.")
print("0")
return
# Visa alla föremål i ryggsäcken
print(f"Ryggsäcken innehåller {len(bagpack)} saker:")
for i, thing in enumerate(bagpack):
print(f"{i}: {thing}")
main.py
# Importera funktioner från inventory-filen
from inventory import pick, drop, swap, inventory
# Konstant för kommandon
INV = "inv"
INV_PICK = "inv pick"
INV_DROP = "inv drop"
INV_SWAP = "inv swap"
# Antal ord för varje kommando
PICK_WORDS = 3
PICK_POSITION = 4
DROP_WORDS = 3
SWAP_WORDS = 4
INV_DROP_ARGS = 2
--------------------------------------------------------------------------------
def main():
bagpack = [] # Tom ryggsäck från början
# Visa instruktioner
print("Hej! Jag är Marvin3 här 🤖.")
print("Skriv kommandon (q för att avsluta).")
print(" inv - Visa innehållet i ryggsäcken")
print(" inv pick - - plocka ett föremål och lägg det sist")
print(" inv pick
-
- plocka ett föremål på specifik position")
print(" inv drop - Visa innehållet i ryggsäcken")
print(" inv drop - - släng ut ett föremål")
print(" inv swap
- bytar plats på två föremål")
while True:
User_input = input("> ").strip()
if User_input == "":
continue
--------------------------------------------------------------------------------
if User_input == "q":
print("Hejdå 👋")
break
--------------------------------------------------------------------------------
if User_input == INV:
inventory(bagpack)
--------------------------------------------------------------------------------
elif User_input.startswith(INV_PICK):
parts = User_input.split()
if len(parts) == PICK_WORDS:
bagpack = pick(bagpack, parts[2])
elif len(parts) == PICK_POSITION:
bagpack = pick(bagpack, parts[2], parts[3])
else:
print("Error: inv pick kräver ett föremål och valfritt en position.")
--------------------------------------------------------------------------------
# Släng föremål eller visa innehåll
elif User_input.startswith(INV_DROP):
parts = User_input.split()
if len(parts) == INV_DROP_ARGS:
inventory(bagpack)
elif len(parts) == DROP_WORDS:
bagpack = drop(bagpack, parts[2])
else:
print("Error: inv drop kräver ett föremål.")
--------------------------------------------------------------------------------
# Byt plats på två föremål
elif User_input.startswith(INV_SWAP):
parts = User_input.split()
# Byt plats om två föremål angivna
if len(parts) == SWAP_WORDS:
bagpack = swap(bagpack, parts[2], parts[3])
else:
print("Error: inv swap kräver två föremål.")
--------------------------------------------------------------------------------
else:
print(f"Error: Okänt kommando '{User_input}'")
if __name__ == "__main__":
main()
Kmom05Kursmoment05: Dictionary & Tuple
Carbon Emissions for Students
You will develop a program that can analyze students' carbon emissions. The program should handle multiple emission categories, such as transportation, food, and energy, and allow the user to:
- Display the total emissions per student
- Show the “greenest” student
- Display emissions per category
- Rank students by category
- Add or update students' emissions
- Remove students from the system
The program should work in a similar way to Marvin, using a menu loop.
emissions.py
def print_menu(): # skriver ut meny med olika val
print("\n--- Välkommen till klimat program ---")
print("1. Visa totalutsläpp per student")
print("2. Visa den grönaste studenten")
print("3. Visa utsläpp per kategori")
print("4. Rangordna studenter per kategori")
print("5. Lägg till eller uppdatera student")
print("6. Ta bort student")
print("q. Avsluta programmet")
print(".................................")
def display_total_emission_per_student(data):
if not data:
print("Ingen studentdata tillgänglig.")
return
for student, categories in data.items():
total = total_emission(categories)
print(
f"{student[0]} ({student[1]}): {total} kg CO2")
--------------------------------------------------------------------------------
def display_the_greenest_student(data):
if not data:
print("Ingen studentdata tillgänglig.")
return
green = None
lowest = None
for (student,categories,) in data.items():
total = total_emission(categories)
if lowest is None or total < lowest:
lowest = total
green = student
print(f"{green[0]} ({green[1]}): {lowest} kg CO2")
--------------------------------------------------------------------------------
def show_emission_per_category(data):
if not data:
print("Ingen studentdata tillgänglig.")
return
category_summa = {}
for categories in data.values():
for (category,value,) in categories.items():
if (category not in category_summa):
category_summa[category] = 0
category_summa[category] += (value)
for cat, total in category_summa.items():
print(f"{cat}: {total} kg CO2")
--------------------------------------------------------------------------------
def display_students_ranking(data, category):
if not data:
print("Ingen studentdata tillgänglig.")
return
rank = []
for student, categories in data.items():
value = categories.get(category, 0)
rank.append((student[0], student[1], value))
swapp = True
while swapp:
swapp = False
i = 0
while i < len(rank) - 1:
first = rank[i]
second = rank[i + 1]
if first[2] < second[2] or (first[2] == second[2] and first[0] > second[0]):
rank[i], rank[i + 1] = rank[i + 1], rank[i]
swapp = True
i = i + 1
index = 1
for namn, student_id, value in rank:
print(f"{index}. {namn} ({student_id}): {value} kg CO2 från {category}")
index = index + 1
--------------------------------------------------------------------------------
def add_update(data, namn, student_id, category, value):
key = (namn, student_id)
if key not in data:
data[key] = {}
data[key][category] = value
print(f"Data uppdaterad för {namn} ({student_id}).")
--------------------------------------------------------------------------------
def delete_student(data, namn, student_id):
key = (namn, student_id)
if key in data:
del data[key]
print(f"{namn} ({student_id}) har tagits bort.")
else:
print(f"Student {namn} ({student_id}) hittades inte.")
--------------------------------------------------------------------------------
def total_emission(categories):
total = 0
for value in categories.values():
total = total + value
return total
main.py
import emissions # här importerar jag filen emissions där alla funktioner finns
def main():
students_data = {
("Bob", 102): {"transport": 5, "food": 15, "energy": 20},
("Dana", 104): {"transport": 40, "food": 10, "energy": 15},
("Alice", 101): {"transport": 15, "food": 25, "energy": 30},
("Charlie", 103): {"transport": 10, "food": 13, "energy": 25, "waste": 5},
}
while True:
emissions.print_menu()
val = input("\nVälja ett alternativ: ").strip().lower() # user väljer sitt val
if val == "1":
emissions.display_total_emission_per_student(students_data)
--------------------------------------------------------------------------------
elif val == "2":
emissions.display_the_greenest_student(students_data)
--------------------------------------------------------------------------------
elif (val == "3"):
emissions.show_emission_per_category(students_data)
--------------------------------------------------------------------------------
elif val == "4":
category = input("Ange kategori: ").strip().lower() # undrar vilken kategory
emissions.display_students_ranking(students_data, category)
--------------------------------------------------------------------------------
elif val == "5":
namn = input("student name: ").strip()
try:
student_id = int(input("Student-ID: "))
except ValueError:
print("Invalid, ID måste va ett heltal")
print("Enter för att försätta")
continue
category = input("Kategori: ").strip().lower()
try:
value = int(input("Utsläppsvärde kg CO2: "))
except ValueError:
print("Invalid, ID måste va ett heltal")
print("Enter för att försätta")
continue
emissions.add_update(students_data, namn, student_id, category, value)
--------------------------------------------------------------------------------
elif val == "6":
namn = input("student name: ").strip()
try:
student_id = int(input("Student-ID: "))
except ValueError:
print("Invalid, ID måste vara ett heltal.")
input("Enter för att fortsätta...")
continue
emissions.delete_student(students_data, namn, student_id)
--------------------------------------------------------------------------------
elif val == "q":
print("programmet avslutas")
break
--------------------------------------------------------------------------------
else:
print("valet är ogiltig, försök igen!")
print("Tryck Enter för att försätta....") # pausa mellan varje val
if __name__ == "__main__":
main()
Kmom06Kursmoment06: File Handling
Analyze Text and Words
In Marvin, we have built a program consisting of two modules and several functions that work together so that Marvin can answer questions. We have also become familiar with dictionaries, where we can store key-value pairs. In this task, we will create a Marvin-like program that takes input and can analyze a text.
analyzer.py
import os
import string
# Läser in textfilen från samma mapp som main.py
def _read_file(filename):
"""Läser textfilen säkert från samma mapp som main.py."""
base_dir = os.path.dirname(__file__)
file_path = os.path.join(base_dir, filename)
try:
with open(file_path, encoding="utf-8") as f:
# returnerar all text i filen som en sträng
return f.read()
except FileNotFoundError:
print(f"Filen '{filename}' hittades inte.")
return ""
--------------------------------------------------------------------------------
# Denna funktion kan main.py och testerna anropa
def read_file(filename):
"""Publik funktion som anropar den privata _read_file."""
return _read_file(filename)
--------------------------------------------------------------------------------
# Hjälpfunktion för sortering
def sortering_nyckel(item):
return (item[1], item[0])
--------------------------------------------------------------------------------
# Räknar hur många rader som inte är tomma
def line_counter(text):
count = 0 # börjar räkna från noll
for line in text.splitlines(): # går igenom varje rad i texten
if line.strip(): # om raden inte tom
count += 1 # ökar räknaren
return count
--------------------------------------------------------------------------------
# Gör texten enklare att räkna (tar bort skiljetecken)
def _clean_text(text):
text = text.lower() # gör om allt till små bokstäver
for p in string.punctuation: # går igenom varje skiljetecken
text = text.replace(p, "") # tar bort det från texten
return text
--------------------------------------------------------------------------------
# Räknar antal ord i texten
def word_counter(text):
clean = _clean_text(text)
words = clean.split() # delar texten i ord
return len(words) # räknar hur många ord det finns
--------------------------------------------------------------------------------
# Räknar antal bokstäver a z
def letter_counter(text):
count = 0
# går igenom varje tecken i texten, omvandlar till små bokstäver
for c in text.lower():
# kontrollerar om tecknet är en bokstav a till z
if c.isalpha():
count += 1 # ökar räknaren med 1 för varje bokstav
return count # return det totala antalet bokstäver i texten
--------------------------------------------------------------------------------
def frequency_count(items):
"""
beräknar hur ofta varje element förekommer i en lista
och beräknar procentandel för varje element.
returnerar en sorterad lista med > element, antal, procent
"""
count = {} # Tom ordbok för att spara antalet förekomster
# räknar hur många gngr varje element finns i listan
for it in items:
if it in count:
count[it] += 1
else:
count[it] = 1
# räknar totala antalet element
total = 0
for _ in items:
total += 1
result = []
for key, value in count.items():
procent = round(value / total * 100, 1)
result.append((key, value, procent))
result.sort(key=sortering_nyckel, reverse=True)
return result
MAX_ITEMS = 7 # antal toppresultat att visa
def simple_word(text):
"""
Skriver ut de 7 mest frekventa orden i texten
med deras antal och procentandel.
"""
# tar bort onödiga tecken och formaterar texten
clean = _clean_text(text)
word_list = clean.split() # delar upp texten i en lista av ord
if not word_list:
return # avbryter om texten är tom
items = frequency_count(word_list) # hämtar statistik över orden
for i, entry in enumerate(items):
if i >= MAX_ITEMS:
break
word, cnt, pct = entry
print(f"{word}: {cnt} | {pct}%")
--------------------------------------------------------------------------------
def simple_letter(text):
"""
Skriver ut de 7 mest frekventa bokstäverna i texten
med deras antal och procentandel.
"""
letters = []
for c in text.lower():
if c.isalpha():
letters.append(c)
if not letters:
return
items = frequency_count(letters)
for i, entry in enumerate(items):
if i >= MAX_ITEMS:
break
letter, cnt, pct = entry
print(f"{letter}: {cnt} | {pct}%")
--------------------------------------------------------------------------------
# Visar alla resultat
def display_all(text):
"""Visar alla analyser i rätt ordning."""
print(line_counter(text)) # antal rader
print(word_counter(text)) # antal ord
print(letter_counter(text)) # antal bokstäver
print()
simple_word(text) # vanligaste orden
print()
simple_letter(text) # vanligaste bokstäverna
lorum.txt
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae aliquet dolor.
Vivamus neque dui, varius in iaculis a, imperdiet at ligula.
Donec dapibus urna.
main.py
import os
import analyzer # importerar analyzer.py där funktionerna finns
def main():
"""Huvudprogram som visar meny och kör valda analyser."""
base_dir = os.path.dirname(__file__) # sökväg till mappen
filename = "phil.txt" # startfil
while True:
print("\n--- Text Analyzer ---")
print(f"Nuvarande fil: {filename}")
print("========================")
print("lines -> beräkna antal rader")
print("words -> beräkna antal ord")
print("letters -> beräkna antal bokstäver")
print("word_frequency -> Vanliga orden")
print("letter_frequency -> Vanliga bokstäver")
print("all -> Visa alla analyser")
print("change -> Byt fil")
print("q -> Avsluta programmet")
print("========================")
val = input("Välj ett alternativ: ").strip().lower() # användarval
# Hantera byte av fil först
if val == "change":
new_file = input("Ange nytt filnamn (t.ex. lorum.txt): ").strip()
# Lägger till sökvägen till filen för att hantera den korrekt i testmiljöer
new_path = os.path.join(base_dir, new_file)
if os.path.exists(new_path): # om filen finns
filename = new_file
else:
print(f"Filen '{new_file}' finns inte i mappen.")
continue # gå tillbaka till meny
# Åtgärda filinläsningen i main.py:
text = analyzer.read_file(filename)
if not text and val not in {"change", "q"}: # om filen inte hittas
continue
if val == "lines":
print(analyzer.line_counter(text))
elif val == "words":
print(analyzer.word_counter(text))
elif val == "letters":
print(analyzer.letter_counter(text))
elif val == "word_frequency":
analyzer.simple_word(text)
elif val == "letter_frequency":
analyzer.simple_letter(text)
elif val == "all":
analyzer.display_all(text)
elif val == "q": # avslutar programmet
print("Programmet avslutas...")
break
else: # ogiltigt val
print("Ogiltigt val, försök igen.")
# input("Tryck Enter för att fortsätta...")
if __name__ == "__main__":
main()
phil.txt
Phil was quick to take a hint. He saw the menace in the shopkeepers
eyes, and, stopping abruptly, ran farther down the street, hugging his
fiddle, which he was afraid the angry tobacconist might seize and break.
This, to him, would be an irreparable misfortune and subject him to a
severe punishment, though the fault would not be his.
Next he strolled into a side street, and began to play in front of some
dwelling-houses. Two or three young children, who had been playing in
the street, gathered about him, and one of them gave him a penny. They
were clamorous for another tune, but Phil could not afford to work for
nothing, and, seeing no prospects of additional pay, took his violin,
and walked away, much to the regret of his young auditors, who, though
not rich, were appreciative. They followed him to the end of the block,
hoping that he would play again, but they were disappointed.
Phil played two or three times more, managing to obtain in all
twenty-five cents additional. He reached the corner of Thirteenth Street
just as the large public school, known as the Thirteenth Street School,
was dismissed for its noon intermission.
Kmom10Kursmoment10: Project & Examination
Project Specification
You will implement a program for keyboard training. The program displays one line at a time for the user to type as quickly as possible. After the user has typed all the lines, the program should calculate how well they performed and display the results.
The basic requirements include 5 menu options:
- 1. Start the typing test using the file
easy.txt. - 2. Start the typing test using the file
medium.txt. - 3. Start the typing test using the file
hard.txt. - 4. Print the results list saved in
scores.txt. - q. Exit the program.
Easy.txt
Medium.txt
Hard.txt
functions.py
import os
import time
# grundläggande filvägar och konstanter
BASE_DIR = os.path.dirname(__file__)
TEXTS_DIR = os.path.join(BASE_DIR, "texts")
SCORES_FILE = os.path.join(BASE_DIR, "scores.txt")
EXPECTED_PARTS = 3
# wpm gränser och motsvarande djurkategorier
WPM_CATEGORIES = [
(5, "Sloth 🦥"),
(15, "Snail 🐌"),
(30, "Manatee 🐋"),
(40, "Human 🧑"),
(50, "Gazelle 🦌"),
(60, "Ostrich 🦩"),
(70, "Cheetah 🐆"),
(80, "Swordfish 🐟"),
(90, "Spur-winged goose 🦢"),
(100, "White-throated needletail 🐦"),
(120, "Golden eagle 🦅"),
]
def get_animal_category(net_wpm):
"""
tar ett värde (net_wpm) och returnerar en sträng med ett
djurnamn och emoji som representerar användarens skrivhastighet.
"""
for limit, category in WPM_CATEGORIES:
if net_wpm <= limit:
return category
return "Peregrine falcon 🦅"
--------------------------------------------------------------------------------
def _compare_words(typed_words, original_words):
"""
jämför användarens ord med originalord, räknar korrekta ord och bygger
ett histogram över felstavade eller saknade ord.
"""
correct_words = 0
wrong_word_histogram = {}
total_original_words = len(original_words)
typed_word_count = len(typed_words)
for i, original_word in enumerate(original_words):
if i < typed_word_count:
if typed_words[i] == original_word:
correct_words += 1
else:
wrong_word_histogram[original_word] = (
wrong_word_histogram.get(original_word, 0) + 1
)
else:
wrong_word_histogram[original_word] = (
wrong_word_histogram.get(original_word, 0) + 1
)
extra_words = max(0, typed_word_count - total_original_words)
return correct_words, extra_words, wrong_word_histogram
--------------------------------------------------------------------------------
def _process_results(results_data, filename):
"""
beräknar wpm och noggrannhet, skriver ut resultaten och sparar poängen i filen.
# hämtar tiden som user använde hur länge testet tog
# hur många ord användaren skrev totalt
# hur många ord det fanns i originaltexten
# hur många ord användaren skrev korrekt (rätt stavade och på rätt plats)
# hur många extra ord användaren skrev utöver originaltexten
# en ordbok (dictionary) som visar vilka ord som var fel
# och hur många gånger varje ord blev fel
"""
time_used = results_data["time_used"]
typed_words_count = results_data["typed_word_count"]
total_words = results_data["total_words"]
correct_words = results_data["correct_words"]
extra_words = results_data["extra_words"]
wrong_word_histogram = results_data["wrong_word_histogram"]
print(f"\nTid det tog: {time_used:.2f} sekunder ({time_used / 60:.2f} minuter)")
minutes = time_used / 60 if time_used > 0 else 1
gross_wpm = typed_words_count / minutes
wrong_total = total_words - correct_words
net_wpm = gross_wpm - ((wrong_total + extra_words) / minutes)
net_wpm = max(net_wpm, 0)
accuracy = (net_wpm / gross_wpm) * 100 if gross_wpm > 0 else 0
animal = get_animal_category(net_wpm)
print("\n--- det totala resultatet ---")
final_accuracy = (correct_words - extra_words) / total_words * 100
print(f"ordprecision: {final_accuracy:.2f}%")
print("\nfelstavade ord:")
for wrong, count in wrong_word_histogram.items():
print(f"{wrong:<20}: {'#' * count}")
print(f"brutto wpm: {gross_wpm:.2f}")
print(f"netto wpm: {net_wpm:.2f}")
print(f"noggrannhet: {accuracy:.2f}%")
print(f"du skriver snabbt som en {animal}")
name = input("\nskriv in ditt namn: ")
level = filename.replace(".txt", "")
try:
with open(SCORES_FILE, "a", encoding="utf-8") as f:
f.write(f"{name},{final_accuracy:.2f},{level}\n")
except OSError:
print("kunde inte spara poängen: filåtkomst nekad.")
--------------------------------------------------------------------------------
def starting_test(filename):
"""
huvudfunktionen som hanterar hela skrivtestet: ladda text, tidtagning,
samla input och visa resultat.
"""
file_path = os.path.join(TEXTS_DIR, filename)
try:
with open(file_path, encoding="utf-8") as f:
text_lines = f.read().splitlines()
except FileNotFoundError:
print(f"filen hittades inte: {file_path}")
return
print("\n--- här är texten du ska skriva ---\n")
for line in text_lines:
print(line)
input("\ntryck enter när du är redo att börja skriva...")
start_time = time.time()
typed_text = input("\nbörja skriva här:\n")
end_time = time.time()
time_used = end_time - start_time
full_text = " ".join(text_lines)
typed_words = typed_text.split()
original_words = full_text.split()
total_words = len(original_words)
correct_words, extra_words, wrong_word_histogram = _compare_words(
typed_words, original_words
)
# data för resultat, tex hur lång tid user tod på sig osv..
results_data = {
"time_used": time_used,
"typed_word_count": len(typed_words),
"total_words": total_words,
"correct_words": correct_words,
"extra_words": extra_words,
"wrong_word_histogram": wrong_word_histogram,
}
_process_results(results_data, filename)
--------------------------------------------------------------------------------
def sorterings_nyckel(result_row):
"""
tar ut vilken nivå testet var på
tar ut noggrannheten i procent
tar ut spelarens namn
returnerar en sorteringsnyckel
"""
level = result_row[2]
precision = result_row[1]
name = result_row[0]
return (level, -precision, name)
--------------------------------------------------------------------------------
def show_scores():
"""
Försöker läsa in alla poäng från filen:
# 1. Skapar en tom lista
# 2. Öppnar poängfilen i läsläge
# 3. Läser in alla rader i listan 'lines'
# 4. Om filen inte finns, fel meddela och funktionen avslutas
"""
print("\n--- poänglista ---")
lines = []
try:
with open(SCORES_FILE, encoding="utf-8") as f:
lines = f.readlines()
except FileNotFoundError:
print("ingen poängfil hittades.")
return
results = [] # lista för att spara resultat
for line in lines: # looper varje rad i filen
parts = line.strip().split(",")
if len(parts) == EXPECTED_PARTS:
name = parts[0] # namn på spelaren
try:
precision = float(parts[1]) # försöker omvandla precision till ett tal
except ValueError:
precision = 0
level = parts[2]
results.append([name, precision, level])
results.sort(key=sorterings_nyckel)
print(f"{'namn':<15}{'precision (%)':<15}{'nivå'}")
print("-" * 40)
for r in results:
print(f"{r[0]:<15}{r[1]:<15.2f}{r[2]}")
main.py
from menu import show_menu, menu_choice
def main():
"""
Kör huvudloopen för programmet Typing.
"""
running = True
while running:
show_menu()
choice = input("Choose an option: ").strip().lower()
running = menu_choice(choice)
if __name__ == "__main__":
main()
menu.py
from functions import starting_test, show_scores
def show_menu():
print("\n=== Typing Test Menu ===")
print("1. Starta skrivtest `Easy txt`")
print("2. Starta skrivtest `Medium txt`")
print("3. Starta skrivtest `Hard txt`")
print("4. Skriv ut resultat som finns sparad i `scores.txt`")
print("q. Avsluta programmet")
def menu_choice(choice):
if choice == "1":
starting_test("easy.txt")
elif choice == "2":
starting_test("medium.txt")
elif choice == "3":
starting_test("hard.txt")
elif choice == "4":
show_scores()
elif choice == "q":
print("Avslutar programmet. Goodbye!")
return False
else:
print("Invalid choice. Please try again.")
return True