Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regular Expression for Binary Numbers Divisible by 3

Tags:

regex

dfa

I am self-studying regular expressions and found an interesting practice problem online that involves writing a regular expression to recognize all binary numbers divisible by 3 (and only such numbers). To be honest, the problem asked to construct a DFA for such a scenario, but I figured that it should be equivalently possible using regular expressions.

I know that there's a little rule in place to figure out if a binary number is divisible by 3: take the number of ones in even places in the digit and subtract by the number of ones in odd places in the digit - if this equals zero, the number is divisible by 3 (example: 110 - 1 in the even 2 slot and a 1 in the odd 1 slot). However, I'm having some trouble adapting this to a regular expression.

The closest I've come is realizing that the number can be 0, so that would be the first state. I also saw that all binary numbers divisible by 3 begin with 1, so that would be the second state, but I'm stuck from there. Could someone help out?

like image 915
John Roberts Avatar asked Mar 11 '13 01:03

John Roberts


People also ask

How do you know if a binary number is divisible by 3?

Basically count the number of non-zero odd positions bits and non-zero even position bits from the right. If their difference is divisible by 3, then the number is divisible by 3. For example: 15 = 1111 which has 2 odd and 2 even non-zero bits.

How do you know if a binary number is divisible by a binary number?

Efficient Approach: In the binary string, check for the last k bits. If all the last k bits are 0, then the binary number is evenly divisible by 2k else it is not evenly divisible.

How do you know if a binary number is divisible by 5?

You start with the number 0 in your head and look at the digits from left-to-right. For each digit you multiply the number in your head by 2 and add the digit you just read. If the number goes to five or above you subtract five. If you end up with 0 the number is divisible by 5.

What is regular expression with example?

Solution: As we know, any number of a's means a* any number of b's means b*, any number of c's means c*. Since as given in problem statement, b's appear after a's and c's appear after b's. So the regular expression could be: R = a* b* c*


3 Answers

I have another way to this problem and I think this is easier to understand. When we are dividing a number by 3 we can have three remainders: 0, 1, 2. We can describe a number which is divisible by 3 using expression 3t (t is a natural number).


When we are adding 0 after a binary number whose remainder is 0, the actual decimal number will be doubled. Because each digit is moving to a higher position. 3t * 2 = 6t, this is also divisible by 3.

When we are adding a 1 after a binary number whose remainder is 0, the actual decimal number will be doubled plus 1. Because each digit is moving to a higher position followed by a 1; 3t * 2 + 1 = 6t + 1, the remainder is 1.


When we are adding a 1 after a binary number whose remainder is 1. The actual decimal number will be doubled plus one, and the remainder is 0; (3t + 1)*2 + 1 = 6t + 3 = 3(2t + 1), this is divisible by 3.

When we are adding a 0 after a binary number whose remainder is 1. The actual decimal number will be doubled. And the remainder will be 2. (3t + 1)*2 = 6t + 2.


When we are adding a 0 after a binary number whose remainder is 2. The remainder will be 1. (3t + 2)*2 = 6t + 4 = 3(2t + 1) + 1

When we are adding a 1 after a binary number whose remainder is 2. Then remainder will still be 2. (3t + 2)*2 + 1 = 6t + 5 = 3(2t + 1) + 2.

No matter how many 1 you add to a binary number whose remainder is 2, remainder will be 2 forever. (3(2t + 1) + 2)*2 + 1 = 3(4t + 2) + 5 = 3(4t + 3) + 2


So we can have the DFA to describe the binary number: DFA describing binary numbers divisible by 3

Note: Edge q2 -> q1 should be labelled 0.

like image 100
Han Avatar answered Sep 28 '22 04:09

Han


Following what Oli Charlesworth says, you can build DFA for divisibility of base b number by a certain divisor d, where the states in the DFA represent the remainder of the division.

For your case (base 2 - binary number, divisor d = 310):

Initial DFA

Note that the DFA above accepts empty string as a "number" divisible by 3. This can easily be fixed by adding one more intermediate state in front:

Fixed DFA

Conversion to theoretical regular expression can be done with the normal process.

Conversion to practical regex in flavors that supports recursive regex can be done easily, when you have got the DFA. This is shown for the case of (base b = 10, d = 710) in this question from CodeGolf.SE.

Let me quote the regex in the answer by Lowjacker, written in Ruby regex flavor:

(?!$)(?>(|(?<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>)

Breaking it down, you can see how it is constructed. The atomic grouping (or non-backtracking group, or a group that behaves possessively) is used to make sure only the empty string alternative is matched. This is a trick to emulate (?DEFINE) in Perl. Then the groups A to G correspond to remainder of 0 to 6 when the number is divided by 7.

(?!$)
(?>
  (|(?<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>)
like image 29
nhahtdh Avatar answered Sep 28 '22 03:09

nhahtdh


Binary numbers divisible by 3 fall into 3 categories:

  1. Numbers with two consecutive 1's or two 1's separated by an even number of 0's. Effectively every pair "cancels" itself out.

(ex. 11, 110, 1100,1001,10010, 1111)

(decimal: 3, 6, 12, 9, 18, 15)

  1. Numbers with three 1's each separated by an odd number of 0's. These triplets also "cancel" themselves out.

(ex. 10101, 101010, 1010001, 1000101)

(decimal: 21, 42, 81, 69)

  1. Some combination of the first two rules (including inside one another)

(ex. 1010111, 1110101, 1011100110001)

(decimal: 87, 117, 5937)

So a regular expression that takes into account these three rules is simply:

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

How to read it:

() encapsulate

* means the previous number/group is optional

| indicates a choice of options on either side within the parentheses

like image 24
Reid Eric Avatar answered Sep 28 '22 02:09

Reid Eric