Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
Day 22 💻
Browse files Browse the repository at this point in the history
Signed-off-by: Mukund Venkatachar <mukund.venkatachar@gmail.com>
  • Loading branch information
mukundv committed Dec 23, 2021
1 parent 73eec17 commit b4e2b46
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 46 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# AOC 2021
![](https://img.shields.io/badge/stars%20⭐-43-yellow) ![](https://img.shields.io/badge/days%20completed-21-red)

![stars](https://img.shields.io/badge/stars%20-42-yellow)

![days](https://img.shields.io/badge/days%20completed-21-red)

Fun with Python :snake: - [aoc 2021](https://adventofcode.com/2021/)

Expand All @@ -26,5 +29,7 @@ Fun with Python :snake: - [aoc 2021](https://adventofcode.com/2021/)
| 19 | [Beacon Scanner](https://github.com/mukundv/AOC2021/blob/master/day19/day19.md) | [day19_input.txt](https://github.com/mukundv/AOC2021/blob/master/day19/day19_input.txt) | [day19.py](https://github.com/mukundv/AOC2021/blob/master/day19/day19.py) | [day19](https://github.com/mukundv/AOC2021/releases/tag/day19) |
| 20 | [Trench Map](https://github.com/mukundv/AOC2021/blob/master/day20/day20.md) | [day20_input.txt](https://github.com/mukundv/AOC2021/blob/master/day20/day20_input.txt) | [day20.py](https://github.com/mukundv/AOC2021/blob/master/day20/day20.py) | [day20](https://github.com/mukundv/AOC2021/releases/tag/day20) |
| 21 | [Dirac Dice](https://github.com/mukundv/AOC2021/blob/master/day21/day21.md) | [day21_input.txt](https://github.com/mukundv/AOC2021/blob/master/day21/day21_input.txt) | [day21.py](https://github.com/mukundv/AOC2021/blob/master/day21/day21.py) | [day21](https://github.com/mukundv/AOC2021/releases/tag/day21) |
| 22 | [Reactor Reboot](https://github.com/mukundv/AOC2021/blob/master/day22/day22.md) | [day22_input.txt](https://github.com/mukundv/AOC2021/blob/master/day22/day22_input.txt) | [day22.py](https://github.com/mukundv/AOC2021/blob/master/day22/day22.py) | [day22](https://github.com/mukundv/AOC2021/releases/tag/day22) |

This document was automatically rendered on 21-12-2021 23:34:21 using [SnakeMD](https://github.com/TheRenegadeCoder/SnakeMD)
This document was automatically rendered on 23-12-2021 16:05:31
using [SnakeMD](https://github.com/TheRenegadeCoder/SnakeMD)
100 changes: 78 additions & 22 deletions day22/day22.py
Original file line number Diff line number Diff line change
@@ -1,66 +1,114 @@
import os
import re
from collections import Counter

from aocd import get_data
from dotenv import load_dotenv

from utils import generate_readme


def get_session() -> str:
load_dotenv()
return os.getenv('SESSION_COOKIE')


def get_input(day: int, year: int, data: str = None):
def run(day: int, year: int, data: str = None, part: int = None):
if not data:
return parse_input(get_data(get_session(), day=day, year=year).splitlines())
if part == 1:
return part1(get_data(get_session(), day=day, year=year).splitlines())
else:
return part2(get_data(get_session(), day=day, year=year).splitlines())
else:
return parse_input(data.splitlines())
if part == 1:
return part1(data.splitlines())
else:
return part2(data.splitlines())


def overlap(values, x, y):
if len(values) == 0 or values[-1] < x or values[0] > y:
return range(-1)
return range(min(max(values[0], x), y), min(max(values[-1], x), y) + 1)


def part2(data):
cubes = get_cubes(data)
ret = 0
for i, (instruction, x, y, z) in enumerate(cubes):
if instruction == 'on':
ret += count_within_range(x, y, z, cubes[i + 1:])
return ret


def get_cubes(data):
cubes = []
reg = re.compile(r"^(on|off) x=(-?[0-9]+)\.\.(-?[0-9]+),y=(-?[0-9]+)\.\.(-?[0-9]+),z=(-?[0-9]+)\.\.(-?[0-9]+)$")
# https://regex101.com/r/GKuwQm/1
for line in data:
_ = reg.search(line)
cubes.append((
_.group(1),
range(int(_.group(2)), int(_.group(3)) + 1),
range(int(_.group(4)), int(_.group(5)) + 1),
range(int(_.group(6)), int(_.group(7)) + 1),
))
return cubes


def count_within_range(x, y, z, remaining):
if len(x) == 0 or len(y) == 0 or len(z) == 0:
return 0
ret = len(x) * len(y) * len(z)
temp = []

for instruction, i, j, k in remaining:
overlap_x = overlap(i, x[0], x[-1])
if len(overlap_x) > 0:
overlap_y = overlap(j, y[0], y[-1])
if len(overlap_y) > 0:
overlap_z = overlap(k, z[0], z[-1])
if len(overlap_z) > 0:
temp.append((instruction, overlap_x, overlap_y, overlap_z))

for i, (instruction, x, y, z) in enumerate(temp):
ret -= count_within_range(x, y, z, temp[i + 1:])

def parse_input(data):
return get_instructions_cubes(data)
return ret


def get_instructions_cubes(data):
instructions = []
steps = []

for lines in data:
x, y = lines[:3].strip(), [lines.replace("\n", "").replace("on ", "").replace("off ", "")]
instructions += [x]
steps += y
return instructions, get_cubes(steps)
return instructions, get_cubes_from_steps(steps)


def get_cubes(steps):
def get_cubes_from_steps(steps):
cubes = []
for i in range(len(steps)):
x, y, z = steps[i].split(',')
x1, x2 = x.replace('x=', '').split('..')
y1, y2 = y.replace('y=', '').split('..')
z1, z2 = z.replace('z=', '').split('..')
if int(x1) >= -50 and int(x2) <= 50 and int(y1) >= -50 and int(y2) <= 50 and int(z1) >= -50 and int(
z2) <= 50:
x1, x2 = steps[i].split(',')[0].replace('x=', '').split('..')
y1, y2 = steps[i].split(',')[1].replace('y=', '').split('..')
z1, z2 = steps[i].split(',')[2].replace('z=', '').split('..')
if less_than_fifty(x1, x2, y1, y2, z1, z2):
cubes += [[[int(x1), int(x2)], [int(y1), int(y2)], [int(z1), int(z2)]]]
else:
continue
return cubes


def part1(instructions, cubes):
def part1(data):
instructions, cubes = get_instructions_cubes(data)
return Counter(initialise(instructions=instructions, cubes=cubes).values())['on']


def initialise(cubes, instructions):
cuboid = {}
for i in range(len(cubes)):
# print(i)
for x in range(cubes[i][0][0], cubes[i][0][1] + 1, 1):
# print(cubes[i][0][0], cubes[i][0][1] + 1, 1)
for y in range(cubes[i][1][0], cubes[i][1][1] + 1, 1):
# print(cubes[i][1][0], cubes[i][1][1] + 1, 1)
for z in range(cubes[i][2][0], cubes[i][2][1] + 1, 1):
# print(cubes[i][2][0], cubes[i][2][1] + 1, 1)
if (x, y, z) not in cuboid:
cuboid[x, y, z] = instructions[i]
else:
Expand All @@ -71,5 +119,13 @@ def initialise(cubes, instructions):
return cuboid


def less_than_fifty(x1, x2, y1, y2, z1, z2):
if int(x1) >= -50 and int(x2) <= 50 and int(y1) >= -50 and int(y2) <= 50 and int(z1) >= -50 and int(
z2) <= 50:
return True


if __name__ == '__main__':
print(f'Part 1: {part1(*get_input(day=22, year=2021))}')
print(f' Part 1: {run(data=None, day=22, year=2021, part=1)}')
print(f' Part 2: {run(data=None, day=22, year=2021, part=2)}')
generate_readme("README", '2021', '22', '../')
35 changes: 15 additions & 20 deletions day22/test_day22.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
import os

from .day22 import part1, get_input
from .day22 import run

data1 = open(os.getcwd() + '//day22//day22_example1.txt').read()
data2 = open(os.getcwd() + '//day22//day22_example2.txt').read()
data3 = open(os.getcwd() + '//day22//day22_example2.txt').read()
data3 = open(os.getcwd() + '//day22//day22_example3.txt').read()


class TestDay22:

def test_part1_example_1(self):
ans = part1(*get_input(data=data1, day=21, year=2021))
ans = run(data=data1, day=22, year=2021, part=1)
assert ans == 39

def test_part1_example_2(self):
ans = part1(*get_input(data=data2, day=21, year=2021))
ans = run(data=data2, day=22, year=2021, part=1)
assert ans == 590784

# def test_part1_example_3(self):
# ans = part1(*get_input(data=data3, day=21, year=2021))
# assert ans == 2758514936282235
# def test_part2_example(self):
# p1, p2 = get_input(data=data, day=21, year=2021)
# ans = part2(play_dirac_dice(p1, p2, 0, 0))
# assert ans == 444356092776315
#
# def test_part1(self):
# ans = play_deterministic_dice(get_input(data=None, day=21, year=2021))
# assert ans == 734820
#
# def test_part2(self):
# p1, p2 = get_input(data=None, day=21, year=2021)
# ans = part2(play_dirac_dice(p1, p2, 0, 0))
# assert ans == 193170338541590
def test_part2_example_1(self):
ans = run(data=data3, day=22, year=2021, part=2)
assert ans == 2758514936282235

def test_part1(self):
ans = run(data=None, day=22, year=2021, part=1)
assert ans == 583636

def test_part2(self):
ans = run(data=None, day=22, year=2021, part=2)
assert ans == 1294137045134837
6 changes: 4 additions & 2 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ def read_readme(directory, year):
return None
else:
if not readme_table:
soup = BeautifulSoup(markdown.markdown(open(f"{directory}README.md").read()), "html.parser")
soup = BeautifulSoup(markdown.markdown(
open(f"{directory}README.md", "r", encoding='utf-8', errors="ignore"
).read()), "html.parser")
a = soup.findAll('a')
i = 1
for row in (a[1:]):
Expand Down Expand Up @@ -113,7 +115,7 @@ def generate_readme(name, year, day, directory):
readme.add_header("AOC 2021")
readme.add_element(
snakemd.Paragraph(
[snakemd.InlineText("stars", url="https://img.shields.io/badge/stars%20-42-yellow", image=True)]))
[snakemd.InlineText("stars", url="https://img.shields.io/badge/stars%20-42-yellow", image=True)]))
readme.add_element(
snakemd.Paragraph(
[snakemd.InlineText("days", url="https://img.shields.io/badge/days%20completed-21-red", image=True)]))
Expand Down

0 comments on commit b4e2b46

Please sign in to comment.