Check String for identical Digits - vb.net

I'm asking my users to enter a 4 - 6 digit numberic PIN. And I'd like to make sure users can't enter 0000 or 11111 or 333333. How can I check a string for 4 consecutive identical digits? I'm using vb.net.

See code snippet below:
Sub Main()
Dim a As String = "001111"
Dim b As String = "1123134"
Dim c As String = "1111"
Console.WriteLine(CheckConsecutiveChars(a, 4)) 'True => Invalid Pin
Console.WriteLine(CheckConsecutiveChars(b, 4)) 'False => Valid Pin
Console.WriteLine(CheckConsecutiveChars(c, 4)) 'True => Invalid Pin
Console.ReadLine()
End Sub
'maxnumber = maximum number of identical consecutive characters in a string
Public Function CheckConsecutiveChars(ByVal j As String, ByVal maxNumber As Integer) As Boolean
Dim index As Integer = 0
While ((index + maxNumber) <= j.Length)
If (j.Substring(index, maxNumber).Distinct.Count = 1) Then
Return True
End If
index = index + 1
End While
Return False
End Function
The method String.Distinct.Count() counts the number of distinct characters in a string. You cast your digit to a String and test for the number of different characters. If the result is 1 then the user has entered the same number.
Note: If you're using the Substring, you must check the length of the string first (is it long enough) to avoid exceptions.

This answer is similar to the accepted answer, but does not create lots of temporary strings in memory.
'maxnumber = maximum number of identical consecutive characters in a string
Public Function HasConsecutiveChars(ByVal j As String, ByVal maxNumber As Integer) As Boolean
Dim result As Boolean = False
Dim consecutiveChars As Integer = 1
Dim prevChar As Char = "x"c
For Each c in j
If c = prevChar Then
consecutiveChars += 1
If consecutiveChars >= maxNumber Then
result = True
Exit For
End If
Else
consecutiveChars = 1
End If
prevChar = c
Next
Return result
End Function

Related

Reversing Digits

I'm trying to make a function that takes a three digit number and reverses it (543 into 345)
I can't take that value from a TextBox because I need it to use the three numbers trick to find a value.
RVal = ReverseDigits(Val)
Diff = Val - RVal
RDiff = ReverseDigits(Diff)
OVal = Diff + RDiff
543-345=198
198+891=1089
Then it puts 1089 in a TextBox
Function ReverseDigits(ByVal Value As Integer) As Integer
' Take input as abc
' Output is (c * 100 + b * 10 + a) = cba
Dim ReturnValue As Boolean = True
Dim Val As String = CStr(InputTextBox.Text)
Dim a As Char = Val(0)
Dim b As Char = Val(1)
Dim c As Char = Val(2)
Value = (c * 100) + (b * 10) + (a)
Return ReturnValue
End Function
I've tried this but can't figure out why it won't work.
You can convert the integer to a string, reverse the string, then convert back to an integer. You may want to enforce the three digit requirement. You can validate the argument before attempting conversion
Public Function ReverseDigits(value As Integer) As Integer
If Not (value > 99 AndAlso value < 1000) Then Throw New ArgumentException("value")
Return Integer.Parse(New String(value.ToString().Reverse().ToArray()))
End Function
My code is pretty simple and will also work for numbers that don't have three digits assuming you remove that validation. To see what's wrong with your code, there are a couple of things. See the commented lines which I changed. The main issue is using Val as a variable name, then trying to index the string like Val(0). Val is a built in function to vb.net and the compiler may interpret Val(0) as a function instead of indexing a string.
Function ReverseDigits(ByVal Value As Integer) As Integer
' Dim ReturnValue As Boolean = True
' Dim Val As String = CStr(InputTextBox.Text)
Dim s As String = CStr(Value)
Dim a As Char = s(0)
Dim b As Char = s(1)
Dim c As Char = s(2)
Value = Val(c) * 100 + Val(b) * 10 + Val(a)
'Return ReturnValue
Return Value
End Function
(Or the reduced version of your function, but I would still not hard-code the indices because it's limiting your function from expanding to more or less than 3 digits)
Public Function ReverseDigits(Value As Integer) As Integer
Dim s = CStr(Value)
Return 100 * Val(s(2)) + 10 * Val(s(1)) + Val(s(0))
End Function
And you could call the function like this
Dim inputString = InputTextBox.Text
Dim inputNumber = Integer.Parse(inputString)
Dim reversedNumber = ReverseDigits(inputNumber)
Bonus: If you really want to use use math to find the reversed number, here is a version which works for any number of digits
Public Function ReverseDigits(value As Integer) As Integer
Dim s = CStr(value)
Dim result As Integer
For i = 0 To Len(s) - 1
result += CInt(Val(s(i)) * (10 ^ i))
Next
Return result
End Function
Here's a method I wrote recently when someone else posted basically the same question elsewhere, probably doing the same homework:
Private Function ReverseNumber(input As Integer) As Integer
Dim output = 0
Do Until input = 0
output = output * 10 + input Mod 10
input = input \ 10
Loop
Return output
End Function
That will work on a number of any length.

Getting 15th digit

variable contains 15 digits,how to get 15th digit value from another function?
Function isvalid(stringvalue As String) As Boolean
Dim methodToCall As String
methodToCall = "somefunction"
isvalid = stringvalue Like "[0-9][0-9][A-Z][A-Z][A-Z][A-Z][A-Z]####[A-Z][A-Z][A-Z][methodToCall(stringvalue)]"
Here the methodToCall will call another function and that function is return value for my 15th digit
How to get the Value from anothor function from isvalid function
Say we have a string containing with a mixture of digits and other characters and we want the 15th digit. The UDF:
Public Function GetFifteenth(sin As String) As Variant
kount = 0
For i = 1 To Len(sin)
ch = Mid(sin, i, 1)
If IsNumeric(ch) Then
kount = kount + 1
If kount = 15 Then
GetFifteenth = CLng(ch)
Exit Function
End If
End If
Next i
GetFifteenth = ""
End Function
should do that. For example:
Sub MAIN()
Dim s As String, L As Variant
s = "t2}nf[aW(494U,Oay8OWkh{xa*9>9b2SY5yPt14;m98AYd$|>U%orIJ[iF*Q)0w21!0:eX9,kU<_ x=B+cAFU<)%#{JMSze}"
L = GetFifteenth(s)
MsgBox L
End Sub
The code would be a little simpler if the string always contained exactly 15 digits.

Extract right side of string specify by separator

This is my code to get right side of string specifying char separator and either to keep separator within string or not. Possibility also to specify if just last occurence of char separator or manually define it. My question is how to make same version but this time to get right side of string instead of left?
Public Shared Function GetLetSideStringByChar(splitterChar As String, searchingWord As String, keepCharAsWell As Boolean, lastindexof As Boolean, splitterCharPosition As Integer) As String
Dim index As Integer
Select Case lastindexof
Case False
index = GetNthIndex(searchingWord, splitterChar, splitterCharPosition)
Case True
index = searchingWord.LastIndexOf(splitterChar)
End Select
If index > 0 Then
If keepCharAsWell Then
searchingWord = searchingWord.Substring(0, index + splitterChar.Length)
Else
searchingWord = searchingWord.Substring(0, index)
End If
Else
searchingWord = String.Empty
End If
Return searchingWord
End Function
'jesli n separator nie odnalzeiony bedzie return -1, np jesli charseparator = . i damy n = 2 a word bedzie mial tlko jedna . to -1
Public Shared Function GetNthIndex(searchingWord As String, charseparator As Char, n As Integer) As Integer
Dim count As Integer = 0
For i As Integer = 0 To searchingWord.Length - 1
If searchingWord(i) = charseparator Then
count += 1
If count = n Then
Return i
End If
End If
Next
Return -1
End Function
I had written a code for your previous problem that you deleted.
To make the code more understandable I used an Enum to specify right or left:
Public Enum Direction
Left = 0
Right = 1
End Enum
then you can call the function like this:
Console.WriteLine(StringExtract("5345.342.323.323#$%", Direction.Right, 2, False))
Here the Seperator Index represents the dot number (starting at 1)
For Example:
648674.2327.12 first dot is 1 second is 2
And here is the function, I'm sure it could be shortened:
Public Function StringExtract(ByVal MyStr As String, ByVal Side As Direction, ByVal SeperatorIndex As Integer, ByVal SeperatorKeep As Boolean) As String
Dim MySubs() As String = MyStr.Split(".".ToCharArray, StringSplitOptions.RemoveEmptyEntries)
Dim IndexOfSplit As Integer
Dim MyResult As String = ""
If Side = Direction.Left Then
IndexOfSplit = SeperatorIndex - 1
For i As Integer = IndexOfSplit To 0 Step -1
MyResult = MyResult.Insert(0, MySubs(i) & ".")
Next
If SeperatorKeep = False Then
MyResult = MyResult.Remove(MyResult.LastIndexOf("."), 1)
End If
Else
IndexOfSplit = SeperatorIndex
For i As Integer = IndexOfSplit To MySubs.Length - 1
MyResult = MyResult & MySubs(i) & "."
Next
If SeperatorKeep = False Then
MyResult = MyResult.Remove(MyResult.LastIndexOf("."), 1)
Else
MyResult = "." & MyResult.Remove(MyResult.LastIndexOf("."), 1)
End If
End If
Return MyResult
End Function
Output example:
Input 1:
StringExtract("5345.342.323.323#$%", Direction.Right, 2, False)
Output 1:
323.323#$%
Input 2:
StringExtract("5345.342.323.323#$%", Direction.Right, 3, True)
Output 2:
.323#$%
Input 3:
StringExtract("4.34!2.3323.", Direction.Left, 2, True)
Output 3:
4.34!2.
PS: If anyone has any suggestions to shorten the function let me know I'm happy to learn.

Take specific string part of string by specific requirments

I am developing function which would give me the right side of specific string. Function has possibility to take the return string based on splitted char, keep char in string and also which is most important to say either return string will be after last occurence of that char separator or say after exactly which positon of separator occerence in string, return string after to take. Can anyone take a look on that and confirm is it right way to go or whether that code contains any issues?
Keep in mind to use as lastindex i set lastindexof to true and doesn't matter what splitterCharPosition is and vice versa when false splitterCharPosition has to be set.
This is my current code to be confirmed:
Public Function GetRightSideStringByCHar(splitterChar As String, searchingWord As String, keepCharAsWell As Boolean, lastindexof As Boolean, splitterCharPosition As Integer) As String
Dim index As Integer
Select Case lastindexof
Case False
index = GetNthIndex(searchingWord, splitterChar, splitterCharPosition)
Case True
index = searchingWord.LastIndexOf(splitterChar)
End Select
If index > 0 Then
If keepCharAsWell Then
searchingWord = searchingWord.Substring(0, index + splitterChar.Length)
Else
searchingWord = searchingWord.Substring(0, index)
End If
Else
searchingWord = String.Empty
End If
Return searchingWord
End Function
Helper function to get n index:
Public Function GetNthIndex(searchingWord As String, charseparator As Char, n As Integer) As Integer
Dim count As Integer = 0
For i As Integer = 0 To searchingWord.Length - 1
If searchingWord(i) = charseparator Then
count += 1
If count = n Then
Return i
End If
End If
Next
Return -1
End Function
Based on your other deleted question, I formulated this for you.
It worked with all your previous examples.
[parameters]
str = input string
strtofind = separator string
occurance = zero-based index to start cutting (optional)
keepstringtofind = append separator to string (optional)
righttoleft = operational direction (optional)
Public Function CutFromString(str As String, strtofind As String, Optional occurance As Integer = 0, Optional keepstrtofind As Boolean = False, Optional righttoleft As Boolean = False) As String
Dim s As String = str
Dim sections As List(Of String) = IIf(String.IsNullOrEmpty(str), New List(Of String), str.Split(strtofind.ToCharArray).ToList)
If sections.Count = 1 AndAlso sections.First = str Then sections.Clear()
If occurance < sections.Count Then
Dim b = sections.Count - occurance
While b > 0
If righttoleft Then
sections.RemoveAt(0)
Else
sections.RemoveAt(sections.Count - 1)
End If
b -= 1
End While
s = Join(sections.ToArray, strtofind)
If keepstrtofind And occurance > 0 Then
If righttoleft Then
s = strtofind + s
Else
s += strtofind
End If
End If
End If
Return s
End Function

Generate unique serial number incrementally

I am writing a vb.net program to generate a three digit serial number I will use in printing a barcode.
The requirements are the counter must count:
001 - 999, A00 - A99, B00 - B99, ..., Z00 - Z99
I cannot use the letters O and I
This code simply increments the value I pass to it by 1. I first check if the value is <=998 and if so return the value in 3 digits. I had to put this in a Try statement because passing the value 'A00' caused an error.
The code is still breaking once I hit Z99.
Problem: If the next serial number = Z90 and the user wants to print 35 barcodes I need to stop the operation before it begins and warn the user there are only 10 avail serial numbers remaining
Also, I am also hoping for advice on how I could have accomplished this in a better manner, any advice would be greatly appreciated
Public Shared Function NextSerial(ByVal value As String) As String
Try
If value <= 998 Then
value += 1
Return ZeroPad(value, 3)
End If
Catch ex As Exception
End Try
Const chars As String = "ABCDEFGHJKLMNPQRSTUVWXYZ"
Dim threenumber As String = ZeroPad(value, 3) 'ensure value is 3 digits.
Dim alpha As String = threenumber.Substring(0, 1).ToUpper() ' 1st digit
Dim beta As String = threenumber.Substring(1, 2) 'remaining two digits
Dim newNumber As String
Dim nextletter As String
If beta = "99" Then
beta = "00"
nextletter = chars.Substring((chars.IndexOf(alpha, System.StringComparison.Ordinal) + 1), 1)
newNumber = nextletter + beta
Return newNumber
Else
beta += 1
newNumber = alpha + ZeroPad(beta, 2)
Return newNumber
End If
End Function
Private Shared Function ZeroPad(ByVal number As String, ByVal toLength As Integer) As String
ZeroPad = number
'add the necessary leading zeroes to build it up to the desired length.
Do Until Len(ZeroPad) >= toLength
ZeroPad = "0" & ZeroPad
Loop
End Function
I think you can do this by assuming your first character is the 'hundreds' and converting to a number and incrementing:
Private Function NextSerial(value As String) As String
Const chars As String = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
Dim numericValue As Integer = 100 * (chars.IndexOf(value.Substring(0, 1))) + Integer.Parse(value.Substring(1, 2))
numericValue += 1
Return chars.Substring(numericValue \ 100, 1) + (numericValue Mod 100).ToString.PadLeft(2, "0")
End Function
You should of course perform some error checking at the start of the function to make sure a valid serial number has been handed into the function. I would also put this function into a class and add functions such as isValid, SerialsRemaining and perhaps a function to retrieve a list of multiple serials.
I created constant strings that represent every available character in each digit position. I then used indexing to lookup the positions of the current serial number & moved one number forward to get the next serial. This will always provide the next serial until you run out of numbers.
Note: this code can easily be made more compact, but I left it as-is thinking it might be clearer.
Const charString1 As String = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
Const charString2 As String = "0123456789"
Const charString3 As String = "0123456789"
Public Function NextSerial(ByVal value As String) As String
' ensures the input is three chars long
Dim threenumber As String = Right("000" & value, 3)
Dim char1 As String = threenumber.Substring(0, 1)
Dim char2 As String = threenumber.Substring(1, 1)
Dim char3 As String = threenumber.Substring(2, 1)
Dim char1Pos As Integer = charString1.IndexOf(char1)
Dim char2Pos As Integer = charString2.IndexOf(char2)
Dim char3Pos As Integer = charString3.IndexOf(char3)
If char1Pos = -1 Or char2Pos = -1 Or char3Pos = -1 Then Throw New Exception("Invalid serial number format")
' move to next serial number
char3Pos += 1
If char3Pos > charString3.Length() - 1 Then
char3Pos = 0
char2Pos += 1
End If
If char2Pos > charString2.Length() - 1 Then
char2Pos = 0
char1Pos += 1
End If
If char1Pos > charString1.Length() - 1 Then Throw New Exception("Out of serial numbers!")
Return charString1.Substring(char1Pos, 1) & charString2.Substring(char2Pos, 1) & charString3.Substring(char3Pos, 1)
End Function
I suggest you use integer for all your check and calculation and only convert to serial number for display. It'll be a lot easier to know how many serial number are remaining.
Your serial number is similar to integer except everything over 100 is a letter instead of a number.
Note: It's very important to add error checking, this assumes that all input are valid.
Module Module1
Sub Main()
Console.WriteLine(SerialNumber.ConvertSerialNumberToInteger("D22"))
Console.WriteLine(SerialNumber.ConvertIntegerToSerialNumber(322))
Console.WriteLine(SerialNumber.GetAvailableSerialNumber("Z90"))
For Each sn As String In SerialNumber.GetNextSerialNumber("X97", 5)
Console.WriteLine(sn)
Next
Console.ReadLine()
End Sub
End Module
Class SerialNumber
Private Const _firstPart As String = "ABCDEFGHJKLMNPQRSTUVWXYZ"
Public Shared Function ConvertSerialNumberToInteger(ByVal serialNumber As String) As Integer
Return (_firstPart.IndexOf(serialNumber(0)) * 100) + Integer.Parse(serialNumber.Substring(1, 2))
End Function
Public Shared Function ConvertIntegerToSerialNumber(ByVal value As Integer) As String
Return _firstPart(value \ 100) & (value Mod 100).ToString("00")
End Function
Public Shared Function GetAvailableSerialNumber(ByVal serialNumber As String)
Dim currentPosition As Integer
Dim lastPosition As Integer
currentPosition = ConvertSerialNumberToInteger(serialNumber)
lastPosition = ConvertSerialNumberToInteger("Z99")
Return lastPosition - currentPosition
End Function
Public Shared Function GetNextSerialNumber(ByVal serialNumber As String, ByVal amount As Integer) As List(Of String)
Dim newSerialNumbers As New List(Of String)
Dim currentPosition As Integer
currentPosition = ConvertSerialNumberToInteger(serialNumber)
For i As Integer = 1 To amount
newSerialNumbers.Add(ConvertIntegerToSerialNumber(currentPosition + i))
Next
Return newSerialNumbers
End Function
End Class