day07.scm (4569B)
1 ; Copyright (c) 2023, Natacha Porté 2 ; 3 ; Permission to use, copy, modify, and distribute this software for any 4 ; purpose with or without fee is hereby granted, provided that the above 5 ; copyright notice and this permission notice appear in all copies. 6 ; 7 ; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 ; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 ; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 ; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 ; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 ; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 ; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15 (import (chicken io) (chicken sort) (chicken string) 16 comparse 17 srfi-1 18 srfi-14) 19 20 ;;;;;;;;;;;;;;;;; 21 ;; Input parsing 22 23 (define (as-number parser) 24 (bind (as-string parser) 25 (lambda (s) 26 (result (string->number s))))) 27 28 (define spaces 29 (one-or-more (is #\space))) 30 31 (define digit 32 (in char-set:digit)) 33 34 (define digits 35 (as-number (one-or-more digit))) 36 37 (define card 38 (in #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\T #\J #\Q #\K #\A)) 39 40 (define hand 41 (sequence* ((hand (repeated card 5)) 42 (_ spaces) 43 (bid digits) 44 (_ (is #\newline))) 45 (result (list hand bid)))) 46 47 (define all-data 48 (zero-or-more hand)) 49 50 (define data (parse all-data (read-string))) 51 ;(write-line (conc "Input: " data)) 52 53 ;;;;;;;;;;;;;;;;; 54 ;; First Puzzle 55 56 (define (card-value c) 57 (cond ((eqv? c #\2) 2) 58 ((eqv? c #\3) 3) 59 ((eqv? c #\4) 4) 60 ((eqv? c #\5) 5) 61 ((eqv? c #\6) 6) 62 ((eqv? c #\7) 7) 63 ((eqv? c #\8) 8) 64 ((eqv? c #\9) 9) 65 ((eqv? c #\T) 10) 66 ((eqv? c #\J) 11) 67 ((eqv? c #\Q) 12) 68 ((eqv? c #\K) 13) 69 ((eqv? c #\A) 14))) 70 71 (define converted-data 72 (map (lambda (x) (list (map card-value (car x)) (cadr x))) data)) 73 74 (define (inner-count-cards sorted-hand prev result) 75 (if (null? sorted-hand) 76 result 77 (inner-count-cards (cdr sorted-hand) 78 (car sorted-hand) 79 (if (= (car sorted-hand) prev) 80 (cons (add1 (car result)) (cdr result)) 81 (cons 1 result))))) 82 (define (count-cards sorted-hand) 83 (inner-count-cards sorted-hand -1 '())) 84 85 (define (list=? list1 list2) 86 (cond ((and (null? list1) (null? list2)) #t) 87 ((or (null? list1) (null? list2)) #f) 88 ((= (car list1) (car list2)) (list=? (cdr list1) (cdr list2))) 89 (else #f))) 90 91 (define (hand-kind hand) 92 (let ((counts (sort (count-cards (sort hand <)) <))) 93 (cond ((list=? counts '(5)) 7) ; five of a kind 94 ((list=? counts '(1 4)) 6) ; four of a kind 95 ((list=? counts '(2 3)) 5) ; full house 96 ((list=? counts '(1 1 3)) 4) ; three of a kind 97 ((list=? counts '(1 2 2)) 3) ; two pairs 98 ((list=? counts '(1 1 1 2)) 2) ; one pair 99 ((list=? counts '(1 1 1 1 1)) 1) ; one pair 100 (else (write-line (conc "Bad hand " hand " with counts " counts)))))) 101 102 (define (list-less? list1 list2) 103 (cond ((and (null? list1) (null? list2)) #f) 104 ((< (car list1) (car list2)) #t) 105 ((> (car list1) (car list2)) #f) 106 (else (list-less? (cdr list1) (cdr list2))))) 107 108 (define (hand-less? hand1 hand2) 109 (let ((kind1 (hand-kind hand1)) 110 (kind2 (hand-kind hand2))) 111 (or (< kind1 kind2) 112 (and (= kind1 kind2) (list-less? hand1 hand2))))) 113 114 (define sorted-converted-data 115 (sort converted-data (lambda (x y) (hand-less? (car x) (car y))))) 116 117 (define (answer-1 todo rank result) 118 (if (null? todo) 119 result 120 (answer-1 (cdr todo) 121 (add1 rank) 122 (+ result (* rank (cadar todo)))))) 123 124 (write-line (conc "First puzzle: " (answer-1 sorted-converted-data 1 0))) 125 126 ;;;;;;;;;;;;;;;;; 127 ;; Second Puzzle 128 129 (define (count-cards sorted-hand) 130 (let* ((no-J-hand (filter (lambda (x) (not (= x 1))) sorted-hand)) 131 (no-J-counts (sort (inner-count-cards no-J-hand -1 '()) >))) 132 (if (null? no-J-counts) 133 '(5) 134 (cons (+ (car no-J-counts) (- 5 (length no-J-hand))) 135 (cdr no-J-counts))))) 136 137 (define converted-data-2 138 (map (lambda (l) (cons 139 (map (lambda (x) (if (= x 11) 1 x)) (car l)) (cdr l))) 140 converted-data)) 141 142 (define sorted-converted-data-2 143 (sort converted-data-2 (lambda (x y) (hand-less? (car x) (car y))))) 144 145 (write-line (conc "Second puzzle: " (answer-1 sorted-converted-data-2 1 0)))