···11+# Change Log
22+All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/).
33+44+## [Unreleased]
55+### Changed
66+- Add a new arity to `make-widget-async` to provide a different widget shape.
77+88+## [0.1.1] - 2025-12-01
99+### Changed
1010+- Documentation on how to make the widgets.
1111+1212+### Removed
1313+- `make-widget-sync` - we're all async, all the time.
1414+1515+### Fixed
1616+- Fixed widget maker to keep working when daylight savings switches over.
1717+1818+## 0.1.0 - 2025-12-01
1919+### Added
2020+- Files from the new template.
2121+- Widget maker public API - `make-widget-sync`.
2222+2323+[Unreleased]: https://sourcehost.site/your-name/aoc2025/compare/0.1.1...HEAD
2424+[0.1.1]: https://sourcehost.site/your-name/aoc2025/compare/0.1.0...0.1.1
+280
LICENSE
···11+Eclipse Public License - v 2.0
22+33+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
44+ PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
55+ OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
66+77+1. DEFINITIONS
88+99+"Contribution" means:
1010+1111+ a) in the case of the initial Contributor, the initial content
1212+ Distributed under this Agreement, and
1313+1414+ b) in the case of each subsequent Contributor:
1515+ i) changes to the Program, and
1616+ ii) additions to the Program;
1717+ where such changes and/or additions to the Program originate from
1818+ and are Distributed by that particular Contributor. A Contribution
1919+ "originates" from a Contributor if it was added to the Program by
2020+ such Contributor itself or anyone acting on such Contributor's behalf.
2121+ Contributions do not include changes or additions to the Program that
2222+ are not Modified Works.
2323+2424+"Contributor" means any person or entity that Distributes the Program.
2525+2626+"Licensed Patents" mean patent claims licensable by a Contributor which
2727+are necessarily infringed by the use or sale of its Contribution alone
2828+or when combined with the Program.
2929+3030+"Program" means the Contributions Distributed in accordance with this
3131+Agreement.
3232+3333+"Recipient" means anyone who receives the Program under this Agreement
3434+or any Secondary License (as applicable), including Contributors.
3535+3636+"Derivative Works" shall mean any work, whether in Source Code or other
3737+form, that is based on (or derived from) the Program and for which the
3838+editorial revisions, annotations, elaborations, or other modifications
3939+represent, as a whole, an original work of authorship.
4040+4141+"Modified Works" shall mean any work in Source Code or other form that
4242+results from an addition to, deletion from, or modification of the
4343+contents of the Program, including, for purposes of clarity any new file
4444+in Source Code form that contains any contents of the Program. Modified
4545+Works shall not include works that contain only declarations,
4646+interfaces, types, classes, structures, or files of the Program solely
4747+in each case in order to link to, bind by name, or subclass the Program
4848+or Modified Works thereof.
4949+5050+"Distribute" means the acts of a) distributing or b) making available
5151+in any manner that enables the transfer of a copy.
5252+5353+"Source Code" means the form of a Program preferred for making
5454+modifications, including but not limited to software source code,
5555+documentation source, and configuration files.
5656+5757+"Secondary License" means either the GNU General Public License,
5858+Version 2.0, or any later versions of that license, including any
5959+exceptions or additional permissions as identified by the initial
6060+Contributor.
6161+6262+2. GRANT OF RIGHTS
6363+6464+ a) Subject to the terms of this Agreement, each Contributor hereby
6565+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
6666+ license to reproduce, prepare Derivative Works of, publicly display,
6767+ publicly perform, Distribute and sublicense the Contribution of such
6868+ Contributor, if any, and such Derivative Works.
6969+7070+ b) Subject to the terms of this Agreement, each Contributor hereby
7171+ grants Recipient a non-exclusive, worldwide, royalty-free patent
7272+ license under Licensed Patents to make, use, sell, offer to sell,
7373+ import and otherwise transfer the Contribution of such Contributor,
7474+ if any, in Source Code or other form. This patent license shall
7575+ apply to the combination of the Contribution and the Program if, at
7676+ the time the Contribution is added by the Contributor, such addition
7777+ of the Contribution causes such combination to be covered by the
7878+ Licensed Patents. The patent license shall not apply to any other
7979+ combinations which include the Contribution. No hardware per se is
8080+ licensed hereunder.
8181+8282+ c) Recipient understands that although each Contributor grants the
8383+ licenses to its Contributions set forth herein, no assurances are
8484+ provided by any Contributor that the Program does not infringe the
8585+ patent or other intellectual property rights of any other entity.
8686+ Each Contributor disclaims any liability to Recipient for claims
8787+ brought by any other entity based on infringement of intellectual
8888+ property rights or otherwise. As a condition to exercising the
8989+ rights and licenses granted hereunder, each Recipient hereby
9090+ assumes sole responsibility to secure any other intellectual
9191+ property rights needed, if any. For example, if a third party
9292+ patent license is required to allow Recipient to Distribute the
9393+ Program, it is Recipient's responsibility to acquire that license
9494+ before distributing the Program.
9595+9696+ d) Each Contributor represents that to its knowledge it has
9797+ sufficient copyright rights in its Contribution, if any, to grant
9898+ the copyright license set forth in this Agreement.
9999+100100+ e) Notwithstanding the terms of any Secondary License, no
101101+ Contributor makes additional grants to any Recipient (other than
102102+ those set forth in this Agreement) as a result of such Recipient's
103103+ receipt of the Program under the terms of a Secondary License
104104+ (if permitted under the terms of Section 3).
105105+106106+3. REQUIREMENTS
107107+108108+3.1 If a Contributor Distributes the Program in any form, then:
109109+110110+ a) the Program must also be made available as Source Code, in
111111+ accordance with section 3.2, and the Contributor must accompany
112112+ the Program with a statement that the Source Code for the Program
113113+ is available under this Agreement, and informs Recipients how to
114114+ obtain it in a reasonable manner on or through a medium customarily
115115+ used for software exchange; and
116116+117117+ b) the Contributor may Distribute the Program under a license
118118+ different than this Agreement, provided that such license:
119119+ i) effectively disclaims on behalf of all other Contributors all
120120+ warranties and conditions, express and implied, including
121121+ warranties or conditions of title and non-infringement, and
122122+ implied warranties or conditions of merchantability and fitness
123123+ for a particular purpose;
124124+125125+ ii) effectively excludes on behalf of all other Contributors all
126126+ liability for damages, including direct, indirect, special,
127127+ incidental and consequential damages, such as lost profits;
128128+129129+ iii) does not attempt to limit or alter the recipients' rights
130130+ in the Source Code under section 3.2; and
131131+132132+ iv) requires any subsequent distribution of the Program by any
133133+ party to be under a license that satisfies the requirements
134134+ of this section 3.
135135+136136+3.2 When the Program is Distributed as Source Code:
137137+138138+ a) it must be made available under this Agreement, or if the
139139+ Program (i) is combined with other material in a separate file or
140140+ files made available under a Secondary License, and (ii) the initial
141141+ Contributor attached to the Source Code the notice described in
142142+ Exhibit A of this Agreement, then the Program may be made available
143143+ under the terms of such Secondary Licenses, and
144144+145145+ b) a copy of this Agreement must be included with each copy of
146146+ the Program.
147147+148148+3.3 Contributors may not remove or alter any copyright, patent,
149149+trademark, attribution notices, disclaimers of warranty, or limitations
150150+of liability ("notices") contained within the Program from any copy of
151151+the Program which they Distribute, provided that Contributors may add
152152+their own appropriate notices.
153153+154154+4. COMMERCIAL DISTRIBUTION
155155+156156+Commercial distributors of software may accept certain responsibilities
157157+with respect to end users, business partners and the like. While this
158158+license is intended to facilitate the commercial use of the Program,
159159+the Contributor who includes the Program in a commercial product
160160+offering should do so in a manner which does not create potential
161161+liability for other Contributors. Therefore, if a Contributor includes
162162+the Program in a commercial product offering, such Contributor
163163+("Commercial Contributor") hereby agrees to defend and indemnify every
164164+other Contributor ("Indemnified Contributor") against any losses,
165165+damages and costs (collectively "Losses") arising from claims, lawsuits
166166+and other legal actions brought by a third party against the Indemnified
167167+Contributor to the extent caused by the acts or omissions of such
168168+Commercial Contributor in connection with its distribution of the Program
169169+in a commercial product offering. The obligations in this section do not
170170+apply to any claims or Losses relating to any actual or alleged
171171+intellectual property infringement. In order to qualify, an Indemnified
172172+Contributor must: a) promptly notify the Commercial Contributor in
173173+writing of such claim, and b) allow the Commercial Contributor to control,
174174+and cooperate with the Commercial Contributor in, the defense and any
175175+related settlement negotiations. The Indemnified Contributor may
176176+participate in any such claim at its own expense.
177177+178178+For example, a Contributor might include the Program in a commercial
179179+product offering, Product X. That Contributor is then a Commercial
180180+Contributor. If that Commercial Contributor then makes performance
181181+claims, or offers warranties related to Product X, those performance
182182+claims and warranties are such Commercial Contributor's responsibility
183183+alone. Under this section, the Commercial Contributor would have to
184184+defend claims against the other Contributors related to those performance
185185+claims and warranties, and if a court requires any other Contributor to
186186+pay any damages as a result, the Commercial Contributor must pay
187187+those damages.
188188+189189+5. NO WARRANTY
190190+191191+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
192192+PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
193193+BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
194194+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
195195+TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
196196+PURPOSE. Each Recipient is solely responsible for determining the
197197+appropriateness of using and distributing the Program and assumes all
198198+risks associated with its exercise of rights under this Agreement,
199199+including but not limited to the risks and costs of program errors,
200200+compliance with applicable laws, damage to or loss of data, programs
201201+or equipment, and unavailability or interruption of operations.
202202+203203+6. DISCLAIMER OF LIABILITY
204204+205205+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
206206+PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
207207+SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
208208+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
209209+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
210210+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
211211+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
212212+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
213213+POSSIBILITY OF SUCH DAMAGES.
214214+215215+7. GENERAL
216216+217217+If any provision of this Agreement is invalid or unenforceable under
218218+applicable law, it shall not affect the validity or enforceability of
219219+the remainder of the terms of this Agreement, and without further
220220+action by the parties hereto, such provision shall be reformed to the
221221+minimum extent necessary to make such provision valid and enforceable.
222222+223223+If Recipient institutes patent litigation against any entity
224224+(including a cross-claim or counterclaim in a lawsuit) alleging that the
225225+Program itself (excluding combinations of the Program with other software
226226+or hardware) infringes such Recipient's patent(s), then such Recipient's
227227+rights granted under Section 2(b) shall terminate as of the date such
228228+litigation is filed.
229229+230230+All Recipient's rights under this Agreement shall terminate if it
231231+fails to comply with any of the material terms or conditions of this
232232+Agreement and does not cure such failure in a reasonable period of
233233+time after becoming aware of such noncompliance. If all Recipient's
234234+rights under this Agreement terminate, Recipient agrees to cease use
235235+and distribution of the Program as soon as reasonably practicable.
236236+However, Recipient's obligations under this Agreement and any licenses
237237+granted by Recipient relating to the Program shall continue and survive.
238238+239239+Everyone is permitted to copy and distribute copies of this Agreement,
240240+but in order to avoid inconsistency the Agreement is copyrighted and
241241+may only be modified in the following manner. The Agreement Steward
242242+reserves the right to publish new versions (including revisions) of
243243+this Agreement from time to time. No one other than the Agreement
244244+Steward has the right to modify this Agreement. The Eclipse Foundation
245245+is the initial Agreement Steward. The Eclipse Foundation may assign the
246246+responsibility to serve as the Agreement Steward to a suitable separate
247247+entity. Each new version of the Agreement will be given a distinguishing
248248+version number. The Program (including Contributions) may always be
249249+Distributed subject to the version of the Agreement under which it was
250250+received. In addition, after a new version of the Agreement is published,
251251+Contributor may elect to Distribute the Program (including its
252252+Contributions) under the new version.
253253+254254+Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
255255+receives no rights or licenses to the intellectual property of any
256256+Contributor under this Agreement, whether expressly, by implication,
257257+estoppel or otherwise. All rights in the Program not expressly granted
258258+under this Agreement are reserved. Nothing in this Agreement is intended
259259+to be enforceable by any entity that is not a Contributor or Recipient.
260260+No third-party beneficiary rights are created under this Agreement.
261261+262262+Exhibit A - Form of Secondary Licenses Notice
263263+264264+"This Source Code may also be made available under the following
265265+Secondary Licenses when the conditions for such availability set forth
266266+in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public
267267+License as published by the Free Software Foundation, either version 2
268268+of the License, or (at your option) any later version, with the GNU
269269+Classpath Exception which is available at
270270+https://www.gnu.org/software/classpath/license.html."
271271+272272+ Simply including a copy of this Agreement, including this Exhibit A
273273+ is not sufficient to license the Source Code under Secondary Licenses.
274274+275275+ If it is not possible or desirable to put the notice in a particular
276276+ file, then You may include the notice in a location (such as a LICENSE
277277+ file in a relevant directory) where a recipient would be likely to
278278+ look for such a notice.
279279+280280+ You may add additional accurate notices of copyright ownership.
···11+(ns aoc2025.core
22+ (:gen-class))
33+44+(defn -main
55+ "I don't do a whole lot ... yet."
66+ [& args]
77+ (println "Hello, World!"))
+138
src/aoc2025/util.clj
···11+(ns aoc2025.util
22+ (:require [clojure.string :as s]
33+ [clojure.walk :as walk]))
44+55+(defn read-file
66+ "Reads fname as a resource into a list of strings of the given resource, split by newlines"
77+ [fname]
88+ (->> fname clojure.java.io/resource slurp s/split-lines))
99+1010+(defn gridify
1111+ "Takes array of strings and turns it into a 2d grid of chars"
1212+ [rows]
1313+ (mapv vec rows))
1414+1515+(defn transpose [m]
1616+ (apply mapv vector m))
1717+1818+(defn parse-int [s] (Integer/parseInt s))
1919+(defn parse-long [s] (Long/parseLong s))
2020+(defn parse-ints [st] (map parse-int (s/split st #"\s+")))
2121+2222+(def reverse-str
2323+ "Just reverses a string into a string"
2424+ (comp (partial apply str) reverse))
2525+2626+(defn indexes-of
2727+ "Returns the indexes of coll where pred-or-val returns true. Values are compared using =, using a function will use that as the predicate instead of ="
2828+ [pred-or-val coll]
2929+ (if (fn? pred-or-val)
3030+ (keep-indexed #(when (pred-or-val %2) %1) coll)
3131+ (keep-indexed #(when (= %2 pred-or-val) %1) coll)))
3232+3333+(defn middle
3434+ "Get the middle element of a collection"
3535+ ([[a b c & rs :as coll]]
3636+ (if rs
3737+ (nth coll (-> coll count dec (/ 2)))
3838+ b)))
3939+4040+(def pairs "Make pairs of a collection" (partial partition 2 1))
4141+4242+(def diffs
4343+ "Calculate the differences of each step of a sequence of numbers"
4444+ (comp (partial map (partial apply -))
4545+ pairs))
4646+4747+(defn re-named-groups
4848+ "Returns map of the named groups in re to the matches in s"
4949+ [re s]
5050+ (let [group-names (->> re str
5151+ (re-seq #"(?:\(\?<([^>]+)>)")
5252+ (map #(-> % second keyword)))
5353+ [_ & matches] (re-matches re s)]
5454+ (zipmap group-names matches)))
5555+5656+(defn -sym?->seq
5757+ "Returns (seq form) if form is a sequence and the first element is sym, else nil"
5858+ [sym form]
5959+ (let [match? (every-pred sequential? #(= sym (first %)))]
6060+ (if (match? form) (seq form) nil)))
6161+6262+(defn get-all
6363+ "Return all elements of ks as a key in m"
6464+ [m ks]
6565+ (for [k ks]
6666+ (get m k)))
6767+6868+(defn divisible?
6969+ ([b] #(divisible? % b))
7070+ ([a b] (zero? (mod a b))))
7171+7272+(defn gcd
7373+ "Calculates the greatest common divisor of a and b"
7474+ ([a b]
7575+ (if (zero? b)
7676+ a
7777+ (let [[a b] (sort > [a b])]
7878+ (recur b (rem a b)))))
7979+ ([a b & xs] (reduce gcd (gcd a b) xs)))
8080+8181+(defn lcm
8282+ "Calculates the least common divisor of a and b"
8383+ ([a b]
8484+ (/ (abs (* a b))
8585+ (gcd a b)))
8686+ ([a b & xs] (reduce lcm (lcm a b) xs)))
8787+8888+(def split-at-space #(clojure.string/split % #" "))
8989+9090+(defn take-until [pred coll]
9191+ (concat
9292+ (take-while (complement pred) coll)
9393+ (list (first (filter pred coll)))))
9494+9595+(def Vector2D [:tuple :int :int])
9696+9797+(defn vec- [[a1 b1] [a2 b2]] [(- a1 a2) (- b1 b2)])
9898+9999+(defn vec+ [[a1 b1] [a2 b2]] [(+ a2 a1) (+ b2 b1)])
100100+101101+(defn determinant [[y1 x1] [y2 x2]] (- (* y1 x2) (* x1 y2)))
102102+103103+(defn drop-nth
104104+ "Returns coll without the nth element (lazily too, I think?)"
105105+ [n coll]
106106+ (lazy-cat (take n coll) (drop (inc n) coll)))
107107+108108+(defn ordered?
109109+ "Returns non-nill if nums are all in an increasing or decreasing order"
110110+ [coll]
111111+ (or (apply < coll) (apply > coll)))
112112+113113+(defn splarse
114114+ "Splits line with re and parses all longs out of the resulting split. Single argument returns a curried call with the specified re"
115115+ ([re] (partial splarse re))
116116+ ([re line]
117117+ (->> (s/split line re) (mapv parse-long))))
118118+119119+(defn between?
120120+ "Defaults to inclusive checking (0 with a min of 0 and max of 10 would return true)"
121121+ ([min-value max-value] #(between? % min-value max-value >=))
122122+ ([min-value max-value pred] #(between? % min-value max-value pred))
123123+ ([x min-value max-value pred] (and (pred x min-value) (pred max-value x))))
124124+125125+(defn invert-map
126126+ "Inverts map, joining duplicate keys as a sequence of values in the result"
127127+ [m]
128128+ (-> (group-by second m) (update-vals (partial mapv first))))
129129+130130+(def adj4 [[0 1] [0 -1] [1 0] [-1 0]])
131131+(def adj8 (conj adj4 [1 1] [1 -1] [-1 1] [-1 -1]))
132132+133133+(defn adj+
134134+ "Returns vector of all adjacent points. Defaults to 8-point, can be passed :4 to only return cardinals"
135135+ ([p] (adj+ :8 p))
136136+ ([t p]
137137+ (let [tm {:4 adj4 :8 adj8}]
138138+ (mapv #(vec+ p %) (get tm t)))))