Day 4

Part 1

  • Read in input file containing a list of section assignment pairs
with open("day4/input.txt") as f:
    input = f.read().splitlines()

First 100 lines of input looks like this:

['28-88,85-88',
 '9-70,18-18',
 '76-90,53-89',
 '17-86,11-17',
 '8-8,8-82',
 '16-85,15-95',
 '20-76,19-20',
 '56-57,57-66',
 '95-99,1-96',
 '14-17,17-67',
 '95-99,32-98',
 '30-99,29-98',
 '12-95,11-94',
 '3-82,1-72',
 '4-88,88-88',
 '2-10,11-59',
 '8-16,8-16',
 '22-95,23-94',
 '46-51,78-99',
 '61-99,62-94',
 '30-72,26-73',
 '6-93,2-92',
 '16-93,17-96',
 '1-99,2-88',
 '23-89,88-93',
 '30-73,3-73',
 '9-75,75-76',
 '75-97,70-99',
 '4-23,22-23',
 '5-94,4-4',
 '16-48,15-22',
 '10-62,61-97',
 '34-82,81-87',
 '16-98,15-99',
 '16-22,17-22',
 '20-40,21-58',
 '67-86,22-87',
 '6-73,6-33',
 '27-73,40-55',
 '57-98,58-97',
 '94-95,14-80',
 '16-90,91-91',
 '2-89,5-89',
 '17-95,96-96',
 '46-48,19-47',
 '50-59,51-60',
 '45-98,44-97',
 '99-99,6-97',
 '3-29,1-29',
 '26-48,25-49',
 '10-17,19-57',
 '28-57,28-56',
 '79-96,80-97',
 '5-78,4-25',
 '35-84,35-84',
 '24-99,20-98',
 '80-80,53-79',
 '88-97,12-88',
 '9-20,9-72',
 '75-78,35-54',
 '11-29,28-91',
 '48-74,49-75',
 '56-56,56-98',
 '41-69,33-42',
 '6-40,6-40',
 '49-80,49-79',
 '12-29,18-70',
 '19-20,13-80',
 '96-96,15-95',
 '5-99,4-4',
 '47-47,41-46',
 '53-82,65-85',
 '88-90,89-90',
 '12-12,12-88',
 '52-68,51-67',
 '1-80,2-81',
 '75-81,70-76',
 '35-58,35-57',
 '19-91,18-19',
 '18-73,72-74',
 '9-13,8-10',
 '5-40,35-37',
 '43-71,70-71',
 '24-24,25-43',
 '60-92,35-60',
 '43-52,47-53',
 '8-97,97-99',
 '57-89,57-89',
 '69-70,31-69',
 '48-49,48-79',
 '5-13,14-97',
 '9-95,9-83',
 '80-80,79-83',
 '30-77,29-78',
 '67-75,67-76',
 '20-67,21-87',
 '22-99,74-99',
 '12-12,11-96',
 '26-61,25-67',
 '19-48,47-91']
samples = """2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8""".splitlines()
  • Create a function to get the range given an assignment

get_range

 get_range (assgn:str)

Return a range object covering the range assignment

Type Details
assgn str a range of sections split by a dash(-)
Returns range
print(get_range("2-4"))
print(get_range("6-8"))
print(get_range("6-6"))
range(2, 4)
range(6, 8)
range(6, 6)
  • Create a function to create a pair of ranges, one for each pair of elves

get_assign_ranges

 get_assign_ranges (sample:str)

Return a list of range assignments, one each for a pair of elves

Type Details
sample str a set of assignments for a pair of elves
Returns list
print(get_assign_ranges(samples[0]))
print(get_assign_ranges(samples[1]))
print(get_assign_ranges(samples[2]))
print(get_assign_ranges(samples[3]))
print(get_assign_ranges(samples[4]))
[range(2, 4), range(6, 8)]
[range(2, 3), range(4, 5)]
[range(5, 7), range(7, 9)]
[range(2, 8), range(3, 7)]
[range(6, 6), range(4, 6)]
  • Create a function to check if one range contains the other

contains

 contains (r1:range, r2:range)

Returns whether the first range contains the other range

Type Details
r1 range a range to check
r2 range the range it contains or not
Returns bool
print(samples[0],contains(*get_assign_ranges(samples[0])))
print(samples[1],contains(*get_assign_ranges(samples[1])))
print(samples[2],contains(*get_assign_ranges(samples[2])))
print(samples[3],contains(*get_assign_ranges(samples[3])))
print(samples[4],contains(*get_assign_ranges(samples[4])))
2-4,6-8 False
2-3,4-5 False
5-7,7-9 False
2-8,3-7 True
6-6,4-6 False
  • Create a function that checks if either range contains the other

contains_each_other

 contains_each_other (r1:range, r2:range)

Returns whether the either range contains the other

Type Details
r1 range a range to check
r2 range another range
Returns bool
print(samples[0],contains_each_other(*get_assign_ranges(samples[0])))
print(samples[1],contains_each_other(*get_assign_ranges(samples[1])))
print(samples[2],contains_each_other(*get_assign_ranges(samples[2])))
print(samples[3],contains_each_other(*get_assign_ranges(samples[3])))
print(samples[4],contains_each_other(*get_assign_ranges(samples[4])))
2-4,6-8 False
2-3,4-5 False
5-7,7-9 False
2-8,3-7 True
6-6,4-6 True
  • Create a function that returns all the overlapping samples given a list of samples

get_overlapping

 get_overlapping (samples:list[str])

Return a list of overlapping pairs of ranges

Type Details
samples list a list of section assignments for a pair of elves
Returns list
print(get_overlapping(samples))
[[range(2, 8), range(3, 7)], [range(6, 6), range(4, 6)]]
  • Finally the answer for the count of overlapping assignments

Click on the Answer tab to view the answer

overlapping = get_overlapping(input)
print(f'the correct answer for part 1 is {len(overlapping)}')
the correct answer for part 1 is 513

Part 2

  • Create a function to check if one range partially contains the other

partly_contains

 partly_contains (r1:range, r2:range)

Returns whether the first range partially contains the other range

Type Details
r1 range a range to check
r2 range the range it contains or not
Returns bool
print(samples[0],partly_contains(*get_assign_ranges(samples[0])))
print(samples[1],partly_contains(*get_assign_ranges(samples[1])))
print(samples[2],partly_contains(*get_assign_ranges(samples[2])))
print(samples[3],partly_contains(*get_assign_ranges(samples[3])))
print(samples[4],partly_contains(*get_assign_ranges(samples[4])))
2-4,6-8 False
2-3,4-5 False
5-7,7-9 True
2-8,3-7 True
6-6,4-6 True
  • Create a function that checks if either range partially or fully contains the other

partly_or_fully_contains_each_other

 partly_or_fully_contains_each_other (r1:range, r2:range)

Returns whether the either range partly or fully contains the other

Type Details
r1 range a range to check
r2 range another range
Returns bool
print(samples[0],partly_or_fully_contains_each_other(*get_assign_ranges(samples[0])))
print(samples[1],partly_or_fully_contains_each_other(*get_assign_ranges(samples[1])))
print(samples[2],partly_or_fully_contains_each_other(*get_assign_ranges(samples[2])))
print(samples[3],partly_or_fully_contains_each_other(*get_assign_ranges(samples[3])))
print(samples[4],partly_or_fully_contains_each_other(*get_assign_ranges(samples[4])))
2-4,6-8 False
2-3,4-5 False
5-7,7-9 True
2-8,3-7 True
6-6,4-6 True
  • Create a function that returns all the partly or fully overlapping samples given a list of samples

get_partly_overlapping

 get_partly_overlapping (samples:list[str])

Return a list of partially or fully overlapping pairs of ranges

Type Details
samples list a list of section assignments for a pair of elves
Returns list
print(get_partly_overlapping(samples))
[[range(5, 7), range(7, 9)], [range(2, 8), range(3, 7)], [range(6, 6), range(4, 6)], [range(2, 6), range(4, 8)]]
  • Finally the answer for the partially or fully overlapping given the input

Click on the Answer tab to view the answer

overlapping = get_partly_overlapping(input)
print(f'the correct answer for part 2 is {len(overlapping)}')
the correct answer for part 2 is 878