advent-of-code

advent of code attempts
git clone git://bvnf.space/advent-of-code.git
Log | Files | Refs

3.scm (2285B)


      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
(import (chicken io)
	(chicken string)
	(srfi-151))

(define txtlines (call-with-input-file "input" read-lines))
(define lines (map string->list txtlines))

(define (transpose matrix)
  (apply map list matrix))

(define (chars->nums l)
  (map (lambda (x) (- x 48)) (map char->integer l)))

(define ints (map chars->nums lines))

; return #t or #f so it works with srfi-151's list->bits
(define (mode-0-1-ind l i)
  (let ((sum (apply + (map (lambda (xl) (list-ref xl i)) l)))
	(n (length l)))
    (if (<= 0.5 (/ sum n))
      #t
      #f)))

(define (construct-modes nums)
  (let loop ((i 0) (lst '()))
    (if (>= i (length (car nums)))
      (reverse lst)
      (loop (+ i 1) (cons (mode-0-1-ind nums i) lst)))))

(define gamma-bitlist (construct-modes ints))
(define epsilon-bitlist (map not gamma-bitlist))

; reverse because the list is interpreted as least sig bit last
(define gamma (list->bits (reverse gamma-bitlist)))
(define epsilon (list->bits (reverse epsilon-bitlist)))

; part 1
(print (* gamma epsilon))


; part 2

; remove-elem returns lst without elements satisfying condit
(define (remove-elem lst condit)
  (cond
    ((null? lst) '())
    ((condit (car lst)) (remove-elem (cdr lst) condit))
    (else (cons (car lst) (remove-elem (cdr lst) condit)))))

(define (bool->int b)
  (unless (boolean? b) (error "not a boolean" b))
  (if b 1 0))

(define (int->bool i)
  (unless (integer? i) (error "not an integer" i))
  (cond ((= 0 i) #f)
	(else #t)))

; most-or least is a boolean: #t to keep values which are the most common
(define (remove-not-matching lst index most-or-least)
  (remove-elem lst
	       (lambda (x)
		      (= (list-ref x index)
			 (bool->int
			   (if most-or-least
			     (not (mode-0-1-ind lst index))
			     (mode-0-1-ind lst index)))))))

; most-or least is a boolean: #t to keep values which are the most common
(define (find-last-matching lst most-or-least)
  (let loop ((i 0) (l lst))
    (cond ((= (length l) 1) (car l))
	  (else (loop (+ i 1) (remove-not-matching l i most-or-least))))))

; reverse because the list is interpreted as least sig bit last
(define co2 (list->bits (reverse (map int->bool (find-last-matching ints #f)))))
(define oxy (list->bits (reverse (map int->bool (find-last-matching ints #t)))))

(print (* oxy co2))