2

我想做一个程序,旨在统计段落中回文单词的数量及其出现次数

规则和假设:

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

样本输入:

奥托想养一只狗。他走上街,正要走进宠物店,就看到门上挂着“禁止携带宠物”的牌子。奥托在宠物店看到了很多动物。他看到了鸟。他看到了松鼠。他看到了变色龙。他看到了狗。“那条狗多少钱?” 奥托说。“十美元,”男人说。奥托给了那个男人腱。奥托买了狗。这只狗和奥托一起走回家。现在奥托有一条狗。“感谢上帝,我现在有了一只狗,”他对自己说。

样本输出: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++;
            }
        }
    }
} 

以及我的代码的输出结果,当我放段落时:

奥托想养一只狗。他走上街,正要走进宠物店,就看到门上挂着“禁止携带宠物”的牌子。奥托在宠物店看到了很多动物。他看到了鸟。他看到了松鼠。他看到了变色龙。他看到了狗。“那条狗多少钱?” 奥托说。“十美元,”男人说。奥托给了那个男人腱。奥托买了狗。这只狗和奥托一起走回家。现在奥托有一条狗。“感谢上帝,我现在有了一只狗,”他对自己说。

我的输出程序是:

otto 是回文 = 1 a 是回文 = 1 otto 是回文 = 1 sees 是回文 = 1

我想要这样的输出程序:

奥托词 = 7,词 A = 5,词 Sees = 6

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

4

2 回答 2

4

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

  1. 将文本拆分为单词
  2. 找到回文
  3. 将相同的单词分组到桶中
  4. 使用 word 将存储桶映射到投影,并在存储桶中计数
  5. 将投影提取到列表中
  6. 然后将该列表输出到控制台

.

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 }

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

于 2012-12-19T17:32:49.223 回答
3

有几十种方法可以做到这一点。出于我的考虑,尝试将段落分成单词,删除重复项和每个结果单词,然后检查它是否是回文。

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


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

狗,”</p>

这显然不是一个词。


有很多方法可以实现正确的拆分。the_joric 答案使用了正则表达式,虽然功能强大,但过于复杂且难以理解,可能会导致错误。

(我并不是说我不会将它用于这个特定的问题;我只是说这对于 C# 新手来说可能是一个太大的飞跃)。

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

让我们为我们的特定问题领域定义一个,好吗?对我来说,单词是一个或多个仅使用字母的字符序列。所以,“guess”、“what”和“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(...)”,你就可以开始了。

于 2012-12-19T17:39:17.603 回答