Friday, November 24, 2006

Forwarding IEnumerable(Of T)

Often we have a class that implements IEnumerable by returning the enumerator from an embedded list or array:

    1 

    2 Public Class Class1

    3     Implements IEnumerable

    4 

    5     Private Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator

    6         Return _items.GetEnumerator

    7     End Function

    8 

    9     Private _items() As Integer

   10 

   11 End Class

   12 

When I tried to do the same thing with a generic class, I had a problem:

    1 

    2 Public Class Class2(Of X As New)

    3     Implements IEnumerable(Of X)

    4 

    5     Private Function GetEnumerator() As IEnumerator(Of X) Implements IEnumerable(Of X).GetEnumerator

    6         Return DirectCast(_items.GetEnumerator, IEnumerator(Of X))  'Throws InvalidCastException

    7     End Function

    8 

    9     Private Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator

   10         Return _items.GetEnumerator

   11     End Function

   12 

   13     Private _items() As X

   14 

   15 End Class

   16 

Line 6 throws an exception with the message "Unable to cast object of type 'SZArrayEnumerator' to type 'System.Collections.Generic.IEnumerator`1[System.Int32]'."

The answer is simple, but had me scratching my head for a while:

    6 Return DirectCast(_items, IEnumerable(Of X)).GetEnumerator

Wednesday, November 08, 2006

Numbers Divisible by their Reverse

Here is my solution Jon Galloway's puzzle (my guess was "tens of numbers"):

    1 Module Module1

    2 

    3     Sub Main()

    4 

    5         Dim testValue As Integer = 21

    6         Const maxTestValue As Integer = 1000000

    7         Dim count As Integer = 0

    8 

    9         Do

   10 

   11             If testValue Mod 10 <> 0 Then

   12                 Dim testString As String = testValue.ToString

   13                 Dim reverseString As String = Reverse(testString)

   14                 If reverseString < testString Then

   15                     Dim reverseValue As Integer = CInt(reverseString)

   16                     If testValue Mod reverseValue = 0 Then

   17                         Console.WriteLine(String.Format("{0} / {1} = {2}", testValue, reverseValue, testValue / reverseValue))

   18                         count += 1

   19                     End If

   20                 End If

   21             End If

   22 

   23             testValue += 1

   24 

   25         Loop Until testValue > maxTestValue

   26 

   27         Console.WriteLine(String.Format("{0} numbers <= {1} are non-trivially divisible by their reverse.", count, maxTestValue))

   28         Console.ReadLine()

   29 

   30     End Sub

   31 

   32     Private Function Reverse(ByVal value As String) As String

   33         Dim chars() As Char = value.ToCharArray

   34         Array.Reverse(chars)

   35         Return New String(chars)

   36     End Function

   37 

   38 End Module

The .NET limitation is that the String class has no Reverse method!

This gives the following rather interesting result:

It is easily seen that (only) numbers of the format "879*12" and "989*01" (using regex * = 0-or-more occurrences) are solutions to this problem.

I have found a rather elegant proof of this but unfortunately it is too large to fit in the margin ;-)

I wonder how this generalizes for bases other than 10.

Update 9/11/06:

Jon's solution post shows I should have taken the sequence a bit further before jumping to conclusions:

The pattern now looks like: (879*12)+ or (989*01)+

Reminds me of this old puzzle:

If you have n points on the circumference of a circle, and join them all together with straight lines, how many regions are outlined? (More than two lines may not cross at the same point.)

1 point => 1 region
2 points => 2 regions
3 points => 4 regions
4 points => 8 regions

n points => 2^(n-1) regions, right?