Browse Source

solve advent of code 2023 day 07 part 2

Mistivia 1 year ago
parent
commit
02e5b2a4bf
1 changed files with 87 additions and 0 deletions
  1. 87 0
      advent-of-code/2023/07/part2.rkt

+ 87 - 0
advent-of-code/2023/07/part2.rkt

@@ -0,0 +1,87 @@
+#lang racket
+
+(define input 
+  (with-input-from-file "input"
+    (lambda ()
+      (let loop ((cards '()))
+        (define line (read-line))
+        (if (or (eof-object? line)
+              (= 0 (string-length line)))
+          (reverse cards)
+          (let ()
+            (define splited-line (string-split line))
+            (define hand (car splited-line))
+            (define bid (string->number (cadr splited-line)))
+            (loop (cons (list hand bid) cards))))))))
+
+(define (card-number char)
+  (cond ((eq? char #\A) 12)
+        ((eq? char #\K) 11)
+        ((eq? char #\Q) 10)
+        ((eq? char #\J) 0)
+        ((eq? char #\T) 9)
+        (else (- (string->number (make-string 1 char))
+                 1))))
+
+(define (joker-transform type)
+  (define joker-num (vector-ref type 0))
+  (vector-set! type 0 0)
+  (vector-sort! type >)
+  (vector-set! type 0 (+ joker-num (vector-ref type 0)))
+  type)
+
+(define (hand-type hand)
+  (define vec (make-vector 13 0))
+  (let loop ((i 0))
+    (if (>= i 5)
+      (vector->list (joker-transform vec))
+      (let ()
+        (define index (card-number (string-ref hand i)))
+        (vector-set! vec index (+ 1 (vector-ref vec index)))
+        (loop (+ i 1))))))
+
+(define (hand-type<? type1 type2)
+  (if (or (null? type1)
+          (null? type2))
+    #f
+    (if (= (car type1) (car type2))
+      (hand-type<? (cdr type1) (cdr type2))
+      (< (car type1) (car type2)))))
+
+(define (hand-type=? type1 type2)
+  (if (null? type1)
+    #t
+    (if (= (car type1) (car type2))
+      (hand-type=? (cdr type1) (cdr type2))
+      #f)))
+
+(define (raw-hand<? hand1 hand2)
+    (define h1 (map card-number (string->list hand1)))
+    (define h2 (map card-number (string->list hand2)))
+    (hand-type<? h1 h2))
+
+(define (hand<? hand1 hand2)
+  (define type1 (hand-type hand1))
+  (define type2 (hand-type hand2))
+  (if (hand-type=? type1 type2)
+    (raw-hand<? hand1 hand2)
+    (hand-type<? type1 type2)))
+
+(define sorted-cards
+  (sort input (lambda (a b)
+                (hand<? (car a) (car b)))))
+
+(define (calc-points card)
+    (* (cadar card) (cadr card)))
+
+(define (enumerate lst)
+  (let loop ((i 1) (ret '()) (remain lst))
+    (if (null? remain)
+      (reverse ret)
+      (loop (+ 1 i) (cons (list (car remain) i) ret) (cdr remain)))))
+
+(define result
+  (apply + (map calc-points (enumerate sorted-cards))))
+
+(display result)
+(newline)