RosettaCodeData/Task/I-before-E-except-after-C/Visual-Basic-.NET/i-before-e-except-after-c.vb

136 lines
5.0 KiB
VB.net

Option Compare Binary
Option Explicit On
Option Infer On
Option Strict On
Imports System.Text.RegularExpressions
#Const USE_REGEX = False
Module Program
' Supports both local and remote files
Const WORDLIST_URI = "http://wiki.puzzlers.org/pub/wordlists/unixdict.txt"
' The support factor of a word for EI or IE is the number of occurrences that support the rule minus the number that oppose it.
' I.e., for IE:
' - increased when not preceded by C
' - decreased when preceded by C
' and for EI:
' - increased when preceded by C
' - decreased when not preceded by C
Private Function GetSupportFactor(word As String) As (IE As Integer, EI As Integer)
Dim IE, EI As Integer
' Enumerate the letter pairs in the word.
For i = 0 To word.Length - 2
Dim pair = word.Substring(i, 2)
' Instances at the beginning of a word count towards the factor and are treated as not preceded by C.
Dim prevIsC As Boolean = i > 0 AndAlso String.Equals(word(i - 1), "c"c, StringComparison.OrdinalIgnoreCase)
If pair.Equals("ie", StringComparison.OrdinalIgnoreCase) Then
IE += If(Not prevIsC, 1, -1)
ElseIf pair.Equals("ei", StringComparison.OrdinalIgnoreCase) Then
EI += If(prevIsC, 1, -1)
End If
Next
If Math.Abs(IE) > 1 Or Math.Abs(EI) > 1 Then Debug.WriteLine($"{word}: {GetSupportFactor}")
Return (IE, EI)
End Function
' Returns the number of words that support or oppose the rule.
Private Function GetPlausabilities(words As IEnumerable(Of String)) As (ieSuppCount As Integer, ieOppCount As Integer, eiSuppCount As Integer, eiOppCount As Integer)
Dim ieSuppCount, ieOppCount, eiSuppCount, eiOppCount As Integer
For Each word In words
Dim status = GetSupportFactor(word)
If status.IE > 0 Then
ieSuppCount += 1
ElseIf status.IE < 0 Then
ieOppCount += 1
End If
If status.EI > 0 Then
eiSuppCount += 1
ElseIf status.EI < 0 Then
eiOppCount += 1
End If
Next
Return (ieSuppCount, ieOppCount, eiSuppCount, eiOppCount)
End Function
' Takes entire file instead of individual words.
' Returns the number of instances of IE or EI that support or oppose the rule.
Private Function GetPlausabilitiesRegex(words As String) As (ieSuppCount As Integer, ieOppCount As Integer, eiSuppCount As Integer, eiOppCount As Integer)
' Gets number of occurrences of the pattern, case-insensitive.
Dim count = Function(pattern As String) Regex.Matches(words, pattern, RegexOptions.IgnoreCase).Count
Dim ie = count("[^c]ie")
Dim ei = count("[^c]ei")
Dim cie = count("cie")
Dim cei = count("cei")
Return (ie, cie, cei, ei)
End Function
Sub Main()
Dim file As String
Dim wc As New Net.WebClient()
Try
Console.WriteLine("Fetching file...")
file = wc.DownloadString(WORDLIST_URI)
Console.WriteLine("Success.")
Console.WriteLine()
Catch ex As Net.WebException
Console.WriteLine(ex.Message)
Exit Sub
Finally
wc.Dispose()
End Try
#If USE_REGEX Then
Dim res = GetPlausabilitiesRegex(file)
#Else
Dim words = file.Split({vbCr, vbLf}, StringSplitOptions.RemoveEmptyEntries)
Dim res = GetPlausabilities(words)
#End If
Dim PrintResult =
Function(suppCount As Integer, oppCount As Integer, printEI As Boolean) As Boolean
Dim ratio = suppCount / oppCount,
plausible = ratio > 2
#If Not USE_REGEX Then
Console.WriteLine($" Words with no instances of {If(printEI, "EI", "IE")} or equal numbers of supporting/opposing occurrences: {words.Length - suppCount - oppCount}")
#End If
Console.WriteLine($" Number supporting: {suppCount}")
Console.WriteLine($" Number opposing: {oppCount}")
Console.WriteLine($" {suppCount}/{oppCount}={ratio:N3}")
Console.WriteLine($" Rule therefore IS {If(plausible, "", "NOT ")}plausible.")
Return plausible
End Function
#If USE_REGEX Then
Console.WriteLine($"Total occurrences of IE: {res.ieOppCount + res.ieSuppCount}")
Console.WriteLine($"Total occurrences of EI: {res.eiOppCount + res.eiSuppCount}")
#Else
Console.WriteLine($"Total words: {words.Length}")
#End If
Console.WriteLine()
Console.WriteLine("""IE is not preceded by C""")
Dim iePlausible = PrintResult(res.ieSuppCount, res.ieOppCount, False)
Console.WriteLine()
Console.WriteLine("""EI is preceded by C""")
Dim eiPlausible = PrintResult(res.eiSuppCount, res.eiOppCount, True)
Console.WriteLine()
Console.WriteLine($"Rule thus overall IS {If(iePlausible AndAlso eiPlausible, "", "NOT ")}plausible.")
End Sub
End Module