AoC '12, Day 13, first problem, rvc


 $ cat 13a.rkt  
 #lang racket 
  
  
 (provide 
   example-input 
   fold-on-constant-x 
   fold-on-constant-y 
   read-input 
   ) 
  
  
 (define (aoc-13a input) 
  
   ; Read the initial configuration and folding instructions from 
   ; the given input, and return the number of spots remaining 
   ; after performing the first fold from the instructions. 
  
   (let-values (((points folds) (read-input input))) 
     (if (null? folds) 
         0 
         (let ((fold (car folds))) 
           (set-count 
             ((if (string=? (car fold) "x") 
                fold-on-constant-x 
                fold-on-constant-y) points (cdr fold))))))) 
  
  
 (define (fold-on-constant-x points v) 
  
   ; Return a set containing the points in the given set reflected 
   ; about the vertical line x = v.  The reflection is done 
   ; "leftward," only points to the right of the reflective 
   ; axis are displaced (x increases to the right). 
    
   (list->set 
     (set-map 
       points 
       (lambda (p)  
         (let ((x (car p))) 
           (if (> x v) 
             (cons (- (* v 2) x) (cdr p)) 
             p)))))) 
  
  
 (define (fold-on-constant-y points v) 
  
   ; Return a set containing the points in the given set reflected 
   ; about the horizontal line y = v.  The reflection is done 
   ; "upward," only points below the reflective axis are displaced 
   ; (y increases down). 
    
   (list->set 
     (set-map 
       points 
       (lambda (p)  
         (let ((y (cdr p))) 
           (if (> y v) 
             (cons (car p) (- (* v 2) y)) 
             p)))))) 
  
  
   (define (read-folds input) 
  
     ; Return a list of fold instructions read from the given input. 
  
     (define (read-fold line) 
       (let ((fold (string-split (caddr (string-split line " ")) "="))) 
         (cons (car fold) (string->number (cadr fold))))) 
  
  
     (let loop ((input (string-split input "\n")) (folds '())) 
       (if (null? input) 
         (reverse folds) 
         (loop (cdr input) (cons (read-fold (car input)) folds))))) 
  
  
   (define (read-points input) 
  
     ; Return the set of points read from the given input. 
  
  
     (define (read-point line) 
       (let ((coords (map string->number (string-split line ",")))) 
         (cons (car coords) (cadr coords)))) 
  
  
     (list->set 
       (let loop ((input (string-split input "\n")) (points '())) 
         (if (null? input) 
           points 
           (let ((line (car input))) 
             (if (non-empty-string? line) 
               (loop (cdr input) (cons (read-point line) points)) 
               points)))))) 
  
    
   (define (split-input input) 
  
     ; Return the values (p, f), where p is a list of point 
     ; coordinates from the given input and f is a list of folds. 
  
     (let ((split (string-split input "\n\n"))) 
       (if (not (= (length split) 2)) 
           (error 'split-input 
             "expecting two pieces of split input, got ~s" (length split)) 
           (values (car split) (cadr split))))) 
  
  
 (define (read-input input) 
  
   ; Read the problem from the given input and return the 
   ; values (p f), where p is a set o points and f is a list 
   ; of folds. 
  
   (let-values (((points folds) (split-input input))) 
     (values (read-points points) (read-folds folds)))) 
  
  
 (define example-input 
   (string-join '( 
     "6,10" 
     "0,14" 
     "9,10" 
     "0,3" 
     "10,4" 
     "4,11" 
     "6,0" 
     "6,12" 
     "4,1" 
     "0,13" 
     "10,12" 
     "3,4" 
     "3,0" 
     "8,4" 
     "1,10" 
     "2,14" 
     "8,10" 
     "9,0" 
     "" 
     "fold along y=7" 
     "fold along x=5" 
     ) 
     "\n")) 
  
  
 (module+ main 
  
   (require "aoc.rkt") 
   (aoc-solve-problem 13 (lambda (x) x) (list aoc-13a))) 
  
  
 (module+ test 
  
   (require rackunit) 
    
   (check-eq? (aoc-13a "0,0\n0,4\n\nfold along y=2") 1) 
   (check-eq? (aoc-13a "0,0\n0,3\n\nfold along y=2") 2) 
   (check-eq? (aoc-13a "0,0\n4,0\n\nfold along x=2") 1) 
   (check-eq? (aoc-13a "0,0\n3,0\n\nfold along x=2") 2) 
   (check-eq? (aoc-13a example-input) 17) 
   ) 
  
 $ raco test 13a.rkt  
 raco test: (submod "13a.rkt" test) 
 5 tests passed 
  
 $