I want to write a function that validates the German tax identification number (Steuer-ID
).
The identification number consists of eleven digits. The last digit is only for checking. This is not what this question is about.
The first ten digits of the identification number contain one digit exactly twice and another digit not at all (as of 2016, a triple occurring digit is also possible, correspondingly then two digits not at all; in case of three equal digits, only two may be in immediate succession, but not all three), the other eight (as of 2016: also seven) digits each exactly once. The first digit must not be 0.
My thought process:
- With a length of 10 digits, one digit must occur twice anyway. But it may occur three times. So I check if the groupList.Count property is 8 or 9. Probably the Boolean "double_or_triple_occurrence" is unnecessary then...
- But there must not be a double occurrence of another digit.
- there must not be 3 of the same digits directly behind each other, only 2 of them.
For Germans among the readers, this is the Wikipedia site.
This is how I implemented it:
Public NotInheritable Class FormMain
Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Text = ""
End Sub
Private Sub ButtonStart_Click(sender As Object, e As EventArgs) Handles ButtonStart.Click
Validate_SteuerId(TextBox1.Text)
End Sub
Private Sub Validate_SteuerId(StringToCheck As String)
Label1.Text = ""
If String.IsNullOrEmpty(StringToCheck) Then
Label1.Text = "Leer" ' Empty
Return
End If
If StringToCheck.StartsWith("0") Then
Label1.Text = "Die erste Ziffer darf nicht 0 sein." ' The first digit must not be zero.
Return
End If
If StringToCheck.Length < 11 Then
Label1.Text = "Zu kurz" ' too short
Return
ElseIf StringToCheck.Length > 11 Then
Label1.Text = "Zu lang" ' too long
Return
End If
Dim myInts As New List(Of Integer)
Dim charArray As Char() = StringToCheck.ToArray()
For i As Integer = 0 To charArray.Length - 2 Step 1
Dim rslt As Integer
If Integer.TryParse(charArray(i), rslt) Then
myInts.Add(rslt)
Else
Label1.Text = "Fehler beim Parsen" ' error
Return
End If
Next
If Not Check_occurrence_of_each_digit(myInts) Then
Label1.Text = "Fehler"
End If
End Sub
Private Function Check_occurrence_of_each_digit(Ints As List(Of Integer)) As Boolean
Dim groupList As List(Of IGrouping(Of Integer, Integer)) = Ints.GroupBy(Function(x) x).Where(Function(y) y.Count <= 3).ToList()
If groupList.Count <> 8 AndAlso groupList.Count <> 9 Then
Return False
End If
Dim double_or_triple_occurrence As Boolean = False
For i As Integer = 0 To groupList.Count - 1 Step 1
Dim currentNumber As Integer = groupList(i).Key
Dim howOften As Integer = groupList(i).Count
If howOften = 2 OrElse howOften = 3 Then
double_or_triple_occurrence = True
End If
Debug.WriteLine($"Die Zahl {currentNumber} kommt {howOften} Mal vor.")
Next
If double_or_triple_occurrence Then
Dim bools As New List(Of Boolean)
For i As Integer = 0 To Ints.Count - 1 Step 1
Dim u As Integer = i
bools.Add(Ints.Any(Function(x) x = u))
Next
If bools.Where(Function(x) x = False).Count > 1 Then
Return False
End If
End If
'max 2 same digits one after the other
Dim old As Integer
Dim middle As Integer
Dim farest As Integer
For i As Integer = 0 To Ints.Count - 3 Step 1
old = Ints(i)
middle = Ints(i + 1)
farest = Ints(i + 2)
If old = Ints(i + 1) AndAlso middle = Ints(i + 1) AndAlso farest = Ints(i + 1) Then
Return False
End If
Next
Return True
End Function
End Class
I would like to ask you to shorten the amount of code lines. I appreciate.