<jupyter_start><jupyter_text>Day 20: Firewall Rulesauthor: <NAME>license: [MIT](https://opensource.org/licenses/MIT)[link to problem statement](http://adventofcode.com/2016/day/20) You'd like to set up a small hidden computer here so you can use it to get back into the network later. However, the corporate firewall only allows communication with certain external [IP addresses](https://en.wikipedia.org/wiki/IPv4Addressing).You've retrieved the list of blocked IPs from the firewall, but the list seems to be messy and poorly maintained, and it's not clear which IPs are allowed. Also, rather than being written in [dot-decimal](https://en.wikipedia.org/wiki/Dot-decimal_notation) notation, they are written as plain [32-bit](https://en.wikipedia.org/wiki/32-bit) integers, which can have any value from `0` through `4294967295`, inclusive.For example, suppose only the values 0 through 9 were valid, and that you retrieved the following blacklist:    5-8    0-2    4-7The blacklist specifies ranges of IPs (inclusive of both the start and end value) that are not allowed. Then, the only IPs that this firewall allows are `3` and `9`, since those are the only numbers not in any range.Given the list of blocked IPs you retrieved from the firewall (your puzzle input), what is the lowest-valued IP that is not blocked?  Solution logicWe start from 0 and continue upwards. The input contains integer ranges that are considered to be blacklisted, so we can skip them. Once we get to a blacklist, we can skip directly to the end of the input. We check at each iteration whether our value lies in any of the blacklisted ranges. To make it simpler to find and work on things, we sort the input rules according to their starting value. This allows us to not check further values if our current value is greater than the rule's ending value.  Parsing rules from input<jupyter_code>import re
numbers = re.compile('(\d+)')

UPPER_LIMIT = 4294967295

with open('../inputs/day20.txt', 'r') as f:
    data = [
        tuple(map(
                int, numbers.findall(line))) 
        for line in f.readlines()]
    data.sort()
rule_index = 0
n = 0

while n <= UPPER_LIMIT:
    for i in range(rule_index, len(data)):
        low, high = data[i]
        if low <= n <= high:
            n += 1
            break
    else:
        print('answer', n)
        break<jupyter_output>answer 4793564<jupyter_text>Part TwoHow many IPs are allowed by the blacklist?  Solution logicInstead of breaking if none of the rules match, we keep a counter that we increment to count the number of IPs.<jupyter_code>rule_index = 0
n = 0
ips = 0

while n <= UPPER_LIMIT:
    for i in range(rule_index, len(data)):
        low, high = data[i]
        if low <= n <= high:
            n = high + 1
            break
    else:
        ips += 1
        n += 1

print(ips)<jupyter_output>146
{'fraction_non_alphanumeric': 0.07994389901823282, 'fraction_numerical': 0.02314165497896213, 'mean_word_length': 3.3959938366718028, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 8, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '514718', 'license': 'MIT', 'n_tokens_mistral': 853, 'n_tokens_neox': 795, 'n_words': 381, 'path': '2016/python3/Day20.ipynb', 'repo_name': 'coolharsh55/advent-of-code', 'size': '2865'}