Project Euler problem 5

Spekk

Member
Joined
Jun 8, 2010
Messages
7
Programming Experience
Beginner
Hi, I'd like a bit of feedback on some code I've written for a mathematical problem.

Problem 5 is:

"2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.

What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"

Answer:

VB.NET:
 'declare a variable for the number, to be incresed by 1 each time the condition can't be met
        'declare a boolean flag to see and have it set to true if the number can be divided by the first 10 factors

        Dim test_num As Long = 20
        Dim final_num As Long
        Dim x As Integer
        Dim Flag As Boolean = False

        While test_num >= 0

            For x = 20 To 1 Step -1         'test the factors 20 to 1, as 20 is the highest factor
                If Not (test_num Mod x = 0) Then
                    Flag = False
                    Exit For                'if an uneven division is found exit the loop and increase the test num
                Else
                    Flag = True
                End If
            Next x




            If Flag = True Then
                final_num = test_num
                Exit While
            End If

            test_num += 20 'increase by 20 because the number must be a multiple of the highest factor
        End While

        MsgBox(final_num) 'show the result of the tests





    End Sub
End Class

I think this is pretty efficient as I've tried to keep the iterations to a minimum by incrementing the test number by 20 and Stepping down in the for loop.


Thx in Advance,
Tom.

Quick question: Is it ok to keep asking questions like this? If it's o.k. I'd like to get feedback on all my solutions so I can keep improving.
 
you may want to keep it in the same thread... instead of having a new thread for each individual problem.


Also the question essentially is asking "What is the lowest common multiple of the values 1->20"

LCM is a simple function:

LCM(m,n) = mn/GCD(m,n)

where GCD is "Greatest Common Divisor"

GCD has several algorithms... I'm going to use Euclid's algorithm because it's easy to implement...

the result:

VB.NET:
Imports System
Imports System.Windows.Forms

Public Class Form1

    Public Sub New()
        Dim result As Long = 1

        For i As Long = 2 To 20
            result = LCM(result, i)
        Next

        Console.WriteLine(result)
    End Sub


    Private Function GCD(ByVal m As Long, ByVal n As Long) As Long
        Dim r As Long

        m = Math.Abs(m)
        n = Math.Abs(n)

        If m < n Then
            r = m
            m = n
            n = r
        End If

        While True
            r = m Mod n
            If r = 0 Then Return n
            m = n
            n = r
        End While

        Return 1
    End Function

    Private Function LCM(ByVal m As Long, ByVal n As Long) As Long
        Return (m * n) / GCD(m, n)
    End Function

End Class

now you might notice, this probably isn't going to be the most efficient problem... when it comes to 1->10 your method would probably loop fewer times (I am not certain of this, I didn't analyze and compare both our methods really... edit: of course yours would loop 252 times for 1-10, and I don't believe GCD is going to loop that much). But for LCM of 1-> 20 is such a large number you won't really notice the difference between the two. With LCM(1->N) and as N approaches larger and larger numbers, using the actual LCM algorithm will quickly approach better efficiency.

But where the LCM and GCD have an important upper hand is that Euler Problem's are a series of questions that build on each other. Just like in math class, you usually reuse knowledge you gained earlier on. This doesn't mean ALL new problems will link to previous problems, just that a whole ton of them will.

My method takes advantage of this. LCM and GCD are very common functions in 'discrete arithmetic', and Euler's Problems are 99% discrete arithmetic problems... so sure enough it'd be nice to have them sitting around and ready to go. There quick ease of use and readily availablness out weighs and efficiency concerns that may arise. This way you're learning both 'math' and 'reusability' as well as 'readable algorithms' vs 'efficient algorithms'.



for example, here are some math classes I wrote in AS3 a while back... I've since ported a couple of them to VB, but I don't have them on my computer at this moment (there at work)

LoDMath - a LOT of math stuff
LoDMath.as - lodgamebox - Project Hosting on Google Code

LoDMatrixTransformer - stuff related to matrices... it surrounds the Flash implementation of a 3x3 matrix, but of course it can be related to other 3x3 matrices pretty easily
LoDMatrixTransformer.as - lodgamebox - Project Hosting on Google Code

LoDNumberUtils - this one has a lot to do with conversions... a lot of it is about storing undefined types inside an 'int' in AS3 because they only have 3 numeric types (int, uint, and Number/double). Also some stuff to do with colour
LoDNumberUtils.as - lodgamebox - Project Hosting on Google Code

LoDRandom - quick access random operations... again this would change quite a bit in VB because the Random implementation is a bit different. But the concepts are there.
LoDRandom.as - lodgamebox - Project Hosting on Google Code
 
Last edited:
I've had a look at the LoDmath class and I'd really like to recreate (port?) some of the functions so I can re-use them in VB but have not used AS3 myself.

It looks fairly intuitive at first glance, but are there m(any) major differences between the two languages that are important? (I intend to just convert LoDmath at the moment.)

I'm thinking a line like:
VB.NET:
 public static const PI:Number         = 3.141592653589793; //number pi

in VB.NET would become

VB.NET:
Const PI as single =  3.141592653589793

And one of the functions, 'fuzzyequal' for example in VB would become

VB.NET:
Public Function fuzzyequal(byval a as integer, byval b as integer, _
                                    byval epsilon as single) as Boolean
epsilon = 0.001
return Math.abs(a-b) < epsilon
End Function
 
give me a sec, I may be able to locate it...

here, this is the port... there may be 1 or 2 methods missing:

VB.NET:
''' <summary>
''' A port of the LoDMath static member class written in AS3 under the MIT license agreement.
''' </summary>
''' <remarks>
''' As per the license agrrement of the lodGameBox license agreement
''' 
''' Copyright (c) 2009 Dylan Engelman
'''
'''Permission is hereby granted, free of charge, to any person obtaining a copy
'''of this software and associated documentation files (the "Software"), to deal
'''in the Software without restriction, including without limitation the rights
'''to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
'''copies of the Software, and to permit persons to whom the Software is
'''furnished to do so, subject to the following conditions:
'''
'''The above copyright notice and this permission notice shall be included in
'''all copies or substantial portions of the Software.
'''
'''THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
'''IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
'''FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
'''AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
'''LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
'''OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
'''THE SOFTWARE.
''' 
''' http://code.google.com/p/lodgamebox/source/browse/trunk/com/lordofduct/util/LoDMath.as
''' </remarks>
Public NotInheritable Class LoDMath

#Region "Public ReadOnly Properties"
    Public Const PI_hh As Double = 3.1415926535897931

    Public Const PI As Double = 3.1415926535897931 ' Number pi
    Public Const PI_2 As Double = 1.5707963267948966 ' PI / 2 OR 90 deg
    Public Const PI_4 As Double = 0.78539816339744828 ' PI / 4 OR 45 deg
    Public Const PI_8 As Double = 0.39269908169872414 ' PI / 8 OR 22.5 deg
    Public Const PI_16 As Double = 0.19634954084936207 ' PI / 16 OR 11.25 deg
    Public Const TWO_PI As Double = 6.2831853071795862 ' 2 * PI OR 180 deg
    Public Const THREE_PI_2 As Double = 4.71238898038469 ' 3 * PI_2 OR 270 deg
    Public Const E As Double = 2.71828182845905 ' Number e
    Public Const LN10 As Double = 2.3025850929940459 ' ln(10)
    Public Const LN2 As Double = 0.69314718055994529 ' ln(2)
    Public Const LOG10E As Double = 0.43429448190325182 ' logB10(e)
    Public Const LOG2E As Double = 1.4426950408889634 ' logB2(e)
    Public Const SQRT1_2 As Double = 0.70710678118654757 ' sqrt( 1 / 2 )
    Public Const SQRT2 As Double = 1.4142135623730951 ' sqrt( 2 )
    Public Const DEG_TO_RAD As Double = 0.017453292519943295 ' PI / 180
    Public Const RAD_TO_DEG As Double = 57.295779513082323 '  180.0 / PI

    Public Const B_16 As Integer = 65536 ' 2^16
    Public Const B_31 As Long = 2147483648 ' 2^31
    Public Const B_32 As Long = 4294967296 ' 2^32
    Public Const B_48 As Long = 281474976710656 ' 2^48
    Public Const B_53 As Long = 9007199254740992 ' 2^53 !!NOTE!! largest accurate double floating point whole value
    ''shared readonly because vb for some reason takes the written value of 2^63 as an overflow... though it ISN'T, so we convert from string at set
    Public Shared ReadOnly B_63 As ULong = ULng("9223372036854775808") ' 2^63
    Public Const B_64_m1 As ULong = ULong.MaxValue '18446744073709551615 or 2^64 - 1 or ULong.MaxValue...

    Public Const ONE_THIRD As Double = 0.33333333333333331 '  1.0/3.0
    Public Const TWO_THIRDS As Double = 0.66666666666666663 '  2.0/3.0
    Public Const ONE_SIXTH As Double = 0.16666666666666666 '  1.0/6.0

    Public Const COS_PI_3 As Double = 0.8660254037844386 ' COS( PI / 3 )
    Public Const SIN_2PI_3 As Double = 0.03654595 '  SIN( 2*PI/3 )

    Public Const CIRCLE_ALPHA As Double = 0.55228474983079345 ' 4*(Math.sqrt(2)-1)/3.0

    Public Const ONN As Boolean = True
    Public Const OFF As Boolean = False

    Public Const SHORT_EPSILON As Double = 0.1 ' round integer epsilon
    Public Const PERC_EPSILON As Double = 0.001 ' percentage epsilon
    Public Const EPSILON As Double = 0.0001 ' single float average epsilon
    Public Const LONG_EPSILON As Double = 0.00000001 ' arbitrary 8 digit epsilon
    ''shared readOnly because you can't set a const from a method call
    Public Shared ReadOnly MACHINE_EPSILON As Double = MathUtil.ComputeMachineEpsilon()


    Public Shared Function ComputeMachineEpsilon() As Double
        Dim fourThirds As Double = 4.0 / 3.0
        Dim third As Double = fourThirds - 1.0
        Dim one As Double = third + third + third
        Return Math.Abs(1.0 - one)
    End Function
#End Region

#Region "Public Shared Methods"

#Region "series"
    Public Shared Function Summation(ByVal ParamArray arr As Short()) As Short
        Dim result As Short = 0
        Dim value As Short

        For Each value In arr
            result += value
        Next

        Return result
    End Function

    Public Shared Function Summation(ByVal ParamArray arr As Integer()) As Integer
        Dim result As Integer = 0
        Dim value As Integer

        For Each value In arr
            result += value
        Next

        Return result
    End Function

    Public Shared Function Summation(ByVal ParamArray arr As Long()) As Long
        Dim result As Long = 0
        Dim value As Long

        For Each value In arr
            result += value
        Next

        Return result
    End Function

    Public Shared Function Summation(ByVal ParamArray arr As Double()) As Double
        Dim result As Double = 0
        Dim value As Double

        For Each value In arr
            result += value
        Next

        Return result
    End Function



    Public Shared Function ProductSeries(ByVal ParamArray arr As Short()) As Double
        If arr Is Nothing OrElse arr.Length = 0 Then Return Double.NaN

        Dim result As Double = 1
        Dim value As Short

        For Each value In arr
            result *= value
        Next

        Return result
    End Function

    Public Shared Function ProductSeries(ByVal ParamArray arr As Integer()) As Double
        If arr Is Nothing OrElse arr.Length = 0 Then Return Double.NaN

        Dim result As Double = 1
        Dim value As Integer

        For Each value In arr
            result *= value
        Next

        Return result
    End Function

    Public Shared Function ProductSeries(ByVal ParamArray arr As Long()) As Double
        If arr Is Nothing OrElse arr.Length = 0 Then Return Double.NaN

        Dim result As Double = 1
        Dim value As Long

        For Each value In arr
            result *= value
        Next

        Return result
    End Function

    Public Shared Function ProductSeries(ByVal ParamArray arr As Double()) As Double
        If arr Is Nothing OrElse arr.Length = 0 Then Return Double.NaN

        Dim result As Double = 1
        Dim value As Double

        For Each value In arr
            result *= value
        Next

        Return result
    End Function
#End Region

#Region "Value interpolating and warping"
    ''' <summary>
    ''' The average of an array of values
    ''' </summary>
    ''' <param name="values">An array of values</param>
    ''' <returns>the average</returns>
    ''' <remarks></remarks>
    Public Shared Function Average(ByVal ParamArray values() As Short) As Double
        Dim avg As Double = 0

        For Each value As Double In values
            avg += value
        Next

        Return avg / values.Length
    End Function

    Public Shared Function Average(ByVal ParamArray values() As Integer) As Double
        Dim avg As Double = 0

        For Each value As Double In values
            avg += value
        Next

        Return avg / values.Length
    End Function

    Public Shared Function Average(ByVal ParamArray values() As Long) As Double
        Dim avg As Double = 0

        For Each value As Double In values
            avg += value
        Next

        Return avg / values.Length
    End Function

    Public Shared Function Average(ByVal ParamArray values() As Double) As Double
        Dim avg As Double = 0

        For Each value As Double In values
            avg += value
        Next

        Return avg / values.Length
    End Function

    ''' <summary>
    ''' a one dimensional linear interpolation of a value.
    ''' </summary>
    ''' <param name="a">from value</param>
    ''' <param name="b">to value</param>
    ''' <param name="weight">lerp value</param>
    ''' <returns>the value lerped from a to b</returns>
    ''' <remarks></remarks>
    Public Shared Function Interpolate(ByVal a As Double, ByVal b As Double, ByVal weight As Double) As Double
        Return (b - a) * weight + a
    End Function

    ''' <summary>
    ''' The percentage a value is from min to max
    ''' 
    ''' eg:
    ''' 8 of 10 out of 0->10 would be 0.8f
    ''' 
    ''' Good for calculating the lerp weight
    ''' </summary>
    ''' <param name="value">The value to text</param>
    ''' <param name="max">The max value</param>
    ''' <param name="min">The min value</param>
    ''' <returns>The percentage value is from min</returns>
    ''' <remarks></remarks>
    Public Shared Function PercentageMinMax(ByVal value As Double, ByVal max As Double, Optional ByVal min As Double = 0) As Double
        value -= min
        max -= min

        If max = 0 Then
            Return 0
        Else
            Return value / max
        End If
    End Function

    ''' <summary>
    ''' The percentage a value is from max to min
    ''' 
    ''' eg:
    ''' 8 of 10 out of 0->10 would be 0.2f
    ''' 
    ''' Good for calculating a discount
    ''' </summary>
    ''' <param name="value">The value to text</param>
    ''' <param name="max">The max value</param>
    ''' <param name="min">The min value</param>
    ''' <returns>The percentage value is from max</returns>
    ''' <remarks></remarks>
    Public Shared Function PercentageOffMinMax(ByVal value As Double, ByVal max As Double, Optional ByVal min As Double = 0) As Double
        value -= max
        min -= max

        If min = 0 Then
            Return 0
        Else
            Return value / min
        End If
    End Function

    ''' <summary>
    ''' Return the minimum value of several values
    ''' </summary>
    ''' <param name="args"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function Min(ByVal value As Double, ByVal ParamArray args() As Double) As Double

        For i As Integer = 0 To args.Length - 1
            If args(i) < value Then value = args(i)
        Next

        Return value
    End Function

    Public Shared Function Min(ByVal value As Short, ByVal ParamArray args() As Short) As Double

        For i As Integer = 0 To args.Length - 1
            If args(i) < value Then value = args(i)
        Next

        Return value
    End Function

    Public Shared Function Min(ByVal value As Integer, ByVal ParamArray args() As Integer) As Double

        For i As Integer = 0 To args.Length - 1
            If args(i) < value Then value = args(i)
        Next

        Return value
    End Function

    Public Shared Function Min(ByVal value As Long, ByVal ParamArray args() As Long) As Double

        For i As Integer = 0 To args.Length - 1
            If args(i) < value Then value = args(i)
        Next

        Return value
    End Function

    ''' <summary>
    ''' Return the maximum of several values
    ''' </summary>
    ''' <param name="args"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function Max(ByVal value As Double, ByVal ParamArray args() As Double) As Double

        For i As Integer = 0 To args.Length - 1
            If args(i) > value Then value = args(i)
        Next

        Return value
    End Function

    Public Shared Function Max(ByVal value As Short, ByVal ParamArray args() As Short) As Double

        For i As Integer = 0 To args.Length - 1
            If args(i) > value Then value = args(i)
        Next

        Return value
    End Function

    Public Shared Function Max(ByVal value As Integer, ByVal ParamArray args() As Integer) As Double

        For i As Integer = 0 To args.Length - 1
            If args(i) > value Then value = args(i)
        Next

        Return value
    End Function

    Public Shared Function Max(ByVal value As Long, ByVal ParamArray args() As Long) As Double

        For i As Integer = 0 To args.Length - 1
            If args(i) > value Then value = args(i)
        Next

        Return value
    End Function

    ''' <summary>
    ''' Wraps a value around some significant range.
    ''' 
    ''' Similar to modulo, but works in a unary direction over any range (including negative values).
    ''' 
    ''' ex:
    ''' Wrap(8,6,2) == 4
    ''' Wrap(4,2,0) == 0
    ''' Wrap(4,2,-2) == -2
    ''' </summary>
    ''' <param name="value">value to wrap</param>
    ''' <param name="max">max in range</param>
    ''' <param name="min">min in range</param>
    ''' <returns>A value wrapped around min to max</returns>
    ''' <remarks></remarks>
    Public Shared Function Wrap(ByVal value As Short, ByVal max As Short, Optional ByVal min As Short = 0) As Short
        value -= min
        max -= min
        If max = 0 Then Return min

        value = value Mod max
        value += min
        While value < min
            value += max
        End While

        Return value

    End Function

    Public Shared Function Wrap(ByVal value As Integer, ByVal max As Integer, Optional ByVal min As Integer = 0) As Integer
        value -= min
        max -= min
        If max = 0 Then Return min

        value = value Mod max
        value += min
        While value < min
            value += max
        End While

        Return value

    End Function

    Public Shared Function Wrap(ByVal value As Long, ByVal max As Long, Optional ByVal min As Long = 0) As Long
        value -= min
        max -= min
        If max = 0 Then Return min

        value = value Mod max
        value += min
        While value < min
            value += max
        End While

        Return value

    End Function

    Public Shared Function Wrap(ByVal value As Double, ByVal max As Double, Optional ByVal min As Double = 0) As Double
        value -= min
        max -= min
        If max = 0 Then Return min

        value = value Mod max
        value += min
        While value < min
            value += max
        End While

        Return value

    End Function

    ''' <summary>
    ''' Arithmetic version of Wrap... unsure of which is more efficient.
    ''' 
    ''' Here for demo purposes
    ''' </summary>
    ''' <param name="value">value to wrap</param>
    ''' <param name="max">max in range</param>
    ''' <param name="min">min in range</param>
    ''' <returns>A value wrapped around min to max</returns>
    ''' <remarks></remarks>
    Public Shared Function ArithWrap(ByVal value As Double, ByVal max As Double, Optional ByVal min As Double = 0) As Double
        max -= min
        If Not max Then Return min

        Return value - max * Math.Floor((value - min) / max)
    End Function

    ''' <summary>
    ''' Clamp a value into a range.
    ''' 
    ''' If input is LT min, min returned
    ''' If input is GT max, max returned
    ''' else input returned
    ''' </summary>
    ''' <param name="input">value to clamp</param>
    ''' <param name="max">max in range</param>
    ''' <param name="min">min in range</param>
    ''' <returns>calmped value</returns>
    ''' <remarks></remarks>
    Public Shared Function Clamp(ByVal input As Short, ByVal max As Short, Optional ByVal min As Short = 0) As Short
        Return Math.Max(min, Math.Min(max, input))
    End Function

    Public Shared Function Clamp(ByVal input As Integer, ByVal max As Integer, Optional ByVal min As Integer = 0) As Integer
        Return Math.Max(min, Math.Min(max, input))
    End Function

    Public Shared Function Clamp(ByVal input As Long, ByVal max As Long, Optional ByVal min As Long = 0) As Long
        Return Math.Max(min, Math.Min(max, input))
    End Function

    Public Shared Function Clamp(ByVal input As Double, ByVal max As Double, Optional ByVal min As Double = 0) As Double
        Return Math.Max(min, Math.Min(max, input))
    End Function

    ''' <summary>
    ''' roundTo some place comparative to a 'base', default is 10 for decimal place
    ''' 
    ''' 'place' is represented by the power applied to 'base' to get that place
    ''' </summary>
    ''' <param name="value">the value to round</param>
    ''' <param name="place">the place to round to</param>
    ''' <param name="base">the base to round in... default is 10 for decimal</param>
    ''' <returns>The value rounded</returns>
    ''' <remarks>e.g.
    ''' 
    ''' 2000/7 ~= 285.714285714285714285714 ~= (bin)100011101.1011011011011011
    ''' 
    ''' roundTo(2000/7,3) == 0
    ''' roundTo(2000/7,2) == 300
    ''' roundTo(2000/7,1) == 290
    ''' roundTo(2000/7,0) == 286
    ''' roundTo(2000/7,-1) == 285.7
    ''' roundTo(2000/7,-2) == 285.71
    ''' roundTo(2000/7,-3) == 285.714
    ''' roundTo(2000/7,-4) == 285.7143
    ''' roundTo(2000/7,-5) == 285.71429
    ''' 
    ''' roundTo(2000/7,3,2)  == 288       -- 100100000
    ''' roundTo(2000/7,2,2)  == 284       -- 100011100
    ''' roundTo(2000/7,1,2)  == 286       -- 100011110
    ''' roundTo(2000/7,0,2)  == 286       -- 100011110
    ''' roundTo(2000/7,-1,2) == 285.5     -- 100011101.1
    ''' roundTo(2000/7,-2,2) == 285.75    -- 100011101.11
    ''' roundTo(2000/7,-3,2) == 285.75    -- 100011101.11
    ''' roundTo(2000/7,-4,2) == 285.6875  -- 100011101.1011
    ''' roundTo(2000/7,-5,2) == 285.71875 -- 100011101.10111
    ''' 
    ''' note what occurs when we round to the 3rd space (8ths place), 100100000, this is to be assumed 
    ''' because we are rounding 100011.1011011011011011 which rounds up.</remarks>
    Public Shared Function roundTo(ByVal value As Double, Optional ByVal place As Integer = 0, Optional ByVal base As UInteger = 10) As Double
        Dim p As Double = Math.Pow(base, -place)

        Return Math.Round(value * p) / p
    End Function

    Public Shared Function floorTo(ByVal value As Double, Optional ByVal place As Integer = 0, Optional ByVal base As UInteger = 10) As Double
        Dim p As Double = Math.Pow(base, -place)
        Return Math.Floor(value * p) / p
    End Function

    Public Shared Function ceilTo(ByVal value As Double, Optional ByVal place As Integer = 0, Optional ByVal base As UInteger = 10) As Double
        Dim p As Double = Math.Pow(base, -place)
        Return Math.Ceiling(value * p) / p
    End Function
#End Region

#Region "Simple fuzzy arithmetic"
    ''' <summary>
    ''' Test if Double is kind of equal to some other value by some epsilon.
    ''' 
    ''' Due to float error, two values may be considered similar... but the computer considers them different. 
    ''' By using some epsilon (degree of error) once can test if the two values are similar.
    ''' </summary>
    ''' <param name="a"></param>
    ''' <param name="b"></param>
    ''' <param name="epsilon"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function FuzzyEqual(ByVal a As Double, ByVal b As Double, ByVal epsilon As Double) As Boolean
        Return Math.Abs(a - b) < epsilon
    End Function

    Public Shared Function FuzzyEqual(ByVal a As Double, ByVal b As Double) As Boolean
        Return FuzzyEqual(a, b, EPSILON)
    End Function

    ''' <summary>
    ''' Test if Double is greater than some other value by some degree of error in epsilon.
    ''' 
    ''' Due to float error, two values may be considered similar... but the computer considers them different. 
    ''' By using some epsilon (degree of error) once can test if the two values are similar.
    ''' </summary>
    ''' <param name="a"></param>
    ''' <param name="b"></param>
    ''' <param name="epsilon"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function FuzzyLessThan(ByVal a As Double, ByVal b As Double, ByVal epsilon As Double) As Boolean
        Return a < b + epsilon
    End Function

    Public Shared Function FuzzyLessThan(ByVal a As Double, ByVal b As Double) As Boolean
        Return FuzzyLessThan(a, b, EPSILON)
    End Function

    ''' <summary>
    ''' Test if Double is less than some other value by some degree of error in epsilon.
    ''' 
    ''' Due to float error, two values may be considered similar... but the computer considers them different. 
    ''' By using some epsilon (degree of error) once can test if the two values are similar.
    ''' </summary>
    ''' <param name="a"></param>
    ''' <param name="b"></param>
    ''' <param name="epsilon"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function FuzzyGreaterThan(ByVal a As Double, ByVal b As Double, ByVal epsilon As Double) As Boolean
        Return a > b - epsilon
    End Function

    Public Shared Function FuzzyGreaterThan(ByVal a As Double, ByVal b As Double) As Boolean
        Return FuzzyGreaterThan(a, b, EPSILON)
    End Function

    ''' <summary>
    ''' Test if a value is near some target value, if with in some range of 'epsilon', the target is returned.
    ''' 
    ''' eg:
    ''' Slam(1.52,2,0.1) == 1.52
    ''' Slam(1.62,2,0.1) == 1.62
    ''' Slam(1.72,2,0.1) == 1.72
    ''' Slam(1.82,2,0.1) == 1.82
    ''' Slam(1.92,2,0.1) == 2
    ''' </summary>
    ''' <param name="value"></param>
    ''' <param name="target"></param>
    ''' <param name="epsilon"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function Slam(ByVal value As Double, ByVal target As Double, ByVal epsilon As Double) As Double
        If Math.Abs(value - target) < epsilon Then
            Return target
        Else
            Return value
        End If
    End Function

    Public Shared Function Slam(ByVal value As Double, ByVal target As Double) As Double
        Return Slam(value, target, EPSILON)
    End Function
#End Region

#Region "Angular Math"
    ''' <summary>
    ''' convert radians to degrees
    ''' </summary>
    ''' <param name="angle"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function RadiansToDegrees(ByVal angle As Double) As Double
        Return angle * RAD_TO_DEG
    End Function

    ''' <summary>
    ''' convert degrees to radians
    ''' </summary>
    ''' <param name="angle"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function DegreesToRadians(ByVal angle As Double) As Double
        Return angle * DEG_TO_RAD
    End Function

    ''' <summary>
    ''' Find the angle of a segment from (x1, y1) -> (x2, y2 )
    ''' </summary>
    ''' <param name="x1"></param>
    ''' <param name="y1"></param>
    ''' <param name="x2"></param>
    ''' <param name="y2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function AngleBetween(ByVal x1 As Double, ByVal y1 As Double, ByVal x2 As Double, ByVal y2 As Double) As Double
        Return Math.Atan2(y2 - y1, x2 - x1)
    End Function

    ''' <summary>
    ''' set an angle with in the bounds of -PI to PI
    ''' </summary>
    ''' <param name="angle"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function NormalizeAngle(ByVal angle As Double, Optional ByVal useRadians As Boolean = True) As Double
        Dim rd As Double = IIf(useRadians, PI, 180)
        Return Wrap(angle, PI, -PI)
    End Function

    ''' <summary>
    ''' closest angle between two angles from a1 to a2
    ''' absolute value the return for exact angle
    ''' </summary>
    ''' <param name="a1"></param>
    ''' <param name="a2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function NearestAngleBetween(ByVal a1 As Double, ByVal a2 As Double, Optional ByVal useRadians As Boolean = True) As Double
        Dim rd_2 As Double = IIf(useRadians, PI_2, 90)
        Dim two_rd As Double = IIf(useRadians, TWO_PI, 360)

        a1 = NormalizeAngle(a1)
        a2 = NormalizeAngle(a2)

        If a1 < -rd_2 And a2 > rd_2 Then a1 += two_rd
        If a2 < -rd_2 And a1 > rd_2 Then a2 += two_rd

        Return a2 - a1
    End Function

    ''' <summary>
    ''' normalizes independent and then sets dep to the nearest value respective to independent
    ''' 
    ''' 
    ''' for instance if dep=-170 degrees and ind=170 degrees then 190 degrees will be returned as an alternative to -170 degrees
    ''' note: angle is passed in radians, this written example is in degrees for ease of reading
    ''' </summary>
    ''' <param name="dep"></param>
    ''' <param name="ind"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function NormalizeAngleToAnother(ByVal dep As Double, ByVal ind As Double, Optional ByVal useRadians As Boolean = True) As Double
        Return ind + NearestAngleBetween(ind, dep, useRadians)
    End Function

    ''' <summary>
    ''' interpolate across the shortest arc between two angles
    ''' </summary>
    ''' <param name="a1"></param>
    ''' <param name="a2"></param>
    ''' <param name="weight"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function InterpolateAngle(ByVal a1 As Double, ByVal a2 As Double, ByVal weight As Double, Optional ByVal useRadians As Boolean = True) As Double
        a1 = NormalizeAngle(a1, useRadians)
        a2 = NormalizeAngleToAnother(a2, a1, useRadians)

        Return Interpolate(a1, a2, weight)
    End Function
#End Region

#Region "Advanced Math"
    ''' <summary>
    ''' Compute the logarithm of any value of any base
    ''' </summary>
    ''' <param name="value"></param>
    ''' <param name="base"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' a logarithm is the exponent that some constant (base) would have to be raised to 
    ''' to be equal to value.
    ''' 
    ''' i.e.
    ''' 4 ^ x = 16
    ''' can be rewritten as to solve for x
    ''' logB4(16) = x
    ''' which with this function would be 
    ''' LoDMath.logBaseOf(16,4)
    ''' 
    ''' which would return 2, because 4^2 = 16
    ''' </remarks>
    Public Shared Function LogBaseOf(ByVal value As Double, ByVal base As Double) As Double
        Return Math.Log(value) / Math.Log(base)
    End Function

    ''' <summary>
    ''' Check if a value is prime.
    ''' </summary>
    ''' <param name="value"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' In this method to increase speed we first check if the value is ltOReq 1, because values ltOReq 1 are not prime by definition. 
    ''' Then we check if the value is even but not equal to 2. If so the value is most certainly not prime. 
    ''' Lastly we loop through all odd divisors. No point in checking 1 or even divisors, because if it were divisible by an even 
    ''' number it would be divisible by 2. If any divisor existed when i > value / i then its compliment would have already 
    ''' been located. And lastly the loop will never reach i == val because i will never be > sqrt(val).
    ''' 
    ''' proof of validity for algorithm:
    ''' 
    ''' all trivial values are thrown out immediately by checking if even or less then 2
    ''' 
    ''' all remaining possibilities MUST be odd, an odd is resolved as the multiplication of 2 odd values only. (even * anyValue == even)
    ''' 
    ''' in resolution a * b = val, a = val / b. As every compliment a for b, b and a can be swapped resulting in b being ltOReq a. If a compliment for b 
    ''' exists then that compliment would have already occured (as it is odd) in the swapped addition at the even split.
    ''' 
    ''' Example...
    ''' 
    ''' 16
    ''' 1 * 16
    ''' 2 * 8
    ''' 4 * 4
    ''' 8 * 2
    ''' 16 * 1
    ''' 
    ''' checks for 1, 2, and 4 would have already checked the validity of 8 and 16.
    ''' 
    ''' Thusly we would only have to loop as long as i ltOReq val / i. Once we've reached the middle compliment, all subsequent factors have been resolved.
    ''' 
    ''' This shrinks the number of loops for odd values from [ floor(val / 2) - 1 ] down to [ ceil(sqrt(val) / 2) - 1 ]
    ''' 
    ''' example, if we checked EVERY odd number for the validity of the prime 7927, we'd loop 3962 times
    ''' 
    ''' but by this algorithm we loop only 43 times. Significant improvement!
    ''' </remarks>
    Public Shared Function IsPrime(ByVal value As Long) As Boolean
        ' check if value is in prime number range
        If value < 2 Then Return False

        ' check if even, but not equal to 2
        If Not (value Mod 2) And value <> 2 Then Return False

        ' if 2 or odd, check if any non-trivial divisors exist
        Dim sqrrt As Long = Math.Floor(Math.Sqrt(value))
        For i As Long = 3 To sqrrt Step 2
            If Not (value Mod i) Then Return False
        Next

        Return True
    End Function

    ''' <summary>
    ''' Relative Primality between two integers
    ''' 
    ''' By definition two integers are considered relatively prime if their 
    ''' 'greatest common divisor' is 1. So thusly we simply just check if 
    ''' the GCD of m and n is 1.
    ''' </summary>
    ''' <param name="m"></param>
    ''' <param name="n"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function IsRelativelyPrime(ByVal m As Short, ByVal n As Short) As Boolean
        Return GCD(m, n) = 1
    End Function

    Public Shared Function IsRelativelyPrime(ByVal m As Integer, ByVal n As Integer) As Boolean
        Return GCD(m, n) = 1
    End Function

    Public Shared Function IsRelativelyPrime(ByVal m As Long, ByVal n As Long) As Boolean
        Return GCD(m, n) = 1
    End Function

    Public Shared Function FactorsOf(ByVal value As Integer) As Integer()
        value = Math.Abs(value)
        Dim arr As New ArrayList()
        Dim sqrrt As Integer = Math.Floor(Math.Sqrt(value))
        Dim c As Integer

        For i As Integer = 1 To sqrrt
            If Not (value Mod i) Then
                arr.Add(i)
                c = value / i
                If c <> i Then arr.Add(c)
            End If
        Next

        arr.Sort()

        Return arr.ToArray(GetType(Integer))
    End Function

    Public Shared Function CommonFactorsOf(ByVal m As Integer, ByVal n As Integer) As Integer()
        Dim arr As New ArrayList()

        Dim i As Integer
        m = Math.Abs(m)
        n = Math.Abs(n)

        If m > n Then
            i = m
            m = n
            n = i
        End If

        For i = 1 To m
            If Not (m Mod i) And Not (n Mod i) Then
                arr.Add(i)
            End If
        Next

        Return arr.ToArray(GetType(Integer))
    End Function

    ''' <summary>
    ''' Greatest Common Denominator using Euclid's algorithm
    ''' </summary>
    ''' <param name="m"></param>
    ''' <param name="n"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GCD(ByVal m As Integer, ByVal n As Integer) As Integer
        Dim r As Integer

        ' make sure positive, GCD is always positive
        m = Math.Abs(m)
        n = Math.Abs(n)

        ' m must be >= n
        If m < n Then
            r = m
            m = n
            n = r
        End If

        ' now start loop, loop is infinite... we will cancel out sooner or later
        While True
            r = m Mod n
            If Not r Then Return n
            m = n
            n = r
        End While

        ' fail safe
        Return 1
    End Function

    Public Shared Function GCD(ByVal m As Long, ByVal n As Long) As Long
        Dim r As Long

        ' make sure positive, GCD is always positive
        m = Math.Abs(m)
        n = Math.Abs(n)

        ' m must be >= n
        If m < n Then
            r = m
            m = n
            n = r
        End If

        ' now start loop, loop is infinite... we will cancel out sooner or later
        While True
            r = m Mod n
            If Not r Then Return n
            m = n
            n = r
        End While

        ' fail safe
        Return 1
    End Function

    Public Shared Function LCM(ByVal m As Integer, ByVal n As Integer) As Integer
        Return (m * n) / GCD(m, n)
    End Function

    ''' <summary>
    ''' Factorial - N!
    ''' 
    ''' Simple product series
    ''' </summary>
    ''' <param name="value"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' By definition 0! == 1
    ''' 
    ''' Factorial assumes the idea that the value is an integer >= 0... thusly UInteger is used
    ''' </remarks>
    Public Shared Function Factorial(ByVal value As UInteger) As Long
        If value <= 0 Then Return 1

        Dim res As Long = value

        While --value
            res *= value
        End While

        Return res
    End Function

    ''' <summary>
    ''' Falling facotiral
    ''' 
    ''' defined: (N)! / (N - x)!
    ''' 
    ''' written subscript: (N)x OR (base)exp
    ''' </summary>
    ''' <param name="base"></param>
    ''' <param name="exp"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function FallingFactorial(ByVal base As UInteger, ByVal exp As UInteger) As Long
        Return Factorial(base) / Factorial(base - exp)
    End Function

    ''' <summary>
    ''' rising factorial
    ''' 
    ''' defined: (N + x - 1)! / (N - 1)!
    ''' 
    ''' written superscript N^(x) OR base^(exp)
    ''' </summary>
    ''' <param name="base"></param>
    ''' <param name="exp"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function RisingFactorial(ByVal base As UInteger, ByVal exp As UInteger) As Long
        Return Factorial(base + exp - 1) / Factorial(base - 1)
    End Function

    ''' <summary>
    ''' binomial coefficient
    ''' 
    ''' defined: N! / (k!(N-k)!)
    ''' reduced: N! / (N-k)! == (N)k (fallingfactorial)
    ''' reduced: (N)k / k!
    ''' </summary>
    ''' <param name="n"></param>
    ''' <param name="k"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function BinCoef(ByVal n As UInteger, ByVal k As UInteger) As Long
        Return FallingFactorial(n, k) / Factorial(k)
    End Function

    ''' <summary>
    ''' rising binomial coefficient
    ''' 
    ''' as one can notice in the analysis of binCoef(...) that 
    ''' binCoef is the (N)k divided by k!. Similarly rising binCoef 
    ''' is merely N^(k) / k! 
    ''' </summary>
    ''' <param name="n"></param>
    ''' <param name="k"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function RisingBinCoef(ByVal n As UInteger, ByVal k As UInteger) As Long
        Return RisingFactorial(n, k) / Factorial(k)
    End Function
#End Region

#End Region

End Class


also that epsilon thing you commented on... in as3 optional params just follow with an = sign... so say:

as3
VB.NET:
function foo( param:int = 0 ):void
{
    //
}

is the same as:

VB.NET:
''sub is the same as a void returning function
Sub Foo(Optional ByVal param As Integer = 0)
    ''
End Foo

but in my port, I use an overload for the fuzzy methods... I use a lot of overloads in the port because AS3 is a more 'dynamically typed' language, and it also does not support overloading. In AS3 the types int, uint, and Number will cast to each other with no problem, all that happens is that they get trimmed to each other (going from Number to int will cut off any fractional values). VB will throw overflow exceptions and the sort.
 
Last edited:
Awesome post mate, I'll try and get my head round some of the code from that.
Onto Problem 6:

The sum of the squares of the first ten natural numbers is,

12 + 22 + ... + 102 = 385
The square of the sum of the first ten natural numbers is,

(1 + 2 + ... + 10)2 = 552 = 3025
Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 385 = 2640.

Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.

My response:

VB.NET:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim sum_squares As Long
        Dim square_sum As Long
        Dim difference As Long


        sum_squares = sum_of_squares(100)
        square_sum = square_of_sum(100)

        difference = square_sum - sum_squares

        MsgBox(difference)



    End Sub



    Private Function sum_of_squares(ByVal x As Integer) As Long


        'Function to find sum of squares
        Dim total As Long
        Dim y As Long

        For y = 1 To x

            total += y ^ 2


        Next
        Return total


    End Function

    Private Function square_of_sum(ByVal x As Integer) As Long

        'Function to find square of sum
        Dim total As Long
        Dim z As Long
        Dim squ_sum As Long

        For z = 1 To x
            total += z
        Next

        squ_sum = total ^ 2

        Return squ_sum
    End Function

I've used functions here so it would be possible to put them in a class and re-use them.
(I think this is the right approach.) :confused:
 
Back
Top