예제 #1
0
def a():
    groups = data.split("\n\n")
    criteria, ticket, nearby = [l.split("\n") for l in groups]

    rules = {}

    for c in criteria:
        k, vs = c.split(":")
        rs = u.lmap(tuple, u.chunks(u.ints(vs.replace("-", " to ")), 2))
        rules[k] = rs

    def valid(val):
        for ruleset in rules.values():
            for a, b in ruleset:
                if a <= val <= b:
                    return True
        return False

    s = 0
    for ticket in nearby[1:]:
        t = u.ints(ticket)
        for v in t:
            if not valid(v):
                s += v
    return s
예제 #2
0
파일: 24.py 프로젝트: rpearl/advent
def parse_segments(prog):
    segments = [seg.splitlines() for seg in prog.split('inp w\n')[1:]]
    out = []
    for segment in segments:
        param1 = u.ints(segment[4]).pop()
        param2 = u.ints(segment[14]).pop()
        out.append((param1, param2))
    return out
예제 #3
0
def b():
    groups = data.split("\n\n")
    criteria, my_ticket, nearby = [g.split("\n") for g in groups]
    my_ticket = u.ints(my_ticket[1])

    rules = {}

    for c in criteria:
        k, vs = c.split(":")
        rs = u.lmap(tuple, u.chunks(u.ints(vs.replace("-", " ")), 2))
        rules[k] = rs

    def valid_for_field(v, field):
        return any(a <= v <= b for a, b in rules[field])

    def valid(val):
        return any(valid_for_field(val, field) for field in rules)

    valid_nearby = []

    for ticket in nearby[1:]:
        t = u.ints(ticket)
        if all(valid(v) for v in t):
            valid_nearby.append(t)

    possible = []
    for _ in range(len(my_ticket)):
        possible.append(set(rules.keys()))

    for ticket in valid_nearby:
        for i, v in enumerate(ticket):
            pl = list(possible[i])
            for field in pl:
                if not valid_for_field(v, field):
                    possible[i].remove(field)

    mapping = {}
    allocated = set()
    for i, p in sorted(enumerate(possible), key=lambda x: x[1]):
        field = (p - allocated).pop()
        mapping[i] = field
        allocated.add(field)

    s = functools.reduce(
        operator.mul,
        (my_ticket[i] for i in mapping if mapping[i].startswith("departure")),
        1,
    )
    return s
예제 #4
0
def b():
    def min_perim(l, w, h):
        return min(2 * sum(s) for s in sides(l, w, h))

    return sum(
        math.prod((l, w, h)) + min_perim(l, w, h)
        for l, w, h in u.chunks(u.ints(data), 3))
예제 #5
0
파일: 9.py 프로젝트: rpearl/advent
def b():
    players, last = u.ints(data)
    last *= 100

    scores = Counter()

    marbles = u.Linked(0)
    st = marbles
    player = 0

    for marble in range(1, last + 1):
        if marble % 23 == 0:
            scores[player] += marble
            other = marbles.move(-7)
            scores[player] += other.item
            marbles = other.move(1)
            other.remove()
        else:
            cur = u.Linked(marble)
            marbles.move(1).add(cur)
            marbles = cur
        player = (player + 1) % players

    return max(scores.values())
    pass
예제 #6
0
파일: 10.py 프로젝트: rpearl/advent
def a():
    pvs = []
    for line in lines:
        pvs.append(list(u.ints(line)))
    i = 0
    pa = math.inf
    grid = None
    while True:
        for pv in pvs:
            pv[0] += pv[2]
            pv[1] += pv[3]

        lt = min(pv[0] for pv in pvs)
        rt = max(pv[0] for pv in pvs)
        up = min(pv[1] for pv in pvs)
        dn = max(pv[1] for pv in pvs)
        a = (rt - lt) * (dn - up)

        if pa < a:
            for y in range(up, dn):
                row = []
                for x in range(lt, rt):
                    row.append(grid[x, y])
                print("".join(row))
            print(i)
            break
        else:
            grid = defaultdict(lambda: ".")
            for pv in pvs:
                grid[pv[0], pv[1]] = "#"
            pa = a
            i += 1
    pass
예제 #7
0
def b():
    reindeer = {}
    for line in lines:
        name = line.split(" ")[0]
        reindeer[name] = tuple(u.ints(line))

    def dist(name, sec):
        s, mi, ri = reindeer[name]
        full, rem = divmod(sec, mi + ri)
        return full * s * mi + min(mi, rem) * s

    points = Counter()

    for sec in range(2503):
        md = -math.inf
        mw = []
        for name in reindeer:
            d = dist(name, sec + 1)
            if d > md:
                mw = [name]
                md = d
            elif d == md:
                mw.append(name)

        points.update(mw)
    return max(points.values())
예제 #8
0
def a():
    sizes = u.ints(data)
    out = 0
    for s in u.powerset(sizes):
        if sum(s) == 150:
            out += 1
    return out
예제 #9
0
def a():
    grid = defaultdict(bool)
    for line in lines:
        nums = u.ints(line)
        if line.startswith("rect"):
            a, b = nums
            for x in range(a):
                for y in range(b):
                    grid[x, y] = True
        elif "row" in line:
            y, b = nums
            row = [grid[x, y] for x in range(width)]
            for x, val in enumerate(row):
                grid[(x + b) % width, y] = val
        else:
            x, b = nums
            col = [grid[x, y] for y in range(height)]
            for y, val in enumerate(col):
                grid[x, (y + b) % height] = val
    for y in range(height):
        o = []
        for x in range(width):
            o.append("#" if grid[x, y] else ".")
        print("".join(o))
    return sum(grid.values())
예제 #10
0
def a():
    s = 0
    for line in lines:
        xs = u.ints(line)
        d = max(xs) - min(xs)
        s += d
    return s
예제 #11
0
파일: 3.py 프로젝트: rpearl/advent
def b():
    nums = [u.ints(line) for line in lines]
    cs = zip(*nums)

    s = 0
    for tri in u.chunks(itertools.chain.from_iterable(cs), 3):
        s += possible(tri)
    return s
예제 #12
0
파일: 24.py 프로젝트: rpearl/advent
def a():
    packages = list(reversed(sorted(u.ints(data))))
    target = sum(packages) // 3

    for k in range(4, len(packages)):
        for subset in itertools.combinations(packages, k):
            if sum(subset) == target:
                return math.prod(subset)
예제 #13
0
def b():
    s = 0
    for line in lines:
        for p in itertools.combinations(u.ints(line), 2):
            y, x = min(p), max(p)
            d, r = divmod(x, y)
            if r == 0:
                s += d
    return s
예제 #14
0
def a():
    def area(l, w, h):
        return sum(2 * math.prod(s) for s in sides(l, w, h))

    def slack(l, w, h):
        return min(math.prod(s) for s in sides(l, w, h))

    return sum(
        area(l, w, h) + slack(l, w, h)
        for l, w, h in u.chunks(u.ints(data), 3))
예제 #15
0
파일: 5.py 프로젝트: rpearl/advent
def a():
    insns = u.ints(data)
    ptr = 0
    s = 0
    while 0 <= ptr < len(insns):
        s += 1
        offs = insns[ptr]
        insns[ptr] += 1
        ptr += offs
    return s
예제 #16
0
파일: 10.py 프로젝트: rpearl/advent
def b():
    adapters = u.ints(data)
    adapters.sort()
    adapters.append(adapters[-1] + 3)
    outputs = []

    ways = Counter({0: 1})
    for jolt in adapters:
        ways[jolt] = ways[jolt - 1] + ways[jolt - 2] + ways[jolt - 3]
    return ways[adapters[-1]]
예제 #17
0
def play(turns):
    spoken = [None] * turns
    d = u.ints(data)
    for i, k in enumerate(d[:-1]):
        spoken[k] = i + 1
    last = d[-1]
    for i in range(len(d), turns):
        s = spoken[last] or i
        spoken[last] = i
        last = i - s
    return last
예제 #18
0
파일: 5.py 프로젝트: rpearl/advent
def b():
    insns = u.ints(data)
    ptr = 0
    s = 0
    while 0 <= ptr < len(insns):
        s += 1
        offs = insns[ptr]
        d = 1 if offs < 3 else -1
        insns[ptr] += d
        ptr += offs
    return s
예제 #19
0
파일: 14.py 프로젝트: rpearl/advent
def b():
    mask = 0
    mem = defaultdict(int)
    for line in lines:
        if line.startswith("mask"):
            mask = line.split("=")[1].strip()
        else:
            m, v = u.ints(line)
            for addr in addrs(mask, m):
                mem[addr] = v
    return sum(mem.values())
예제 #20
0
파일: 21.py 프로젝트: rpearl/advent
 def fight_cost(items, player_hp=100):
     boss_hp, boss_damage, boss_armor = u.ints(data)
     cost = sum(item[1] for item in items)
     damage = sum(item[2] for item in items)
     armor = sum(item[3] for item in items)
     necessary_hits = boss_hp // max(damage - boss_armor, 1)
     my_damage = (necessary_hits - 1) * max(boss_damage - armor, 1)
     if my_damage < player_hp:
         return -math.inf
     else:
         return cost
예제 #21
0
def a():
    reindeer = {}
    for line in lines:
        name = line.split(" ")[0]
        reindeer[name] = tuple(u.ints(line))

    def dist(name, sec):
        s, mi, ri = reindeer[name]
        full, rem = divmod(sec, mi + ri)
        return full * s * mi + min(mi, rem) * s

    return max(dist(name, 2503) for name in reindeer)
예제 #22
0
def a():
    boss_hp, boss_dmg = u.ints(data)
    state = State(
        player_hp=50,
        player_armor=0,
        player_mana=500,
        shield_effect=0,
        poison_effect=0,
        recharge_effect=0,
        boss_hp=boss_hp,
        boss_dmg=boss_dmg,
    )
    return search(state, 0, False)
예제 #23
0
파일: 14.py 프로젝트: rpearl/advent
def a():
    mask = 0
    mem = defaultdict(int)
    for line in lines:
        if line.startswith("mask"):
            mask = line.split("=")[1].strip()
            ors = int(mask.replace("X", "0"), 2)
            ands = int(mask.replace("X", "1"), 2)
        else:
            m, v = u.ints(line)
            mem[m] = (v | ors) & ands
    return sum(mem.values())
    pass
예제 #24
0
def b():
    sizes = u.ints(data)
    bestln = math.inf
    out = 0
    for s in u.powerset(sizes):
        if sum(s) != 150:
            continue
        l = len(s)
        if l < bestln:
            bestln = l
            best = 0
        if l == bestln:
            best += 1
    return best
예제 #25
0
파일: 6.py 프로젝트: rpearl/advent
def b():
    grid = defaultdict(int)
    ops = {
        "turn on": lambda pos: grid[pos] + 1,
        "turn of": lambda pos: max(grid[pos] - 1, 0),
        "toggle ": lambda pos: grid[pos] + 2,
    }
    for line in lines:
        l, t, r, b = u.ints(line)
        op = line[:len("turn on")]
        for pos in itertools.product(range(l, r + 1), range(t, b + 1)):
            grid[pos] = ops[op](pos)
    return sum(grid.values())

    pass
예제 #26
0
def decompress(s):
    out = []
    i = 0
    while i < len(s):
        c = s[i]
        if c == "(":
            end = s.find(")", i)
            marker = s[i:end]
            l, rpt = u.ints(marker)
            val = s[end + 1:end + 1 + l]
            out.append(val * rpt)
            i = end + l
        else:
            out.append(c)
        i += 1
    return "".join(out)
예제 #27
0
파일: 13.py 프로젝트: rpearl/advent
def a():
    ts = int(lines[0])
    ids = u.ints(lines[1])

    best = math.inf
    bi = None

    for b in ids:
        earliest = math.ceil(ts / b) * b
        l = earliest - ts
        if l < best:
            best = l
            bi = b
    return bi * best

    pass
예제 #28
0
def a():
    length = 0
    i = 0
    s = data
    while i < len(s):
        c = s[i]
        if c == "(":
            end = s.find(")", i)
            marker = s[i:end]
            l, rpt = u.ints(marker)
            val = s[end + 1:end + 1 + l]
            length += len(val) * rpt
            i = end + l
        else:
            length += 1
        i += 1
    return length
예제 #29
0
 def find_length(s):
     length = 0
     i = 0
     while i < len(s):
         c = s[i]
         if c == "(":
             end = s.find(")", i)
             marker = s[i:end]
             l, rpt = u.ints(marker)
             val = s[end + 1:end + 1 + l]
             tot = find_length(val)
             length += tot * rpt
             i = end + l
         else:
             length += 1
         i += 1
     return length
예제 #30
0
파일: 10.py 프로젝트: rpearl/advent
def a():
    cpos = 0
    skip = 0
    l = list(range(256))

    for length in u.ints(data):
        left = cpos
        right = cpos + length - 1
        while left < right:
            lt = left % len(l)
            rt = right % len(l)
            tmp = l[lt]
            l[lt] = l[rt]
            l[rt] = tmp
            left += 1
            right -= 1
        cpos += length
        cpos += skip
        skip += 1
    return l[0] * l[1]