Example #1
0
def test_claim_overlap():
    c1 = Claim.new_from_string("#1 @ 1,3: 4x4")
    c2 = Claim.new_from_string("#2 @ 3,1: 4x4")
    c3 = Claim.new_from_string("#3 @ 5,5: 2x2")
    c4 = Claim.new_from_string("#4 @ 1,1: 1x1")
    assert c1.overlaps(c2)
    assert c2.overlaps(c1)
    assert c1.overlaps(c3) == False
    assert c4.overlaps(c4)
Example #2
0
def part2_v3(file_name: str) -> str:
    """
    Find the one claim that doesn't overlap any other claim. Return its id.

    This version is similar to part2_v2(), but we handle the filtering of the
    claim ID's differently. In my haphazard benchmarking, it seems marginally
    slower.
    """
    with open(file_name) as f:
        claims = [Claim.new_from_string(line.rstrip()) for line in f]
    # Each value is a claim ID.
    set_claim_ids = set()
    # Each key is a sq inch tuple. Each value is a list of claim ID's.
    d_sq_inches: DefaultDict[Tuple[int, int], List[str]] = defaultdict(list)
    # set_claim_ids will end up with all claim ID's.
    # d_sq_inches will end up with all square inches that have claims on them,
    # and a list of the claim ID's that have the claims.
    for claim in claims:
        set_claim_ids.add(claim.id)
        for sq_inch in claim.sq_inches:
            d_sq_inches[sq_inch].append(claim.id)
    # Now for all square inches with more than one claim,
    # discard the claim ID's from set_claim_ids.
    for claim_list in d_sq_inches.values():
        if len(claim_list) > 1:
            for claim_id in claim_list:
                set_claim_ids.discard(claim_id)
    # The only claim ID left is one we want.
    return set_claim_ids.pop()
Example #3
0
def part2_v2(file_name: str) -> str:
    """
    Find the one claim that doesn't overlap any other claim. Return its id.

    This version is much faster than part2_v1().
    """
    with open(file_name) as f:
        claims = [Claim.new_from_string(line.rstrip()) for line in f]
    # Each key is a claim ID. Each value is a bool.
    d_claim_ids = {}
    # Each key is a sq inch tuple. Each value is a list of claim ID's.
    d_sq_inches: DefaultDict[Tuple[int, int], List[str]] = defaultdict(list)
    # Load both dictionaries. d_claim_ids will end up with all claim ID's.
    # d_sq_inches will end up with all square inches that have claims on them,
    # and a list of the claim ID's that have the claims.
    for claim in claims:
        d_claim_ids[claim.id] = True
        for sq_inch in claim.sq_inches:
            d_sq_inches[sq_inch].append(claim.id)
    # Now for all square inches with more than one claim,
    # flip d_claim_ids_no_overlap to False.
    for claim_list in d_sq_inches.values():
        if len(claim_list) > 1:
            for claim_id in claim_list:
                d_claim_ids[claim_id] = False
    # Now return the one claim ID that's still True.
    for claim_id, b in d_claim_ids.items():
        if b:
            return claim_id
    raise Exception(NOT_FOUND)
Example #4
0
def test_claim_new_from_string():
    s = "#14 @ 690,863: 12x20"
    claim = Claim.new_from_string(s)
    assert claim.id == "14"
    assert claim._x == 690
    assert claim._y == 863
    assert claim._width == 12
    assert claim._height == 20
Example #5
0
def part2_v1(file_name: str) -> str:
    """
    Find the one claim that doesn't overlap any other claim. Return its id.
    """
    with open(file_name) as f:
        claims = [Claim.new_from_string(line.rstrip()) for line in f]
    for claim in claims:
        if _no_overlap(claim, claims):
            return claim.id
    raise Exception(NOT_FOUND)
Example #6
0
def part1(file_name: str) -> int:
    """
    How many square inches of fabric are within two or more claims?
    """
    with open(file_name) as f:
        claims = [Claim.new_from_string(line.rstrip()) for line in f]
    d: DefaultDict[Tuple[int, int], int] = defaultdict(lambda: 0)
    # Count how many times each square inch appears in a claim
    for claim in claims:
        for sq_inch in claim.sq_inches:
            d[sq_inch] += 1
    # Count the # of values in d that are > 1
    return len([v for v in d.values() if v > 1])
Example #7
0
def test_claim_sq_inches():
    c1 = Claim.new_from_string("#1 @ 1,3: 4x4")
    assert c1.sq_inches == [
        (1, 3),
        (1, 4),
        (1, 5),
        (1, 6),
        (2, 3),
        (2, 4),
        (2, 5),
        (2, 6),
        (3, 3),
        (3, 4),
        (3, 5),
        (3, 6),
        (4, 3),
        (4, 4),
        (4, 5),
        (4, 6),
    ]