Initial commit
This commit is contained in:
commit
f242d2b0df
420 changed files with 62521 additions and 0 deletions
98
2020/day09/day09.c
Normal file
98
2020/day09/day09.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
bool in_state(unsigned int m, unsigned int state[m][m], unsigned int x) {
|
||||
for (int i = 0; i < m; ++i) {
|
||||
for (int j = i + 1; j < m; ++j) {
|
||||
if (state[i][j] == x) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void print_state(unsigned int m, unsigned int state[m][m]) {
|
||||
for (int i = 0; i < m; ++i) {
|
||||
for (int j = 0; j < m; ++j) {
|
||||
printf("%u ", state[i][j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void update_state(unsigned int m, unsigned int state[m][m], unsigned int *input,
|
||||
unsigned int k) {
|
||||
for (int i = k - m +1; i < k; ++i) {
|
||||
state[k % m][i % m] = input[i] + input[k];
|
||||
state[i % m][k % m] = input[i] + input[k];
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 3) {
|
||||
printf("Usage: %s <input file> <preamble size>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(argv[1], "r");
|
||||
if (fp == NULL) {
|
||||
printf("Could not open file %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int m;
|
||||
sscanf(argv[2], "%d", &m);
|
||||
|
||||
unsigned int input[1024] = {0};
|
||||
unsigned int n = 0;
|
||||
unsigned int d;
|
||||
while (fscanf(fp, "%d\n", &d) == 1) {
|
||||
input[n] = d;
|
||||
n++;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
// Part 1
|
||||
unsigned int state[m][m];
|
||||
for (int i = 0; i < m; ++i) {
|
||||
for (int j = 0; j < m; ++j) {
|
||||
if (i != j) {
|
||||
state[i][j] = input[i] + input[j];
|
||||
} else {
|
||||
state[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int k = m;
|
||||
while (in_state(m, state, input[k])) {
|
||||
update_state(m, state, input, k);
|
||||
k++;
|
||||
}
|
||||
|
||||
printf("%u\n", input[k]);
|
||||
|
||||
// Part 2
|
||||
unsigned int invalid_number = input[k];
|
||||
for (int width = 2; width < n; ++width) {
|
||||
for (int i = 0; i < n - width; ++i) {
|
||||
unsigned int sum = 0;
|
||||
unsigned int min = UINT_MAX;
|
||||
unsigned int max = 0;
|
||||
for (int j = 0; j < width; ++j) {
|
||||
sum += input[i + j];
|
||||
min = (input[i + j] < min) ? input[i + j] : min;
|
||||
max = (input[i + j] > max) ? input[i + j] : max;
|
||||
}
|
||||
if (sum == invalid_number) {
|
||||
printf("%u\n", min + max);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
6
2020/day09/day09.dyalog
Normal file
6
2020/day09/day09.dyalog
Normal file
|
@ -0,0 +1,6 @@
|
|||
⎕IO←0
|
||||
p←⍎¨⊃⎕NGET'input'1
|
||||
m←25
|
||||
⊢x←p⌷⍨m+⍸~(m↓p)∊¨{(,∘.<⍨⍳m)/,⍵}¨∘.+⍨¨¯1↓m,/p ⍝ Part 1
|
||||
⍝+/∊{{(x=+/⍵)×(⌈/+⌊/)⍵}¨⍵,/p}¨2+⍳⍴p ⍝ Part 2
|
||||
(⌈/+⌊/)p[{(1+1⊃⍵)+⍳⊃-/⍵}⊃⍸x=∘.-⍨+\p] ⍝ Part 2 (faster)
|
65
2020/day09/day09.rkt
Normal file
65
2020/day09/day09.rkt
Normal file
|
@ -0,0 +1,65 @@
|
|||
#lang racket
|
||||
|
||||
(module+ test
|
||||
(require rackunit))
|
||||
|
||||
(module+ main
|
||||
(displayln "Day 9"))
|
||||
|
||||
(define (read-input filename)
|
||||
(list->vector (map string->number (file->lines filename))))
|
||||
|
||||
(define (initial-state p m)
|
||||
(reverse (for/list ([x (in-vector p 0 m)])
|
||||
(for/list ([y (in-vector p 0 m)]
|
||||
#:unless (= x y))
|
||||
(+ x y)))))
|
||||
|
||||
(define (update-state s p k)
|
||||
(define m (length (car s)))
|
||||
(define new-sums (for/list ([x (in-vector p (- k m) k)])
|
||||
(+ x (vector-ref p k))))
|
||||
(append (cdr s) (list new-sums)))
|
||||
|
||||
(define (in-state? s x)
|
||||
(member x (flatten s)))
|
||||
|
||||
;; The initial state is computed in O(m^2), and the search itself is
|
||||
;; only O(nm), where n is the length of the input, because updating
|
||||
;; the state is linear in m. So the overall complexity is O(m^2 + nm)
|
||||
;; instead of O(nm^2) for the naïve solution.
|
||||
(define (find-invalid-number p m)
|
||||
(define-values (s x)
|
||||
(for/fold ([s (initial-state p m)]
|
||||
[x (vector-ref p m)])
|
||||
([k (in-naturals m)]
|
||||
#:break (not (in-state? s x)))
|
||||
(values (update-state s p k)
|
||||
(vector-ref p k))))
|
||||
x)
|
||||
|
||||
(define (part1 filename m)
|
||||
(find-invalid-number (read-input filename) m))
|
||||
|
||||
(module+ test
|
||||
(check-equal? (part1 "test" 5) 127))
|
||||
|
||||
(module+ main
|
||||
(displayln (part1 "input" 25)))
|
||||
|
||||
(define (part2 filename m)
|
||||
(define p (read-input filename))
|
||||
(define n (vector-length p))
|
||||
(define invalid (find-invalid-number p m))
|
||||
(for*/last ([width (in-range 2 n)]
|
||||
[i (in-range 0 (- n width))])
|
||||
(define contiguous (vector->list (vector-copy p i (+ i width))))
|
||||
#:final (= invalid (apply + contiguous))
|
||||
(+ (apply min contiguous)
|
||||
(apply max contiguous))))
|
||||
|
||||
(module+ test
|
||||
(check-equal? (part2 "test" 5) 62))
|
||||
|
||||
(module+ main
|
||||
(displayln (part2 "input" 25)))
|
1000
2020/day09/input
Normal file
1000
2020/day09/input
Normal file
File diff suppressed because it is too large
Load diff
20
2020/day09/test
Normal file
20
2020/day09/test
Normal file
|
@ -0,0 +1,20 @@
|
|||
35
|
||||
20
|
||||
15
|
||||
25
|
||||
47
|
||||
40
|
||||
62
|
||||
55
|
||||
65
|
||||
95
|
||||
102
|
||||
117
|
||||
150
|
||||
182
|
||||
127
|
||||
219
|
||||
299
|
||||
277
|
||||
309
|
||||
576
|
Loading…
Add table
Add a link
Reference in a new issue