Quest 5: Fishbone Order

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

Link to participate: https://everybody.codes/

  • vole@lemmy.world
    link
    fedilink
    English
    arrow-up
    2
    ·
    edit-2
    5 days ago

    What a fiddlybit. I needed records to save me from list-hell on this one.

    Scheme/Guile

    (import (rnrs io ports (6))
            (rnrs records syntactic))
    
    (define (parse-file file-name)
      (let* ((lines (string-split (string-trim-both (call-with-input-file file-name get-string-all)) #\newline)))
        (map (lambda (line)
           (let* ((colon-split (string-split line #\:))
                 (segments (map string->number (string-split (cadr colon-split) #\,)))
                 (label (string->number (car colon-split))))
            (cons label segments)))
           lines)))
    
    (define-record-type fishbone-segment (fields middle left right))
    (define (construct-fishbone fishbone segments)
      (if (null? segments)
          fishbone
          (let ((fishbone (add-fishbone-segment fishbone (car segments))))
            (construct-fishbone fishbone (cdr segments)))))
    (define (add-fishbone-segment fishbone segment)
      (if (null? fishbone)
          (list (make-fishbone-segment segment #f #f))
          (let* ((fish-head (car fishbone))
                 (fish-middle (fishbone-segment-middle fish-head))
                 (fish-left (fishbone-segment-left fish-head))
                 (fish-right (fishbone-segment-right fish-head)))
            (cond
              ((and (< segment fish-middle) (not fish-left)) (cons (make-fishbone-segment fish-middle segment fish-right) (cdr fishbone)))
              ((and (> segment fish-middle) (not fish-right)) (cons (make-fishbone-segment fish-middle fish-left segment) (cdr fishbone)))
              (else (cons fish-head (add-fishbone-segment (cdr fishbone) segment)))))))
    (define (score-fishbone fishbone)
      (string->number (string-join (map (compose number->string fishbone-segment-middle) fishbone) "")))
    
    (define-record-type sword (fields id fishbone quality))
    (define (parse-swords file-name)
      (map (lambda (sword-line)
              (let ((fishbone (construct-fishbone '() (cdr sword-line))))
                (make-sword (car sword-line) fishbone (score-fishbone fishbone))))
        (parse-file file-name)))
    
    (format #t "P1 Answer: ~a\n\n" (sword-quality (car (parse-swords "notes/everybody_codes_e2025_q05_p1.txt"))))
    
    (let* ((swords (parse-swords "notes/everybody_codes_e2025_q05_p2.txt"))
           (sword-scores (map sword-quality swords)))
      (format #t "P2 Answer: ~a\n\n" (- (apply max sword-scores) (apply min sword-scores))))
    
    
    (define (segment-score segment)
      (string->number
        (string-join
         (map (lambda (n) (if (eqv? #f n) "" (number->string n)))
          (list (fishbone-segment-left segment) (fishbone-segment-middle segment) (fishbone-segment-right segment)))
         "")))
    (define (sort-fishbones a b)
      (if (null? a) '()
      (let ((line-score-a (segment-score (car a)))
            (line-score-b (segment-score (car b))))
        (cond
          ((> line-score-a line-score-b) #t)
          ((< line-score-a line-score-b) #f)
          (else (sort-fishbones (cdr a) (cdr b)))))))
    (define (sort-swords a b)
      (cond
        ((> (sword-quality a) (sword-quality b)) #t)
        ((< (sword-quality a) (sword-quality b)) #f)
        (else (let ((fb-sort (sort-fishbones (sword-fishbone a) (sword-fishbone b))))
          (cond
            ((null? fb-sort) (> (sword-id a) (sword-id b)))
            (else fb-sort))))))
    (let* ((swords (parse-swords "notes/everybody_codes_e2025_q05_p3.txt"))
           (sorted-swords (sort swords sort-swords))
           (swords-length (length swords)))
      (let loop ((i 1) (total 0) (sorted-swords sorted-swords))
        (if (<= i swords-length)
            (loop (1+ i) (+ total (* i (sword-id (car sorted-swords)))) (cdr sorted-swords))
            (format #t "P2 Answer: ~a\n\n" total))))