Advent of Code 2025 Discussions

Not quite dead yet.

Part 1 for day 9, in Typed Racket
#lang typed/racket/base

(require racket/fixnum racket/match racket/string)

(: string->fixnum : String -> Fixnum)
(define (string->fixnum s) (assert (string->number s) fixnum?))

(: fxadd1 : Fixnum -> Fixnum)
(define (fxadd1 n) (fx+ n 1))

(: parse-input : Path-String -> (Vectorof (List Fixnum Fixnum)))
(define (parse-input filename)
  (call-with-input-file filename
    (lambda ([port : Input-Port])
      (for/vector : (Vectorof (List Fixnum Fixnum)) ([line (in-lines port)])
        (match (string-split line ",")
          [(list c r) (list (string->fixnum c) (string->fixnum r))])))))

(: part1 : (Vectorof (List Fixnum Fixnum)) -> Fixnum)
(define (part1 squares)
  (define len (vector-length squares))
  (let loop ([i 0] [j 1] [max-area : Fixnum -1])
    (cond
      [(= i len) max-area]
      [(= j len) (loop (add1 i) (+ i 2) max-area)]
      [else
       (define c1 (vector-ref squares i))
       (define c2 (vector-ref squares j))
       (loop i (add1 j)
             (fxmax max-area
                    (fx* (fxadd1 (fxabs (fx- (car c2) (car c1))))
                         (fxadd1 (fxabs (fx- (cadr c2) (cadr c1)))))))])))

(define sample-input (parse-input "day09_sample.txt"))
(define input (parse-input "day09.txt"))

(printf "Part 1 (Sample): ~A\n" (part1 sample-input))
(printf "Part 1: ~A\n" (part1 input))

First version used for*/fold instead of a complicated named let, but I found out that in-vector doesn't play well with TR without an inst wrapper around it, and the optimization coach warns about that and not being able to optimize it.

2 Likes