使用C#检测段落中的单词回文

时间:2012-12-19 17:16:34

标签: c# palindrome

我想制作一个程序,用于计算段落中回文词的数量及其出现次数

规则和假设:

  1. 输入:用户可以输入包含尽可能多句子的段落。每个字 由空格分隔,每个句子用句点分隔。
  2. 输出:输入中找到的回文词列表及其数量 发生。
  3. 在标点符号之前或之后的标点符号将被忽略,而标点符号则被忽略 里面的单词将被计算在内。回文也忽略了字母的情况。 一个。我有一辆本田思域。 Civicis回文,这个词之后的标点符号 忽略。 湾我的兄弟正在睡觉。 li'l不是回文,因为有一个 字里面标点符号。
  4. 示例输入:

    奥托想养一只狗。他走上街头,准备走进宠物 当他看到挂在门上的“踩下没有宠物”的标志时,便会存放。玫瑰油 在宠物商店看到很多动物。他看到了鸟儿。他看到了松鼠。他 看到变色龙。他看到了狗。 “这只狗多少钱?”奥托说。 “十美元,”男子说。奥托给了男人的女孩子。奥托买了狗。该 狗跟奥托一起走回家。现在奥托有一只狗。 “感谢上帝,我有一只狗,”他说 对自己说。

    示例输出: Otto = 7 A = 5 Sees = 6

    我的代码是:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace PalindromeProgram
    {
        class Program
        {
            static void Main(string[] args)
            {
                int i = 0;
                Console.WriteLine("Enter a String"); 
                string s = Console.ReadLine();
                string words = s.ToLower();
                string[] hasil = words.Split(' ');
                foreach (string temp in hasil)
                {
                    string str = string.Empty;
                    int x = temp.Length;
    
                    for (int y = x - 1; y >= 0; y--)
                    {
                        str = str + temp[y];
                    }
    
                    int count = 0;
                    if (str == temp)
                    {
                        count++;
                        Console.WriteLine(temp + " is palindrome = " + count);
                    }
                    i++;
                }
            }
        }
    } 
    

    和我的代码的输出结果,我把paragrapht:

    奥托想养一只狗。当他看到门上挂着“踩着没有宠物”的牌子时,他走上街头,准备走进宠物商店。奥托在宠物商店看到了很多动物。他看到了鸟儿。他看到了松鼠。他看到了变色龙。他看到了狗。 “这只狗多少钱?”奥托说。 “十美元,”男子说。奥托给了男人的女孩子。奥托买了狗。狗跟奥托一起走回家。现在奥托有一只狗。 “现在感谢上帝,我有一只狗,”他对自己说。

    我的输出计划是:

    otto是回文= 1 a是回文= 1 otto是回文= 1看是回文= 1

    我想要我的输出程序:

    单词Otto = 7,单词A = 5,单词Sees = 6

    请修改我的输出结果......

2 个答案:

答案 0 :(得分:4)

想象一下,您通过管道处理文本,步骤如下:

  1. 将文字拆分为文字
  2. 找到palindromes
  3. 将相同的词汇分组为水桶
  4. 将存储桶映射到带有字的投影,并将其计入存储桶
  5. 将投影提取到列表
  6. 然后将该列表输出到控制台
  7. var s = @"<<< your input string here >>>";
    
    var result = Regex.Matches(s, @"\w+").Cast<Match>() //1
            .Select(m => m.Value.ToLower()) //1
            .Where(w => String.Join("", w.Reverse()) == w) //2
            .GroupBy(w => w) //3
            .Select(g => new {Word = g.Key, Count = g.Count()}) //4
            .ToList(); //5
    
    result.ForEach(Console.WriteLine); //6
    

    输出:

    { Word = otto, Count = 7 }
    { Word = a, Count = 5 }
    { Word = sees, Count = 6 }
    

    不确定它是否会涵盖标点符号 - 需要调整reqular表达式。会让它给你。 :)我想唯一的例子是像I'll这样的单词中的撇号。这种情况可以通过将正则表达式模式更改为\w|'+来处理(这意味着任何字母或撇号,发生一次或多次)。

答案 1 :(得分:3)

有很多方法可以做到这一点。在我的脑海中,尝试将段落分成单词,删除重复项和每个结果单词,然后检查它是否是回文。

当然,有很多方法可以优化此算法。


查看您的代码,唯一的错误 - 可能是此问题中最复杂的问题 - 正确地拆分段落。您使用了string.Split(''),这意味着只有空格分隔的字符序列才会变成“单词”(数组中的项目)。但是,生成的数组可能包含带

的项目
  

狗,”

这显然不是一个词。


有很多方法可以实现正确的分割。 the_joric答案使用了Regex,虽然功能强大,但它太复杂且难以理解,这可能导致错误。

(我不是说我不会用它来解决这个特殊的问题;我只是说这可能对C#newcomer来说太大了一步)。

所以我会尝试用其他方式编写解决方案:

让我们为我们特定的问题域定义什么是,不是吗?对我来说,单词是一个只使用字母的一个或多个字符的序列。所以,“猜测”,“什么”和“asd”是一个词。但是,“123asd”或“a1s2d3”或“asd123”不是。

另一方面,也许是“asd”。是一段时间后的一个词。所以,让我们遵循启发式方法,除了字母以外的任何东西都是“分隔符”。因此,“123asd”将产生“asd”作为单词,“a1s2d3”将产生“a”,“b”和“c”。

const string validChars = "abcdefghijklmenopqrstuvwxyz";

List<string> GetAllWords(string inputSentence)
{
    var list = new List<string>();

    string word = string.Empty;
    foreach (var c in inputSentence.ToLower())
    {
        if (validChars.IndexOf(c) >= 0)
        {
            word += c;
        }
        else if (word != string.Empty)
        {
            list.Add(word);
            word = string.Empty;
        }
    }

    return list;
}

上面的方法将返回我们的启发式后面的单词列表。正如我已经说过的那样,这并不完美,但考虑到格式良好的文本,它会起作用。用这个算法替换你的“string.Split(...)”,你就可以了。