in reply to Regex refresher

Heh, looks like it will match every string in the world to me. Were there supposed to be anchors on the ends?

Update: With anchors, it will match binary numbers divisible by 3. though I haven't figured out exactly why.

Update: Here's a couple hints though. Left shifting a number divisible by 3 yields another number that is divisible by three. Adding two such numbers (obviously) still preserves this property. The innermost part of the regex is still a stumper though...

What kind of bits match /^(01*0)*$/, and why can you shove them between two '1's and get a number divisible by 3???


Replies are listed 'Best First'.
Re(2): Regex refresher
by Arien (Pilgrim) on Sep 12, 2002 at 09:02 UTC
    With anchors, it will match binary numbers divisible by 3. though I haven't figured out exactly why...

    I think you are right, assuming the empty string is divisble by 3.

    Here is why:

    To start at the front of the regex, /^0*$/ will match a number made up of zero or more zeros. Assuming the empty string qualifies as being divisible by 3, all matching strings are divisble by 3: they all have the value 0.

    Putting zeroes at the back of the number just results in numbers that are twice as large and thus divisible by 3, if the original number was.

    Going to the other side of the alternation, and simplifying we see /^(11)*$/, that is: a string consisting of zero or more pairs of adjacent 1-bits. It is easy to show that the value produced by every pair is divisible by 3: 2n+1 + 2n = 3 * 2n.

    We've already seen that zero repetitions of the inner group of /^(1(01*0)*1)*$/ result in a number divisible by 3. Mixing substrings of two zeroes into a binary number will not alter its divisibilty by 3. The cases of adding to the front and back are obvious, but what happens when they are put in between? In that case the 1 representing 2n gets to represent 2n+2, which will just add 3 * 2n to the sum of the digits.

    What happens when we start using (and repeating) the 1 from the group in /1(01*0)1/? For every 1, you shift the left-most 1 one position to the left, doubling its value and obtain a 1 representing half the value of the left-most 1 before shifting. This adds 2n + 2n-1 = 3 * 2n-1. So the number is still divisible by 3.

    I think that covers all variations... I could have dreamt typing in some of them, though. ;-)

    — Arien

      ++ Very well explained. You've convinced me that this regex will match numbers divisible by three. How about the converse though? Can you show that if a number is divisible by three it will be matched by this regex? For example, in base10 /8$/ will only match even numbers, but it wont match all of them.