#!/usr/local/bin/chicken-csi -ss ;; the day, the functional programming, died! ;; - Don McLean ;; ;; Parsing this one is gonna be hard without set! (import srfi-69 ; hash tables (chicken io) (chicken sort) (chicken irregex) (chicken string)) ; globals (define cwd "") (define sizes (make-hash-table)) ; my first macro! :) (define-syntax setnret! (syntax-rules () ((_ x y) (begin (set! x y) x)))) (define (filter pred lst) (if (null? lst) '() (if (pred (car lst)) (cons (car lst) (filter pred (cdr lst))) (filter pred (cdr lst))))) (define (parent dir) (irregex-replace "[^/]*/$" dir "")) (define (cd! dir) (cond ((equal? dir "..") (setnret! cwd (parent cwd))) ((equal? dir "/") (setnret! cwd "/")) (else (setnret! cwd (string-append cwd dir "/"))))) (define (add-size! n) (define (add-size-dir! dir) (let ((newsize (+ n (hash-table-ref/default sizes dir 0)))) (hash-table-set! sizes dir newsize))) ; TODO: would be more efficient to do this after all lines processed (let loop ((dir cwd)) (if (not (equal? dir "")) (begin (add-size-dir! dir) (loop (parent dir)))))) (define (parse line) (let ((parts (string-split line))) (cond ((equal? (car parts) "$") (cond ((equal? (cadr parts) "ls") 'no-op) ((equal? (cadr parts) "cd") (cd! (caddr parts))) (else (error "Bad cmd " (cadr parts))))) ((equal? (car parts) "dir") 'no-op) (else (add-size! (string->number (car parts))))))) (define (big-enough? n) (>= n (- 30000000 (- 70000000 (hash-table-ref sizes "/"))))) (define (main args) (let ((lines (read-lines))) (for-each parse lines) ; (hash-table-for-each sizes (lambda (x n) (print x n))) (print (apply + (filter (lambda (x) (<= x 100000)) (hash-table-values sizes)))) (print (car (sort (filter big-enough? (hash-table-values sizes)) <)))))