0

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:

  1. Misspeled word.
  2. Swapped letters.
  3. Extra letter.
  4. 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();
        }
    }
}

Raluca123
  • 9
  • 4
  • Sorry, i edited. I want to reduce it's "cyclomatic complexity". This is determined by the complexity and number of conditional branches in a code. – Raluca123 Dec 19 '22 at 11:04
  • How have you measured that the [cyclomatic complexity](https://en.wikipedia.org/wiki/Cyclomatic_complexity) of your existing code is 27? – Theodor Zoulias Dec 19 '22 at 11:12
  • Btw I am not familiar with the concept of cyclomatic complexity. From what I read in Wikipedia it's not the same as [tag:performance], correct? – Theodor Zoulias Dec 19 '22 at 11:22
  • 1
    Correct. It's just a metric to measure the complexity , basically the number of decisions of a code. For ex: an if/else statement measure "2" cyclomatic complexity? – Raluca123 Dec 19 '22 at 11:53
  • 1
    Splitting the main method into shorter methods would be usefull, but i dont know how to do it without modifying the functionallity of the code. – Raluca123 Dec 19 '22 at 11:55

0 Answers0