I'm doing a past-year lab test in preparation for my upcoming test and I came across this question that took me a while to solve.
It asks the programmer to create a function, trace_contacts(), that takes in 2 parameters (patient, history), and outputs a list of people who may have been infected (either directly or indirectly from the initial patient).
patient - Contains a name in string format
history - Contains a list of recent interactions
patient = "Jason" history = [ ("Jason", "Gideon", -3), ("Zac", "Yacob", -3), ("Gideon", "Brian", -1), ("Cindy", "Gideon", -2), ("Darren", "Jason", -5), ("Jason", "Vivian", -6) ]
The history list is a list of tuples. Each tuple has 3 sets of values, the first 2 strings contain the names of the 2 people who met. The 3rd index repesents the day they met (in relation to the day the initial patient was diagnosed, which is day 0). See below for a hopefully clearer visualization haha.
|catches the virus||not yet infectious||infectious period||develops symptoms & stops meeting people|
|-7 (7 days before Day 0)||-6||-5 to -1||Day 0|
The trace_contacts() function should first check the history for any interactions with the initial patient during his infectious period. It should ignore any meeting before the infectious period.
It should then check, of those who met the patient during his infectious period, if they had met anyone else during their infectious period (2-6 days after their first interection with the initial patient). Again, interactions 0-1 days after them meeting the initial infected should be ignored (because they are not yet infectious).
The function should then keep looping, to check for the next layer of indirect cases. And only stop and output the list, of people at risk, when there are no more indirect interactions.
- There should be no duplicate names in the output list.
- The names in each tuple within history can be in any order. The function should be able to find risky interactions no matter where the infected patient is in the tuple.
- The code should be able to be written within 15-20mins (average time/qn in my lab test haha)
The code I've written is as follows: Just wondering if anyone has any, more efficient way to write code for this question? Thanks in advance!
def trace_contacts(patient, history): caught_virus_list =  for meet in history: per_details =  if (patient in meet) and (meet>-6): if meet == patient: per_details.append(meet) elif meet == patient: per_details.append(meet) per_details.append(meet) caught_virus_list.append(per_details) store_list = caught_virus_list[:] first_round = True while store_list != caught_virus_list or first_round: first_round = False store_list = caught_virus_list[:] #sort earliest meet date caught_virus_list.sort() prev_pax = "" sorted_caught_virus_list =  for pax in caught_virus_list: if pax != prev_pax: sorted_caught_virus_list.append(pax) else: continue prev_pax = pax caught_virus_list = sorted_caught_virus_list infect_names = [pax for pax in caught_virus_list] infect_date = [(pax+2) for pax in caught_virus_list] infect_names.insert(0,patient) infect_date.insert(0,-5) for meet in history: output_details =  name1 = meet name2 = meet date = meet if (name1 in infect_names) and (name2 not in infect_names): date_idx = infect_names.index(name1) if date >= infect_date[date_idx]: output_details.append(name2) output_details.append(date) caught_virus_list.append(output_details) elif (name2 in infect_names) and (name1 not in infect_names): date_idx = infect_names.index(name2) if date >= infect_date[date_idx]: output_details.append(name1) output_details.append(date) caught_virus_list.append(output_details) infect_names.pop(0) return infect_names