Skip to content

Instantly share code, notes, and snippets.

@phongphan
Last active August 15, 2017 10:10
Show Gist options
  • Save phongphan/6e1af0ca20e9c721b6c451c65a1df5aa to your computer and use it in GitHub Desktop.
Save phongphan/6e1af0ca20e9c721b6c451c65a1df5aa to your computer and use it in GitHub Desktop.
Racket version
#lang typed/racket
;; (normalize-range (list (range 1 2) (range 3 4) (range 4 83) (range 0 0) (range 1 6)))
(struct range ([from : Integer] [to : Integer]) #:transparent)
(: to-integer (-> String Integer))
(define (to-integer str)
(assert (string->number str) exact-integer?))
(: range-overlapped? (-> range range Boolean))
(define (range-overlapped? range1 range2)
(and (>= (range-from range2) (range-from range1)) (<= (range-from range2) (range-to range1))))
(: normalize-range (-> (Listof range) (Listof range)))
(define (normalize-range ranges)
(let ((sorted-ranges (sort ranges (λ ([a : range] [b : range])
(< (range-from a) (range-from b))))))
(if (empty? sorted-ranges)
'()
(foldl
(λ ([value : range] [acc : (Listof range)])
(let ((src (car acc)))
(if (range-overlapped? src value)
(append (list (range (range-from src) (max (range-to src) (range-to value)))) (cdr acc))
(append (list value) acc))))
(list (car sorted-ranges))
sorted-ranges))))
(: parse-range (-> String (Listof range)))
(define (parse-range str)
(let ((ranges
(map (λ ([a : String]) (string-split a "-" #:trim? #t))
(string-split str "," #:trim? #t) )))
(map (λ ([r : (Listof String)])
(if ( = (length r) 1)
(let ((value (to-integer (car r))))
(range value value))
(range (to-integer (car r)) (to-integer (cadr r)))))
ranges)))
(: print-ranges (-> (Listof range) Void))
(define (print-ranges ranges)
(let ((str
(map (λ ([r : range])
(if (= (range-from r) (range-to r))
(number->string (range-from r))
(string-join (list (number->string (range-from r)) (number->string (range-to r))) "-")))
ranges)))
(displayln (string-join str ","))))
;(normalize-range (list (range 1 2) (range 3 4) (range 4 83) (range 0 0) (range 1 6)))
(define (main)
(let loop ()
(display ">> ")
(let ((line (read-line (current-input-port) 'any)))
(cond
[(not (eof-object? line))
(print-ranges (reverse (normalize-range (parse-range line))))
(loop)])))
(displayln "bye!"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment