diff options
Diffstat (limited to '2020/aoc2020-d16.py')
| -rw-r--r-- | 2020/aoc2020-d16.py | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/2020/aoc2020-d16.py b/2020/aoc2020-d16.py new file mode 100644 index 0000000..86cd8eb --- /dev/null +++ b/2020/aoc2020-d16.py @@ -0,0 +1,71 @@ +#advent of code 2020 +#day 16 +#I spent a lot of time fixing its logic during solving +#so the code was cleaned thorougly after finishing +#which was a good idea because i was doing it directly after +#and still have to think for a minute what some lines are actually doing +#I think there's a way to skip looping over tickets for second time +#but it would make it unnecessarily convoluted +#I also tried making understandable variable names way too hard for a puzzle code +p1 = 0; +p2 = 1; +requirements = dict(); +NearbyTickets = []; +PuzzleInput = open("16.in","r").read().split("\n\n"); +#rules for ticket fields +for line in PuzzleInput[0].split("\n"): + FieldName, FieldValues = line.split(":"); + FieldValues = [ tuple([int(v) for v in fv.split("-")]) for fv in FieldValues.split(" or ")]; + requirements[FieldName] = FieldValues; +#your ticket +MyTicket = [int(val) for val in PuzzleInput[1].split("\n")[1].split(",")]; +#nearby tickets +for line in PuzzleInput[2].split("\n")[1:]: + if len(line) <= 1: continue; + NearbyTickets.append([int(val) for val in line.split(",")]); + +GoodTickets = []; +for ticket in NearbyTickets: + ValidTicket = True; + for TicketValue in ticket: + for FieldValues1, FieldValues2 in requirements.values(): + test1 = FieldValues1[0] <= TicketValue <= FieldValues1[1]; + test2 = FieldValues2[0] <= TicketValue <= FieldValues2[1]; + valid = test1 or test2; + if valid: break; + if not valid: + p1 += TicketValue; + ValidTicket = False; + if ValidTicket: GoodTickets.append(ticket); + +Fields = dict(); +InvalidFields = dict(); +#find for which fields the numbers in tickets are viable for +#store them in InvalidFields dict +for ticket in GoodTickets: + for ti, TicketValue in enumerate(ticket): + for FieldName in requirements: + if FieldName in Fields.values(): continue; + FieldValues1, FieldValues2 = requirements[FieldName]; + test1 = FieldValues1[0] <= TicketValue <= FieldValues1[1]; + test2 = FieldValues2[0] <= TicketValue <= FieldValues2[1]; + valid = test1 or test2; + if not valid: + if FieldName not in InvalidFields: InvalidFields[FieldName] = set(); + InvalidFields[FieldName].add(ti); + +#all fields have different number of possible places and its linear +#that is: field 1 has 19/20 possible assignments, field 2 has 18/20 etc. +#by sorting it from longest to shortest we make assign the fields in a single loop +#check which indexes are missing and skip the indexes that have their field assigned +for FieldName in sorted(InvalidFields, key = lambda f: len(InvalidFields[f]) , reverse=True): + FieldIndexes = [FieldIndex for FieldIndex in range(len(requirements)) if FieldIndex not in InvalidFields[FieldName]]; + FieldIndexes = [FieldIndex for FieldIndex in FieldIndexes if FieldIndex not in Fields]; #trim already assigned fields + Fields[FieldIndexes[0]] = FieldName; + +for key in Fields: + if "departure" in Fields[key]: p2 *= MyTicket[key]; + +print("part 1 =",p1); +print("part 2 =",p2); + |
