Skip to content

Instantly share code, notes, and snippets.

@neoeno
Last active April 7, 2024 11:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neoeno/feb340fbc61e566a68593de618c7168c to your computer and use it in GitHub Desktop.
Save neoeno/feb340fbc61e566a68593de618c7168c to your computer and use it in GitHub Desktop.
Jobhunter Simulation Script
# This isn't shared as an example of beautiful code or anything!
# It was a quick and dirty script I wrote to simulate how the
# job market might work for bootcamp grads given a few different
# assumptions.
# I'm sharing it so that you can open it up and plug in your own
# beliefs, either by changing the numbers or even adding new logic.
# Through this I hope you might test your own beliefs and their
# outcomes.
from dataclasses import dataclass
import random
@dataclass
class Candidate:
period: int
strength: float
original_strength: float
def __init__(self, period, strength):
self.period = period
self.strength = strength
self.original_strength = strength
def report(hired, given_up, remaining):
all_candidates = hired + given_up + remaining
# Go through the strength in intervals of 0.05
for i in range(20, 0, -1):
start = (i - 1) * 5
end = i * 5
total_candidates_in_interval = len([c for c in all_candidates if start <= c.original_strength < end])
if total_candidates_in_interval == 0:
continue
hired_pct = len([c for c in hired if start <= c.original_strength < end]) / total_candidates_in_interval * 100
given_up_pct = len([c for c in given_up if start <= c.original_strength < end]) / total_candidates_in_interval * 100
remaining_pct = len([c for c in remaining if start <= c.original_strength < end]) / total_candidates_in_interval * 100
print(f"Strength: {start}-{end}, Hired: {hired_pct:.2f}%, Given up: {given_up_pct:.2f}%, Remaining: {remaining_pct:.2f}%")
# This is the first graph I show in the video
def simulate_constrained_hires():
MONTHS_TO_SIMULATE = 120
CHANCE_OF_GIVING_UP_EACH_MONTH = 0.1
HIRES_MADE_PER_MONTH = 5
STUDENTS_GRADUATING_PER_MONTH = 25
jobhunters = []
all_hired = []
all_given_up = []
for month in range(MONTHS_TO_SIMULATE):
# Sort by strength
jobhunters.sort(key=lambda c: c.strength, reverse=True)
# Simulate hiring
hired = jobhunters[:HIRES_MADE_PER_MONTH]
all_hired += hired
jobhunters = jobhunters[HIRES_MADE_PER_MONTH:]
# Simulate giving up
given_up = []
for candidate in jobhunters:
if random.uniform(0, 1) < CHANCE_OF_GIVING_UP_EACH_MONTH:
given_up.append(candidate)
jobhunters = [candidate for candidate in jobhunters if candidate not in given_up]
all_given_up += given_up
# Simulate graduation
jobhunters += [Candidate(month, random.uniform(0, 100)) for _ in range(STUDENTS_GRADUATING_PER_MONTH)]
# Print results
print(f"Month {month} -> Graduated: {STUDENTS_GRADUATING_PER_MONTH}, Hired: {len(hired)}, Given up: {len(given_up)}, Remaining: {len(jobhunters)}")
return all_hired, all_given_up, jobhunters
# This is the last graph I show in the video
def simulate_constrained_hires_with_improvement():
MONTHS_TO_SIMULATE = 120
CHANCE_OF_GIVING_UP_EACH_MONTH = 0.1
HIRES_MADE_PER_MONTH = 5
STUDENTS_GRADUATING_PER_MONTH = 25
jobhunters = []
all_hired = []
all_given_up = []
for month in range(MONTHS_TO_SIMULATE):
# Sort by strength
jobhunters.sort(key=lambda c: c.strength, reverse=True)
# Simulate hiring
hired = jobhunters[:HIRES_MADE_PER_MONTH]
all_hired += hired
jobhunters = jobhunters[HIRES_MADE_PER_MONTH:]
# Simulate giving up
given_up = []
for candidate in jobhunters:
if random.uniform(0, 1) < CHANCE_OF_GIVING_UP_EACH_MONTH:
given_up.append(candidate)
jobhunters = [candidate for candidate in jobhunters if candidate not in given_up]
all_given_up += given_up
# Simulate improvement
for c in jobhunters:
c.strength += 5
# Simulate graduation
jobhunters += [Candidate(month, random.uniform(0, 100)) for _ in range(STUDENTS_GRADUATING_PER_MONTH)]
# Print results
print(f"Month {month} -> Graduated: {STUDENTS_GRADUATING_PER_MONTH}, Hired: {len(hired)}, Given up: {len(given_up)}, Remaining: {len(jobhunters)}")
return all_hired, all_given_up, jobhunters
# This is the middle graph I show in the video
def simulate_unconstrained_hires():
MONTHS_TO_SIMULATE = 120
CHANCE_OF_GIVING_UP_EACH_MONTH = 0.1
STUDENTS_GRADUATING_PER_MONTH = 25
CHANCE_OF_INTERVIEW = 0.25
jobhunters = []
all_hired = []
all_given_up = []
for month in range(MONTHS_TO_SIMULATE):
# Sort by strength
jobhunters.sort(key=lambda c: c.strength, reverse=True)
# Simulate hiring
for candidate in jobhunters:
if random.uniform(0, 1) > CHANCE_OF_INTERVIEW and candidate.strength > random.uniform(20, 120):
all_hired.append(candidate)
jobhunters = [candidate for candidate in jobhunters if candidate not in all_hired]
# Simulate giving up
given_up = []
for candidate in jobhunters:
if random.uniform(0, 1) < CHANCE_OF_GIVING_UP_EACH_MONTH:
given_up.append(candidate)
jobhunters = [candidate for candidate in jobhunters if candidate not in given_up]
all_given_up += given_up
# Simulate graduation
jobhunters += [Candidate(month, random.uniform(0, 100)) for _ in range(STUDENTS_GRADUATING_PER_MONTH)]
# Print results
print(f"Month {month} -> Graduated: {STUDENTS_GRADUATING_PER_MONTH}, Hired: {len(hired)}, Given up: {len(given_up)}, Remaining: {len(jobhunters)}")
return all_hired, all_given_up, jobhunters
# Uncomment one of these three depending on what simulation you want.
hired, given_up, remaining = simulate_constrained_hires()
# hired, given_up, remaining = simulate_constrained_hires_with_improvement()
# hired, given_up, remaining = simulate_unconstrained_hires()
report(hired, given_up, remaining)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment