raevnos's recent activity

  1. Comment on Day 8: Handheld Halting in ~comp

    raevnos
    Link Parent
    I used vectors instead of lists for my scheme solution; the O(1) access to elements makes it a lot more efficient than using lists.

    I used vectors instead of lists for my scheme solution; the O(1) access to elements makes it a lot more efficient than using lists.

    2 votes
  2. Comment on Day 9: Encoding Error in ~comp

    raevnos
    Link
    Chicken Scheme #!/usr/local/bin/csi -s (import (chicken format) (chicken io) (srfi 1) (srfi 158) (srfi 193)) (declare (fixnum-arithmetic) (block)) (define (sums-of-pairs numbers)...
    Chicken Scheme
    #!/usr/local/bin/csi -s
    (import (chicken format)
            (chicken io)
            (srfi 1)
            (srfi 158)
            (srfi 193))
    (declare (fixnum-arithmetic) (block))
    
    (define (sums-of-pairs numbers)
      (make-coroutine-generator
       (lambda (yield)
         (pair-for-each
          (lambda (pair)
            (let ((num1 (car pair)))
              (for-each (lambda (num2) (yield (+ num1 num2))) (cdr pair))))
          numbers))))
    
    (define (solve1 numbers window-length)
      (let-values (((preamble numbers) (split-at numbers window-length))
                   ((wl-1) (sub1 window-length)))
        (let loop ((numbers numbers)
                   (preamble (reverse! preamble)))
          (if (null? numbers)
              #f
              (let ((candidate (car numbers)))
                (if (generator-find (cut = <> candidate) (sums-of-pairs preamble))
                    (loop (cdr numbers) (cons candidate (take! preamble wl-1)))
                    candidate))))))
    
    (define (numbers-to-total numbers goal)
      (let loop ((numbers numbers)
                 (total 0)
                 (acc '()))
        (cond
         ((= total goal) (reverse! acc))
         ((or (> total goal) (null? numbers)) #f)
         (else
          (loop (cdr numbers) (+ (car numbers) total) (cons (car numbers) acc))))))
    
    (define (minmax lst #!optional (less-than? <))
      (let loop ((minval (car lst))
                 (maxval (car lst))
                 (lst (cdr lst)))
        (if (null? lst)
            (values minval maxval)
            (loop (if (less-than? (car lst) minval) (car lst) minval)
                  (if (less-than? maxval (car lst)) (car lst) maxval)
                  (cdr lst)))))
    
    (define (solve2 numbers key)
      (let loop ((numbers numbers))
        (cond
         ((null? numbers) #f)
         ((numbers-to-total numbers key) =>
          (lambda (range) (call-with-values (lambda () (minmax range)) +)))
         (else (loop (cdr numbers))))))
    
    ;;; Take an optional window size from the first command line argument
    (define window-size
      (let ((cl (command-line)))
        (if (>= (length cl) 2)
            (string->number (cadr cl))
            25)))
    (define input (read-list))
    (define key (solve1 input window-size))
    (printf "Part 1: ~A~%" key)
    (printf "Part 2: ~A~%" (solve2 input key))
    

    Only interesting thing here is using a generator to lazily calculate the sums of pairs of the preamble.

    3 votes
  3. Comment on Day 8: Handheld Halting in ~comp

    raevnos
    Link
    I think last year ended up with too many hard problems, but this year so far is too easy... Scheme #!/usr/local/bin/csi -s (import (chicken format) (chicken io) (srfi 133)) (define (read-input...

    I think last year ended up with too many hard problems, but this year so far is too easy...

    Scheme
    #!/usr/local/bin/csi -s
    (import
     (chicken format)
     (chicken io)
     (srfi 133))
    
    (define (read-input #!optional (port (current-input-port)))
      (let loop ((input (read-list port))
                 (acc '()))
        (if (null? input)
            (reverse-list->vector acc)
            (loop (cddr input) (cons (vector (car input) (cadr input) #f) acc)))))
    
    (define (reset-instructions! instructions)
      (vector-for-each (cut vector-set! <> 2 #f) instructions))
    
    (define (solve1 instructions)
      (let loop ((accumulator 0)
                 (ip 0))
        (if (>= ip (vector-length instructions))
            (values #t accumulator)
            (let ((insn (vector-ref instructions ip)))
              (if (vector-ref insn 2)
                  (values #f accumulator)
                  (begin
                    (vector-set! insn 2 #t)
                    (case (vector-ref insn 0)
                      ((nop) (loop accumulator (add1 ip)))
                      ((acc) (loop (+ accumulator (vector-ref insn 1)) (add1 ip)))
                      ((jmp) (loop accumulator (+ ip (vector-ref insn 1)))))))))))
    
    (define (flip-and-try instructions ip from to)
      (vector-set! (vector-ref instructions ip) 0 to)
      (let-values (((terminated? acc) (solve1 instructions)))
        (vector-set! (vector-ref instructions ip) 0 from)
        (values terminated? acc)))
    
    (define (solve2 instructions)
      (let loop ((ip 0))
        (reset-instructions! instructions)
        (if (>= ip (vector-length instructions))
            #f
            (case (vector-ref (vector-ref instructions ip) 0)
              ((acc) (loop (add1 ip)))
              ((nop jmp) =>
               (lambda (op)
                 (let*-values (((from to) (if (eq? op 'nop)
                                              (values 'nop 'jmp)
                                              (values 'jmp 'nop)))
                               ((terminated? acc)
                                (flip-and-try instructions ip from to)))
                   (if terminated?
                       acc
                       (loop (add1 ip))))))))))
    
    (define instructions (read-input))
    (let-values (((_ accumulator) (solve1 instructions)))
      (printf "Part 1: ~A~%" accumulator))
    (printf "Part 2: ~A~%" (solve2 instructions))
    
    4 votes
  4. Comment on Day 6: Custom Customs in ~comp

    raevnos
    Link
    This year I'm using (chicken) scheme. Today's problems lended themselves to a short, elegant solution using sets. Both parts #!/usr/local/bin/csi -s (import (chicken format) (chicken io) (srfi 1)...

    This year I'm using (chicken) scheme. Today's problems lended themselves to a short, elegant solution using sets.

    Both parts
    #!/usr/local/bin/csi -s
    (import
     (chicken format)
     (chicken io)
     (srfi 1)
     (srfi 14))
    
    (define (read-group #!optional (port (current-input-port)))
      (let loop ((answers '())
                 (line (read-line port)))
        (if (or (eof-object? line) (string=? line ""))
            answers
            (loop (cons (string->char-set line) answers) (read-line port)))))
    
    (define (read-groups #!optional (port (current-input-port)))
      (let loop ((groups '()))
        (let ((new-group (read-group port)))
          (if (null? new-group)
              groups
              (loop (cons new-group groups))))))
    
    (define (solve reduce-op groups)
      (fold (lambda (group total)
              (+ total (char-set-size (reduce reduce-op (char-set) group))))
            0 groups))
    
    (define (solve1 groups) (solve char-set-union groups))
    (define (solve2 groups) (solve char-set-intersection groups))
    
    (define input (read-groups))
    (printf "Part 1: ~A~%" (solve1 input))
    (printf "Part 2: ~A~%" (solve2 input))
    
    3 votes