;;; solver.el --- Day 12 -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2022 Óscar Nájera ;; ;; Author: Óscar Nájera ;; Maintainer: Óscar Nájera ;; Created: December 12, 2022 ;; Modified: December 12, 2022 ;; ;; This file is not part of GNU Emacs. ;; ;;; Commentary: ;; ;; Day 12 ;; ;;; Code: (require 'ert) (cl-defstruct (land (:constructor land--create) (:copier nil)) "Contaner for the land layout" grid (width nil :read-only t) (height nil :read-only t)) (defun solver-directions (pos land) ;; point on grid is p=x+y*width (let* ((width (land-width land)) (height (land-height land)) (x (mod pos width)) (y (/ pos width))) (delq nil (list (when (< -1 x (1- width)) (1+ pos)) ;; right move (when (< -1 y (1- height)) (+ pos width)) ;; down move (when (< 0 x width) (1- pos)) ;; left move (when (< 0 y height) (- pos width)))))) ;; up move (should (equal (solver-directions 6 (land--create :width 5 :height 5)) '(7 11 5 1))) (should (equal (solver-directions 0 (land--create :width 5 :height 5)) '(1 5))) (defun solver-land (data) (vconcat (mapconcat (lambda (row) (cl-map 'string (lambda (chr) (cl-case chr (?S 0) (?E 27) (t (- chr 96)))) row)) data ""))) (defun solver-next-steps (pos land paths) (let ((elevation (aref (land-grid land) pos))) (unless (= 27 elevation) ;; reached destination (mapcan (lambda (option) (when (and (not (gethash option paths)) (>= (1+ elevation) (aref (land-grid land) option))) ;; allowed move (puthash option (cons option (gethash pos paths)) paths) (list option))) (solver-directions pos land))))) (defun solver-search (queue land paths) (when-let ((next (mapcan (lambda (place) (solver-next-steps place land paths)) queue))) (solver-search next land paths))) (with-temp-buffer ;; (insert "Sabqponm ;; abcryxxl ;; accszExk ;; acctuvwj ;; abdefghi") (insert-file-contents "input") (let* ((data (split-string (buffer-string) "\n" t)) (height (length data)) (width (length (car data))) (land (land--create :grid (solver-land data) :width width :height height)) (start (seq-position (land-grid land) 0 #'eq)) (finish (seq-position (land-grid land) 27 #'eq)) (paths (make-hash-table :test #'eq))) (puthash start (list start) paths) (solver-search (list start) land paths) (1- (length (gethash finish paths))) ))