Zulip Chat Archive
Stream: general
Topic: Advent of Code program verification?
Jason Orendorff (Dec 13 2025 at 17:53):
I'm solving Advent of Code in Lean this year. Is anyone else trying program verification for these, as an exercise? For a beginner like me, they are plenty complicated. I'd love to hang out in a chat where people are doing this... as things stand, I feel pretty alone :)
suhr (Dec 13 2025 at 18:12):
There's one difficulty: a proof is not very useful when the specification and the code are basically the same. This is a common problem with AoC.
But some problems can be fun to verify, like https://adventofcode.com/2025/day/5. In part 2 of this day the naive solution is not feasible, but a with a bit of thinking you can solve it quite elegantly.
suhr (Dec 13 2025 at 18:12):
And these bits of thinking demand a proof.
suhr (Dec 13 2025 at 18:14):
By the way, here's my solution in K: https://gist.github.com/suhr/4dde948d1d138d56fcc27da892bdb5b8. Which is basically an application of https://www.jsoftware.com/papers/50/50_05.htm.
Jakub Nowak (Dec 13 2025 at 18:54):
Even when specification and the code are basically the same, you can still prove well-formedness, e.g. that you doesn't lookup array outside it bounds.
Jakub Nowak (Dec 13 2025 at 18:57):
Also, you can do things like, write a program that can enumerate all possible (or some subset of) problems together with their solutions, and then you can prove that your program finds the solution for every problem.
Jakub Nowak (Dec 13 2025 at 18:59):
The specification of generating a problem from a solution, can be different, then that of finding a solution, so you get an extra check, that these two specification you wrote coincide.
Jakub Nowak (Dec 13 2025 at 19:05):
Though, in some cases, enumerating possible problems for a given solution can be much more difficult then finding a solution. .-.
Jason Orendorff (Dec 13 2025 at 19:58):
The problem, properly expressed, is not the same as my solution for any of the problems this year except day 1. Finding a reasonable way to express the spec is the first problem, for me...
(although the problem for day 12 is NP-complete, so... maybe set that aside for now)
Jason Orendorff (Dec 13 2025 at 20:00):
Jakub, i don't understand - all my solutions give the puzzle input a type, so the possibility space is clearly enumerable (?)
Jason Orendorff (Dec 13 2025 at 20:06):
The problem I've been thinking about today is day 3. It talks about "the largest possible" something. The use of the definite article in the question implies at least one such something exists, and that the set is finite...
Mapping that to Lean isn't super easy
suhr (Dec 13 2025 at 20:09):
largest (x: α) (p: α → Prop) := p x ∧ ∀y, p y → y ≤ x
suhr (Dec 13 2025 at 20:15):
If 987654321111111 is an a list of digits, then what needed is sublist of a certain length which then is turned into a number.
suhr (Dec 13 2025 at 20:18):
A useful way to think about sublist in this case is selection (as in https://mlochbaum.github.io/BQN/doc/select.html).
suhr (Dec 13 2025 at 20:21):
Then you basically take advantage of order relation on both indicies (more specifically, remaining choices) and digits.
suhr (Dec 13 2025 at 20:26):
Jason Orendorff said:
The problem, properly expressed, is not the same as my solution for any of the problems this year except day 1.
Funny enough, I wrote an informal proof for part 2 in order to debug my solution. It was not effective though, since the bug was in the code, not in how I solved the problem.
suhr (Dec 13 2025 at 20:28):
Here it is: https://gist.github.com/suhr/70f87b73e763b6238403f0abeaa2d675
Jason Orendorff (Dec 13 2025 at 21:04):
ok you would not believe what i was doing before, trying to write a spec for day 3, but now I have this
Spec for Day 3
Jakub Nowak (Dec 14 2025 at 15:14):
Jason Orendorff said:
Jakub, i don't understand - all my solutions give the puzzle input a type, so the possibility space is clearly enumerable (?)
Enumerating just inputs will only let you check that the program is well-formed.
Let's say, you have types Statement and Solution for the input and output of the solution program. So the solution code would be a function solution : Statement → Solution. Nothing interesting so far. Now, what you could do, is write a function statements : Solution → Set Statement. Function statements, given the solution, would generate some statements, for a particular given solution. With these two functions, you can prove ∀ sol : Solution, ∀ stmt ∈ statements sol, solution stmt = sol.
Creating Set Statement of all statements is usually easy. Creating Solution → Set Statement that enumerates all statements for a given solution, is often not easy.
Of course, you could define statements sol := { stmt : Statement | solution stmt = sol }, but then, the aforementioned proof is just tautology. The point is to write it independently.
Jakub Nowak (Dec 14 2025 at 15:17):
(deleted)
Last updated: Dec 20 2025 at 21:32 UTC