#lang racket
(provide cell_bytes single_cell_limit double_cell_limit
int->bytes double->bytes string->bytes)
(define decimal_digits (string->list "0123456789"))
(define (digit? char)
(if (member char decimal_digits) #t #f))
(define punctuation (string->list "+,-./:"))
(define (punct? char)
(if (member char punctuation) #t #f))
(define cell_bytes 4) (define single_cell_limit (expt 2 (* cell_bytes 8)))
(define double_cell_limit (expt 2 (* (* cell_bytes 2) 8)))
(define (int->bytes num)
(integer->integer-bytes
(modulo num single_cell_limit) cell_bytes #f #t))
(define (double->bytes num)
(integer->integer-bytes
(modulo num double_cell_limit) (* 2 cell_bytes) #f #t))
(define (string->bytes str)
(define (create-bytes num punct)
(if punct
(double->bytes num)
(int->bytes num)))
(define (get-num pos result punct negate)
(if (= pos (string-length str))
(create-bytes (if negate (- result) result) punct)
(let [(new_digit (string-ref str pos))]
(cond [(digit? new_digit)
(get-num (+ pos 1)
(+ (* result 10)
(- (char->integer new_digit) (char->integer #\0)))
punct
negate)]
[(punct? new_digit)
(get-num (+ pos 1) result #t negate)]
[else #f]))))
(cond [(and (= (string-length str) 1) (not (digit? (string-ref str 0)))) #f]
[(eq? #\- (string-ref str 0))
(get-num 1 0 #f #t)]
[else (get-num 0 0 #f #f)]))