importreadj={}visited={}withopen("Problem-7/Day 7: Handy Haversacks.txt")asfile:forlineinfile:# Every line in the input was in the format outerbags contain x innerbags, y innerbags, so on..
# So we can split every line into two parts using the word "contain " as separator.
# As split funtion returns a list, we now have outerbag name as first element and it's dependencies as second element. Unpacked them into two variables as shown below.
outer_bag,innerbags=line.split("contain ")# Now the outer_bag variable has outerbagname with suffix bags in it. We can just slice the string to remove the suffix
# Similarly, innerbags will now has a string in the format x innerbags, y innerbags, so on..
# We can extract the count and the innerbag name using regex and grouping as shown below
innerbags=re.findall(r"(\d{1,}) ([a-z ]+) bag|bags",innerbags)# visited list is useful when we are exploring the graph to avoid cycles. Initially we should mark every bag as not visited
visited[outer_bag[:-6]]=Falseifouter_bag[:-6]notinadj:adj[outer_bag[:-6]]={}# Adding edges from outer bag to each inner bag
forcount,bagininnerbags:ifcountandbag:ifbagnotinadj:adj[bag]={}adj[outer_bag[:-6]][bag]=int(count)# Now we have our adjacency list ready for our directed graph
defpart_one(adj,visited,bag_name):# dfs of a graph
defdfs(adj,visited,start,count):foredgeinadj[start].keys():ifnotvisited[edge]:visited[edge]=Truecount=dfs(adj,visited,edge,count+1)returncount# reverse the graph
adj_reverse={}forouter,innerinadj.items():ifouternotinadj_reverse:adj_reverse[outer]={}forkey,countininner.items():ifkeyinadj_reverse:adj_reverse[key][outer]=countelse:adj_reverse[key]={outer:count}# Now as the graph is reversed, we can find the vertices that previously had a directed edge towards the shiny gold bag now in new adjacency list at shiny gold vertex.
# Simply exploring and counting the number of vertices explored from shiny gold bag vertex will be the result
returndfs(adj_reverse,visited,bag_name,0)defpart_two(adj,start,count):ifnotadj[start]:return0temp=0foredge,cinadj[start].items():temp+=c+c*part_two(adj,edge,count)count+=tempreturncountprint("Part 1: Total number of bag colors that contain at least one shiny gold bag :",part_one(adj,visited,"shiny gold"))print("Part 2: Shiny gold bag contains total {} number of bags".format(part_two(adj,"shiny gold",0)))
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Discussion on: Advent of Code 2020 Solution Megathread - Day 7: Handy Haversacks
For further actions, you may consider blocking this person and/or reporting abuse