Day 11

Previous: Day 10 | Next: Day 12
###AUTO-ACQUIRED DATA FOLLOWS…
archivist/day11.lisp
archivist/day11.lisp
(asdf:load-system :split-sequence)
    (asdf:load-system :iterate)
    (asdf:load-system :alexandria)
    (defpackage \#:aoc-11
      (:use \#:cl \#:split-sequence \#:iterate \#:alexandria))
    (in-package \#:aoc-11)
    
    (defun getinput ()
        (let ((in (uiop:read-file-lines "input")))
          (make-array (list (length in)
                            (length (car in)))
                      :initial-contents in)))
    
    (defun cval (c)
        (cond ((eq c \#\\#) 1)
              ((eq c \#\L) 0)
              ((eq c \#\.) 0)))
    
    (defun getval (x y arr dims)
        (if (or (> x (1- (car dims)))
                (< x 0)
                (> y (1- (cadr dims)))
                (< y 0)
                )
            0
            (cval (aref arr x y))))
    
    (defun next (x y arr dims)
        (let ((sum 
                (+ 
                  (getval (1+ x) y arr dims)
                  (getval (1+ x) (1+ y) arr dims)
                  (getval x (1+ y) arr dims)
                  (getval (1- x) (1+ y) arr dims)
                  (getval (1- x) y arr dims)
                  (getval (1- x) (1- y) arr dims)
                  (getval x (1- y) arr dims)
                  (getval (1+ x) (1- y) arr dims)
                   
                   ))
              (state (aref arr x y)))
          (cond ((and (eq state \#\L)
                      (eq sum 0))
                 \#\\#)
                ((and (eq state \#\\#)
                      (>= sum 4))
                 \#\L) 
                (t state))))
    
    
    (defun part1 ()
        (let\* ((grid (getinput))
               (grid-2 (copy-array grid))
               (dims (array-dimensions grid)))
        (do ((stable nil)
             (filled 0 ))
            ((eq stable t) filled)
            (setf stable t)
            (setf filled 0)
          (do ((i 0 (1+ i)))
              ((> i (1- (car dims))))
            (do ((j 0 (1+ j)))
                ((> j (1- (cadr dims))))
                (let ((new (next i j grid dims)))
                  (if (not (eq new (aref grid i j)))
                      (setf stable nil))
                  (setf (aref grid-2 i j) new)
                  (if (equal \#\\# new) (incf filled)))))
          (setf grid (copy-array grid-2)))))
    
    (defun look (x y dirx diry arr dims)
        (if (or (> x (1- (car dims)))
                (< x 0)
                (> y (1- (cadr dims)))
                (< y 0))
            0
            (if (or (eq (aref arr x y) \#\\#)
                    (eq (aref arr x y) \#\L)) 
                (cval (aref arr x y))
                (look (+ x dirx) (+ y diry) dirx diry
                      arr dims))))
    
    (defun next-2 (x y arr dims)
        (let ((sum 
                (+ 
                  (look (1+ x) y 1 0 arr dims)
                  (look (1+ x) (1+ y) 1 1 arr dims)
                  (look x (1+ y) 0 1 arr dims)
                  (look (1- x) (1+ y) -1 1 arr dims)
                  (look (1- x) y -1 0 arr dims)
                  (look (1- x) (1- y) -1 -1 arr dims)
                  (look x (1- y) 0 -1 arr dims)
                  (look (1+ x) (1- y) 1 -1 arr dims)))
              (state (aref arr x y)))
          ;(format t "~a,~a: ~a~%" x y sum)
          (cond ((and (eq state \#\L)
                      (eq sum 0))
                 \#\\#)
                ((and (eq state \#\\#)
                      (>= sum 5))
                 \#\L) 
                (t state))))
    
    (defun part2 ()
        (let\* ((grid (getinput))
               (grid-2 (copy-array grid))
               (dims (array-dimensions grid)))
        (do ((stable nil)
             (filled 0 ))
            ((eq stable t) filled)
            (setf stable t)
            (setf filled 0)
          (do ((i 0 (1+ i)))
              ((> i (1- (car dims))))
            (do ((j 0 (1+ j)))
                ((> j (1- (cadr dims))))
                (let ((new (next-2 i j grid dims)))
                  (if (not (eq new (aref grid i j)))
                      (setf stable nil))
                  (setf (aref grid-2 i j) new)
                  (if (equal \#\\# new) (incf filled)))))
          (setf grid (copy-array grid-2))
          )))
    
unknown-cnile/ucnile-day11.c
unknown-cnile/ucnile-day11.c
\#include <stdlib.h>
    \#include <stdio.h>
    \#include <string.h>
    \#include <sys/types.h>
    \#include <sys/stat.h>
    \#include <fcntl.h>
    \#include <sys/mman.h>
    \#include <unistd.h>
    \#include <stdint.h>
    \#include <limits.h>
    
    void die(char \*str) {
        fprintf(stderr, "[ERROR] %s\n", str);
        exit(-1);
    }
    
    FILE \*map\_file(const char \*filename) {
        int fd;
        if ((fd = open(filename, O\_RDONLY)) == -1) die("failed to open file");
        struct stat fd\_stat;
        if (fstat(fd, &fd\_stat) == -1) die("failed to stat file");
        void \*data;
        // never unmapped, probably fine
        if ((data = mmap(NULL,
                         fd\_stat.st\_size,
                         PROT\_READ,
                         MAP\_PRIVATE,
                         fd, 0)) == MAP\_FAILED) die("failed to map file");
        close(fd);
        return fmemopen(data, fd\_stat.st\_size, "r");
    }
    
    \#define MAX\_X 128
    \#define MAX\_Y 4096
    
    uint8\_t data\_orig[MAX\_X\*MAX\_Y];
    uint8\_t data\_1[MAX\_X\*MAX\_Y];
    uint8\_t data\_2[MAX\_X\*MAX\_Y];
    uint8\_t \*data\_cur = data\_orig;
    uint8\_t \*data\_nxt = data\_1;
    int row\_cnt = 0;
    
    \#define MAX\_LINE 512
    
    \#define FLOOR 0
    \#define EMPTY 1
    \#define FULL 2
    
    void restore() {
        data\_cur = data\_orig;
        data\_nxt = data\_1;
    }
    
    void swap() {
        data\_cur = (data\_cur == data\_1) ? data\_2 : data\_1;
        data\_nxt = (data\_nxt == data\_1) ? data\_2 : data\_1;
    }
    
    uint8\_t \*next\_seat(int x, int y, int dx, int dy, int is\_p1) {
        while (1) {
            x += dx;
            y += dy;
            if ((x < 0) || (x >= MAX\_X) || (y < 0) || (y >= row\_cnt)) return NULL;
            uint8\_t \*r = data\_cur + (y\*MAX\_X+x);
            if (\*r != FLOOR) return r;
            if (is\_p1) return NULL;
        }
    }
    
    int find\_adj(int is\_p1, int x, int y) {
        int acc = 0;
        for (int dx = -1; dx < 2; dx++) {
            for (int dy = -1; dy < 2; dy++) {
                if (dx | dy) {
                    uint8\_t \*ptr = next\_seat(x, y, dx, dy, is\_p1);
                    if (ptr && (\*ptr == FULL)) acc++;
                }
            }
        }
        return acc;
    }
    
    int tick(int is\_p1) {
        for (int y = 0; y < row\_cnt; y++) {
            for (int x = 0; x < MAX\_X; x++) {
                switch (data\_cur[y\*MAX\_X+x]) {
                    case FLOOR: data\_nxt[y\*MAX\_X+x] = FLOOR; break;
                    case EMPTY: data\_nxt[y\*MAX\_X+x] = find\_adj(is\_p1, x, y) ? EMPTY : FULL; break;
                    case FULL: data\_nxt[y\*MAX\_X+x] = ((find\_adj(is\_p1, x, y) + is\_p1) >= 5) ? EMPTY : FULL; break;
                    default: \_\_builtin\_trap();
                }
            }
        }
        uint8\_t \*old\_nxt = data\_nxt;
        int r = !!memcmp(data\_cur, data\_nxt, row\_cnt\*MAX\_X);
        swap();
        return r;
    }
    
    void prt() {
        for (int y = 0; y < row\_cnt; y++) {
            for (int x = 0; x < MAX\_X; x++)
            switch (data\_cur[y\*MAX\_X+x]) {
                case FLOOR: putchar(&\#39;.&\#39;); break;
                case EMPTY: putchar(&\#39;L&\#39;); break;
                case FULL: putchar(&\#39;@&\#39;); break;
            }
            putchar(&\#39;\n&\#39;);
        }
    }
    
    int cnt\_occ() {
        int acc = 0;
        for (int i = 0; i < MAX\_X\*row\_cnt; i++) {
            acc += data\_cur[i] == FULL;
        }
        return acc;
    }
    
    int main(int argc, char \*\*argv) {
        // read input
        FILE \*fd = map\_file("test.txt");
        char line[MAX\_LINE];
        while (fgets(line, MAX\_LINE, fd) != NULL) {
            for (int i = 0; line[i] > &\#39;\n&\#39;; i++) {
                if (i == MAX\_X) die("overflow");
                uint8\_t v;
                switch (line[i]) {
                    case &\#39;L&\#39;: v = EMPTY; break;
                    case &\#39;\#&\#39;: v = FULL; break;
                    default: v = FLOOR; break;
                }
                data\_orig[MAX\_X\*row\_cnt+i] = v;
            }
            row\_cnt++;
        }
        // part one
        while (tick(1)) {}
        printf("P1: %d\n", cnt\_occ());
        restore();
        // part two
        while (tick(0)) {}
        printf("P2: %d\n", cnt\_occ());
        return 0;
    }
    

Tags: