You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

2.9 KiB

Solution to p23

Solution

Load links as a cons list; in hindsight, we could just load them as a list of pairs, but heh…

  (require 'dash)
  (with-temp-buffer
      (insert-file-contents "input")
      (goto-char (point-min))
      (advent/replace-multiple-regex-buffer
       '(("^\\(.*\\)-\\(.*\\)$" . "(\"\\1\" . \"\\2\")")))
      (insert "(setq data-asym '(")
      (goto-char (point-max))
      (insert "))")
      (eval-buffer))

  (setq data (--mapcat (list it (cons (cdr it) (car it))) data-asym)
        computer-list (-distinct (-map #'car data)))

The following is for part 1

  (defun triples (dataset)
    (-distinct
     (--map  (-sort #'string< it)
             (-mapcat (lambda (pair)
                        (--map (list (car pair) (cdr pair) it)
                               (-intersection (neighbours (car pair))
                                              (neighbours (cdr pair)))))
                      dataset))))

  (defun neighbours (computer)
    (-map #'cdr (--filter (string= (car it) computer) data)))

  (defun good-computer-p (s)
    (string-match-p "t." s)
    )

  (defun good-link-p (link)
    (or (good-computer-p (car link))
        (good-computer-p (cdr link))))

  (length (triples (-filter #'good-link-p data-asym)))
1218

This one is an auxiliary function that plays well with unfold

  (defun split (l)
    (when l (cons l l)))

This is a rather ad-hoc function: takes a list of sets and returns a list of disjoint sets such that each set in the original list intersects with one set in the returned list.

  (defun disjoint-core (clusters)
    (let ((remove-list (car clusters))
          (remainder (cdr clusters)))
      (when remove-list
        (cons remove-list
              (disjoint-core (--remove
                          (-intersection it remove-list)
                          remainder))))))

This is the core of part 2: it is an inductive procedure. We start from a set of clusters of rank n and we find all clusters of rank n+1 that intersect those clusters; we can iterate starting from links and eventually we will get to the top cluster. In order to optimize the induction, at each step we can only work with a disjoint core of clusters the clusters obtained at the previous step

  (defun grow-clusters (dataset)
    (disjoint-core
     (-mapcat (lambda (cluster)
                (--map (cons it cluster)
                       (-reduce #'-intersection
                                (-map #'neighbours cluster))))
              dataset)))

  (setq links (disjoint-core (--map (list (car it) (cdr it)) data-asym))
        poly-sequence (--unfold (split (grow-clusters it)) links))
                                          ;
  (mapconcat #'identity
             (-sort #'string< (car (-last-item poly-sequence)))
             ",")