Loop through a string to find the odd numbers VB - vba

I am looping through a card number finding all the odd numbers and multiplying them by the card digits. Its kind of hard to explain. I am having trouble multiplying the odd number and the card number. Here's an example my teacher gave me. You multiply card number 1 and and odd number 1 and so forth. I am not getting any errors, it just kind of freezes.
Sums
Card #: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
Multiples 1 2 3 4 5 6 7 8
Evens: 2 4 6 8 0 2 4 6 32 =Sum 1
Odds: 1 6 15 28 45 6 21 40 162 =Sum 2
Sum 3: 194
194 =Sum 3
Step 4: =1+9+4 = 14
= 1 + 4 = 5 = check digit
Public Class Payment
Private Sub OK_Click(sender As Object, e As EventArgs) Handles OK.Click
Dim Sum1 = 0
Dim Sum2 = 0
Dim Sum3 = 0
Dim ready As Boolean
Dim ccnumb = CardNumber.Text
Format(CardNumber.Text, "################")
Dim exp = Mid(ExpDate.Text, 1, 3)
Dim checkdigit = 0
If FullName.TextLength = 0 Or cardtype.Text.Length = 0 And ccnumb.Length <= 16 Or exp.Length = 2 Then
MessageBox.Show("Please enter all credit card information before proceeding.")
ready = False
Else ready = True
End If
If ready = True Then
For Each num As Char In ccnumb
If CInt(CStr(num)) Mod 2 <> 0 Then
Sum1 += CInt(CStr(num)) * CInt(CStr(num)) Mod 2 <> 0
Else
Sum2 += CInt(CStr(num))
End If
Next
Sum3 = Sum1 + Sum2
Do While Sum3 > 10
For j = 0 To Sum3.ToString.Length - 1
For k = 1 To Sum3.ToString.Length - 1
Sum3 = j + k
Next
Next
Loop
Do While exp.Length > 1
checkdigit = Mid(ExpDate.Text, 1, 1) + Mid(ExpDate.Text, 1, 2)
Loop
If Sum3 = checkdigit Then
MessageBox.Show("Congratulations! Your payment was successful.")
CustInv.Show()
Else MessageBox.Show("The checkdigit," & Space(1) & Sum3 & Space(1) & "does not match the month code," & Space(1) & checkdigit & "." & Space(1) & "Please reenter your card information.")
End If
End If
End Sub

"it kind of freezes" is lay speak for "my code enters an infinite loop".
This looks suspicious:
Do While Sum3 > 10
For j = 0 To Sum3.ToString.Length - 1
For k = 1 To Sum3.ToString.Length - 1
Sum3 = j + k
Next
Next
Loop
To enter the loop, Sum3 must be greater than 10. For the loop to exit, Sum3 must not be greater than 10, but your code only increments Sum3, so Sum3 can only stay greater than 10.
This means that once entered, this loop is infinite.

If changing outer loop to inside loop doesn't help you
Try this
Do While Sum3 > 10 and j < sum3 ' adding j < sum3 might stop the loop
For j = 0 To Sum3.ToString.Length - 1
For k = 1 To Sum3.ToString.Length - 1
Sum3 = j + k
Next
Next
Loop

Related

Test if a permutation of a number exists in a collection

I'm trying to list all numbers with 3 digits where the individual digits sum to a given number.
So far I can return a list of all numbers using this Visual Basic code:
target = 17
i = 1
j = 1
k = 1
Do While i < 10
Do While j < 10
Do While k < 10
r = i + j + k
If r = target Then
If i <> j And j <> k And k <> i Then
lsNumbers.Add(i & j & k )
End If
End If
k += 1
Loop
If k = 10 Then k = 1
j += 1
Loop
If j = 10 Then j = 1
i += 1
Loop
But I want only unique, non repeating combinations.
For example for the target number 17:
179, 197, 269, 278, 287...
I want to be able to test the current number before I add it to the list, to check if it is a combination of a number already in the list - so 197 would fail because of 179, and 287 would fail because of 278
Observations
Just curious, is excluding the 0 digit on purpose?
To iterate through the possible digits, a well suited instruction pair is FOR NEXT. Definitely simpler than the DO WHILE that you used.
Loop
If k = 10 Then k = 1
Loop
If j = 10 Then j = 1
Upon loop completion, the iterator is sure to contain 10. The IF is redundant.
Solution
In order to check if a number, that obeys the condition, is unique in the sense that it is not composed of the same 3 digits as an already validated number, you could consult a 3-D array. If the new number corresponds to a non-zero element in this array, it means that the new number would be using the same digits as an earlier number. That's reason to reject it.
Next code runs in QBasic. You'll have no trouble rewriting it for Visual BASIC.
DIM r%(1 TO 9, 1 TO 9, 1 TO 9)
FOR i% = 1 TO 9
FOR j% = 1 TO 9
FOR k% = 1 TO 9
r%(i%, j%, k%) = 0
NEXT
NEXT
NEXT
target% = 17
FOR i% = 1 TO 9
FOR j% = 1 TO 9
FOR k% = 1 TO 9
IF i% + j% + k% = target% THEN
IF r%(i%, j%, k%) = 0 THEN
PRINT i% * 100 + j% * 10 + k%; " ";
r%(i%, j%, k%) = 1 ' Could do without this one because of the ascending order
r%(i%, k%, j%) = 1
r%(j%, i%, k%) = 1
r%(j%, k%, i%) = 1
r%(k%, i%, j%) = 1
r%(k%, j%, i%) = 1
END IF
END IF
NEXT
NEXT
NEXT
This is my output of valid numbers:
179 188 269 278 359 368 377 449 458 467 557 566

EXPLAIN what this VB CODE means

Function convertToText(ByVal data As String) As String
Dim result As String = Nothing
Dim i As Integer = 0
Dim j As Integer = 0
For Each c As Char In data.ToCharArray
j *= 2
If c = "1"c Then j += 1
i += 1
If i = 8 Then
i = 0
result &= Chr(j)
j = 0
End If
Next
Return result
End Function
It converts binary to text but its a bit difficult for me to understand the logic behind it.
Someone please help.
The code seems to convert a text containing a binary number representing 8 bit character codes to a string containing these characters.
The for each loop loops over all binary digits ("0" or "1") of the input. The code of each result character is computed and after every 8 input characters the code is considered to be complete and the new character whose code was determined is added to the result (result &= Chr(j) is the same as result = result & Chr(j). Chr(j) converts an Integer containing a character code into a character). The variable i counts the bits.
The variable j holds the character code. If a bit is "1", then 1 is added to j (j += 1 is the same as j = j + 1), but not if it is "0".
A "1" in the right most bit position has a (decimal) value of 1. The next to its left a value of 2. The next 4 and so on. The value doubles for each position until it reaches 128 for the left most bit of an 8 bit number. Therefore j is doubled on each loop (j *= 2 is the same as j = j * 2).
Example with just 4 bits:
data = "1010"
The binary number 1010 means
1 * 8 + 0 * 4 + 1 * 2 + 0 * 1 = (decimal)10
The code does this
j = 0 => 0
j *= 2 => 0
j += 1 => 1 'since c = "1"
j *= 2 => 2
'no += 1 since c = "0"
j *= 2 => 4
j += 1 => 5 'since c = "1"
j *= 2 => 10
'no += 1 since c = "0"
The first 1 we added is doubled 3 times and becomes 8. The second 1 we added is doubled only once and becomes 2. 8 + 2 = 10.

project euler problem17 vb code bug

If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.
If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?
NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of "and" when writing out numbers is in compliance with British usage.
my answer is coming 21148. i cant find the mistake here is my code in vb
the answer should be 21124
Dim length As UInt32 = 11
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For i = 1 To 999
If i / 10 < 1 Then
single_digit(i)
ElseIf i / 10 = 1 Then
ten()
ElseIf i / 10 > 1 And i / 10 < 2 Then
ele_twe_thi(i)
ElseIf i / 10 >= 2 And i / 10 < 10 Then
multiple_10(Math.Floor(i / 10) * 10)
single_digit(i Mod 10)
ElseIf i = 100 Then
single_digit(i / 100)
length += 7
ElseIf i Mod 100 >= 11 And i Mod 100 <= 19 Then
length += 10
single_digit(Math.Floor(i / 100))
ele_twe_thi(i Mod 100)
ElseIf i Mod 100 = 10 Then
length += 3
single_digit(Math.Floor(i / 100))
length += 10
Else
length += 10
single_digit(Math.Floor(i / 100))
multiple_10(Math.Floor((i Mod 100) / 10) * 10)
single_digit(i Mod 10)
End If
Next
MsgBox(length)
End Sub
Private Sub single_digit(num)
If num = 1 Then
length = length + 3
ElseIf num = 2 Then
length = length + 3
ElseIf num = 3 Then
length = length + 5
ElseIf num = 4 Then
length = length + 4
ElseIf num = 5 Then
length = length + 4
ElseIf num = 6 Then
length = length + 3
ElseIf num = 7 Then
length = length + 5
ElseIf num = 8 Then
length = length + 5
ElseIf num = 9 Then
length = length + 4
End If
End Sub
Private Sub ele_twe_thi(num)
If num = 11 Or num = 12 Then
length = length + 6
ElseIf num = 13 Or num = 14 Or num = 18 Or num = 19 Then
length = length + 8
ElseIf num = 17 Then
length = length + 9
ElseIf num = 15 Or num = 16 Then
length = length + 7
End If
End Sub
Private Sub multiple_10(num)
If num = 20 Then
length = length + 6
ElseIf num = 30 Then
length = length + 6
ElseIf num = 40 Then
length = length + 5
ElseIf num = 50 Then
length = length + 5
ElseIf num = 60 Then
length = length + 5
ElseIf num = 70 Then
length = length + 7
ElseIf num = 80 Then
length = length + 6
ElseIf num = 90 Then
length = length + 6
End If
End Sub
Private Sub ten()
length = length + 3
End Sub
every time the program reaches 100, 200, 300 etc. is it adding an "and" unnecessarily?

Why doesn't my VBA function work properly?

I'm very new to VBA and programming, so this might be a dumb question. I have written the following code:
Function central(X)
Dim xc(300, 10), xa(200)
m = X.Rows.Count
n = X.Columns.Count
For j = 1 To n
xa(j) = 0
For i = 1 To m
xa(j) = xa(j) + X(i, j)
Next i
xa(j) = xa(j) / m
For i = 1 To m
xc(i, j) = X(i, j) - xa(j)
Next i
Next
central = xc()
End Function
This should output a matrix whose elements are subtracted from the average value of their columns.
My problem is that the output is shifted with one row and column. So for example for this table:
1 1 1
2 2 2
3 3 3
it gives me:
0 0 0
0 -1 -1
0 0 0
Thanks in advance!

Visual Basic - 1-100 with numbers that are divisible by 2 and 3

The console seems to keep printing a repetition of the value '1'
Maybe this is because I am not incrementing the value correctly within the loop?
Or am I declaring the value of the variable in an incorrect location
Dim divx As Integer
Dim divy As Integer
divx = 1
Do While divx < 100
divy = divx Mod 2
If Not (divy = 0) Then
Console.WriteLine(divx)
Else
divx += 1
End If
Loop
Yes, you are not incrementing it, you can omit the Else:
Do While divx < 100
divy = divx Mod 2
If Not (divy = 0) Then
Console.WriteLine(divx)
End If
divx += 1
Loop
But if you also want to show numbers that are divisible by 3 you can modify your loop in this way:
Dim divx As Integer = 1
Do While divx < 100
Dim isDivisableBy2Or3 = divx Mod 2 = 0 OrElse divx Mod 3 = 0
If isDivisableBy2Or3 Then
Console.WriteLine(divx)
End If
divx += 1
Loop
If your goal is just to list out numbers that are divisible by 2 and 3, this should be the shortest route. Just trying to help :) If 2 or 3 then change And to Or.
For x As Integer = 1 To 100
If (x Mod 2 = 0) And (x Mod 3 = 0) Then Console.WriteLine(x)
Next x
If condition is 2 and 3 but not 5 then...
For x As Integer = 1 To 100
If (x Mod 2 = 0) And (x Mod 3 = 0) And Not (x Mod 5 = 0) Then Console.WriteLine(x)
Next x
Do While divx < 100
If Not (divx Mod 2 = 0) Then
Console.WriteLine("Divisible by 2: " & divx)
End If
If Not (divx Mod 3 = 0) Then
Console.WriteLine("Divisible by 3: " & divx)
End If
divx += 1
Loop