Haskell 2063 + 2 * 151 = 2365
Nó được đảm bảo regex được tạo có độ dài O (log n log log n).
matchIntRange 12345 7654321
1(2(3(4(5[6-9]|[6-9]\d)|[5-9]\d\d)|[4-9]\d{3})|[3-9]\d{4})|[2-9]\d{5}|[1-6]\d{6}|7([0-5]\d{5}|6([0-4]\d{4}|5([0-3]\d{3}|4([012]\d\d|3([01]\d|2[01])))))
import Data.Digits
data RegEx = Range Int Int | MatchNone | All Int
| Or RegEx RegEx | Concat [RegEx]
alphabet = "\\d"
instance Show RegEx where
show (Range i j)
| i == j = show i
| i+1 == j = concat ["[",show i,show j,"]"]
| i+2 == j = concat ["[",show i,show (i+1), show (i+2),"]"]
| otherwise = concat ["[",show i,"-",show j,"]"]
show (Or a b) = show a ++ "|" ++ show b
show MatchNone = "^$"
show (All n)
| n < 3 = concat $ replicate n alphabet
| otherwise = concat [alphabet,"{",show n,"}"]
show e@(Concat xs)
| atomic e = concatMap show xs
| otherwise = concatMap show' xs
where show' (Or a b) = "("++show (Or a b)++")"
show' x = show x
atomic (Concat xs) = all atomic xs
atomic (Or _ _) = False
atomic _ = True
-- Match integers in a certain range
matchIntRange :: Int->Int->RegEx
matchIntRange a b
| 0 > min a b = error "Negative input"
| a > b = MatchNone
| otherwise = build (d a) (d b)
where build :: [Int]->[Int]->RegEx
build [] [] = Concat []
build (a@(x:xs)) (b@(y:ys))
| sl && x == y = Concat [Range x x, build xs ys]
| sl && all9 && all0 = Concat [Range x y, All n]
| sl && all0 = Or (Concat [Range x (y-1), All n]) upper
| sl && all9 = Or lower (Concat [Range (x+1) y, All n])
| sl && x+1 <= y-1 = Or (Or lower middle) upper
| sl = Or lower upper
| otherwise = Or (build a (nines la)) (build (1:zeros la) b)
where (la,lb) = (length a, length b)
sl = la == lb
n = length xs
upper = Concat [Range y y, build (zeros n) ys]
lower = Concat [Range x x, build xs (nines n)]
middle = Concat [Range (x+1) (y-1), All n]
all9 = all (==9) ys
all0 = all (==0) xs
zeros n = replicate n 0
nines n = replicate n 9
d 0 = [0]
d n = digits 10 n
Mã dưới đây là một phiên bản đơn giản giúp hiểu được thuật toán, nhưng nó không thực hiện bất kỳ tối ưu hóa nào để cải thiện kích thước regex.
matchIntRange 123 4321
(((1((2((3|[4-8])|9)|[3-8]((0|[1-8])|9))|9((0|[1-8])|9))|[2-8]((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9)))|9((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9)))|((1((0((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9))|[1-8]((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9)))|9((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9)))|[2-3]((0((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9))|[1-8]((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9)))|9((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9))))|4((0((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9))|[1-2]((0((0|[1-8])|9)|[1-8]((0|[1-8])|9))|9((0|[1-8])|9)))|3((0((0|[1-8])|9)|1((0|[1-8])|9))|2(0|1)))))
Biểu thức chính quy có 680 ký tự. Đây là mã
import Data.Digits
data RegEx = Range Int Int | MatchNone | Or RegEx RegEx | Concat [RegEx]
alphabet = "\\d"
instance Show RegEx where
show (Range i j)
| i == j = show i
| otherwise = concat ["[",show i,"-",show j,"]"]
show (Or a b) = concat ["(",show a,"|",show b,")"]
show MatchNone = "^$"
show (Concat xs) = concatMap show xs
matchIntRange :: Int->Int->RegEx
matchIntRange a b
| 0 > min a b = error "Negative input"
| a > b = MatchNone
| otherwise = build (d a) (d b)
where build :: [Int]->[Int]->RegEx
build [] [] = Concat []
build (a@(x:xs)) (b@(y:ys))
| sl && x == y = Concat [Range x x, build xs ys]
| sl && x+1 <= y-1 = Or (Or lower middle) upper
| sl = Or lower upper
| otherwise = Or (build a (nines la)) (build (1:zeros la) b)
where (la,lb) = (length a, length b)
sl = la == lb
n = length xs
upper = Concat [Range y y, build (zeros n) ys]
lower = Concat [Range x x, build xs (nines n)]
middle = Concat [Range (x+1) (y-1), build (zeros n) (nines n)]
zeros n = replicate n 0
nines n = replicate n 9
d 0 = [0]
d n = digits 10 n
re_size*5 + prog_size
(nhỏ hơn = tốt hơn), trong đóre_size
tối đa chom
và tối đan
5 chữ số. Có nhiều cách khác để làm điều đó - điều quan trọng là chúng ta có thể chấm điểm các câu trả lời.