diff --git a/collects/2htdp/batch-io.rkt b/collects/2htdp/batch-io.rkt index 0d0f9d922f..9cf97144a4 100644 --- a/collects/2htdp/batch-io.rkt +++ b/collects/2htdp/batch-io.rkt @@ -35,6 +35,9 @@ read-words/line ;; String -> [Listof [Listof String]] ;; read the specified file as a list of lines, each line as a list of words + read-words-and-numbers/line ;; String -> [Listof [Listof String]] + ;; read the specified file as a list of lines, each line as a list of words + read-csv-file ;; String -> [Listof [Listof (U Any)]] ;; -- f must be formated as a a file with comma-separated values (Any) ;; read the specified file as a list of lists---one per line---of values (Any) @@ -77,6 +80,12 @@ ;; read the specified file as a list of lines, each line as a list of words (read-words/line/internal f cons)) +(def-reader (read-words-and-numbers/line f) + ;; String -> [Listof [Listof (U String Number)]] + ;; read the specified file as a list of lines, each line as a list of words and numbers + (read-words/line/internal f (lambda (line1 r) + (cons (for/list ((t (in-list line1))) (or (string->number t) t)) r)))) + (define (read-words/line/internal f combine) (define lines (read-chunks f *read-line (lambda (x) x))) (foldl (lambda (f r) @@ -147,7 +156,7 @@ ;; String (-> X) ([Listof X] -> [Listof X]) -> [Listof X] ;; read a file as a list of X where process-accu is applied to accu when eof -(define (read-chunks f read-chunk process-accu) +(define (read-chunks f read-chunk process-accu) (with-input-from-file f #:mode 'text (lambda () diff --git a/collects/2htdp/tests/batch-io3.rkt b/collects/2htdp/tests/batch-io3.rkt new file mode 100644 index 0000000000..7bad16bf28 --- /dev/null +++ b/collects/2htdp/tests/batch-io3.rkt @@ -0,0 +1,107 @@ +#lang racket + +;; test for pr11445 + +(require 2htdp/batch-io) + +(define batch-io3 + #< Void + ;; read input, process queries, write output + (define (solution file-name) + ;; S-expression [Dataset -> String] -> String + (define (input->output i) + (let loop ((ds# (first (first i))) (file (rest i))) + (cond + [(zero? ds#) ""] + [else + (let*-values ([(file sales-records# queries#) (apply values (rest file) (first file))] + [(file sales-records) (split file sales-records#)] + [(file queries) (split file queries#)]) + (string-append (process-dataset sales-records queries) "\n" (loop (sub1 ds#) file)))]))) + ;; Dataset -> String + ;; process one dataset + (define (process-dataset sales-records queries) + (foldr (λ (query r) (string-append (total-message sales-records (first query)) r)) "" queries)) + + ;; [Listof [List Number String Number]] String -> String + ;; compute query result and turn into string + (define (total-message sales-records query) + (define good* (filter (λ (sales-record) (string=? (second sales-record) query)) sales-records)) + (define count (apply + (map first good*))) + (define value (apply + (map third good*))) + (format "You sold ~a ~a for a total of $~a.\n" + count (add-s query (length good*)) (real->decimal-string value 2))) + ;; String Natural -> String + ;; add s to string if plurality calls for it + (define (add-s str n) + (if (and (> n 1) (not (string=? (substring str (- (string-length str) 1)) "s"))) + (string-append str "s") + str)) + ;; -- in -- ;; should be write-file from batch io + (with-output-to-string (λ () (printf (input->output batch-io3.sexpr))))) + + (check-equal? (solution "don't care") batch-io3-expected)) \ No newline at end of file diff --git a/collects/2htdp/xtest b/collects/2htdp/xtest index a67cdddca5..9e3ad684c5 100755 --- a/collects/2htdp/xtest +++ b/collects/2htdp/xtest @@ -15,6 +15,8 @@ run bad-draw.rkt run error-in-tick.rkt run error-in-draw.rkt run -t batch-io.rkt +run -t batch-io2.rkt +run -t batch-io3.rkt run clause-once.rkt run full-scene-visible.rkt run image-too-large.rkt diff --git a/collects/teachpack/2htdp/scribblings/batch-io.scrbl b/collects/teachpack/2htdp/scribblings/batch-io.scrbl index c007cc6186..564ccd037c 100644 --- a/collects/teachpack/2htdp/scribblings/batch-io.scrbl +++ b/collects/teachpack/2htdp/scribblings/batch-io.scrbl @@ -89,7 +89,7 @@ This time, however, the extra leading space of the second line of a part of the separator that surrounds the word @racket["good"]. } -@item{@reading[read-words/line (listof string?)]{a list of lists, one per line; each line is represented as a list of white-space separated tokens} +@item{@reading[read-words/line (listof string?)]{a list of lists, one per line; each line is represented as a list of strings} @examples[#:eval (examples-batch-io) (read-words/line "data.txt") @@ -99,6 +99,14 @@ except that the organization of the file into lines is preserved. In particular, the empty third line is represented as an empty list of words. } +@item{@reading[read-words-and-numbers/line (listof (or number? string?))]{a list of lists, one per line; each line is represented as a list of strings and numbers} + +@examples[#:eval (examples-batch-io) +(read-words-and-numbers/line "data.txt") +] +The results is like the one that @racket[read-words/line] produces, +except strings that can be parsed as numbers are represented as numbers.} + @item{@reading[read-csv-file (listof (listof any/c))]{a list of lists of comma-separated values} @examples[#:eval (examples-batch-io)