# Project Euler #1-3 in VBA

Self explanatory, and all the functions contain descriptions of their specific problem statements.

Since this is project Euler, I would be particularly interested in any analysis of the functions' computational efficiency.

Option Explicit

Public Function ProjectEuler1() As Long

'/ Problem statement: sum all multiples of 3 and 5 from 1 to 999

Dim total As Long
Dim i As Long

For i = 1 To 999

If i Mod 3 = 0 Or i Mod 5 = 0 Then

total = total + i

End If

Next i

ProjectEuler1 = total

End Function

Public Function ProjectEuler2() As Long

'/ Problem statement: sum all even Fibonacci numbers below 4 Million

Dim fiboA As Long, fiboB As Long, currentFibo As Long '/ alternating fibonacci numbers
Dim bIsHigher As Boolean

fiboA = 1
fiboB = 1
currentFibo = 2

Dim total As Long

Do While currentFibo < 4000000

If currentFibo Mod 2 = 0 Then total = total + currentFibo

If bIsHigher Then
fiboA = currentFibo
Else
fiboB = currentFibo
End If

bIsHigher = Not bIsHigher

currentFibo = fiboA + fiboB

Loop

ProjectEuler2 = total

End Function

Public Function ProjectEuler3(ByVal numToFactorise As Long) As Long

'/ Problem statement: find the largest prime factor of <big number>
'/ I decided to generalise it

Dim i As Long
Dim sqrtLimit As Long
Dim partiallyFactorisedNum As Long
Dim largestPrimeDivisor As Long

sqrtLimit = Application.Floor(numToFactorise ^ 0.5, 1)
partiallyFactorisedNum = numToFactorise

i = 2
If partiallyFactorisedNum Mod i = 0 Then
largestPrimeDivisor = i
partiallyFactorisedNum = KeepDividingWhileInt(partiallyFactorisedNum, i)
End If

i = 3
Do While i <= sqrtLimit

If isPrime(i) Then

If partiallyFactorisedNum Mod i = 0 Then
largestPrimeDivisor = i
partiallyFactorisedNum = KeepDividingWhileInt(partiallyFactorisedNum, i)
End If

End If

i = i + 2
sqrtLimit = Application.Floor(partiallyFactorisedNum ^ 0.5, 1)
Loop

If partiallyFactorisedNum > largestPrimeDivisor Then largestPrimeDivisor = partiallyFactorisedNum
ProjectEuler3 = largestPrimeDivisor

End Function

Public Function isPrime(ByVal numTocheck As Long)

Dim i As Long
Dim sqrtLimit As Long
sqrtLimit = Application.Floor(numTocheck ^ 0.5, 1)

isPrime = True

If numTocheck Mod 2 = 0 And numTocheck <> 2 Then isPrime = False

i = 3
Do While i <= sqrtLimit And isPrime
If numTocheck Mod i = 0 Then isPrime = False
i = i + 2
Loop

End Function

Public Function KeepDividingWhileInt(ByVal numToDivide As Long, ByVal divisor As Long) As Long

Dim isDivisible As Boolean

isDivisible = True
Do While isDivisible
If numToDivide Mod divisor = 0 Then
numToDivide = numToDivide / divisor
Else
isDivisible = False
End If
Loop

KeepDividingWhileInt = numToDivide

End Function


While quickly running over your code, my eyes stopped on your function KeepDividingWhileInt.

It seemed over-complicated.

Let's write what it does:

1. Creates isDivisible
2. Sets isDivisible to true
3. Loops while isDividible is true:
1. If numToDivide Mod divisor is 0
1. Divides numToDivide by divisor
2. Else
1. Sets isDivisible to false
4. Returns numToDivide

Well, there is a subtle bug on step 2: You assume that the number is divisible by divisor, which may not be true (e.g.: KeepDividingWhileInt(3,2)).

Also, the whole code could be extremely simplified, by moving the condition inside that if into the while.

Also, you could try to use While ... Wend instead of Do While ... Loop, as suggested by @Mat's Mug. This point actually applies everywhere on your code.

The final result:

Public Function KeepDividingWhileInt(ByVal numToDivide As Long, ByVal divisor As Long) As Long

While numToDivide Mod divisor = 0
numToDivide = numToDivide / divisor
Wend

KeepDividingWhileInt = numToDivide

End Function


Oh my! The function is so simple that you can read it in a single sentence:

Divide numToDivide by divisor while the reminder is 0, returning the final result.

So simple, right?

• Nice answer, except I don't know what Do While...Loop is doing in the language - it's just one of the several redundant-yet-different-because-why-not ways of looping available in VBA. A simpler variant would be While...Wend. Dec 4 '15 at 2:43
• @Mat'sMug Thanks a lot for that tip! Has been a few years since I've written any serous VB code. It is indeed simpler and to the point. It really looks a lot more natural. Once again, thank you. Dec 4 '15 at 2:49
• Just a case of Do While ... Loop being what I initially encountered when learning the language.
– Kaz
Dec 4 '15 at 4:00

## Euler2

bIsHigher is a confusing variable name. It has the disadvantage of resembling Hungarian notation, so those exposed to that may read it as booleanIsHigher which makes no sense.

Rather than trying to find a better name, you can actually factor out the need for the variable. You get the same result from the following:

    Do While currentFibo < 4000000
If currentFibo Mod 2 = 0 Then total = total + currentFibo
fiboA = fiboB
fiboB = currentFibo
currentFibo = fiboA + fiboB
Loop


which I would argue is closer to how the fibonacci sequence is actually derived as fiboA will always be (n-2) and fiboB will always be (n-1) instead of repeatedly trading places.

• Awesome, that's exactly the logic I was grasping at but couldn't quite articulate :)
– Kaz
Dec 4 '15 at 14:26