From 26416fffb9bad00b9739f4b8f161ca37b712cb11 Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Thu, 9 Dec 2021 12:07:49 +0100 Subject: [PATCH] initial commit --- .gitignore | 2 ++ README.md | 10 +++++++ day03.py | 42 ++++++++++++++++++++++++++ day03.scala | 27 +++++++++++++++++ day03.scm | 17 +++++++++++ day04.py | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ day05.py | 50 +++++++++++++++++++++++++++++++ day06.nim | 16 ++++++++++ 8 files changed, 250 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 day03.py create mode 100644 day03.scala create mode 100644 day03.scm create mode 100644 day04.py create mode 100755 day05.py create mode 100644 day06.nim diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..552b246 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.in +.metals/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..c531c66 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Advent of Code 2021 + +| Day | Chicken Scheme | Scala | Python | Nim | | +|-----|----------------|--------|--------|-----|---| +| 1 | | | | | | +| 2 | | | | | | +| 3 | part 1 | part 1 | ✅ | | | +| 4 | | | ✅ | | | +| 5 | | | ✅ | | | +| 6 | | | | ✅ | | diff --git a/day03.py b/day03.py new file mode 100644 index 0000000..79c77dc --- /dev/null +++ b/day03.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +import fileinput +from copy import deepcopy + +numbers = [[int(i) for i in line.strip()] for line in fileinput.input()] +bit_count = len(numbers[0]) + +occurrences = [0] * bit_count +for number in numbers: + for i, bit in enumerate(number): + occurrences[i] += bit + +gamma, epsilon = 0, 0 +for i, freq in enumerate(occurrences): + shifted = 1 << (len(occurrences) - 1) >> i + if freq > len(numbers) // 2: + gamma |= shifted + else: + epsilon |= shifted + +print("part 1:", gamma * epsilon) + +most_common = deepcopy(numbers) +least_common = deepcopy(numbers) + +for i in range(bit_count): + ones = sum(number[i] for number in most_common) + lc = int(ones * 2 >= len(most_common)) + most_common = [number for number in most_common if number[i] == lc] + if len(most_common) == 1: + break + +for i in range(bit_count): + zeros = sum(not number[i] for number in least_common) + lc = int(zeros * 2 > len(least_common)) + least_common = [number for number in least_common if number[i] == lc] + if len(least_common) == 1: + break + +mc = int("".join(str(x) for x in most_common[0]), 2) +lc = int("".join(str(x) for x in least_common[0]), 2) +print("part 2:", mc * lc) diff --git a/day03.scala b/day03.scala new file mode 100644 index 0000000..1d1424d --- /dev/null +++ b/day03.scala @@ -0,0 +1,27 @@ +object day03 { + def main(args: Array[String]): Unit = { + val numbers = io.Source.stdin + .getLines() + .map(ln => ln.chars.map(_ - '0').toArray) + .toArray + + var occurences = Array.fill(numbers(0).length)(0) + for (number <- numbers) { + for ((bit, i) <- number.zipWithIndex) + occurences(i) += bit + } + + var gamma = 0 + var epsilon = 0 + for ((freq, i) <- occurences.zipWithIndex) { + val shifted = 1 << occurences.length - 1 >> i + if (freq > (numbers.length / 2)) + gamma |= shifted + else + epsilon |= shifted + } + + val part1 = gamma * epsilon + println(s"part1: $part1") + } +} diff --git a/day03.scm b/day03.scm new file mode 100644 index 0000000..c886379 --- /dev/null +++ b/day03.scm @@ -0,0 +1,17 @@ +(import (chicken string)) +(import (chicken format)) +(import (chicken io)) +(import srfi-14) +(import srfi-60) + +(define (add-lines l r) + (map (lambda (l r) (+ l (- (char->integer r) 48))) l r)) + +(define lines (map string->list (read-lines))) +(define counts (foldl add-lines (map (lambda (_) 0) (car lines)) lines)) + +(define hl (/ (length lines) 2)) +(define gamma (list->integer (map (lambda (x) (> x hl)) counts))) +(define epsilon (list->integer (map (lambda (x) (< x hl)) counts))) + +(format #t "part 1: ~A~%" (* gamma epsilon)) diff --git a/day04.py b/day04.py new file mode 100644 index 0000000..9e95248 --- /dev/null +++ b/day04.py @@ -0,0 +1,86 @@ +import fileinput +from typing import List, Tuple, Set + +numbers = [int(x) for x in input().split(",")] +input() + +Board = List[List[int]] + +boards: List[Board] = [] +board: Board = [] + +while True: + try: + line = input().strip() + except EOFError: + break + + if line: + board.append([int(x) for x in line.split()]) + else: + boards.append(board) + board = [] + +if board: + boards.append(board) + + +def find_bingo(drawn: Set[int], wins: Set[int]) -> Tuple[int, int]: + for n in numbers: + drawn.add(n) + + for b, board in enumerate(boards): + for row in board: + for col in row: + if col not in drawn: + break + else: + if b not in wins: + wins.add(b) + return b, n + + for x in range(len(board[0])): + for y in range(len(board)): + if board[y][x] not in drawn: + break + else: + if b not in wins: + wins.add(b) + return b, n + + raise RuntimeError("no bingo found") + + +def print_board(board, drawn=frozenset()): + for r in board: + for c in r: + if c in drawn: + print("\033[91m", end="") + print(str(c).rjust(4), end="\033[0m") + print() + print() + + +print(", ".join(str(n) for n in numbers)) +print() +for b in boards: + print_board(b) + +print("===") + +drawn = set() +wins = set() + +b, last_drawn = find_bingo(drawn, wins) +undrawn = sum(number for row in boards[b] for number in row if number not in drawn) +part1 = last_drawn * undrawn + +while len(wins) < len(boards): + b, last_drawn = find_bingo(drawn, wins) + print_board(boards[b], drawn) + +undrawn = sum(number for row in boards[b] for number in row if number not in drawn) +part2 = last_drawn * undrawn + +print("part1:", part1) +print("part2:", part2) diff --git a/day05.py b/day05.py new file mode 100755 index 0000000..46b9476 --- /dev/null +++ b/day05.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import fileinput + +N = 1000 + + +def main(): + diag = [[0] * N for _ in range(N)] + + vents = [ + [ + tuple(int(coord) for coord in coords.split(",")) + for coords in str(line).split(" -> ") + ] + for line in fileinput.input() + ] + + for (x1, y1), (x2, y2) in vents: + xsign = -1 if x2 < x1 else 1 + ysign = -1 if y2 < y1 else 1 + + if x1 == x2: + # vertical line + for y in range(y1, y2 + ysign, ysign): + diag[y][x1] += 1 + elif y1 == y2: + # horizontal line + for x in range(x1, x2 + xsign, xsign): + diag[y1][x] += 1 + + part1 = sum(point >= 2 for row in diag for point in row) + print("part 1:", part1) + + for (x1, y1), (x2, y2) in vents: + xsign = -1 if x2 < x1 else 1 + ysign = -1 if y2 < y1 else 1 + + if x1 != x2 and y1 != y2: + # diagonal line + y = y1 + for x in range(x1, x2 + xsign, xsign): + diag[y][x] += 1 + y += ysign + + part2 = sum(point >= 2 for row in diag for point in row) + print("part 2:", part2) + + +if __name__ == "__main__": + main() diff --git a/day06.nim b/day06.nim new file mode 100644 index 0000000..1b60d1e --- /dev/null +++ b/day06.nim @@ -0,0 +1,16 @@ +from std/strutils import split, parseInt +from std/sequtils import map, foldl + +let numbers = readLine(stdin).split(',').map(parseInt) +var buckets: array[9, int] + +for number in numbers: + buckets[number] += 1 + +for i in 0..<256: + buckets[(i + 7) mod 9] += buckets[i mod 9] + + if i == 79: + echo("part 1: ", buckets.foldl(a + b)) + +echo("part 2: ", buckets.foldl(a + b))