import Data.List
-- uncomment if you want \d instead of [0-9]
-- | min == 0 && max == 9 = "\\d"
| min >= 10 || max <= 9 = "[" ++ rangeToStr
(digit
min) (digit
max) ++ "]" | otherwise = "[" ++ rangeToStr
(digit
min) '9' ++ rangeToStr
'a' (digit
max) ++ "]" where
digit d
numberRangeToRegex base
min max | cmin
== cmax
= intercalate
"|" $ map formatRanges
$ step dmin dmax
(map formatRanges
$ step dmin
(replicate cmin
(base
-1))) ++ (if cmin + 1 < cmax then [digitRangeToRegex 1 (base - 1) ++ digitRangeToRegex 0 (base-1) ++ formatCount cmin (cmax-2)] else []) ++
(map formatRanges
$ step
(1 : replicate
(cmax
-1) 0) dmax
) where
digits 0 = [0]
step [] [] = [[]]
step (a:as) (b:bs) =
if a == b then
prepend a $ step as bs
else
(if zeroHead then [] else prepend a $ step as nines) ++
(if na
> nb
then [] else [(na
, nb
) : replicate
(length as) (0, base
-1)]) ++ (if nineTail then [] else prepend b $ step zeros bs)
where
nineTail
= all (== base
-1) bs
na = if zeroHead then a else a+1
nb = if nineTail then b else b-1
zeros = replicate suffixLen 0
nines = replicate suffixLen (base-1)
prepend x
= map ((x
, x
):
) formatGroup xs
@((min, max) :
_)
main
= putStrLn $ numberRangeToRegex
10 42 100500
aW1wb3J0IERhdGEuQ2hhcgppbXBvcnQgRGF0YS5MaXN0CgpkaWdpdFJhbmdlVG9SZWdleCA6OiBJbnRlZ2VyIC0+IEludGVnZXIgLT4gU3RyaW5nCmRpZ2l0UmFuZ2VUb1JlZ2V4IG1pbiBtYXgKICAgIHwgbWluID09IG1heCA9IGRpZ2l0IG1pbiA6ICIiCi0tIHVuY29tbWVudCBpZiB5b3Ugd2FudCBcZCBpbnN0ZWFkIG9mIFswLTldCi0tICAgIHwgbWluID09IDAgJiYgbWF4ID09IDkgPSAiXFxkIgogICAgfCBtaW4gPj0gMTAgfHwgbWF4IDw9IDkgPSAiWyIgKysgcmFuZ2VUb1N0ciAoZGlnaXQgbWluKSAoZGlnaXQgbWF4KSArKyAiXSIKICAgIHwgb3RoZXJ3aXNlID0gIlsiICsrIHJhbmdlVG9TdHIgKGRpZ2l0IG1pbikgJzknICsrIHJhbmdlVG9TdHIgJ2EnIChkaWdpdCBtYXgpICsrICJdIgogICAgd2hlcmUKICAgICAgICByYW5nZVRvU3RyIG1pbiBtYXgKICAgICAgICAgICAgfCBtaW4gPT0gbWF4ID0gbWluIDogIiIKICAgICAgICAgICAgfCBvdGhlcndpc2UgPSBtaW4gOiAnLScgOiBtYXggOiAiIgogICAgICAgIGRpZ2l0IGQKICAgICAgICAgICAgfCBkID49IDAgJiYgZCA8PSA5ID0gY2hyIChvcmQgJzAnICsgZnJvbUludGVncmFsIGQpCiAgICAgICAgICAgIHwgZCA8IDM2ID0gY2hyIChvcmQgJ2EnICsgZnJvbUludGVncmFsIGQgLSAxMCkKCm51bWJlclJhbmdlVG9SZWdleCA6OiBJbnRlZ2VyIC0+IEludGVnZXIgLT4gSW50ZWdlciAtPiBTdHJpbmcKbnVtYmVyUmFuZ2VUb1JlZ2V4IGJhc2UgbWluIG1heAogICAgfCBtaW4gPT0gMCAmJiBtYXggPT0gMCA9ICIwIgogICAgfCBjbWluID09IGNtYXggPSBpbnRlcmNhbGF0ZSAifCIgJCBtYXAgZm9ybWF0UmFuZ2VzICQgc3RlcCBkbWluIGRtYXgKICAgIHwgb3RoZXJ3aXNlID0gaW50ZXJjYWxhdGUgInwiICQKICAgICAgICAobWFwIGZvcm1hdFJhbmdlcyAkIHN0ZXAgZG1pbiAocmVwbGljYXRlIGNtaW4gKGJhc2UtMSkpKSArKwogICAgICAgIChpZiBjbWluICsgMSA8IGNtYXggdGhlbiBbZGlnaXRSYW5nZVRvUmVnZXggMSAoYmFzZSAtIDEpICsrIGRpZ2l0UmFuZ2VUb1JlZ2V4IDAgKGJhc2UtMSkgKysgZm9ybWF0Q291bnQgY21pbiAoY21heC0yKV0gZWxzZSBbXSkgKysKICAgICAgICAobWFwIGZvcm1hdFJhbmdlcyAkIHN0ZXAgKDEgOiByZXBsaWNhdGUgKGNtYXgtMSkgMCkgZG1heCkKICAgIHdoZXJlCiAgICAgICAgZGlnaXRzIDAgPSBbMF0KICAgICAgICBkaWdpdHMgbiA9IHJldmVyc2UgJCBtYXAgKGBtb2RgIGJhc2UpICQgdGFrZVdoaWxlICg+MCkgJCBpdGVyYXRlIChgZGl2YCBiYXNlKSBuCiAgICAgICAgZG1pbiA9IGRpZ2l0cyBtaW4KICAgICAgICBkbWF4ID0gZGlnaXRzIG1heAogICAgICAgIGNtaW4gPSBsZW5ndGggZG1pbgogICAgICAgIGNtYXggPSBsZW5ndGggZG1heAogICAgICAgIHN0ZXAgW10gW10gPSBbW11dCiAgICAgICAgc3RlcCAoYTphcykgKGI6YnMpID0KICAgICAgICAgICAgaWYgYSA9PSBiIHRoZW4KICAgICAgICAgICAgICAgIHByZXBlbmQgYSAkIHN0ZXAgYXMgYnMKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgKGlmIHplcm9IZWFkIHRoZW4gW10gZWxzZSBwcmVwZW5kIGEgJCBzdGVwIGFzIG5pbmVzKSArKwogICAgICAgICAgICAgICAgKGlmIG5hID4gbmIgdGhlbiBbXSBlbHNlIFsobmEsIG5iKSA6IHJlcGxpY2F0ZSAobGVuZ3RoIGFzKSAoMCwgYmFzZS0xKV0pICsrCiAgICAgICAgICAgICAgICAoaWYgbmluZVRhaWwgdGhlbiBbXSBlbHNlIHByZXBlbmQgYiAkIHN0ZXAgemVyb3MgYnMpCiAgICAgICAgICAgIHdoZXJlCiAgICAgICAgICAgICAgICBzdWZmaXhMZW4gPSBsZW5ndGggYXMKICAgICAgICAgICAgICAgIHplcm9IZWFkID0gYWxsICg9PSAwKSBhcwogICAgICAgICAgICAgICAgbmluZVRhaWwgPSBhbGwgKD09IGJhc2UtMSkgYnMKICAgICAgICAgICAgICAgIG5hID0gaWYgemVyb0hlYWQgdGhlbiBhIGVsc2UgYSsxCiAgICAgICAgICAgICAgICBuYiA9IGlmIG5pbmVUYWlsIHRoZW4gYiBlbHNlIGItMQogICAgICAgICAgICAgICAgemVyb3MgPSByZXBsaWNhdGUgc3VmZml4TGVuIDAKICAgICAgICAgICAgICAgIG5pbmVzID0gcmVwbGljYXRlIHN1ZmZpeExlbiAoYmFzZS0xKQogICAgICAgICAgICAgICAgcHJlcGVuZCB4ID0gbWFwICgoeCwgeCk6KQogICAgICAgIGZvcm1hdFJhbmdlcyA9IGNvbmNhdE1hcCBmb3JtYXRHcm91cCAuIGdyb3VwIC4gZHJvcFdoaWxlICg9PSAoMCwwKSkgd2hlcmUKICAgICAgICAgICAgZm9ybWF0R3JvdXAgWyhtaW4sIG1heCldID0gZGlnaXRSYW5nZVRvUmVnZXggbWluIG1heAogICAgICAgICAgICBmb3JtYXRHcm91cCB4c0AoKG1pbiwgbWF4KSA6IF8pCiAgICAgICAgICAgICAgICB8IG1pbiA9PSBtYXggPSBjb25jYXQgJCByZXBsaWNhdGUgKGxlbmd0aCB4cykgJCBkaWdpdFJhbmdlVG9SZWdleCBtaW4gbWF4CiAgICAgICAgICAgICAgICB8IG90aGVyd2lzZSA9IGRpZ2l0UmFuZ2VUb1JlZ2V4IG1pbiBtYXggKysgInsiICsrIHNob3cgKGxlbmd0aCB4cykgKysgIn0iCiAgICAgICAgZm9ybWF0Q291bnQgbWluIG1heAogICAgICAgICAgICB8IG1pbiA9PSAxICYmIG1heCA9PSAxID0gIiIKICAgICAgICAgICAgfCBtaW4gPT0gbWF4ID0gInsiICsrIHNob3cgbWluICsrICJ9IgogICAgICAgICAgICB8IG90aGVyd2lzZSA9ICJ7IiArKyBzaG93IG1pbiArKyAiLCIgKysgc2hvdyBtYXggKysgIn0iCgptYWluID0gcHV0U3RyTG4gJCBudW1iZXJSYW5nZVRvUmVnZXggMTAgNDIgMTAwNTAw