Skip to content

Instantly share code, notes, and snippets.

@amno1
Last active December 4, 2023 23:56
Show Gist options
  • Save amno1/08f4d98b425b44bb342acbfbe183116a to your computer and use it in GitHub Desktop.
Save amno1/08f4d98b425b44bb342acbfbe183116a to your computer and use it in GitHub Desktop.
Small utility to generate an empty skeleton file for solving AoC puzzles
;;; aoc-helper.el --- Gen AOC skeleton -*- lexical-binding: t; -*-
;; Copyright (C) 2023 Arthur Miller
;; Author: Arthur Miller <arthur.miller@live.com>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; To install, put this file somewhere in your path and require this file
;; To change wher files are generated, modify aoc-repo variable
;; Save your input via web browser from teh AOC challenge per each day under the
;; name of the day, without any suffix (1, 2, 3, etc). The program will generate
;; corresponding file 1.el, 2.el and code to load the input into a temporary
;; Emacs buffer
;; To use with some previous year modify aoc-year, as in example.
;; To use with the latest year challenges (current year) set aoc-year to nil
;; To generate an empty skeleton file, or open an existing one, run aoc-do-day.
;; It will ask you for the day and create a file with the same name or open it
;; if it already exists
;; Optional:
;; It is possible to download the input from withing the Emacs for
;; extra automation, but it does require some fiddling.
;; I have only tested this in Firefox, and all credit is due
;; to Matthias Paulmier https://github.com/mattplm<. You can also see the
;; discussion on Reddit:
;; https://www.reddit.com/r/emacs/comments/187h4e3/aoc_puzzle_skeleton_generator/kbivv4t/?context=3
;; 1. In Firefox, login to adventofcode.com
;; 2. Press F12 while still on the page.
;; 3. Go to the storage tab. Under the "Cookies" menu on the left side of the pane, you
;; should have a line that reads "https://adventofcode.com" (it is most probably
;; already selected). In there, only one cookie exists.
;; 4. copy the content into a file, any file, I chose session-cookie.txt, and
;; there you have your file.
;; 5. Set the value of aoc-cookie to name of that file (defvar aoc-cookie ... )
;; 6. Be sure you have evaluated the aoc-cookie
;; If no cookie file is found no URL requests are made
;; If the cookie file has expired, you will most likely get error response which
;; should be displayed in the input buffer; You will have to repeat the above
;; steps, or just delete the file and download it manually
;;; Code:
(defvar aoc-repo (expand-file-name "~/repos/"))
(defvar aoc-year "2015")
(defvar aoc-cookie (expand-file-name "aoc-cookie" default-directory))
(defun save-input-for-day (year day)
"Save the input of the YEAR and DAY."
(let* ((url (format "https://adventofcode.com/%s/day/%s/input" year day))
(input (expand-file-name (format "AOC%s/%s" year day) aoc-repo))
(cookie (with-temp-buffer
(insert-file-contents aoc-cookie)
(buffer-substring-no-properties (point-min) (1- (point-max)))))
(url-request-extra-headers (list (cons "Cookie" (concat "session=" cookie)))))
(unless (file-exists-p input)
(url-copy-file url input))))
(defun insert-header (year day)
(insert (format ";;; %s --- AOC%s Day %s -*- lexical-binding: t; -*-\n\n"
(file-name-nondirectory (buffer-file-name)) year day))
(insert (format ";; Copyright (C) %s %s\n" (format-time-string "%Y")
user-full-name))
(insert (format ";; Author: %s <%s>\n" (user-full-name) user-mail-address))
(insert "
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; _
;;; Code:\n")
(insert (format ";;; %s ends here" (file-name-nondirectory (buffer-file-name)))))
(defun gen-code (year day)
`(defun ,(make-symbol (format "aoc-%s-%s" year day)) ()
(interactive)
(let ((p1 0)
(p2 0))
(with-temp-buffer
(insert-file-contents-literally ,(expand-file-name (format "%s" day)))
(goto-char (point-min)))
(message "Part I: %s, Part II: %s" p1 p2))))
;;;###autoload
(defun aoc-do-day ()
"Interactively ask and open code and input file for a given day.
If files do not exist, new code file is generated.
If a session cookie exists, see the comment section at the top of this file,
and there is no input file for the day, the input file will be downloaded.
When input file is present, open it in a split screen."
(interactive)
(let* ((auto-insert nil)
(year (or aoc-year (format-time-string "%Y")))
(path (expand-file-name (format "AOC%s/" year) aoc-repo))
(day (read-number "Which day: "))
(input (expand-file-name (format "%s" day) path))
(lisp (expand-file-name (format "%s.el" day) path))
(do-insert nil))
(unless (< 0 day 26) (error "Invalid day; must be in range [1,25]."))
(unless (file-exists-p path)
(message "Created directory %s" path)
(mkdir path t))
(delete-other-windows)
(dired path)
(unless (file-exists-p lisp)
(make-empty-file lisp t)
(setf do-insert t))
(find-file lisp)
(when do-insert (insert-header year day)
(goto-char 1)
(search-forward "Code:")
(insert "\n\n" (pp (gen-code year day)))
(search-backward "nil")
(replace-match "()")
(search-forward "goto-char")
(goto-char (line-end-position))
(forward-char -1)
(insert "\n\n")
(forward-char -1)
(indent-region (point-min) (point-max))
(call-interactively #'indent-for-tab-command))
(when (file-exists-p aoc-cookie)
(save-input-for-day year day))
(when (file-exists-p input)
(find-file-other-window input)
(other-window 1)))
(provide 'aoc-helper)
;;; aoc-helper.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment