advent-utils
A Clojure library of helper utilities for solving Advent of Code puzzles
Usage
Add the following to your Leiningen :dependencies
[advent-utils "0.1.4"]
advent-utils.core
The core
namespace contains the main helper functions for loading the
puzzle inputs (saved as files) plus a variety of small utility functions
that tend to be needed across multiple puzzles
Managing puzzle inputs
(ns foo
(:require [advent-utils.core :as u]))
; Save your puzzle input to the `resources` directory of your project and then
; `puzzle-input` will return a seq, with an element for each row in the input file
=> (def day01-input (u/puzzle-input "day01-input.txt"))
; Sometimes puzzle inputs will consist of multiple "chunks", with each chunk
; separated by a blank line. For those cases, use `split-at-blankline`
=> (u/split-at-blankline ["Chunk 1"
"Some values"
""
"Chunk 2"
"Some other values"])
[["Chunk 1" "Some values"]
["Chunk 2" "Some other values"]]
Helper/utility functions
; Apply a function to the values of a map
=> (u/fmap inc {:a 1 :b 2 :c 3})
{:a 2 :b 3 :c 4}
; ...or the keys of a map
=> (u/kmap inc {0 :a 1 :b 2 :c})
{1 :a 2 :b 3 :c}
; Return a map with certain keys excluded
=> (u/without-keys {:a 1 :b 2 :c 3 :d 4} [:a :d])
{:b 2 :c 3}
; Swap the keys/vals of a map, for a 1:1 mapping
=> (u/invert-map {:a 0 :b 1 :c 2})
{0 :a 1 :b 2 :c}
; Rotate the elements of a collection, keeping the same size.
; Positive shifts rotate "left". Negative shifts rotate "right"
=> (u/rotate 1 '(0 1 2 3 4))
(1 2 3 4 0)
=> (u/rotate -1 '(0 1 2 3 4))
(4 0 1 2 3)
; Find the position in a collection of the first occurrence of x
=> (u/index-of 8 [1 2 4 8 16])
3
; Count the elements of a collection that satisfy a predicate
=> (u/count-if (range 10) odd?)
5
advent-utils.binary
The binary
namespace contains the helper functions for converting to-and-from binary repesentations of numbers
(ns foo
(:require [advent-utils.binary :as b]))
; Convert an int value into a binary string representation of 0s and 1s
=> (u/int->bitstr 2147483647)
"1111111111111111111111111111111"
=> (u/int->bitstr 9223372036854775808N)
"1000000000000000000000000000000000000000000000000000000000000000"
; And convert the binary string representation back to a value
=> (u/bitstr->int "11011")
27
advent-utils.digest
The digest
namespace contains the helper functions for working with message digests (e.g. MD5)
(ns foo
(:require [advent-utils.digest :as d]))
=> (d/md5-str "hello")
"5d41402abc4b2a76b9719d911017c592"
advent-utils.graph
The graph
namespace provides a couple of data structures for representing
graphs (sets of nodes and edges), as well as classic graph algorithms like
Dijkstra's algorithm.
(ns foo
(:require [advent-utils.graph :as graph]))
TODO: Add more documentation
advent-utils.grid
The grid
namespace has helpers for dealing with values on a regular
2D grid of values, i.e. where there are values/objects at given [x y]
coordinates.
The namespace defines a protocol Grid2D
, for which there
are two implementations.
-
MapGrid2D
uses a map as its underlying data structure, with the[x y]
positions as keys. This implementation is particularly useful if the grid size does not remain static -
VecGrid2D
uses a vector of vectors as its underlying structure.
(ns foo
(:require [advent-utils.grid :as grid :refer [width height value neighbors-4 neighbors-8]]
[advent-utils.grid.mapgrid :as mg]
[advent-utils.grid.vecgrid :as vg]))
; Compute the adjacent coordinates for a given position
=> (grid/adj-coords-2d [0 0])
[[0 -1] [-1 0] [0 1] [1 0]]
; Can specify :include-diagonals true to get the 8 adjacent coordinates
=> (grid/adj-coords-2d [0 0] :include-diagonals true)
[[-1 -1] [0 -1] [1 -1] [-1 0] [1 0] [-1 1] [0 1] [1 1]]
; ascii->MapGrid2D converts ASCII-art grids into a data structure
; The keys of `:grid` are [x y] positions, indexed from the upper-left corner
=> (mg/ascii->MapGrid2D {\. :space \# :wall} ["..#" ".#." "#.."]))
#MapGrid2D{:width 3 :height 3 :grid {[0 0] :space [1 0] :space [2 0] :wall
[0 1] :space [1 1] :wall [2 1] :wall
[0 2] :wall [1 2] :space [2 2] :space}}
; Alternatively, ascii->VecGrid2D converts the same ASCII grids into the
; VecGrid2D structure
=> (def foo (vg/ascii->VecGrid2D {\. :space \# :wall} ["..#" ".#." "#.."])
#VecGrid2D{:v [[:space :space :wall]
[:space :wall :space]
[:wall :space :space]]}
; Either implementation supports all the functions defined in the `Grid2D` protocol
=> (width foo)
3
=> (height foo)
3
=> (value foo [1 0])
:space
=> (neighbors-4 foo [1 1])
{[1 0] :space, [0 1] :space, [1 2] :space, [2 1] :space}
=> (neighbors-8 foo [1 1])
{[0 0] :space [1 0] :space [2 0] :wall
[0 1] :space [2 1] :space
[0 2] :wall [1 2] :space [2 2] :space}
advent-utils.math
The math
namespace contains helper functions, especially for modular arithmetic
(ns foo
(:require [advent-utils.math :as math]))
TODO: Add more documentation
advent-utils.maze
The maze
namespace has functions that help with path-finding in a maze.
(ns foo
(:require [advent-utils.math :as math]))
TODO: Add more documentation
License
Copyright © 2022 Ken Smith
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.