Zulip Chat Archive

Stream: general

Topic: Advent Of Code 2025 - Day 7


Alfredo Moreira-Rosa (Dec 11 2025 at 20:43):

This is my solution for day 7 of Advent of Code.
I'm really happy with the solution, using HashSet for part 1 and HashMap for part 2.
Main surprise was that Lean core don't define intersection, difference or unionWith out of the box.
So i defined them.
The solution ends up being really small thanks to those helpers. Parsing was also really simple.

Solution

Here are my HashSet Helpers :

import Std.Data.HashSet

namespace Std.HashSet

def map [BEq α] [BEq β] [Hashable α] [Hashable β] (s : HashSet α) (f : α  β) : HashSet β :=
  s.fold (fun acc x => acc.insert (f x)) (HashSet.emptyWithCapacity)

def intersection {α : Type} [BEq α] [Hashable α] (s1 s2 : HashSet α) : HashSet α :=
  s1.filter (fun x => s2.contains x)

def difference {α : Type} [BEq α] [Hashable α] (s1 s2 : HashSet α) : HashSet α :=
  s1.filter (fun x => ¬ s2.contains x)

instance {α : Type} [BEq α] [Hashable α] : Inter (HashSet α) where
  inter := intersection

instance {α : Type} [BEq α] [Hashable α] : SDiff (HashSet α) where
  sdiff := difference

end Std.HashSet

And here are the HashMap ones :

import Std.Data.HashMap

namespace Std.HashMap

def mapKey [BEq α] [BEq β] [BEq γ] [Hashable α] [Hashable β] [Hashable γ]
    (m : HashMap α β) (f : α  γ) : HashMap γ β :=
  m.fold (fun acc k v => acc.insert (f k) v) (HashMap.emptyWithCapacity)

def unionWith {α β : Type} [BEq α] [Hashable α] [BEq β] [Hashable β] (f : β  β  β) (m1 m2 : HashMap α β) : HashMap α β :=
  m2.fold (fun acc k v =>
    match acc.get? k with
    | some v' => acc.insert k (f v' v)
    | none => acc.insert k v) m1

def intersection {α β : Type} [BEq α] [Hashable α] [BEq β] [Hashable β] (m1 m2 : HashMap α β) : HashMap α β :=
  m1.fold (fun acc k v =>
    if m2.contains k then
      acc.insert k v
    else
      acc) (HashMap.emptyWithCapacity)

def difference {α β : Type} [BEq α] [Hashable α] [BEq β] [Hashable β] (m1 m2 : HashMap α β) : HashMap α β :=
  m1.fold (fun acc k v =>
    if ¬ m2.contains k then
      acc.insert k v
    else
      acc) (HashMap.emptyWithCapacity)

instance {α β : Type} [BEq α] [Hashable α] [BEq β] [Hashable β] : Inter (HashMap α β) where
  inter := intersection

instance {α β : Type} [BEq α] [Hashable α] [BEq β] [Hashable β] : SDiff (HashMap α β) where
  sdiff := difference

class UnionPlus (α : Type u) where
  unionPlus : α  α  α

infixl:65 " ∪⁺ " => UnionPlus.unionPlus

instance {α β : Type} [BEq α] [Hashable α] [BEq β] [Hashable β] [Add β] : UnionPlus (HashMap α β) where
  unionPlus := unionWith (· + ·)

end Std.HashMap

Alfredo Moreira-Rosa (Dec 11 2025 at 21:02):

And execution time are also suprisingly good (so i suspect i'm measuring it badly, because part 2 is expected to be slower):

Running Day 7...
Parsing time: 8.12ms
Part 1: 1524 (461ns)
Part 2: 32982105837605 (237ns)

Kim Morrison (Dec 11 2025 at 21:37):

Alfredo Moreira-Rosa said:

Main surprise was that Lean core don't define intersection, difference or unionWith out of the box.

I think these are (mostly?) in the nightlies, arriving in v4.27.0-rc1 in a few days.

Alfredo Moreira-Rosa (Dec 11 2025 at 21:46):

Good news. Thanks for the insight!


Last updated: Dec 20 2025 at 21:32 UTC