Click here to Skip to main content
15,886,724 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
We have an input text file, containing sentences.

Each sentence is delimited by “.”, “!”, “?”
Each sentence contains words, delimited by one or more “ ”.

A program should be written, to read the text file, to find the sentences, to sort them and to write them back to output file.

The output file should be one sentence per line.

The criteria for sorting are:
1) A sentence is bigger than other if it contains more equal words
2) A sentence is bigger, if contains more words
3) A sentence is bigger, if contains more characters

The criteria should be applied in order 1, 2, 3

Example input file:

Hello World. Hello hello beautiful world! There are
more words in the world than worlds in the word. This is
a sentence. My name is Neo.

Expected output file:

Hello hello beautiful world!
There are more words in the world than worlds in the word.
This is a sentence.
My name is Neo.
Hello World.

I wrote the methods for checking for words count, letters count and repeating words. I don't get how to iterate through the sentences and sort them

C#
class CountWords
{
    static void Main(string[] args)
    {

        string text = File.ReadAllText("../../words.txt");

        string[] sentences = Regex.Split(text, @"(?<=[\.!\?])\s");
        
        var wordsCount = new int[sentences.Length];

        for (int i = 0; i < sentences.Length; i++)
        {
            var biggest = sentences[0];

        }


       
    }
    public int[] WorldCounter(string[] sentences)
    {
        var wordsCount = new int[sentences.Length];

        for (int i = 0; i < sentences.Length; i++)
        {
            wordsCount[i] = sentences[i]
                                .Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)
                                .Count();
        }

        return wordsCount;
    }

    public int[] LetterCounter(string[] sentences)
    {
        return sentences
                .Select(c => c.Length)
                .ToArray();
    }

    public int[] DublicatesCounter(string[] sentences)
    {
        int[] dublicates = new int[sentences.Length];

        for (int i = 0; i < sentences.Length; i++)
        {
            var splited = sentences[i].Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);

            bool[] isChecked = new bool[splited.Length];

            for (int j = 0; j < splited.Length - 1; j++)
            {
                var currentWord = splited[j];

                for (int k = j + 1; k < splited.Length; k++)
                {
                    if (isChecked[k])
                    {
                        continue;
                    }

                    if (currentWord == splited[k])
                    {
                        dublicates[i]++;
                        isChecked[k] = true;
                    }
                }
            }
        }

        return dublicates;
    }
}
Posted
Updated 1-Sep-16 0:18am
v3
Comments
Richard MacCutchan 1-Sep-16 5:01am    
Do you have a question?
Member 12714658 1-Sep-16 5:18am    
My question is how do i iterate through sentences and sort them. I wrote the methods that check for the criteria but i got stuck there.
Richard MacCutchan 1-Sep-16 5:28am    
You can use the Array.Sort Method (System)[^] to sort a simple array of strings.
Mehdi Gholam 1-Sep-16 5:02am    
Looks like homework.
Member 12714658 1-Sep-16 5:21am    
I'm self educated. I don't have homeworks :)

Hi !

First it seems that the expected output is not the one which respects your rules.

"There are more words in the world than worlds in the word" should be first since it contains two duplicates : "in" and "the".

The expected output is now :
There are more words in the world than worlds in the word.
Hello hello beautiful world!
This is a sentence.
My name is Neo.
Hello World.

After here is my suggestion :

What about creating a class with a custom Sort() method.
It's not possible to override Sort() method of the String class since this class is sealed.

So we create a class only to encapsulate your String and create your own Sort() method.
Lets call this class CustomString.

In order to be able to use the Sort() method, you have to implement the IComparable interface. In order to implement this interface, all you have to do is to create the method CompareTo().

CompareTo indicates how two elements should be compared. The good point is that you know your comparison elements :
- Duplicate words
- Number of words
- Number of characters

See here how to implement the inteface :

Sorting Lists using IComparable and IComparer Interface in .NET

And after, you just have to use Sort() on your List of CustomString.


Since you seems to struggle a bit and be afraid by my solution, i must show you how simple it is.

80% of the code is your.

Solution :

C#
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

namespace CustomCompare
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            //Your code
            var text = File.ReadAllText("Your File");

            var sentences = Regex.Split(text, @"(?<=[\.!\?])\s");

            //Will contain the sorted elements 
            var sortedList = sentences.Select(sentence => new CustomString(sentence)).ToList();

            //Simple Sort call 
            sortedList.Sort();

            //Display
            foreach (var customString in sortedList)
            {
                Console.WriteLine(customString.CustString);
            }
            //Wait to be able to read output
            Console.Read();
        }
    }

    internal class CustomString : IComparable<CustomString>
    {
        //Simple constructor
        public CustomString(string custString)
        {
            CustString = custString;
        }

        //The encapsulated string 
        public string CustString { get; set; }
        //The implementation of compare to. 
        public int CompareTo(CustomString other)
        {
            //We compare the number of duplicated words
            var thisNumberOfDuplicate = DublicatesCounter(CustString);
            var otherNumberOfDuplicate = DublicatesCounter(other.CustString);

            if (thisNumberOfDuplicate > otherNumberOfDuplicate)
                return -1;
            if (thisNumberOfDuplicate < otherNumberOfDuplicate)
                return 1;

            //We compare the number of words
            var thisNumberOfWords = WordCounter(CustString);
            var otherNumberOfWords = WordCounter(other.CustString);

            if (thisNumberOfWords > otherNumberOfWords)
                return -1;
            if (thisNumberOfWords > otherNumberOfWords)
                return 1;

            //We compare the number or characters
            var thisNumberOfCharacter = LetterCounter(CustString);
            var otherNumberOfCharacter = LetterCounter(other.CustString);

            if (thisNumberOfCharacter > otherNumberOfCharacter)
                return -1;
            if (thisNumberOfCharacter < otherNumberOfCharacter)
                return 1;
            return 0;
        }

        //Your code without array
        private int WordCounter(string sentence)
        {
            var wordsCount = 0;
            wordsCount = sentence
                .Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries)
                .Count();
            return wordsCount;
        }

        //Your code without array 
        private int LetterCounter(string sentence)
        {
            return sentence.Length;
        }

        //Your code without array 
        //Modified because Hello != hello
        //Your expected output expects that Hello = hello
        //So you need to add .toLower()
        private int DublicatesCounter(string sentence)
        {
            var numberOfDuplicate = 0;

            var splited = sentence.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries);
            var isChecked = new bool[splited.Length];

            for (var j = 0; j < splited.Length - 1; j++)
            {
                var currentWord = splited[j];

                for (var k = j + 1; k < splited.Length; k++)
                {
                    if (isChecked[k])
                    {
                        continue;
                    }

                    if (currentWord.ToLower() == splited[k].ToLower())
                    {
                        numberOfDuplicate++;
                        isChecked[k] = true;
                    }
                }
            }
            return numberOfDuplicate;
        }
    }
}


Output:

There are more words in the world than worlds in the word.
Hello hello beautiful world!
This is a sentence.
My name is Neo.
Hello World.
 
Share this answer
 
v3
Comments
Member 12714658 1-Sep-16 10:23am    
Thank you so so much! I haven't even saw your solution from my phone. Тhat makes sense. Although it does sound scary when you describe it. I took a look at it and played a little bit with the solution you gave. I'll get the most of it change things around so i can get comfortable with it. And it makes sense. You even went the extra mile. Thanks!
DimitriStPi 2-Sep-16 3:14am    
Hi,
You're welcome.
If something is still unclear, I'm able help you.
The most important is that you understand the idea underlying the solution !
Start by looking at the problem: the sort algorithm has three phases:
1) equal words
Then
2) Word count
Finally
3) Character count.
The last two are pretty trivial.
The first isn't difficult either.
Start by taking the string arrays that contain the words and sort them:
C#
Array.Sort(words);
will do it.
Now, identical words are next to each other, and very easy to spot in a loop:
C#
int copies = 0;
string lastWord = null;
foreach (string word in words)
    {
    if (word == lastWord) copies++;
    lastWord = word;
    }
 
Share this answer
 
Comments
Member 12714658 1-Sep-16 6:55am    
I struggled a lot with this can't get it to work
OriginalGriff 1-Sep-16 7:19am    
Which part did you struggle with? How far did you get?
And seriously, "self educated" in any framework generally means "useless at" because you aren't aware of what you are missing! As Richard suggested, a good book - and working all the way through, doing all the exercises - is a much, much better approach.
Member 12714658 1-Sep-16 7:29am    
When I said self educated I didn't mean that i have never read any book or done any exercise. I've solved a lot of problems with arrays and conditional statements, loops. I specialize in another part of the programming world. I find it hard to work with strings in c# and as we know strings in js are even more of a mess. I wanted to see how this problem is solved. It's always like that when you see it solved it makes sense to you.
OriginalGriff 1-Sep-16 7:40am    
The problem is that unless you follow a book or course pretty closely, you don't pick up on the details - and this kind of "string based" problem is fairly basic - I'd expect it around chapter two or three of most books.
And "seeing how it's solved" doesn't really teach you anything - you don't get to understand why it is like it is, what other options there were and why were they discarded. All you get is a "fait accompli" which gives you "a solution" without any context to say "this is the way you should always do it". And I could probably think of half a dozen other ways to do it if I throw in Linq and suchlike, some of which would be a "better solution" for slightly different environments or conditions. Doing it yourself teaches you a lot more!

Anyway: Which part did you struggle with? How far did you get?
Member 12714658 1-Sep-16 7:55am    
You are absolutely right. I agree with you. I consider enrolling classes this fall. I tried solving it using my approach with the functions that i wrote. (Is it totally wrong?) so i do a foreach(string sentence in sentences){ then what then... i struggle here. Maybe I don't think abstract enough. or should i use a for loop so i can set the first to be the biggest = sentences[0]; how do i check for each sentence using my functions? and then compare. It might be easy but i don't see it.
For self-education, the following book is very useful: .NET Book Zero by Charles Petzold[^].
 
Share this answer
 
Comments
Member 12714658 1-Sep-16 5:48am    
Thank you so much I'll check it out. Really appreciate it. I do front-end but I want to expand my knowledge. I really want to get to the bottom of this problem though. But i kinda don't get it. Hope I don't sound dumb. :\
Richard MacCutchan 1-Sep-16 6:05am    
Not at all, you have obviously made an effort to solve your problem. And remember, just like you, we were all struggling learners once.

As to your problem, it helps us if you try and provide as much detail as possible about the items you are having trouble with. Where necessary, show as much code as needed just to demonstrate the problem.
Member 12714658 1-Sep-16 6:17am    
Honestly I struggle with the whole problem. But I understand that I have a text I have to get that and Split it by .!? then I'm left with an array where the elements of the array are the sentences. Each element is a sentence, right? Then I gotta iterate through these sentences, check for the criteria, and compare each sentence to each of the other sentences. I've created methods for the rules got stuck there. I think i understand the logic but I struggle to execute the whole program in C#. Would it be too much to ask if you could write how it's done from start to finish. I've struggled 2 days with this. I don't want to leave it unsolved.
Richard MacCutchan 1-Sep-16 6:37am    
I don't think I can do that, as I have other calls on my time. Using the simple Array.Sort method will sort your array into alphabetical order. However your criteria are non-standard so you will need to write your own comparer routine to do the sorting, and use this alternative Array.Sort Method (Array, IComparer) (System)[^]. The sample code at that page shows you the basic idea. You will receive two refence objects which will be your two sentences. You need to split them into arrays so you can check for equal words, word count, and character count. It sounds harder than it needs to be, and you can do it in stages. Firstly, just implement the word count compare which is fairly straightforward:

string[] sentenceOne = x.split(' ');
string[] sentenceTwo = y.split(' ');
// < 0 sentenceOne has fewer words
// = 0 both have the same number
// > 0 sentenceOne has more words
return sentenceOne.Length - sentenceTwo.Length;

Note I have not tested this yet, so it may need modifying.

Once you have that working then the other comparison code should be fairly easy.
Member 12714658 1-Sep-16 11:13am    
Thanks the time you spent on this. I appreciate it. You were extremely sweet and helpful.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900