Advent 2021, day 8: use actual hash sets.

Smaller code and intentions are clearer.
This commit is contained in:
Érico Nogueira 2021-12-08 17:31:41 -03:00
parent 157c011341
commit c52bce683b
1 changed files with 23 additions and 33 deletions

View File

@ -1,36 +1,30 @@
#lang racket/base
(require racket/string)
(require racket/list)
(require racket/set)
(define (cdrm l)
(car (cdr l)))
(define (make-line t)
(map string-split (string-split t " | ")))
(define r (map string-split (string-split t " | ")))
(define (string->set s) (list->set (string->list s)))
(cons (map string->set (car r)) (map string->set (cdrm r))))
(define slist (for/list ([t (in-lines)]) (make-line t)))
(define (is-1-4-7-8 v)
(define l (string-length v))
(define l (set-count v))
(or (= l 2) (or (= l 4) (or (= l 3) (or (= l 7))))))
; part 1
(for/sum ([s slist])
(define digits (cdrm s))
(define digits (cdr s))
(for/sum ([v digits] #:when (is-1-4-7-8 v)) 1))
; part 2
(define (normalize s)
(list->string (remove-duplicates (sort (string->list s) char<?) char=?)))
(define (unionize-list l)
(normalize (string-join l "")))
(define (iterate-chars s)
(string->list (normalize s)))
(define (correspond-length v)
(define l (string-length v))
(define l (set-count v))
(if (= l 2) 1 (if (= l 4) 4 (if (= l 3) 7 8))))
(for/sum ([s slist])
@ -39,41 +33,37 @@
(define string-number (make-hash))
(define (add-number value number)
(define s (normalize value))
(hash-set! string-number s number)
(hash-set! number-string number s))
(hash-set! string-number value number)
(hash-set! number-string number value))
(define (unionize value number)
(unionize-list (list (hash-ref number-string number) value)))
(set-union (hash-ref number-string number) value))
; pick out 1, 4, 7 and 8
(for ([v pattern] #:when (is-1-4-7-8 v)) (define number (correspond-length v)) (add-number v number))
(define proto-nine (unionize-list (list (hash-ref number-string 4) (hash-ref number-string 7))))
; pick out nine
(for ([v pattern] #:when (= (string-length v) 6))
(define union-proto-nine (unionize-list (list (hash-ref number-string 4) (hash-ref number-string 7) v)))
(when (= (string-length union-proto-nine) (string-length v))
(for ([v pattern] #:when (= (set-count v) 6))
(define union-proto-nine (set-union (hash-ref number-string 4) (hash-ref number-string 7) v))
(when (= (set-count union-proto-nine) (set-count v))
(add-number v 9)))
; pick out three
(for ([v pattern] #:when (= (string-length v) 5))
(when (= (string-length (unionize v 1)) (string-length v))
(for ([v pattern] #:when (= (set-count v) 5))
(when (= (set-count (unionize v 1)) (set-count v))
(add-number v 3)))
; pick out five and two
(for ([v pattern] #:when (and (= (string-length v) 5) (not (hash-has-key? string-number (normalize v)))))
(define four-list (string->list (hash-ref number-string 4)))
(for ([c (iterate-chars v)])
(set! four-list (remove c four-list)))
(when (= (length four-list) 1)
(for ([v pattern] #:when (and (= (set-count v) 5) (not (hash-has-key? string-number v))))
(define four-set (hash-ref number-string 4))
(when (= (set-count (set-subtract four-set v)) 1)
(add-number v 5))
(when (= (length four-list) 2)
(when (= (set-count (set-subtract four-set v)) 2)
(add-number v 2)))
; pick out zero and six
(for ([v pattern] #:when (and (= (string-length v) 6) (not (hash-has-key? string-number (normalize v)))))
(if (= (string-length (unionize v 7)) (string-length v))
(for ([v pattern] #:when (and (= (set-count v) 6) (not (hash-has-key? string-number v))))
(if (= (set-count (unionize v 7)) (set-count v))
(add-number v 0)
(add-number v 6)))
; final sum
(for/sum ([v (cdrm s)] [multiplier '(1000 100 10 1)])
(* multiplier (hash-ref string-number (normalize v)))))
(for/sum ([v (cdr s)] [multiplier '(1000 100 10 1)])
(* multiplier (hash-ref string-number v))))