advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

day07.scm (4023B)

    1 (use-modules (ice-9 popen))
    2 (use-modules (ice-9 rdelim))
    3 (use-modules (ice-9 format))
    4 (use-modules (ice-9 hash-table))
    5 (use-modules (srfi srfi-1))
    6 
    7 (define (score-card card)
    8   (case card
    9     ((#\A) 13)
   10     ((#\K) 12)
   11     ((#\Q) 11)
   12     ((#\J) 10)
   13     ((#\T) 9)
   14     ((#\9) 8)
   15     ((#\8) 7)
   16     ((#\7) 6)
   17     ((#\6) 5)
   18     ((#\5) 4)
   19     ((#\4) 3)
   20     ((#\3) 2)
   21     ((#\2) 1)
   22     (else #nil)))
   23 
   24 (define (check-hand hand)
   25   (let ((card-tally (make-hash-table)))
   26     (for-each (lambda (card) (hash-set! card-tally card (1+ (hash-ref card-tally card 0)))) (string->list hand))
   27     (let ((count (sort (hash-map->list (lambda (k v) v) card-tally) >)))
   28       (cond
   29        ((equal? count '(1 1 1 1 1)) 1)
   30        ((equal? count '(2 1 1 1)) 2)
   31        ((equal? count '(2 2 1)) 3)
   32        ((equal? count '(3 1 1)) 4)
   33        ((equal? count '(3 2)) 5)
   34        ((equal? count '(4 1)) 6)
   35        ((equal? count '(5)) 7)))))
   36 
   37 (define (hand-less-raw hand-a hand-b scorer)
   38   (if (and (null? hand-a) (null? hand-b))
   39       #f
   40       (let ((card-a (car hand-a))
   41             (card-b (car hand-b)))
   42         (if (eq? card-a card-b)
   43             (hand-less-raw (cdr hand-a) (cdr hand-b) scorer)
   44             (< (scorer card-a) (scorer card-b))))))
   45 
   46 (define (hand-less hand-a hand-b)
   47   (let ((hand-type-a (check-hand hand-a))
   48         (hand-type-b (check-hand hand-b)))
   49     (if (eq? hand-type-a hand-type-b)
   50         (hand-less-raw (string->list hand-a) (string->list hand-b) score-card)
   51         (< hand-type-a hand-type-b))))
   52 
   53 (define (calc-winning hands-and-bids sorted-hands curr-rank)
   54   (if (null? sorted-hands)
   55       0
   56       (+ (* curr-rank (hash-ref hands-and-bids (car sorted-hands)))
   57          (calc-winning hands-and-bids (cdr sorted-hands) (1+ curr-rank)))))
   58 
   59 (define (parse-input filename)
   60   (let ((file (open-input-file filename))
   61         (hands-and-bids (make-hash-table)))
   62     (while #t
   63            (let ((line (car (%read-line file))))
   64              (if (eof-object? line)
   65                  (break)
   66                  (let* ((tmp (string-split line #\ ))
   67                         (hand (car tmp))
   68                         (bid (string->number (car (cdr tmp)))))
   69                    (hash-set! hands-and-bids hand bid)))))
   70     hands-and-bids))
   71 
   72 (let* ((input (parse-input "input.txt"))
   73        (hands (hash-map->list (lambda (k v) k) input))
   74        (sorted-hands (sort hands hand-less)))
   75   ;; 249390788
   76   (format #t "Part 1: ~d" (calc-winning input sorted-hands 1))
   77   (newline))
   78 
   79 (define (score-card-2 card)
   80   (case card
   81     ((#\A) 13)
   82     ((#\K) 12)
   83     ((#\Q) 11)
   84     ((#\T) 9)
   85     ((#\9) 8)
   86     ((#\8) 7)
   87     ((#\7) 6)
   88     ((#\6) 5)
   89     ((#\5) 4)
   90     ((#\4) 3)
   91     ((#\3) 2)
   92     ((#\2) 1)
   93     ((#\J) 0)
   94     (else #nil)))
   95 
   96 (define (check-hand-2 hand)
   97   (let ((card-tally (make-hash-table))
   98         (wild-card-count 0))
   99     (for-each
  100      (lambda (card)
  101        (if (eq? card #\J)
  102            (set! wild-card-count (1+ wild-card-count))
  103            (hash-set! card-tally card (1+ (hash-ref card-tally card 0)))))
  104      (string->list hand))
  105     (let* ((count (sort (hash-map->list (lambda (k v) v) card-tally) >))
  106            (count-adjusted (if (null? count) '(5) (cons (+ wild-card-count (car count)) (cdr count)))))
  107       (cond
  108        ((equal? count-adjusted '(1 1 1 1 1)) 1)
  109        ((equal? count-adjusted '(2 1 1 1)) 2)
  110        ((equal? count-adjusted '(2 2 1)) 3)
  111        ((equal? count-adjusted '(3 1 1)) 4)
  112        ((equal? count-adjusted '(3 2)) 5)
  113        ((equal? count-adjusted '(4 1)) 6)
  114        ((equal? count-adjusted '(5)) 7)))))
  115 
  116 (define (hand-less-2 hand-a hand-b)
  117   (let ((hand-type-a (check-hand-2 hand-a))
  118         (hand-type-b (check-hand-2 hand-b)))
  119     (if (eq? hand-type-a hand-type-b)
  120         (hand-less-raw (string->list hand-a) (string->list hand-b) score-card-2)
  121         (< hand-type-a hand-type-b))))
  122 
  123 (let* ((input (parse-input "input.txt"))
  124        (hands (hash-map->list (lambda (k v) k) input))
  125        (sorted-hands (sort hands hand-less-2)))
  126   ;; 248750248
  127   (format #t "Part 2: ~d" (calc-winning input sorted-hands 1))
  128   (newline))