Hard code golf: Regex for divisibility by 7

76

28

Matthias Goergens has a 25,604-character (down from the original 63,993-character) regex to match numbers divisible by 7, but that includes a lot of fluff: redundant parentheses, distribution (xx|xy|yx|yy rather than [xy]{2}) and other issues, though I'm sure a fresh start would be helpful in saving space. How small can this be made?

Any reasonable variety of regular expressions are allowed, but no executable code in the regex.

The regular expression should match all strings containing the decimal representation of a number divisible by 7 and no others. Extra credit for a regex that does not allow initial 0s.

Charles

Posted 2011-08-19T20:21:45.450

Reputation: 2 435

That leaves out Perl 6 as a Regex inherits from Method so is a form of executable code. – Brad Gilbert b2gills – 2016-01-17T19:26:19.840

Would you please clarify whether you want to allow the number zero in the case of no "initial 0s"? – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2016-03-16T03:55:57.653

2@n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Yes, 0 should be allowed in either version. – Charles – 2016-03-16T05:28:14.073

1By any chance... need the regex not match numbers indivisible by 7? – boothby – 2014-01-07T08:25:24.960

@boothby: Absolutely, else you could just use the empty expression. – Charles – 2014-01-07T09:12:12.610

What is the precise intention? Does it have to match all numbers of any size divisible by 7, or, for example, only valid 32-bit uints? – Peter Taylor – 2011-08-19T20:38:12.630

2@Peter Taylor: It should match all strings that are the decimal representation of a number divisible by 7. Extra credit for solutions that disallow leading 0s. – Charles – 2011-08-19T22:13:05.583

Answers

24

10791 characters, leading zeros allowed

(0|7|46*[29]|(1|8|46*3|(2|9|46*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(4|63*[18]|(1|8|63*5)(6|43*5)*(2|9|43*[18]))|(2|9|46*4)(3|56*4)*(1|8|56*[29])|(3|46*5|(1|8|46*3|(2|9|46*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4))|(2|9|46*4)(3|56*4)*(4|56*5)|(5|46*[07]|(1|8|46*3|(2|9|46*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))|(2|9|46*4)(3|56*4)*(6|56*[07]))(4|36*[07]|(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4))|(1|8|36*4)(3|56*4)*(4|56*5)))(1|8|(0|7|[29]6*4)(3|56*4)*(4|56*5)|[29]6*5|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))|(6|(0|7|[29]6*4)(3|56*4)*(2|9|56*3)|[29]6*3|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3)))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4)|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))))*(5|34*6|(0|7|34*[18]|(2|9|34*3)(6|[07]4*3)*(4|[07]4*[18]))(3|56*4|(6|56*[07])(4|36*[07])*(1|8|36*4))*(1|8|64*6|(5|64*3)(6|[07]4*3)*(2|9|[07]4*6))|(2|9|34*3)(6|[07]4*3)*(2|9|[07]4*6)|(6|(0|7|[29]6*4)(3|56*4)*(2|9|56*3)|[29]6*3|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3)))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(4|63*[18]|(1|8|63*5)(6|43*5)*(2|9|43*[18])|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(6|36*[29]|(1|8|36*4)(3|56*4)*(1|8|56*[29]))))|(5|46*[07]|(1|8|46*3|(2|9|46*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))|(2|9|46*4)(3|56*4)*(6|56*[07]))(4|36*[07]|(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))|(1|8|36*4)(3|56*4)*(6|56*[07]))*(6|36*[29]|(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(4|63*[18]|(1|8|63*5)(6|43*5)*(2|9|43*[18]))|(1|8|36*4)(3|56*4)*(1|8|56*[29]))|(6|46*[18]|(1|8|46*3|(2|9|46*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(3|63*[07]|(1|8|63*5)(6|43*5)*(1|8|43*[07]))|(2|9|46*4)(3|56*4)*(0|7|56*[18])|(3|46*5|(1|8|46*3|(2|9|46*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4))|(2|9|46*4)(3|56*4)*(4|56*5)|(5|46*[07]|(1|8|46*3|(2|9|46*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))|(2|9|46*4)(3|56*4)*(6|56*[07]))(4|36*[07]|(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4))|(1|8|36*4)(3|56*4)*(4|56*5)))(1|8|(0|7|[29]6*4)(3|56*4)*(4|56*5)|[29]6*5|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))|(6|(0|7|[29]6*4)(3|56*4)*(2|9|56*3)|[29]6*3|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3)))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4)|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))))*(4|34*5|(0|7|34*[18]|(2|9|34*3)(6|[07]4*3)*(4|[07]4*[18]))(3|56*4|(6|56*[07])(4|36*[07])*(1|8|36*4))*(0|7|64*5|(5|64*3)(6|[07]4*3)*(1|8|[07]4*5))|(2|9|34*3)(6|[07]4*3)*(1|8|[07]4*5)|(6|(0|7|[29]6*4)(3|56*4)*(2|9|56*3)|[29]6*3|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3)))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(3|63*[07]|(1|8|63*5)(6|43*5)*(1|8|43*[07])|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(5|36*[18]|(1|8|36*4)(3|56*4)*(0|7|56*[18]))))|(5|46*[07]|(1|8|46*3|(2|9|46*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))|(2|9|46*4)(3|56*4)*(6|56*[07]))(4|36*[07]|(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))|(1|8|36*4)(3|56*4)*(6|56*[07]))*(5|36*[18]|(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(3|63*[07]|(1|8|63*5)(6|43*5)*(1|8|43*[07]))|(1|8|36*4)(3|56*4)*(0|7|56*[18])))(2|9|53*[07]|(0|7|53*5)(6|43*5)*(1|8|43*[07])|(1|8|53*6|(0|7|53*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(5|36*[18]|(1|8|36*4)(3|56*4)*(0|7|56*[18]))|(4|[07]6*3|(1|8|53*6|(0|7|53*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(5|[07]6*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(3|63*[07]|(1|8|63*5)(6|43*5)*(1|8|43*[07])|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(5|36*[18]|(1|8|36*4)(3|56*4)*(0|7|56*[18])))|(6|53*4|(0|7|53*5)(6|43*5)*(5|43*4)|(1|8|53*6|(0|7|53*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))|(4|[07]6*3|(1|8|53*6|(0|7|53*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(5|[07]6*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4)|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))))(1|8|(0|7|[29]6*4)(3|56*4)*(4|56*5)|[29]6*5|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))|(6|(0|7|[29]6*4)(3|56*4)*(2|9|56*3)|[29]6*3|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3)))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4)|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))))*(4|34*5|(0|7|34*[18]|(2|9|34*3)(6|[07]4*3)*(4|[07]4*[18]))(3|56*4|(6|56*[07])(4|36*[07])*(1|8|36*4))*(0|7|64*5|(5|64*3)(6|[07]4*3)*(1|8|[07]4*5))|(2|9|34*3)(6|[07]4*3)*(1|8|[07]4*5)|(6|(0|7|[29]6*4)(3|56*4)*(2|9|56*3)|[29]6*3|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3)))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(3|63*[07]|(1|8|63*5)(6|43*5)*(1|8|43*[07])|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(5|36*[18]|(1|8|36*4)(3|56*4)*(0|7|56*[18])))))*(3|53*[18]|(0|7|53*5)(6|43*5)*(2|9|43*[18])|(1|8|53*6|(0|7|53*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(6|36*[29]|(1|8|36*4)(3|56*4)*(1|8|56*[29]))|(4|[07]6*3|(1|8|53*6|(0|7|53*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(5|[07]6*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(4|63*[18]|(1|8|63*5)(6|43*5)*(2|9|43*[18])|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(6|36*[29]|(1|8|36*4)(3|56*4)*(1|8|56*[29])))|(6|53*4|(0|7|53*5)(6|43*5)*(5|43*4)|(1|8|53*6|(0|7|53*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))|(4|[07]6*3|(1|8|53*6|(0|7|53*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(5|[07]6*4)(3|56*4)*(2|9|56*3))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4)|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))))(1|8|(0|7|[29]6*4)(3|56*4)*(4|56*5)|[29]6*5|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))|(6|(0|7|[29]6*4)(3|56*4)*(2|9|56*3)|[29]6*3|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3)))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(0|7|63*4|(1|8|63*5)(6|43*5)*(5|43*4)|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(2|9|36*5|(1|8|36*4)(3|56*4)*(4|56*5))))*(5|34*6|(0|7|34*[18]|(2|9|34*3)(6|[07]4*3)*(4|[07]4*[18]))(3|56*4|(6|56*[07])(4|36*[07])*(1|8|36*4))*(1|8|64*6|(5|64*3)(6|[07]4*3)*(2|9|[07]4*6))|(2|9|34*3)(6|[07]4*3)*(2|9|[07]4*6)|(6|(0|7|[29]6*4)(3|56*4)*(2|9|56*3)|[29]6*3|(3|[07]3*6|(2|9|[07]3*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3)))(5|[18]6*3|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(0|7|36*3|(1|8|36*4)(3|56*4)*(2|9|56*3))|(6|[18]6*4)(3|56*4)*(2|9|56*3))*(4|63*[18]|(1|8|63*5)(6|43*5)*(2|9|43*[18])|(2|9|63*6|(1|8|63*5)(6|43*5)*(0|7|43*6))(4|36*[07]|(1|8|36*4)(3|56*4)*(6|56*[07]))*(6|36*[29]|(1|8|36*4)(3|56*4)*(1|8|56*[29]))))))+

10795 characters, leading zeros forbidden

0|((foo)0*)+, where the above regex is (0|foo)+.

Explanation

Numbers divisible by 7 are matched by the obvious finite automaton with 7 states Q = {0, …, 6}, initial and final state 0, and transitions d: i ↦ (10i + d) mod 7. I converted this finite automaton into a regular expression, using recursion on the set of allowed intermediate states:

Given i, j ∈ Q and S ⊆ Q, let f(i, S, j) be a regular expression that matches all automaton paths from i to j using only intermediate states within S. Then,

f(i, ∅, j) = (j − 10i) mod 7,

f(i, S ∪ {k}, j) = f(i, S, j) ∣ f(i, S, k) f(k, S, k)* f(k, S, j).

I used dynamic programming to choose k so as to minimize the length of the resulting expression.

Anders Kaseorg

Posted 2011-08-19T20:21:45.450

Reputation: 29 242

I think you have to add 2 character for in the leading zero case, since I guess zero has to be allowed 0|((foo)0*)+ – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2016-03-16T03:05:08.010

3I have commented on the question, but by common sense, "no leading zero" usually means that no redundant leading 0, but it does not exclude the number zero. – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2016-03-16T03:56:44.063

95

13,755 12,699 12,731 Characters

This regex does not reject leading zero.

(0|7|[18]5*4|(2|9|[18]5*6)(3|[29]5*6)*(1|8|[29]5*4)|(3|[18]5*[07]|(2|9|[18]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(5|65*4|(0|7|65*6)(3|[29]5*6)*(1|8|[29]5*4))|(4|[18]5*[18]|(2|9|[18]5*6)(3|[29]5*6)*(5|[29]5*[18])|(3|[18]5*[07]|(2|9|[18]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(2|9|35*4|(4|35*6)(3|[29]5*6)*(1|8|[29]5*4)|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(5|65*4|(0|7|65*6)(3|[29]5*6)*(1|8|[29]5*4)))|(5|[18]5*[29]|(2|9|[18]5*6)(3|[29]5*6)*(6|[29]5*[29])|(3|[18]5*[07]|(2|9|[18]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))|(4|[18]5*[18]|(2|9|[18]5*6)(3|[29]5*6)*(5|[29]5*[18])|(3|[18]5*[07]|(2|9|[18]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(0|7|35*[29]|(4|35*6)(3|[29]5*6)*(6|[29]5*[29])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))))(4|[07]5*[29]|(1|8|[07]5*6)(3|[29]5*6)*(6|[29]5*[29])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))|(3|[07]5*[18]|(1|8|[07]5*6)(3|[29]5*6)*(5|[29]5*[18])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(0|7|35*[29]|(4|35*6)(3|[29]5*6)*(6|[29]5*[29])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))))*(6|[07]5*4|(1|8|[07]5*6)(3|[29]5*6)*(1|8|[29]5*4)|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(5|65*4|(0|7|65*6)(3|[29]5*6)*(1|8|[29]5*4))|(3|[07]5*[18]|(1|8|[07]5*6)(3|[29]5*6)*(5|[29]5*[18])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(2|9|35*4|(4|35*6)(3|[29]5*6)*(1|8|[29]5*4)|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(5|65*4|(0|7|65*6)(3|[29]5*6)*(1|8|[29]5*4))))|(6|[18]5*3|(2|9|[18]5*6)(3|[29]5*6)*(0|7|[29]5*3)|(3|[18]5*[07]|(2|9|[18]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(4|65*3|(0|7|65*6)(3|[29]5*6)*(0|7|[29]5*3))|(4|[18]5*[18]|(2|9|[18]5*6)(3|[29]5*6)*(5|[29]5*[18])|(3|[18]5*[07]|(2|9|[18]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(1|8|35*3|(4|35*6)(3|[29]5*6)*(0|7|[29]5*3)|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(4|65*3|(0|7|65*6)(3|[29]5*6)*(0|7|[29]5*3)))|(5|[18]5*[29]|(2|9|[18]5*6)(3|[29]5*6)*(6|[29]5*[29])|(3|[18]5*[07]|(2|9|[18]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))|(4|[18]5*[18]|(2|9|[18]5*6)(3|[29]5*6)*(5|[29]5*[18])|(3|[18]5*[07]|(2|9|[18]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(0|7|35*[29]|(4|35*6)(3|[29]5*6)*(6|[29]5*[29])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))))(4|[07]5*[29]|(1|8|[07]5*6)(3|[29]5*6)*(6|[29]5*[29])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))|(3|[07]5*[18]|(1|8|[07]5*6)(3|[29]5*6)*(5|[29]5*[18])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(0|7|35*[29]|(4|35*6)(3|[29]5*6)*(6|[29]5*[29])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))))*(5|[07]5*3|(1|8|[07]5*6)(3|[29]5*6)*(0|7|[29]5*3)|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(4|65*3|(0|7|65*6)(3|[29]5*6)*(0|7|[29]5*3))|(3|[07]5*[18]|(1|8|[07]5*6)(3|[29]5*6)*(5|[29]5*[18])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(1|8|35*3|(4|35*6)(3|[29]5*6)*(0|7|[29]5*3)|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(4|65*3|(0|7|65*6)(3|[29]5*6)*(0|7|[29]5*3)))))(2|9|45*3|(5|45*6)(3|[29]5*6)*(0|7|[29]5*3)|(6|45*[07]|(5|45*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(4|65*3|(0|7|65*6)(3|[29]5*6)*(0|7|[29]5*3))|(0|7|45*[18]|(5|45*6)(3|[29]5*6)*(5|[29]5*[18])|(6|45*[07]|(5|45*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(1|8|35*3|(4|35*6)(3|[29]5*6)*(0|7|[29]5*3)|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(4|65*3|(0|7|65*6)(3|[29]5*6)*(0|7|[29]5*3)))|(1|8|45*[29]|(5|45*6)(3|[29]5*6)*(6|[29]5*[29])|(6|45*[07]|(5|45*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))|(0|7|45*[18]|(5|45*6)(3|[29]5*6)*(5|[29]5*[18])|(6|45*[07]|(5|45*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(0|7|35*[29]|(4|35*6)(3|[29]5*6)*(6|[29]5*[29])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))))(4|[07]5*[29]|(1|8|[07]5*6)(3|[29]5*6)*(6|[29]5*[29])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))|(3|[07]5*[18]|(1|8|[07]5*6)(3|[29]5*6)*(5|[29]5*[18])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(0|7|35*[29]|(4|35*6)(3|[29]5*6)*(6|[29]5*[29])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))))*(5|[07]5*3|(1|8|[07]5*6)(3|[29]5*6)*(0|7|[29]5*3)|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(4|65*3|(0|7|65*6)(3|[29]5*6)*(0|7|[29]5*3))|(3|[07]5*[18]|(1|8|[07]5*6)(3|[29]5*6)*(5|[29]5*[18])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(1|8|35*3|(4|35*6)(3|[29]5*6)*(0|7|[29]5*3)|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(4|65*3|(0|7|65*6)(3|[29]5*6)*(0|7|[29]5*3)))))*(3|45*4|(5|45*6)(3|[29]5*6)*(1|8|[29]5*4)|(6|45*[07]|(5|45*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(5|65*4|(0|7|65*6)(3|[29]5*6)*(1|8|[29]5*4))|(0|7|45*[18]|(5|45*6)(3|[29]5*6)*(5|[29]5*[18])|(6|45*[07]|(5|45*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(2|9|35*4|(4|35*6)(3|[29]5*6)*(1|8|[29]5*4)|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(5|65*4|(0|7|65*6)(3|[29]5*6)*(1|8|[29]5*4)))|(1|8|45*[29]|(5|45*6)(3|[29]5*6)*(6|[29]5*[29])|(6|45*[07]|(5|45*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))|(0|7|45*[18]|(5|45*6)(3|[29]5*6)*(5|[29]5*[18])|(6|45*[07]|(5|45*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(0|7|35*[29]|(4|35*6)(3|[29]5*6)*(6|[29]5*[29])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))))(4|[07]5*[29]|(1|8|[07]5*6)(3|[29]5*6)*(6|[29]5*[29])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))|(3|[07]5*[18]|(1|8|[07]5*6)(3|[29]5*6)*(5|[29]5*[18])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(0|7|35*[29]|(4|35*6)(3|[29]5*6)*(6|[29]5*[29])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(3|65*[29]|(0|7|65*6)(3|[29]5*6)*(6|[29]5*[29]))))*(6|[07]5*4|(1|8|[07]5*6)(3|[29]5*6)*(1|8|[29]5*4)|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(5|65*4|(0|7|65*6)(3|[29]5*6)*(1|8|[29]5*4))|(3|[07]5*[18]|(1|8|[07]5*6)(3|[29]5*6)*(5|[29]5*[18])|(2|9|[07]5*[07]|(1|8|[07]5*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))(6|35*[18]|(4|35*6)(3|[29]5*6)*(5|[29]5*[18])|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(2|9|65*[18]|(0|7|65*6)(3|[29]5*6)*(5|[29]5*[18])))*(2|9|35*4|(4|35*6)(3|[29]5*6)*(1|8|[29]5*4)|(5|35*[07]|(4|35*6)(3|[29]5*6)*(4|[29]5*[07]))(1|8|65*[07]|(0|7|65*6)(3|[29]5*6)*(4|[29]5*[07]))*(5|65*4|(0|7|65*6)(3|[29]5*6)*(1|8|[29]5*4))))))*

This is tested with The Regex Coach.

How We Get There

The Regex above produced by first constructing a DFA which would accept the input we want (decimals divisible by 7) and then converting to a Regular Expression and fixing the notaion

To understand this, it helps to first make a DFA which accepts the following language:

L = {w | w is a binary representation of an integer divisible by 7 }

That is, it will 'match' binary numbers that are divisible by 7.

The DFA looks like this:

Mod 7 NFA

How it works

You keep a current value A that represents the value of the bits the DFA has read. When you read a 0 then A = 2*A and when you read a 1 A = 2*A + 1. At each step you calculate A mod 7 then you go to the state that represents the answer.

So a test run:

We're reading in 10101 which is the binary representation for 21 in decimal.

  1. We start at state q0, currently A=0
  2. We read a 1, from the 'rule' above A = 2*A + 1 so A = 1. A mod 7 = 1 so we move to state q1
  3. We read a 0, A = 2*A = 2, A mod 7 = 2 so we move to q2
  4. Read a 1, A = 2*A + 1 = 5, A mod 7 = 5, move to q5
  5. Read a 0, A = 2*A = 10, A mod 7 = 3, move to q3
  6. Read a 1, A = 2*A + 1 = 21, A mod 7 = 0, move to q0
  7. The input is accepted so the number 10101 is divisible by 7!

Converting the DFA to a Regular Expression is a tricky task so I got JFLAP to do it for me, producing the following:

(0|111|100((1|00)0)*011|(101|100((1|00)0)*(1|00)1)(1((1|00)0)*(1|00)1)*(01|1((1|00)0)*011)|(110|100((1|00)0)*010|(101|100((1|00)0)*(1|00)1)(1((1|00)0)*(1|00)1)*(00|1((1|00)0)*010))(1|0(1((1|00)0)*(1|00)1)*(00|1((1|00)0)*010))*0(1((1|00)0)*(1|00)1)*(01|1((1|00)0)*011))*

For Decimal Numbers

The process is much the same:

I constructed a DFA which accepts the language:

L = {w | w is a decimal number that is divisible by 7}

Here is the DFA:

The logic is similar, same number of states just many more transitions to handle all the extra digits decimal numbers bring.

Now the rule to change A at each step is: when you read a decimal digit n: A = 10*A + n. Then again you just mod A by 7 and go to the next state.

Revisions

Revision 5

The above regular expression now rejects numbers leading zeros - apart from zero itself of course.

This makes the DFA slightly different, basically you branch off from the initial node when you read the first zero. Reading another zero puts you into an infinite loop on the branched state. I haven't fixed the diagram to show this.

Revision 7

Did some "metaregex" and shortened my regex by replacing some of the unions with character classes.

Revision 10 and 11 (by nhahtdh)

The author's modification to reject leading zero is incorrect. It makes the regexes fail to match valid numbers, such as 1110 (decimal = 14) in the case of binary regex, and 70 in the case of decimal regex. These revision reverts the modification, and consequently, allows arbitrary leading zeros and empty string to match.

This revision increases the size of the decimal regex, since it corrects a bug in the original regex, caused by a missing an edge (9) from state 5 to state 3 in the original DFA.

Griffin

Posted 2011-08-19T20:21:45.450

Reputation: 4 349

2Neither of the regexes shown in this answer are correct. The binary one doesn't match 1110, and the one for decimal doesn't match 70. This was tested in both python and perl. (python required converting every ( to (?: first) – Daniel Martin – 2015-11-09T18:53:38.020

@Griffin: As per Daniel Martin's comment, I have made changes to the regex to correct the errors. To prevent the leading zero, you can't take out the 0 from the repetition, since it is also used for the case where the number ends in 0 and divisible by 7. – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2016-03-10T11:10:21.120

Why don't you use the common divisibility by 7 criterion ? from the first link on google: 'To find out if a number is divisible by seven, take the last digit, double it, and subtract it from the rest of the number. If you get an answer divisible by 7 (including zero), then the original number is divisible by seven. If you don't know the new number's divisibility, you can apply the rule again.' – lcrmorin – 2016-03-10T20:00:11.823

@Were_cat: If you have any idea to encode that into a regex, please post an answer. Regex can only do matching, not subtraction, unless you are dealing with unary, but if it's in unary, then you don't need to encode such a complex instruction - simply (.{7})* is enough. – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ – 2016-03-16T02:38:54.053

3

btw i think you used DFA, not NFA

– binarycode – 2013-12-23T19:02:11.800

@binarycode but they're equivalent! ;) good spot, edited to fix. – Griffin – 2013-12-29T01:40:39.490

@binarycode every DFA is trivially also an NFA ;) – Tim Seguine – 2014-01-08T11:04:20.670

I will clarify the question to specify decimal. Yes, it's much easier in bases b where 7 | b(b-1). – Charles – 2011-08-19T22:14:23.177

I have amended my answer. Decimal is all good :D – Griffin – 2011-08-19T22:19:09.313

Too late for me to amend my comment, though... I meant 7 | B(B-1) where B is a small power of b. Binary has a short regex since 7 | 8(8-1). Decimal is larger since 7 | 999999000000 is the smallest that works. – Charles – 2011-08-19T23:11:10.650

shouldn't the + be replaced with | in there? – ratchet freak – 2011-08-19T23:18:48.237

@ratchet, you're right, doing that makes it a valid Regex, it's just a matter of notation. But I'll amend my answer since it's more useful as a regex rather than a regular expression. Cheers – Griffin – 2011-08-19T23:27:27.370

@Charles. My Regex now conforms to your "Extra credit for a regex that does not allow initial 0s." Zero itself is of course accepted, however. – Griffin – 2011-08-19T23:41:35.233

Heh, you get an extra .01 extra credit points for catching the exception to the "no leading zeros" rule. – Charles – 2011-08-20T03:56:13.660

35

.NET regex, 119 118 105 bytes

^(?>(?=[1468](?<4>)|)(?=[2569](?<4>){2}|)([3-6]()|\d)((?<-2>)(){3}|){7}((?<-4>){7}|(?<2-4>)|){9})+$(?!\2)

111 characters disallowing initial 0s:

^(?!0.)(?>(?=[1468](?<4>)|)(?=[2569](?<4>){2}|)([3-6]()|\d)((?<-2>)(){3}|){7}((?<-4>){7}|(?<2-4>)|){9})+$(?!\2)

113 characters disallowing initial 0s and supporting negative numbers:

^-?(?>(?=[1468](?<4>)|)(?=[2569](?<4>){2}|)([3-6]()|\d)((?<-2>)(){3}|){7}((?<-4>){7}|(?<2-4>)|){9})+$(?!\2)

Try it here.

Explanation (of the previous version)

It uses the techniques used by various answers in this question: Cops and Robbers: Reverse Regex Golf. The .NET regex has a feature called balancing group, which can be used for doing arithmetic. (?<a>) pushes a group a. (?<-a>) pops that and doesn't match if there isn't a group a matched before.

  • (?>...) Match and don't backtrack later. So it will always match only the first matched alternative.
  • ((?<-t>)(){3}|){6} Multiply the number of group t by 3. Save the result in the number of group 2.
  • (?=[1468](?<2>)|)(?=[2569](?<2>){2}|)([3-6](?<2>){3}|\d) Match a number, and that number of group 2.
  • ((?<-2>){7}|){3} Remove group 2 a multiple of 7 times.
  • ((?<t-2>)|){6} Remove group 2 and match the same number of group t.
  • $(?(t)a) If there is still a group t matched, match a after the end of string, which is impossible.

I thought this 103 byte version should also work, but didn't find a workaround of the bug in the compiler.

^(?(?(?((?<3>){2}[2569]|)([3-6])?((?<-1>)(){3}|){7})(?<3>[1468])?((?<-3>){7}|(?<1-3>)|){9})\d)+$(?(1)a)

jimmy23013

Posted 2011-08-19T20:21:45.450

Reputation: 34 042

I don't think this is gonna be beaten, but I prefer at least having to implement the DFA with recursion, this is just insane. I wonder if someone can prove or disprove .NET regexes as Turing complete. – ThePlasmaRailgun – 2019-02-27T05:48:07.823

@ThePlasmaRailgun .NET regex is not Turing complete, because it doesn't allow repeating empty captures more than the lower bound (example). So each group with quantifiers could have only a finite number of alternatives if the input has a fixed length.

– jimmy23013 – 2019-02-27T09:48:12.790

Ah. Without that bound, would it be Turing complete? – ThePlasmaRailgun – 2019-02-27T17:31:46.577

@ThePlasmaRailgun Yes. You can use it to simulate Minsky machines. More practically, you can use two balancing groups as stacks if the input has at least 1 character, but you have to hardcode the output for the empty input this way. – jimmy23013 – 2019-02-27T18:18:54.490

Very short. I'd love an explanation of how this works! – Charles – 2014-10-25T23:13:12.407

@Charles Edited. – jimmy23013 – 2014-10-26T03:36:59.623

30

468 characters

Ruby's regex flavor allows recursion (although it's sort of cheating), so it is straightforward to implement a DFA that recognizes numbers divisible by 7 using that. Each named group corresponds to a state, and each branch in the alternations consumes one digit and then jumps to the appropriate state. If the end of the number is reached, the regex matches only if the engine is in the "A" group, otherwise it fails.

It recognizes leading zeros.

(?!$)(?>(|(?<B>4\g<A>|5\g<B>|6\g<C>|[07]\g<D>|[18]\g<E>|[29]\g<F>|3\g<G>))(|(?<C>[18]\g<A>|[29]\g<B>|3\g<C>|4\g<D>|5\g<E>|6\g<F>|[07]\g<G>))(|(?<D>5\g<A>|6\g<B>|[07]\g<C>|[18]\g<D>|[29]\g<E>|3\g<F>|4\g<G>))(|(?<E>[29]\g<A>|3\g<B>|4\g<C>|5\g<D>|6\g<E>|[07]\g<F>|[18]\g<G>))(|(?<F>6\g<A>|[07]\g<B>|[18]\g<C>|[29]\g<D>|3\g<E>|4\g<F>|5\g<G>))(|(?<G>3\g<A>|4\g<B>|5\g<C>|6\g<D>|[07]\g<E>|[18]\g<F>|[29]\g<G>)))(?<A>$|[07]\g<A>|[18]\g<B>|[29]\g<C>|3\g<D>|4\g<E>|5\g<F>|6\g<G>)

Lowjacker

Posted 2011-08-19T20:21:45.450

Reputation: 4 466

I made a generator based on your post that creates these for arbitrary divisors and bases: https://github.com/ThePlasmaRailgun/DivisibilityRegexes. It also has the option to generate the .jff files for JFLAP.

– ThePlasmaRailgun – 2019-02-27T05:27:33.800

3I had intended to disallow that, but I guess I didn't. This allows for very short solutions in Ruby, Perl, PCRE, and .NET languages. – Charles – 2011-08-21T17:13:19.853

2recursion makes it a context-free grammar (if it can decide {a*b*|a and b an equal amount of times}) – ratchet freak – 2011-08-21T19:38:07.717

@ratchet freak: I know that this technically isn't a regular expression, but the question states that any regex flavor is acceptable. – Lowjacker – 2011-08-21T20:09:16.277

24

I was really impressed by Griffin's answer and needed to figure out how it worked! The result is the following JavaScript. (It's 3.5k characters, which is shorter in a way!) The gen function takes a divisor and base and generates a regular expression that matches numbers in the specified base that are divisible by that divisor.

I've generalized Griffin's NFA for any base: the nfa function takes a divisor and base and returns a two dimensional array of transitions. The input required to go from state 0 to state 2, for example, is states[0][2] == "1".

The reduce function takes in the states array and runs it through this algorithm to translate the NFA to regex. The regexes that are generated are huge and look like they have a lot of redundant clauses, despite my attempts at optimization. The regex for 7 base 10 is about ~67k characters long; Firefox throws an "InternalError" for n > 5 trying to parse the regex; running the regex on Chrome starts getting slow for n > 6.

There's also the test function that takes a regex and base and runs it against the numbers 0 to 100, so test(gen(5)) == [0, 5, 10, 15, ...].

Despite the suboptimal result, this was a fantastic learning opportunity, and I hope some of this code will be useful in the future!

function gen(b, base) {
    var states = nfa(b, base)
    for (var i = 0; i < states.length; i++)
        states = reduce(states, i);
    return states[0][0] != 'phi' && new RegExp('^' + wrap(states[0][0]) + '$');
}

function test(reg, base) {
    if (!base)
        base = 10;

    var x = [];
    for (var i = 0; i < 100; i++)
        x.push(i);
    return x.map(function (a) {return a.toString(base)}).filter(reg.test.bind(reg)).map(function (a) {return parseInt(a, base)})
}

function nfa(b, base) {
    if (!base)
        base = 10;

    var states = [];
    for (var i = 0; i < b; i++) {
        states[i] = [];
        for (var j = 0; j < b; j++)
            states[i][j] = [];
    }

    for (var i = 0; i < b; i++)
        for (var n = 0; n < base; n++)
            states[i][(i * base + n) % b].push(n.toString());

    for (var i = 0; i < b; i++)
        for (var j = 0; j < b; j++)
            states[i][j] = states[i][j].length > 1 ? '[' + states[i][j].join('') + ']' : (states[i][j][0] || 'phi');
    return states;
}

// http://www.cs.umbc.edu/~squire/cs451_l7.html
function reduce(states, n) {
    var s = states.length;
    var reduced = [];
    for (var i = 0; i < s; i++) {
        reduced[i] = [];
        for (var j = 0; j < s; j++) {
            // reduced[i][j] = wrap(states[i][n] + wrap(states[n][n]) + '*' + states[n][j] + '|' + states[i][j]);
            reduced[i][j] = '';

            if (states[i][n] == 'phi' || states[n][j] == 'phi') {
                reduced[i][j] = states[i][j];
                continue;
            }

            if (states[i][n] != states[n][n])
                reduced[i][j] += wrap(states[i][n]);

            if (states[n][n] != 'phi') {
                reduced[i][j] += wrap(states[n][n]);

                if (states[i][n] == states[n][n] && states[n][j] == states[n][n])
                    reduced[i][j] += wrap(states[n][n]);

                if (states[i][n] == states[n][n] || states[n][j] == states[n][n])
                    reduced[i][j] += '+';
                else
                    reduced[i][j] += '*';
            }

            if (states[n][j] != states[n][n])
                reduced[i][j] += wrap(states[n][j]);

            reduced[i][j] = states[i][j] == 'phi' ? wrap(reduced[i][j]) : alternate(reduced[i][j], states[i][j]);
        }
    }
    return reduced;
}

function matching(x, open, close) {
    // Test if the parens are actually matching
    if ('(['.indexOf(x.charAt(open)) != -1 && ')]'.indexOf(x.charAt(close)) != -1) {
        var count = 0;
        for (var i = open; i <= close; i++) {
            if ('(['.indexOf(x.charAt(i)) != -1)
                count++;
            else if (')]'.indexOf(x.charAt(i)) != -1) {
                count--;

                if (count == 0)
                    return i == close;
            }
        }
    }

    return false;
}

function wrap(x) {
    if (x.length < 2 || matching(x, 0, x.length - 1))
        return x;
    return '(' + x + ')';
}

function optional(cond) {
    if (matching(cond, 0, cond.length - 2)) {
        var op = cond.charAt(cond.length - 1);
        if (op == '+')
            return cond.slice(0, -1) + '*';
        else if (op == '*' || op == '?')
            return cond;
    } else if (matching(cond, 0, cond.length - 1))
        return optional(cond.slice(1, -1));

    return wrap(cond) + '?';
}

function alternate(cond1, cond2) {
    cond2 = wrap(cond2);
    var index = cond1.indexOf(cond2);
    var len = cond2.length;
    var cond = '';

    if (index == 0) {
        var op = cond1.charAt(len);
        if (op == '*')
            cond = cond2 + '+' + optional(cond1.slice(len));
        else if (op == '+')
            cond = cond1;
        else 
            cond = cond2 + optional(cond1.slice(len));
    } else if (index == cond1.length - len)
        cond = optional(cond1.slice(0, index)) + cond2;
    else if (cond1.length == 1 && cond2.length == 1)
        cond = '[' + cond1 + cond2 + ']';
    else
        cond = cond1 + '|' + cond2;

    return wrap(cond);
}

Casey Chu

Posted 2011-08-19T20:21:45.450

Reputation: 1 661

7

Perl/PCRE, 370 characters

^(?!$|0.)([07]*(?:[18](?2)|[29](?3)|3(?4)|4(?5)|5(?7)|6(?9)|$))|(5*(?:[07](?4)|[18](?5)|[29](?7)|4(?1)|6(?3)|3(?9)))(3*(?:[18](?1)|[29](?2)|[07](?9)|4(?4)|5(?5)|6(?7)))([18]*(?:[07](?3)|[29](?5)|5(?1)|6(?2)|3(?7)|4(?9)))(6*([29](?1)|[07](?7)|[18](?9)|3(?2)|4(?3)|5(?4)))(4*([07](?2)|[18](?3)|[29](?4)|6(?1)|3(?5)|5(?9)))([29]*([07](?5)|[18](?7)|3(?1)|4(?2)|5(?3)|6(?4)))

Rejects the empty string, as well as strings with leading 0’s (except "0").

Grimmy

Posted 2011-08-19T20:21:45.450

Reputation: 12 521

@Charles This is valid PHP PCRE, and does indeed work to validate divisibility -- try it here

– cat – 2016-03-10T22:56:09.907