For the people, familiar with my blog, it is known that usually I am resolving problems from Codeforces.com.
Codeforces supports plenty of languages, unfortunately VBA is not one of them. Thus, I have decided to build up a small algorithm testing system, which follows the following pattern – the input and the expected output are both provided via separate text files. Then, the person who writes the algorithm, should be able to write a function, reading from the first file and getting exactly the values from the other file.
Thus, let’s imagine that the task sounds like:
Take an input of 3 numbers and sum them. However, if the third number is even, do sum only the first two and subtract the third. This is easily achievable through this function:
1 2 3 4 5 |
If c Mod 2 = 0 Then MainTest = a + b + c Else MainTest = a + b - c End If |
Another possible problem may sound like this:
Give me the next character of a string. Thus “a b c d” would result to “b c d e” and “a z” would be “b a”. This problem is solvable through the following code:
1 2 3 4 5 6 7 8 9 |
inputVar = Split(consoleInput) ReDim outputVar(UBound(inputVar)) For cnt = LBound(inputVar) To UBound(inputVar) If Asc(inputVar(cnt)) = Asc("z") Then MainTest = MainTest & " a" Else MainTest = MainTest & " " & Chr(Asc(inputVar(cnt)) + 1) End If Next cnt |
Thus, to solve the first problem, we need the following input and output files.
Input:
1 2 3 4 5 6 7 |
2 2 2 2 2 2 2 3 4 54 1 2 2 54 23 6 45 45 10 |
Input:
1 2 3 4 5 6 7 |
6 1 1 58 100 121 100 |
To make it more presentable, the file with the results, has some runtime errors and wrong calculation errors. Thus this is the result in the immediate window:
1 2 3 4 5 6 7 8 |
6 Test 1............................................ ok! Runtime error on 2! Test 3............................................ ok! Error on test 4! Expected -> 57 Received -> 58 Runtime error on 5! Error on test 6! Expected -> 83 Received -> 121 Test 7............................................ ok! |
Now the question – how do we actually do this? The answer is in less than 130 lines here, one should only change the paths of the notepad files (pathInputTests and pathOutputTests) and start the challenge through Main:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
Attribute VB_Name = "Modul1" Option Explicit Public Sub Main() Dim totalTests As Long Dim pathInputTests As String Dim pathOutputTests As String Dim inputTests As Variant Dim outputTests As Variant Dim cntTests As Long Dim cnt As Long pathInputTests = "C:\Desktop\Test002.txt" pathOutputTests = "C:\Desktop\Result002.txt" inputTests = Split(ReadFileLineByLineToString(pathInputTests), vbCrLf) outputTests = Split(ReadFileLineByLineToString(pathOutputTests), vbCrLf) For cnt = LBound(inputTests) To UBound(inputTests) Dim expectedValue As Variant Dim receivedValue As Variant On Error Resume Next expectedValue = outputTests(cnt) receivedValue = MainTest(Trim(inputTests(cnt))) If Err.Number <> 0 Then Debug.Print runtimeError(cnt) Err.Clear Else If Trim(expectedValue) = Trim(receivedValue) Then Debug.Print positiveResult(cnt) Else Debug.Print negativeResult(cnt, expectedValue, receivedValue) End If End If Next cnt End Sub Public Function runtimeError(ByVal cnt As Long) As String cnt = cnt + 1 runtimeError = "Runtime error on " & cnt & "!" End Function Public Function positiveResult(ByVal cnt As Long) As String cnt = cnt + 1 positiveResult = "Test " & cnt & "..................................... ok!" End Function Public Function negativeResult(ByVal cnt As Long, expected As Variant, _ received As Variant) As String cnt = cnt + 1 negativeResult = "Error on test " & cnt & "!" & _ " Expected -> " & vbTab & expected & vbTab & _ " Received -> " & vbTab & received End Function '--------------------------------------------------------------------------------------- ' Method : MainTest ' Purpose: This is where the competitors paste their solution. '--------------------------------------------------------------------------------------- Public Function MainTest(ByVal consoleInput As String) As String Dim inputVar As Variant Dim cnt As Long Dim outputVar As Variant inputVar = Split(consoleInput) ReDim outputVar(UBound(inputVar)) For cnt = LBound(inputVar) To UBound(inputVar) If Asc(inputVar(cnt)) = Asc("z") Then MainTest = MainTest & " a" Else MainTest = MainTest & " " & Chr(Asc(inputVar(cnt)) + 1) End If Next cnt ' Dim a As Double ' Dim b As Double ' Dim c As Double ' ' a = Split(consoleInput)(0) ' b = Split(consoleInput)(1) ' c = Split(consoleInput)(2) ' ' If c Mod 2 = 0 Then ' MainTest = a + b + c ' Else ' MainTest = a + b - c ' End If End Function Public Function ReadFileLineByLineToString(path As String) As String Dim fileNo As Long fileNo = FreeFile Open path For Input As #fileNo Do While Not EOF(fileNo) Dim textRowInput As String Line Input #fileNo, textRowInput ReadFileLineByLineToString = ReadFileLineByLineToString & textRowInput If Not EOF(fileNo) Then ReadFileLineByLineToString = ReadFileLineByLineToString & vbCrLf End If Loop Close #fileNo End Function |