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.
 

3.1 KiB

Solution to p12

Load the file into a list of lines

(require 'dash)
  (with-temp-buffer
    (insert-file-contents "input")
    (goto-char (point-min))
    (replace-regexp "^" "\"")
       (goto-char (point-min))
       (replace-regexp "$" "\"")
    (goto-char (point-min))
     (insert "(setq data '(")
    (goto-char (point-max))
    (insert "))")
    (eval-buffer))

and split into a list of list of chars

  (setq data-chars (-map (lambda (str) (--map (string-to-char it) (split-string str "\\|.+" t)))
             data)
      height (length data-chars)
      width (length (car data-chars)))
140
  (defun acceptable-p (p)
    (let ((x (car p))
	  (y (cadr p)))
      (and (>= x 0) (>= y 0) (< x width) (< y height)) ))

  (defun neighbours (p)
    (let ((x (car p))
	  (y (cadr p)))
      (-map (lambda (q) (list (+ x (car q)) (+ y (cadr q)))) '((+1 0) (-1 0) (0 1) (0 -1)))))

  (defun acceptable-neighbours (p)
    (-filter #'acceptable-p (neighbours p)))

  (defun plant (p)
    (if (not (acceptable-p p)) ?. 
      (nth (car p) (nth (cadr p) data-chars))))

collect all plants type and return a list of list of positions

  (setq plants (-distinct (-mapcat #'identity data-chars)))

  (setq groups (-map (lambda (pl)
		       (-map #'cadr
			      (--filter (eq (car it) pl)
					(-mapcat #'identity
						  (-map-indexed (lambda (y l) (-map-indexed (lambda (x el) (list el (list x y))) l)) data-chars)))))
		     plants))

now we need to split each group into regions ACC is a list of regions. The function

   (defun agglomerate (acc el)
     (let ((nbhs (acceptable-neighbours el)))
(cons (-mapcat #'identity (cons (list el) (--filter (-intersection it nbhs) acc))) 
      (--filter (not (-intersection it nbhs)) acc))
)
     )

   (setq regions (--mapcat (-reduce-from #'agglomerate nil it) groups))
  (defun count-fence (el)
    (let ((i (plant el))
	  (pos el))
      (length (--filter (not (eq i it)) (-map #'plant (neighbours pos))))))

  (defun vertex-p (el dir)
    (let* ((x (car el))
	   (y (cadr el))
	   (a (car dir))
	   (b (cadr dir))
	   (opposite (list (+ x a) (+ y b)))
	   (adjh (list (+ x a) y))
	   (adjv (list x (+ y b))))
      (or (and (not (eq (plant el) (plant adjh)))
	       (not (eq (plant el) (plant adjv))))
	  (and (eq (plant el) (plant adjh))
	       (eq (plant el) (plant adjv))
	       (not (eq (plant el) (plant opposite))))))
    )
  (defun count-vertices (el)
    (length (-non-nil (--map (vertex-p el it) '((1 1) (1 -1) (-1 1) (-1 -1)))))
    )

  (-reduce #'+  (--map (* (car it) (cdr it))
		       (-zip-pair (-map #'length regions)
				  (-map (lambda (region) (-reduce #'+ (-map #'count-fence region))) regions))))

    (-reduce #'+  (--map (* (car it) (cdr it))
		       (-zip-pair (-map #'length regions)
				  (-map (lambda (region) (-reduce #'+ (-map #'count-vertices region))) regions))))
859494