14

I want to write a regular expression for Binary Numbers Divisible by 5.
I have already done the regular expressions for Binary Numbers Divisible by 2 and for 3 but I couldn't find one for 5.

Any suggestions?

5
  • 1
    Please show us what you've tried and how it's not working. Commented Dec 26, 2015 at 23:58
  • i don't really know where to start because the numbers are very differents : 0101 , 1010 , 1111 , 10100 ... there is no special rule to apply Commented Dec 27, 2015 at 0:04
  • 2
    Generalized Pascal divisibility criteria gives reduce sequence of (1, 2, 4, 3, 1, ...) and I hardly can see how this can be utilized by regex. However, if your final goal is just to check huge binary number for divisibility, you can use it directly. Simply pass through your number from lowest digit multiplying digits on sequence numbers and collecting total. The remainder of total is the remainder of initial number. That's the best link I found so far mathworld.wolfram.com/DivisibilityTests.html Commented Dec 27, 2015 at 0:19
  • 2
    A regular expression is not the right tool for this job. Commented Dec 27, 2015 at 2:19
  • @VasilyLiaskovsky, this is a classical example of FDA/regular expression exercise. Check out my answer. Commented Dec 27, 2015 at 14:58

3 Answers 3

34
(0|1(10)*(0|11)(01*01|01*00(10)*(0|11))*1)*

Add ^$ to test it with regexp. See it working here.


You can build a DFA and convert it to regular expression. The DFA was already built in another answer. You can read it, it is very well explained.
The general idea is to remove nodes, adding edges. before

Becomes:

after


Using this transformation and the DFA from the answer I linked, here are the steps to get the regular expression:
(EDIT: Note that the labels "Q3" and "Q4" have been mistakenly swapped in the diagram. These states represent the remainder after modulus 5.) step1 step2 step3 step4 step5

Sign up to request clarification or add additional context in comments.

7 Comments

I would be very happy if your answer is correct. But if your answer is correct, why this isn't matching? regex101.com/r/hP1cO0/1
Found it why. OK. You are right, congrats! I'm very pleased to see your answer working, because I spent 3 hours for searching a regex, and disappointed as I thought there is no solution.
However, "^(0|1(10)*(0|11)(01*01|01*00(10)*(0|11))*1)*$" matches empty string.
nice answer with the images. Kudos for that. Just one short comment after trying to decipher this logic myself from scratch: you seem to have the Q3 and Q4 state names mixed up in the starting image making it bit harder to follow (obviously that doesn't have any effect on the correct result - just makes it a bit harder to understand how the the starting situation is created).
In case anyone is looking for the pattern that will not match an empty string: ^(0|1(10)*(0|11)(01*01|01*00(10)*(0|11))*1)+$
|
2
2^0 =  1 =  1 mod 5
2^1 =  2 =  2 mod 5
2^2 =  4 = -1 mod 5
2^3 =  8 = -2 mod 5
2^4 = 16 =  1 mod 5
2^5 = 32 =  2 mod 5
   ...     -1 mod 5
   ...     -2 mod 5

So we have a 1, 2, -1, -2 pattern. There are two subpatterns where only the sign of the number alternates: Let n is the digit number and the number of the least significant digit is 0; odd pattern is

(-1)^(n)

and even pattern is

2x((-1)^(n))

So, how to use this?

Let the original number be 100011, divide the numbers digits into two parts, even and odd. Sum each parts digits separately. Multiply sum of the odd digits by 2. Now, if the result is divisible by sum of the even digits, then the original number is divisible by 5, else it is not divisible. Example:

100011
1_0_1_ 1+0+1 = 2
_0_0_1 0+0+1 = 1; 1x2 = 2

2 mod(2) equals 0? Yes. Therefore, original number is divisible.

How to apply it within a regex? Using callout functions within a regex it can be applied. Callouts provide a means of temporarily passing control to the script in the middle of regular expression pattern matching.

However, ndn's answer is more appropriate and easier, therefore I recommend to use his answer.

2 Comments

I think OP wanted the mathematical concept of regular expressions, not regexp with callouts.
"There is no way to do it in pure regex" - false, see my answer.
0

For non empty binary sequence divisible by 5 you can use [probably the shortest] explicit regex :

(0|1(10)*(0|11)(01*0(01)*(1|00))*1)+

If you want to use it in some programming language and your environment allows to make replacement { 0->1, 1->0 } then you can make your code shorter because in correctly formed regex there always exist reversed common part :

 (0| 1(10)*(0|11) \
(01* 0(01)*(1|00) )*1)+
     ^-^^---^-^^-       xor 1

(here spaces used for highlighting only)

The existence of reversible common part caused by the symmetry of every odd graph regex-div-5-init.png

This graph was built using the table of remainders :

from #     : 0 1 2 3 4
to 2*# + 0 : 0 2 4 1 3  mod 5
to 2*# + 1 : 1 3 0 2 4  mod 5
         |   ^-^-^-^-^- vertices
       edges

For non empty binary sequences divisible by (5 * 2^N) you can use this pattern :

^(0+|(0*1(10)*(0|11)(01*0(01)*(1|00))*1)+0*)$    : divisible by  5
^(0+|(0*1(10)*(0|11)(01*0(01)*(1|00))*1)+00*)$   : divisible by 10
^(0+|(0*1(10)*(0|11)(01*0(01)*(1|00))*1)+000*)$  : divisible by 20
^(0+|(0*1(10)*(0|11)(01*0(01)*(1|00))*1)+0{3,})$ : divisible by 40
^(0+|(0*1(10)*(0|11)(01*0(01)*(1|00))*1)+0{4,})$ : divisible by 80, and so on ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.