Last active
August 15, 2017 10:10
-
-
Save phongphan/6e1af0ca20e9c721b6c451c65a1df5aa to your computer and use it in GitHub Desktop.
Racket version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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