I have to implement a simple spell checker. Basically I have to user input an incorrect sentence or a word, then a number N, and then N correct words each on new line. The program has to output "incorrect word: suggestion". If there is no suggestions available it should output "incorrect word: no suggestions" and if all the words from sentence are correct it should display "Correct text!". The typos can be:
- Misspeled word.
- Swapped letters.
- Extra letter.
- Missing letter.
To do this I implemented Levensthein minumim distance algorithm, which calculates the minimum number of modifications that a string has to take to be transformed into another string. All the test cases are fine but I want to reduce the cyclomatic complexity of the main method from 27 to below 26. Any suggestion would be helpful. For the example:
Thsi is an texzt fr tet
5
This
an
text
for
test
It displays:
Thsi: This
an: no suggestions
texzt: text
fr: for
tet: text test
using System;
using System.Collections.Generic;
namespace MisspelledWords
{
class Program
{
static void Main(string[] args)
{
string sentence = Console.ReadLine();
sentence = sentence.ToLower();
int numWords = int.Parse(Console.ReadLine());
const int doi = 2;
const int doi2 = 3;
int index = 0;
int index1 = 0;
string[] correctWords = new string[numWords];
for (int i = 0; i < numWords; i++)
{
correctWords[i] = Console.ReadLine();
}
foreach (string word in sentence.Split(' '))
{
index++;
int minDistance = int.MaxValue;
string closestWord = "";
foreach (string correctWord in correctWords)
{
int distance = GetLevenshteinDistance(word, correctWord);
if (distance < minDistance)
{
minDistance = distance;
closestWord = correctWord;
}
}
Message(minDistance, closestWord, word, index, ref index1, correctWords);
if (index1 != 0)
{
return;
}
}
static void Message(int minDistance, string closestWord, string word, int index, ref int index1, string[] correctWords)
{
if (minDistance >= doi)
{
// Print the misspelled word followed by "no suggestions"
Console.WriteLine(word + ": (no suggestion)");
}
else if (minDistance < doi && closestWord != word || minDistance >= doi2)
{
// Find all correct words that have the same minimum distance
List<string> suggestions = new List<string>();
foreach (string correctWord in correctWords)
{
int distance = GetLevenshteinDistance(word, correctWord);
if (distance == minDistance)
{
suggestions.Add(correctWord);
}
}
// Print the misspelled word followed by the suggestions
Console.Write(word + ": ");
Console.WriteLine(string.Join(" ", suggestions));
}
else if (minDistance == 0 && index > 1)
{
Console.WriteLine("Text corect!");
index1++;
}
}
static int Min(int value1, int value2, int value3)
{
return Math.Min(Math.Min(value1, value2), value3);
}
static int GetLevenshteinDistance(string word1, string word2)
{
int[,] distance = new int[word1.Length + 1, word2.Length + 1];
InitializeDistanceMatrix(distance, word1, word2);
CalculateLevenshteinDistance(distance, word1, word2);
return distance[word1.Length, word2.Length];
}
static void InitializeDistanceMatrix(int[,] distance, string word1, string word2)
{
for (int i = 0; i <= word1.Length; i++)
{
for (int j = 0; j <= word2.Length; j++)
{
if (i == 0)
{
distance[i, j] = j;
}
else if (j == 0)
{
distance[i, j] = i;
}
}
}
}
static void CalculateLevenshteinDistance(int[,] distance, string word1, string word2)
{
for (int i = 0; i <= word1.Length; i++)
{
for (int j = 0; j <= word2.Length; j++)
{
CLD(i, j, distance, word1, word2);
}
}
}
static void CLD(int i, int j, int[,] distance, string word1, string word2)
{
const int v = 2;
if (i <= 0 || j <= 0)
{
return;
}
distance[i, j] = Min(
distance[i - 1, j] + 1,
distance[i, j - 1] + 1,
distance[i - 1, j - 1] + (word1[i - 1] == word2[j - 1] ? 0 : 1));
// Check if swapping the characters at positions i and j results in a new minimum distance
if (i <= 1 || j <= 1 || word1[i - 1] != word2[j - v] || word1[i - v] != word2[j - 1])
{
return;
}
distance[i, j] = Math.Min(distance[i, j], distance[i - v, j - v] + 1);
}
Console.ReadLine();
}
}
}