I am wondering if I did correctly. The "Print to screen if show = True", is confusing me a bit on how to implement into my code so the rest of my functions will work properly.
# Display results of scenario
def display_flow(show, # print to screen if show = True`
scen_year,
age,
s_bal,
bal_pv,
inv_gains,
ann_savings,
ss_payment,
major_inc,
major_exp,
tax_rate,
tar_ret_spend,
net_ret_spend,
ret_pre_tax_spend,
taxes,
end_bal
):
""" display_flow() test output
>>> display_flow(show = True,
... scen_year = 0,
... age = 60,
... s_bal = 100000,
... bal_pv = 100000,
... inv_gains = 1000,
... ann_savings = 1000,
... ss_payment = 1000,
... major_inc = 1000,
... major_exp = 1000,
... tax_rate = 0.15,
... tar_ret_spend = 50000,
... net_ret_spend = 40000,
... ret_pre_tax_spend = 60000,
... taxes = 10000,
... end_bal = 120000
... )
Year : 0
Age : 60
Start Bal : 100,000.00
Start Bal PV : 100,000.00
Invest Gains : 1,000.00
Ann Savings : 1,000.00
SS Payment : 1,000.00
Major Inc : 1,000.00
Major Exp : 1,000.00
Tax Rate : 15.00%
Targ Ret Spend : 50,000.00
Net Ret Spend : 40,000.00
Ret Pre-tax Spend: 60,000.00
Taxes : 10,000.00
End Bal : 120,000.00
"""
#==============================================================================================
print(' Year :' , scen_year,
'\n Age :',age,
'\n Start Bal :', (format(s_bal, ',.2f')),
'\n Start Bal PV :', (format(bal_pv, ',.2f')),
'\n Invest Gains :', (format(inv_gains, ',.2f')),
'\n Ann Savings :', (format(ann_savings,',.2f')),
'\n SS Payment :', (format(ss_payment, ',.2f')),
'\n Major Inc :', (format(major_inc, ',.2f')),
'\n Major Exp :', (format(major_exp, ',.2f')),
'\n Tax Rate :', (format(tax_rate, '.2%')),
'\n Targ Ret Spend :', (format(tar_ret_spend, ',.2f')),
'\n Net Ret Spend :', (format(net_ret_spend, ',.2f')),
'\n Ret Pre-tax Spend :', (format(ret_pre_tax_spend, ',.2f')),
'\n Taxes :', (format(taxes, ',.2f')),
'\n End Bal :', (format(end_bal, ',.2f')))
#==============================================================================================
# test function
display_flow(show = True,
scen_year = 0,
age = 60,
s_bal = 100000,
bal_pv = 100000,
inv_gains = 1000,
ann_savings = 1000,
ss_payment = 1000,
major_inc = 1000,
major_exp = 1000,
tax_rate = 0.15,
tar_ret_spend = 50000,
net_ret_spend = 40000,
ret_pre_tax_spend = 60000,
taxes = 10000,
end_bal = 120000
)
The output I receive is exactly what i need. But basically wondering if I need the if show=True. My code is in between the long comment sections of "===".
Everything below it and above it are ways to test my code and parameters I need.
Apologies if made any mistakes on this post, this is my first time posting here asking for help. :(
You do not need show if you always want to print.
If you want to have the option of show then you need an conditional, if else, in your code
If show:
print()
I assume you already know using a print will return a string and not the dictionary you have created. If you need it as dict wrap it in {} and use a return instead of print if you need it like a dictionary
Related
So I'm very new to Python programming and just testing out some stuff in classes and methods.
Im writing a program for a restaurant that have 4 dictionaries that contains key=food and value=price
The dict's are stored in brunch_items, early_bird_items, dinner_items and kids_items, and then I created a object for each of them to my Menu class.
from main import *
dinner_items = {
'crostini with eggplant caponata': 13.00,
'caesar salad': 16.00,
'pizza with quattro formaggi': 11.00,
'duck ragu': 19.50,
'mushroom ravioli (vegan)': 13.50, 'coffee': 2.00, 'espresso': 3.00,
}
kids_items = {
'chicken nuggets': 6.50,
'fusilli with wild mushrooms': 12.00,
'apple juice': 3.00
}
brunch_menu = Menu("Brunch Menu", brunch_items, 1100, 1600)
early_bird_menu = Menu("Early Bird Menu", early_bird_items, 1500, 1800)
dinner_menu = Menu("Dinner Menu", dinner_items, 1700, 1100)
kids_menu = Menu("Kids Menu", kids_items, 1100, 2100)
print(brunch_menu.calculate_bill(["pancakes", "waffles"]))
In the Menu class have the method that returns the different menus and when they are available.
The next method is calculating the bill and return the price for the items.
Output from printing the bill: 16.5
class Menu:
def __init__(self, name, items, start_time, end_time):
self.name = name
self.items = items
self.start_time = start_time
self.end_time = end_time
self.daily_income = 0
def __repr__(self):
return "{} is available from {} - {}".format(self.name, self.start_time, self.end_time)
def calculate_bill(self, purchased_items):
bill = 0
for purchased_item in purchased_items:
if (purchased_item in self.items):
bill += self.items[purchased_item]
return bill
def total_income(self, purchased_items):
return self.daily_income + purchased_items
I dont know where this is going, but the problem is to define a method that takes the calculated bill and store it to a daily income/profit from the purchased items. The idea is to store the total sum from bills
I tried to make self.daily_income = 0 and eventually return that to a variable that keep tracking the payments
Any suggestions to help out?
There are some modeling choices that you have made that I think you will want to revisit, but with light changes to your code you can get a running total by moving daily_income from an instance variable to a shared variable.
class Menu:
daily_income = 0 # shared between all instances
def __init__(self, name, items, start_time, end_time):
self.name = name
self.items = items
self.start_time = start_time
self.end_time = end_time
def __repr__(self):
return "{} is available from {} - {}".format(self.name, self.start_time, self.end_time)
def calculate_bill(self, purchased_items):
bill = 0
for purchased_item in purchased_items:
if (purchased_item in self.items):
bill += self.items[purchased_item]
Menu.daily_income + bill ## Update the shared total
return bill
dinner_items = {
'crostini with eggplant caponata': 13.00,
'caesar salad': 16.00,
'pizza with quattro formaggi': 11.00,
'duck ragu': 19.50,
'mushroom ravioli (vegan)': 13.50, 'coffee': 2.00, 'espresso': 3.00,
}
kids_items = {
'chicken nuggets': 6.50,
'fusilli with wild mushrooms': 12.00,
'apple juice': 3.00
}
## ---------------------------
## Simulate table A
## ---------------------------
my_bill = Menu("Dinner Menu", dinner_items, 1700, 1100).calculate_bill(["caesar salad", "duck ragu"])
my_bill += Menu("Kids Menu", kids_items, 1100, 2100).calculate_bill(["chicken nuggets"])
Menu.daily_income += my_bill
print(f"Total Table Bill: ${my_bill}. Our revenue so far: ${Menu.daily_income}")
## ---------------------------
## ---------------------------
## Simulate table B
## ---------------------------
my_bill = Menu("Dinner Menu", dinner_items, 1700, 1100).calculate_bill(["pizza with quattro formaggi"])
Menu.daily_income += my_bill
print(f"Total Table Bill: ${my_bill}. Our revenue so far: ${Menu.daily_income}")
## ---------------------------
That should give you:
Total Table Bill: $42.0. Our revenue so far: $42.0
Total Table Bill: $11.0. Our revenue so far: $53.0
Here is my code (it is kind of long and could probably be simplified)
hours = float(input("Enter the number of hours worked in a week:"))
dep = float(input("Enter the number of dependents you have:"))
rate = 16.68
ovrate = 25.02
if hours<=40:
gross = "{:.2f}".format(float(hours * rate))
else:
gross = "{:.2f}".format(float((40*rate)+((hours-40)*ovrate)))
gross2 = float(gross)
print("Gross pay: $",gross)
ss = "{:.2f}".format(gross2*.06)
print("Social Security tax: $",ss)
federal = "{:.2f}".format(gross2*0.14)
print("Federal income tax: $",federal)
state = "{:.2f}".format(gross2*0.5)
print("State income tax: $",state)
union=10
print("Union dues: $10.00")
unionString=str(union)
if dep>=3:
family = 35
print("Family health insurance: $35.00 (additional insurance premiums for your family)")
else:
family = 0
familyString = str(family)
netDed = ss+federal+state+unionString+familyString
netDedFloat = float(netDed)
netDed2 = "{:.2f}".format(netDedFloat)
print("Total deductions: $",netDed2)
netPay = gross2-netDed
print("Net pay: $",netPay)
When I run it, I get the following message:
Traceback (most recent call last):
File "main.py", line 39, in <module>
netDedFloat = float(netDed)
ValueError: could not convert string to float: '52.04121.43433.681035'
I have tried everything I have read online. I get a different error every time. Please help me understand this error and how to solve it.
Edit:
'52.04121.43433.681035' is because I entered 48 for hours and 4 for dependents. This number varies depending on the inputs. This is the complete output for this scenario.
Enter the number of hours worked in a week:48
Enter the number of dependents you have:4
Gross pay: $ 867.36
Social Security tax: $ 52.04
Federal income tax: $ 121.43
State income tax: $ 433.68
Union dues: $10.00
Family health insurance: $35.00 (additional insurance premiums for your family)
Traceback (most recent call last):
File "main.py", line 39, in <module>
netDedFloat = float(netDed)
ValueError: could not convert string to float: '52.04121.43433.681035'
I am a beginner, so please forgive me if I ask you to elaborate.
Your code gives an error because in this line
netDed = ss+federal+state+unionString+familyString every variable is a string and you try to add string to string.('123.0'+'12'='123.012')
You need to convert these values to float.I am comment where I change the code.
hours = float(input("Enter the number of hours worked in a week:"))
dep = float(input("Enter the number of dependents you have:"))
rate = 16.68
ovrate = 25.02
if hours<=40:
gross = "{:.2f}".format(float(hours * rate))
else:
gross = "{:.2f}".format(float((40*rate)+((hours-40)*ovrate)))
gross2 = float(gross)
print("Gross pay: $",gross)
ss = float("{:.2f}".format(gross2*.06)) # Converting in to float
print("Social Security tax: $",ss)
federal = float("{:.2f}".format(gross2*0.14)) # Converting in to float
print("Federal income tax: $",federal)
state = float("{:.2f}".format(gross2*0.5)) # Converting in to float
print("State income tax: $",state)
union=10
print("Union dues: $10.00")
unionString=float(union) # Converting in to float
if dep>=3:
family = 35
print("Family health insurance: $35.00 (additional insurance premiums for your family)")
else:
family = 0
familyString = float(family) # Converting in to float
netDed = ss+federal+state+unionString+familyString
netDedFloat = float(netDed)
netDed2 = "{:.2f}".format(netDedFloat)
print("Total deductions: $",netDed2)
netPay = gross2-netDed
print("Net pay: $",netPay)
The problem here is that ss, federal, state, unionString and familyString are all strings. When you add strings, you concatenate them, you don't add their numerical values.
What you need to do is keep those things as floats. You can use format when you print them, but don't keep the string values.
hours = float(input("Enter the number of hours worked in a week:"))
dep = float(input("Enter the number of dependents you have:"))
rate = 16.68
ovrate = 25.02
if hours<=40:
gross2 = hours * rate
else:
gross2 = 40*rate + (hours-40)*ovrate
print("Gross pay: ${:.2f}".format(gross2))
ss = gross2*.06
print("Social Security tax: ${:.2f}".format(ss))
federal = gross2*0.14
print("Federal income tax: ${:.2f}".format(federal))
state = gross2*0.5
print("State income tax: ${:.2f}".format(state))
union=10
print("Union dues: $10.00")
if dep>=3:
family = 35
print("Family health insurance: $35.00 (additional insurance premiums for your family)")
else:
family = 0
netDed = ss+federal+state+union+family
print("Total deductions: ${:.2f}".format(netDed))
netPay = gross2-netDed
print("Net pay: $",netPay)
Output:
C:\tmp>python x.py
Enter the number of hours worked in a week:123
Enter the number of dependents you have:34
Gross pay: $2743.86
Social Security tax: $164.63
Federal income tax: $384.14
State income tax: $1371.93
Union dues: $10.00
Family health insurance: $35.00 (additional insurance premiums for your family)
Total deductions: $1965.70
Net pay: $ 778.1579999999999
So i have a list that contains an object, but I wanted to do a searching algorithm with it, meaning that if the word is similar, it will show the items with the similar category. But there was an error.
code:
print("\nHere are the results of your search")
if param == 'Electric Guitar':
results = inventory[item_006:item_010]
Objects:
class Product:
def __init__(self, hproduct, htype, hprice, havail):
self.name = hproduct
self.type = htype
self.price = hprice
self.avail = havail
def __eq__(self,other):
return self.type == other
item_001 = Product('Tyma TD-10E Dreadnought', 'Acoustic Guitar', 23450, 'In Stock')
item_002 = Product('Baton Rouge AR21C/ME Traveler', 'Acoustic Guitar', 14900, 'In Stock')
item_003 = Product('Phoebus Baby 30 GS Mini', 'Acoustic Guitar', 6900, 'In Stock')
item_004 = Product('Maestro Project X X1-V1 OM', 'Acoustic Guitar', 32500, 'In Stock')
item_005 = Product('Sire A4 Grand Auditorium', 'Acoustic Guitar', 27490, 'In Stock')
item_006 = Product('Tagima TW55', 'Electric Guitar', 9500, 'In Stock')
item_007 = Product('Epiphone G400 ', 'Electric Guitar', 19500, 'In Stock')
item_008 = Product('D’Angelico Premiere DC', 'Electric Guitar', 49000, 'In Stock')
item_009 = Product('PRS Silver Sky', 'Electric Guitar', 138950, 'In Stock')
item_010 = Product('Vintage V100 Reissued', 'Electric Guitar', 27950, 'In Stock')
item_011 = Product('Phoebus Buddie 30 GS-E', 'Bass Guitar', 8720, 'In Stock')
item_012 = Product('Sire U5', 'Bass Guitar', 27490, 'In Stock')
item_013 = Product('Lakland Skyline Vintage J', 'Bass Guitar', 82950, 'In Stock')
item_014 = Product('Schecter Model T Session 5', 'Bass Guitar', 45900, 'In Stock')
item_015 = Product('Tagima Millenium Coda 4', 'Bass Guitar', 14900, 'In Stock')
item_016 = Product('Boss Katana 50 Mk II ', 'Accessory', 15950, 'In Stock')
item_017 = Product('TC Electronic BH250 Micro Bass', 'Accessory', 18990, 'In Stock')
item_018 = Product('Kemper Profiler Powerhead', 'Accessory', 130000, 'In Stock')
item_019 = Product('Headrush Pedal Board', 'Accessory', 27490, 'In Stock')
item_020 = Product('NUX MG30', 'Accessory', 12900, 'In Stock')
inventory = [item_001, item_002, item_003, item_004, item_005, item_006, item_007, item_008, item_009, item_010, item_011, item_012, item_013, item_014, item_015, item_016, item_017, item_018, item_019, item_020]
desired output:
Tagima TW55 Electric Guitar 9500 In Stock
Epiphone G400 Electric Guitar 19500 In Stock
D’Angelico Premiere DC Electric Guitar 49000 In Stock
PRS Silver Sky Electric Guitar 138950 In Stock
Vintage V100 Reissued Electric Guitar 27950 In Stock
error:
slice indices must be integers or None or have an __index__ method
Thank you for any tips and help.
Since you need to match all the object with the type equal to the parameter, you can do something more dynamic than hardcoding the positions of the results:
results = [obj for obj in inventory if obj.type == param]
slice indices must be integers or None or have an __index__ method
This mean you should implement __index__ magic method in your object. __index__ needs to return integer, in your case with position in list. Consider following simple example
class Thing:
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Thing("' + self.name + '")'
def __index__(self):
return inventory.index(self)
uno = Thing("uno")
dos = Thing("dos")
tres = Thing("tres")
inventory = [uno,dos,tres]
print(inventory[:dos])
print(inventory[dos:])
print(inventory[dos:tres])
output
[Thing("uno")]
[Thing("dos"), Thing("tres")]
[Thing("dos")]
Disclaimer: this solution assume all your object are hold in exactly one list.
The reason for this behavior is you are slicing a list using objects item_006 and item_010 in inventory[item_006:item_010], while slice works with indexes as mentioned below
[start : stop : steps]
which means that slicing will start from index start will go up to
stop in step of steps. Default value of start is 0, stop is last
index of list and for step it is 1
To get the desired ouput just do this:
param = "Electric Guitar"
results = [item for item in inventory if item.type == param]
print (results)
The most direct fix to what you've done is this.
results = inventory[5:10]
You have to give slices integers as indices, not Products.
However, in your case, it might be better simply to find the products with a type of "Electric Guitar":
results = [p for p in inventory if p.type == "Electric Guitar"]
If your full code ends up looking like
if param == "Electric Guitar":
results = [p for p in inventory if p.type == "Electric Guitar"]
elif param == "Acoustic Guitar":
results = [p for p in inventory if p.type == "Acoustic Guitar"]
...
then you can simplify it to just:
if param in {"Electric Guitar", "Acoustic Guitar", ...}:
results = [p for p in inventory if p.type == param]
I am trying to order my csvfile of food items by time whenever a new item is added. I have found a solution which I really like in which each time is compared against each other. My only issue is that I am unsure as to what variable/data structure I should place into the position marked with times.
What should happen is that the new row is added to the 2D list myRows, and then the contents of myRows is sorted based on time. The order should be earliest at the start, latest at the end.
myRows = []
with open("dataset.txt") as csvfile:
reader = csv.reader(csvfile)
for row in reader:
myRows.append(row)
newRow = [time, myType, desc, serving, kcal, sfat]
myRows.append(newRow)
myRows = sorted(times, key=cmp_to_key(compareTimes))
Compare Times Function
def compareTimes(timeStr1,timeStr2):
#Convert the time Strings passed into function into time objects
time1 = time.strptime(timeStr1, timeFormat)
time2 = time.strptime(timeStr2, timeFormat)
if time1 < time2:
return -1
elif time > time2:
return 1
else:
#If times are the same
return 0
Dataset.txt
22:30, Snack, Cereal, 200, 210,1.6
08:11, Breakfast, Cereal, 200, 210,1.6
08:20, Breakfast, Coffee, 200, 20,0.4
08:20, Breakfast, Pancake, 38, 74,1.4
10:30, Snack, Chocolate, 10, 56,2.5
I have tried myRows[0],myRows etc however this has not worked.
You have to use myRows as argument in sorted()
myRows = sorted(myRows ...)
But to sort strings like 22:30 with 08:11 you don't need function which convert strings to datetime because you can compare "22:30" < "08:11". So you can use
myRows = sorted(myRows, key=lambda x:x[0])
text = '''22:30, Snack, Cereal, 200, 210,1.6
08:11, Breakfast, Cereal, 200, 210,1.6
08:20, Breakfast, Coffee, 200, 20,0.4
08:20, Breakfast, Pancake, 38, 74,1.4
10:30, Snack, Chocolate, 10, 56,2.5'''
import csv
import io
myRows = []
#with open("dataset.txt") as csvfile:
with io.StringIO(text) as csvfile:
reader = csv.reader(csvfile)
for row in reader:
myRows.append(row)
#newRow = [time, myType, desc, serving, kcal, sfat]
#myRows.append(newRow)
myRows = sorted(myRows, key=lambda x:x[0])
for row in myRows:
print(row)
Result
['08:11', ' Breakfast', ' Cereal', ' 200', ' 210', '1.6']
['08:20', ' Breakfast', ' Coffee', ' 200', ' 20', '0.4']
['08:20', ' Breakfast', ' Pancake', ' 38', ' 74', '1.4']
['10:30', ' Snack', ' Chocolate', ' 10', ' 56', '2.5']
['22:30', ' Snack', ' Cereal', ' 200', ' 210', '1.6']
EDIT: The same with pandas is much shorter
text = '''22:30, Snack, Cereal, 200, 210,1.6
08:11, Breakfast, Cereal, 200, 210,1.6
08:20, Breakfast, Coffee, 200, 20,0.4
08:20, Breakfast, Pancake, 38, 74,1.4
10:30, Snack, Chocolate, 10, 56,2.5'''
import pandas as pd
import io
#myRows = pd.read_csv("dataset.txt", sep=', ', names=['time', 'myType', 'desc', 'serving', 'kcal', 'sfat'])
myRows = pd.read_csv(io.StringIO(text), sep=', ', names=['time', 'myType', 'desc', 'serving', 'kcal', 'sfat'])
myRows = myRows.sort_values('time')
print(myRows)
EDIT: version with function
text = '''22:30, Snack, Cereal, 200, 210,1.6
08:11, Breakfast, Cereal, 200, 210,1.6
08:20, Breakfast, Coffee, 200, 20,0.4
08:20, Breakfast, Pancake, 38, 74,1.4
10:30, Snack, Chocolate, 10, 56,2.5'''
import csv
from functools import cmp_to_key
import time
import io
def compare_times(row1, row2): # 'lower_case_names' for functions
#time1 = time.strptime(row1[0], '%H:%M') # converting to time object
#time2 = time.strptime(row2[0], '%H:%M') # converting to time object
time1 = row1[0] # without converting to time object
time2 = row2[0] # without converting to time object
if time1 < time2:
return -1
elif time1 > time2:
return 1
else:
return 0
myRows = []
#with open("dataset.txt") as csvfile:
with io.StringIO(text) as csvfile:
reader = csv.reader(csvfile)
for row in reader:
myRows.append(row)
#newRow = [time, myType, desc, serving, kcal, sfat]
#myRows.append(newRow)
myRows = sorted(myRows, key=cmp_to_key(compare_times))
for row in myRows:
print(row)
I am trying to get the first_name and last_name to combine together into a new dictionary entry. How many depends on how many people buy in the shop. If I buy 50 troops I always receive less than that.
import random, math
first_name = [ "Emily", "Steve" , "Dave" , "Bob" , "James" , "Jim" , "Jenny" , "Will" , "Ryan" ]
last_name = [ "Wright" , "Kalman" , "Meitzen" , "Cole" , "Robins" , "Harrison" , "Saturn" ]
troops = {}
money = 1000
def shop():
loop = 0
global money, first_name, last_name, troops
while loop == 0 :
print("""
Your Money = {}
(Number , Item , cost)
0, Quit ,N/A
1, Troop, 10
""".format(money))
shopq = int( input("What do you want to buy"))
if shopq == 1:
shopq2 = int( input("How many"))
if shopq2 > money :
print(" You cannot by this many")
else:
print("You can buy that many")
money = money - shopq2
troop_number = 0
while troop_number < shopq2 :
s_name = random.choice(first_name) + " " + random.choice(last_name)
troops[s_name] = 100
troop_number = troop_number + 1
print(troops)
print(" Money = {}".format(money))
elif shopq == 0:
break
class dropship:
def create(self, troops):
troop_number = 0
for k in troops :
troop_number = troop_number + 1
print("troops = {}".format(troop_number))
shop()
x = dropship()
x.create(troops)
Output:
Your Money = 1000
(Number , Item , cost)
0, Quit ,N/A
1, Troop, 10
What do you want to buy1
How many50
You can buy that many
{'Ryan Wright': 100, 'Bob Cole': 100, 'Bob Kalman': 100, 'Will Wright': 100, 'Dave Cole': 100, 'Dave Robins': 100, 'Emily Kalman': 100, 'Jenny Kalman': 100, 'Bob Harrison': 100, 'Emily Wright': 100, 'Will Cole': 100, 'Jim Wright': 100, 'Dave Kalman': 100, 'Dave Wright': 100, 'Bob Meitzen': 100, 'Jenny Wright': 100, 'Jenny Harrison': 100, 'Dave Saturn': 100, 'James Robins': 100, 'Bob Robins': 100, 'Dave Meitzen': 100, 'Steve Wright': 100, 'Bob Wright': 100, 'Steve Kalman': 100, 'Ryan Harrison': 100, 'Jim Saturn': 100, 'Steve Robins': 100, 'Ryan Cole': 100, 'Jim Meitzen': 100, 'James Cole': 100, 'Emily Cole': 100, 'Ryan Saturn': 100, 'Steve Harrison': 100}
Money = 950
Your Money = 950
(Number , Item , cost)
0, Quit ,N/A
1, Troop, 10
What do you want to buy0
troops = 33
You are creating random names and some of them will be the same, by chance, so they replace the previous entries in the dictionary (dictionary keys are unique). You'll have to change the way you do that. For instance:
import random
import itertools
random.sample(list(itertools.product(first_name, last_name)), 50)
But you should also get much larger pools of first and last names, otherwise you can only have 63 different full names.
The problem with your dictionary is that dictionary keys must be unique. Since you are using randomly chosen names spliced together as keys, it is very likely that you will generate 'Ryan Wright' (for example) more than once.
Here is what your code is doing that is causing you to come up with a "short" count:
troops['Ryan Wright'] = 100
troops['Bob Cole'] = 100
troops['Ryan Wright'] = 100
The third assignment used the same slot in the dictionary troops because the key is the same. If your code was just those three lines you'd have a dictionary with two entries in it, not the three that you'd hope for. You can see this happen in your code by adding the assert statement:
s_name = random.choice(first_name) + " " + random.choice(last_name)
assert s_name not in troops
troops[s_name] = 100
It won't fix your problem, but it will show you that your keys are colliding.