Skip to content

Instantly share code, notes, and snippets.

@tomtheisen
Last active December 8, 2025 23:20
Show Gist options
  • Select an option

  • Save tomtheisen/988313020d199284954dd722d3fee7fc to your computer and use it in GitHub Desktop.

Select an option

Save tomtheisen/988313020d199284954dd722d3fee7fc to your computer and use it in GitHub Desktop.
AOC 2025
! AOC 2025 Day 1-1
#(
(
/^/ => fx { 50 set(pos) }
/L(\d+)/ => { get(pos) $1 + 100 % set(pos) }
/R(\d+)/ => { get(pos) $1 - 100 + 100 % set(pos) }
)
/\b0\b/ => fx{ inc(zeroes) }
{ get(zeroes) }
)
! AOC 2025 Day 1-2
def(move) {
get(pos) + 100 + 100 % set(pos)
0 = if { inc(zeroes) }
}
#(
(
/^/ => fx{ 50 set(pos) }
/L(\d+)/ => fx{ $1 times { -1 do(move) } }
/R(\d+)/ => fx{ $1 times { 1 do(move) } }
)
{ get(zeroes) }
)
! AOC 2025 Day 2-1
#(
! ensure equal sizes for start, end
/\b((?:\d{2})+\d)-/ => ( /^/ => "1" /\d/ => "0" )
/-((?:\d{2})+\d)\b/ => ( /-\d/ => "-" /\d/ => "9" )
! format for readability
(/\s/ => "" ',' => "\n")
! delimit halfway point of each number
/\d+/ => { _ _ len 2 / take "," _ _ len 2 / skip}
! split each number in half rounding as necessary
/(\d+),(\d+)-/ => { $1 $2 $1 > + "-" }
/-(\d+),(\d+)/ => { "-" $1 $2 $1 < - }
! unroll each range
/(\d+)-(\d+)/ => {
$2 $1 >= if {
$1
$2 $1 - times { copy " " swap 1 + }
}
}
! running total of duplicated prefixes
/\d+/ => fx{ _ _ cat get(total) + set(total) }
{ get(total) }
)
! AOC 2025 Day 2-2
#(
! format for readability
(/\s/ => "" ',' => "\n")
! normalize mismatched lengths
/(\d+)-(\d+)/ => {
$2 len $1 len > if
{
$1 "-" $1 len times { 9 }
"\n"
1 $1 len times { 0 } "-" $2
}
{ _ }
}
/(\d+)-(\d+)/ => {
empty(invalid)
1 set(reps) drop
10 times {
inc(reps)
$1 len get(reps) % 0 = if {
! get adjusted prefix for range start
$1 $1 len get(reps) / take set(pfx)
get(reps) 1 - times { get(pfx) cat }
$1 < if { inc(pfx) }
get(pfx) set(start_unit) drop
! get adjusted prefix for range end
$2 $2 len get(reps) / take set(pfx)
get(reps) 1 - times { get(pfx) cat }
$2 > if { dec(pfx) }
get(pfx) set(end_unit) drop
! iterate
get(start_unit) set(i) drop
get(end_unit) 1 + get(start_unit) - times {
get(reps) times { get(i) cat }
push(invalid)
inc(i)
}
}
}
_
uniq(invalid) for(invalid) {
get(total) _ + set(total) drop
"\n" _
}
count(invalid) 0 = if { "\nnone" }
"\n"
}
/^/ => { "Grand total: " get(total) "\n---\n" }
)
! AOC 2025 Day 3-1
#(
/(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*9|.*8|.*7|.*6|.*5|.*4|.*3|.*2|.*1).*/ => {
_ " "
$1 10 %
$2 10 %
}
/\d+ (\d+)/ => fx{ get(total) $1 + set(total) }
/^/ => { "Total: " get(total) "\n" }
)
! AOC 2025 Day 3-1
#(
/(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1)(.*?9|.*?8|.*?7|.*?6|.*?5|.*?4|.*?3|.*?2|.*?1).*/ => {
_ " "
$1 10 %
$2 10 %
$3 10 %
$4 10 %
$5 10 %
$6 10 %
$7 10 %
$8 10 %
$9 10 %
$10 10 %
$11 10 %
$12 10 %
}
/\d+ (\d+)/ => fx{ get(total) $1 + set(total) }
/^/ => { "Total: " get(total) "\n" }
)
! AOC 2025 Day 4-1
def(countRolls) #(/[^@]/ => "" { _ len })
#(
/^.+/ => { _ len 1 + times { " " } "\n" _ }
/\s+$/ => ""
/.+$/ => { _ "\n" _ len 1 + times { " " } }
/(?<=(.{3}).{138}(.))@(?=(.).{138}(.{3}))/s => {
$1 $2 $3 $4 cat cat cat
do(countRolls) 4 < if { "X" } { "@" }
}
'X' => fx{ inc(accessible) }
/^/ => { "Rolls accessible: " get(accessible) "\n" }
)
! AOC 2025 Day 4-2
def(countRolls) #(/[^@]/ => "" { _ len })
#(
/^.+/ => { _ len 1 + times { " " } "\n" _ }
/\s+$/ => ""
/.+$/ => { _ "\n" _ len 1 + times { " " } }
@/(?<=(.{3}).{138}(.))@(?=(.).{138}(.{3}))/s => {
$1 $2 $3 $4 cat cat cat
do(countRolls) 4 < if { "X" } { "@" }
}
'X' => fx{ inc(accessible) }
/^/ => { "Rolls accessible: " get(accessible) "\n" }
)
! AOC 2025 Day 5-1
#(
fx { 15 set(width) }
/\d+/ => { _ get(width) zpad }
(
/\d+-\d+/ => fx{ _ push(range) }
/\d+/ => {
0 set(fresh) drop
_ set(ingredientId) drop
for(range) {
_ get(width) take get(ingredientId) <=
_ get(width) 1 + skip get(ingredientId) >=
* if { 1 set(fresh) drop }
}
_ get(fresh) if
{ " fresh" inc(totalFresh) }
{ " spoiled" }
}
)
/$/ => { "\nTotal fresh: " get(totalFresh) }
)
! AOC 2025 Day 5-2
#(
! remove ingredient list
/^\d+$/m => ""
! pad to fixed width, sort and add 'R' prefix to indicate raw input
/\d+/ => { _ 15 zpad }
/.+/ => fx{ _ push(range) }
{ sort(range) for(range) { "R " _ "\n" } }
! State prefixes: (R)aw (D)eduped
@1(
! Repeatedly test first two (R)aw ranges for overlap
/R (\d+)-(\d+)\s+R (\d+)-(\d+)/ => {
$3 $2 <= if
{
! overlap
"R " $1 "-" $2 $4 max
}
{
! disjoint
"D " $1 "-" $2 "\n"
"R " $3 "-" $4
}
}
)
/[RD] / => ""
/(\d+)-(\d+)/ => {
_ " ("
$2 $1 - 1 +
copy get(total) + set(total) drop
" fresh ingredients in range)"
}
/^/ => { get(total) " total fresh ingredients\n---\n" }
)
! AOC 2025 Day 6-1
#(
! transpose into column arrays e.g. `col7`
/.+\d.+/ => #(
fx{ 0 set(col) }
/\d+/ => fx{
inc(col)
_ "col" get(col) cat push
}
)
! store operations array
/[*+]/ => fx{ _ push(ops) }
! do the arithmetic
{
0 set(col) drop
for(ops) {
_ set(op) drop
inc(col) "col" get(col) cat for {
_
" " get(op) " " cat cat
}
drop " = "
get(op) "*" = if { 1 } { 0 } ! initial value
"col" get(col) cat for {
_ get(op) "*" = if { * } { + }
}
copy get(total) + set(total) drop
"\n"
}
"---\nTotal: " get(total)
}
)
! AOC 2025 Day 6-2
def(isAllSpaces) (
/^\s*$/ => "1"
/.+/s => "0"
)
def(multiply) {
uncons(cols)
copy do(isAllSpaces) if { drop } { * do(multiply) }
}
def(add) {
uncons(cols)
copy do(isAllSpaces) if { drop } { + do(add) }
}
(
! push each char of the first line, then concat while rotating
! at the end, we will have an array of columns
/(?:\d|\s)+\d */ => (
/^.+/ => /./ => fx{ _ push(cols) }
/./ => fx{ uncons(cols) _ cat push(cols) }
)
'*' => {
1 do(multiply)
copy get(total) + set(total) drop
}
'+' => {
0 do(add)
copy get(total) + set(total) drop
}
/$/ => { "---\nTotal: " get(total) }
)
! AOC 2025 Day 7-1
#(
@1(
/([S|].{141})\./s => { $1 "|" }
/\|(.{140})[.|]\^\./s => {
inc(splits)
"|" $1 "|^|"
}
)
/^/ => {
"Splits: " get(splits) "\n"
}
)
! AOC 2025 Day 7-2
(
/^.+/ => fx(
'S' => { 1 push(timelines) }
'.' => { 0 push(timelines) }
)
'^' => fx{
uncons(timelines)
set(carry) ! preserve value for carry
pop(timelines) + push(timelines) ! augment previous entry
0 push(timelines) ! no timelines below splitter
}
'.' => fx{
uncons(timelines)
get(carry) + push(timelines) ! add `carry` to timelines above
0 set(carry) drop ! reset `carry`
}
/$/ => { "\nTimelines: " 0 for(timelines) { _ + } }
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment