Character Counter using Array List - c#

I need to design a program that reads in an ASCII text file and creates an output file that contains each unique ASCII character and the number of times it appears in the file. Each unique character in the file must be represented by a character frequency class instance. The character frequency objects must be stored in an array list. My code is below:
using System.IO;
using System;
using System.Collections;
namespace ASCII
{
class CharacterFrequency
{
char ch;
int frequency;
public char getCharacter()
{
return ch;
}
public void setCharacter(char ch)
{
this.ch = ch;
}
public int getfrequency()
{
return frequency;
}
public void setfrequency(int frequency)
{
this.frequency = frequency;
}
static void Main()
{
string OutputFileName;
string InputFileName;
Console.WriteLine("Enter the file path");
InputFileName = Console.ReadLine();
Console.WriteLine("Enter the outputfile name");
OutputFileName = Console.ReadLine();
StreamWriter streamWriter = new StreamWriter(OutputFileName);
string data = File.ReadAllText(InputFileName);
ArrayList al = new ArrayList();
//create two for loops to traverse through the arraylist and compare
for (int i = 0; i < data.Length; i++)
{
int k = 0;
int f = 0;
for (int j = 0; j < data.Length; j++)
{
if (data[i].Equals(data[j]))
{
f++;
if (i > j) { k++; }
}
}
al.Add(data[i] + "(" + (int)data[i] + ")" + f + " ");
foreach (var item in al)
{
streamWriter.WriteLine(item);
}
}
streamWriter.Close();
}
}
}
When I run the program, the program does not stop running and the output file keeps getting larger until it eventually runs out memory and I get an error stating that. I am not seeing where the error is or why the loop won't terminate. It should just count the characters but it seems to keep looping and repeating counting the characters. Any help?

Try this approach :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace yourNamespace
{
class Char_frrequency
{
Dictionary<Char, int> countMap = new Dictionary<char, int>();
public String getStringWithUniqueCharacters(String input)
{
List<Char> uniqueList = new List<Char>();
foreach (Char x in input)
{
if (countMap.ContainsKey(x))
{
countMap[x]++;
}
else
{
countMap.Add(x, 1);
}
if (!uniqueList.Contains(x))
{
uniqueList.Add(x);
}
}
Char[] uniqueArray = uniqueList.ToArray();
return new String(uniqueArray);
}
public int getFrequency(Char x)
{
return countMap[x];
}
}
}
This might not be the ideal solution. But you can use these methods

Related

C# Sliding Window Algorithm

So i have to sent a message from a Sender to a Destination(Shown in main class) by specifing how many letters i wanna sent (the size variable).When the laters left are less than letters i wanna sent,it automaticaly sent how many i have left,and after the algorithm stops;
The problem is when the message i supossely sent is 9 characters long,and when i wanna sent 6 characters and another 3 it throws me an error (System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'
)
using System;
using System.Text;
using System.Threading;
namespace homework
{
internal class slidingWindow
{
private string name;
private StringBuilder message = new StringBuilder();
private bool isSource = false;
private int fin = 0;
public slidingWindow(string name, bool isSource)
{
this.name = name;
this.isSource = isSource;
}
public void messageSet(string _message)
{
if (isSource == true) message.Append(_message);
else Console.WriteLine("Is not source");
}
public void sendMessage(slidingWindow destination)
{
int counter= 0;
Console.WriteLine("Specify the size of data sent: ");
int size = Convert.ToInt32(Console.ReadLine()); //the size of how manny letters i should send
int countCharacterSent=size;
for (int x = 0; x < message.Length+(message.Length%size); x = x + size)
{
counter++;
for (int y = 0; y < size; y++)
{
if (x + size > message.Length + (message.Length % size)) { size=size-(message.Length%size); countCharacterSent = message.Length; }
else {destination.message.Append(message[x + y]); }
}
Console.WriteLine("Sennder---- " + destination.message + " ----->Destination" + " (" + counter+ ")"+ " Characters sent: "+size+ " Characters received: "+countCharacterSent+ '\n');
Thread.Sleep(TimeSpan.FromSeconds(1));
countCharacterSent = countCharacterSent + size;
}
fin = 1;
if (message.Length % size != 0) destination.fin = 1;
destination.print();
}
public void print()
{
Console.WriteLine("Destination has receveid the message: " + message+" FIN: "+fin);
}
}
and the main class
using System;
namespace homework
{
class main
{
static void Main(string[] args)
{
while (true)
{
int option = 0;
slidingWindow a = new slidingWindow("Sender", true);
a.messageSet("exampless");
slidingWindow b = new slidingWindow("Destination", false);
a.sendMessage(b);
Console.WriteLine("If you want to exit write 1:"+'\n');
option = Convert.ToInt32(Console.ReadLine());
if (option == 1) break;
}
}
}
example:
input:
message='example'
size=3;
output:
exa
mpl
e
Honestly I can see you try hard (too hard) to handle the limit case of the last block that can just not meet the expect size.
Since you do this in dotnet C#, and depending on the version you will see you have many different options....
Especially to create a batch of x out of a simple sequence....
here is a homemade version of things you will find for free in libraries like moreLinq and probably in latest Linq lib..
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
public static class LinqExtensions
{
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size)
{
return source
.Select( (c, i) => (c, index : i))
.Aggregate(
new List<List<T>>(),
(res, c) =>
{
if (c.index % size == 0)
res.Add(new List<T> { c.c });
else
res.Last().Add(c.c);
return res;
});
}
}
public class Program
{
public static void Main(string[] args)
{
var test = "xxxxxxxxxxx".AsEnumerable();
var blocks = test
.Batch(3)
.Select(b=> new string(b.ToArray()));
blocks.ToList().ForEach(System.Console.WriteLine);
}
}

Check if string contains all required characters

I need to import a number of characters in a string format with a comma and check if a string is valid by containing all of them. The string must be in a format like that "AB2345CD" . This is the code I have for now but i dont know how to check if it is valid by containing all of the input characters and every digit between 0 and 9.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace License_Plates
{
class Program
{
static void Main(string[] args)
{
string input = Console.ReadLine();
var allowedCharacters = input.ToList();
int platesToValidate = int.Parse(Console.ReadLine());
List<string> plateNumbers = new List<string>();
for (int i = 0; i < platesToValidate; i++)
{
string plate = Console.ReadLine();
plateNumbers.Add(plate);
}
List<string> validNumbers = new List<string>();
foreach (var number in plateNumbers)
{
if (number.Contains(allowedCharacters.ToString()))
{
validNumbers.Add(number);
}
}
for (int i = 0; i < validNumbers.Count; i++)
{
Console.WriteLine(i);
}
}
}
}
Check if string contains all required characters
you could use the linq extension All:
var allowedstring = "A,B,C,D";
var allowednumber = "0,1,2,3,4,5,6,7,8,9";
var test1 = "ABC0";
var test2 = "AZ9";
var allowed = $"{allowedstring}{allowednumber}".Replace(",", "");
Console.WriteLine(test1.All(c => allowed.Contains(c))); //True
Console.WriteLine(test2.All(c => allowed.Contains(c))); //False

C# Reading from file, removing numbers and special characters and add to hashtable

The task is to read from a file, retrieve words (no numbers or special characters) and adding it to a hash table. If the same word (key) already exist in the hash table, update the frequency of the word(value) +1.
So far in the code blow, all text is retrieved from the file including words with numbers and special characters into a string array "words".
I would like to update the values based on a regex to only keep words with letters, in lowercase.
I have tried the regex in all different ways but it does not work. The Split() method only allows individual characters to be removed. (eventually, this code will need to be applied to 200 files with unknown amount of special characters and numbers).
Is there a clean way to read the file, save only words and omit special characters and numbers?
this is what i have so far:
using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
String myLine;
String[] words;
Hashtable hashT = new Hashtable();
TextReader tr = new StreamReader("C:\\file including numbers and spacial charecters.txt");
while ((myLine = tr.ReadLine()) != null)
{
words = myLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string pattern = #"^[a - z] +$";
Regex term = new Regex(pattern);
for (int i = 0; i < words.Length; i++)
{
Console.WriteLine(words[i]);
words[i] = Regex.Replace(words[i], term, "");
if (hashT.ContainsKey(words[0]))
{
hashT[words[i]] = double.Parse(hashT[words[i]].ToString()) + 1;
}
else
{
hashT.Add(words[i], 1.00);
}
}
foreach (String word in hashT.Keys)
{
Console.WriteLine(word + " " + hashT[words]);
}
Console.ReadKey();
}
}
}
}
try this
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
//file content read form your file
string fileContent = #"Hello Wor1d
fun f1nd found
";
//split file content to lines
string[] line = fileContent.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
Regex r = new Regex("[a-zA-Z]+");
List<string> matchesList = new List<string>();
for (int i = 0; i < line.Length; i++)
{
//split line to string, like Hello Wor1d => string[]{ Hello, Wor1d }
string[] lineData = line[i].Split(' ');
for (int j = 0; j < lineData.Length; j++)
{
string str = lineData[j];
//get matches form string
//if count == 0, string is not include words
//if count > 1 string is have some not words, because Wor1d have 2 matches => Wor and d
if (r.Matches(str).Count == 1)
{
matchesList.Add(str);
}
}
}
for (int i = 0; i < matchesList.Count; i++)
{
Console.WriteLine($"{matchesList[i]} is ok");
}
Console.ReadLine();
}
}
}

c# from string with letters and numbers how to read and seperate into and place in array

i need to write a program where from a user determined file i need to find which poker hand type is input into the program. i have where i can count the number of each suit in the hand but i cant think of way to find the numbers of the cards in a way it can have double digits. it would be preferable if it was in an array but am focusing on getting it into a string for now. im mostly wanting to count each card value so then i can have if statements of the criteria for each hand to find the inputed hand matches what the hand is supposed to be
the layout for the cards in each hand are like the following
file title: Flush.txt
file content: C 6 C 9 C 10 C 11 C 12
this is all the code i have for the program right now
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace pokertask
{
class Program
{
static void Main(string[] args)
{
string fileName = "";
string fileContent = "";
int clubSuit = 0;
int heartSuit = 0;
int spadeSuit = 0;
int diamondSuit = 0;
//int[] array = new int[5];
string cardNum = "";
//read text file
Console.WriteLine("type the file name of the hand that you are testing including its file extension.");
fileName = Console.ReadLine();
try
{//open and read selected file
StreamReader inFile = new StreamReader(fileName);
fileContent = inFile.ReadLine();
inFile.Close();
Console.WriteLine("{0}", fileContent);
Console.ReadLine();
}
catch
{//response if failed
Console.WriteLine("File Handling error has occured. Press any button to close the program.");
Console.ReadLine();
}
//display
foreach (char C in fileContent)
{
if ( C == 'C')
{
clubSuit ++;
}
}
foreach (char S in fileContent)
{
if (S == 'S')
{
spadeSuit++;
}
}
foreach (char H in fileContent)
{
if (H == 'H')
{
heartSuit++;
}
}
foreach (char D in fileContent)
{
if (D == 'D')
{
diamondSuit++;
}
}
Console.WriteLine(" number of clubs {0}", clubSuit);
Console.WriteLine(" number of spades {0}", spadeSuit);
Console.WriteLine(" number of hearts {0}", heartSuit);
Console.WriteLine(" number of diamonds {0}", diamondSuit);
Console.ReadLine();
cardNum = fileContent.Trim('C','H','D','S');
Console.WriteLine("{0}", cardNum);
Console.ReadLine();
}
}
}
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string input = "C 6 C 9 C 10 C 11 C 12";
string[] array = input.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < 10; i += 2)
{
string suit = array[i];
string rank = array[i + 1];
Console.WriteLine("Card {0} , Suit : {1}, Rank : {2}" , i/2, suit, rank);
}
Console.ReadLine();
}
}
}
​
As already suggested by others, it is much better to use a more flexible format like XML and JSON, but if you are stuck with this format:
You could split the input by spaces and read the data in groups of two:
var split = fileContent.Split(' ');
var cards = new List<KeyValuePair<string, int>>();
for (var i = 0; i < split.Length; i += 2)
{
var suit = split[i];
var digits = int.Parse(split[i + 1]);
cards.Add(new KeyValuePair<string, int>(suit, digits));
}
// TODO: read the input from cards list
The cards list defined up there is made up of KeyValuePairs where the Key is the suit (e.g. "C") and Value is the digit (e.g. 9)
First I would recommend using a container for your card suits. List<int> will do, but you may need something more depending on your needs (Dict? class?). I don't think this solution is ideal and there's no error checking, but it assumes the layout you show in your example file.
var clubs = new List<int>();
var hearts = new List<int>();
var diamonds = new List<int>();
var spades = new List<int>();
Then use a code similar to the snippet shown below to parse your suits.
var parts = fileContent.Split(' ');
for (int i = 0; i < parts.Length; i+=2)
{
if (parts[i] == "C")
{
clubs.Add(Int32.Parse(parts[i+1]));
}
}
Full program below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Poker
{
class Program
{
static void Main(string[] args)
{
var clubs = new List<int>();
var hearts = new List<int>();
var diamonds = new List<int>();
var spades = new List<int>();
var fileContent = "C 6 C 9 C 10 C 11 C 12";
var parts = fileContent.Split(' ');
for (int i = 0; i < parts.Length; i += 2)
{
switch (parts[i])
{
case "C": clubs.Add(Int32.Parse(parts[i + 1])); break;
case "H": hearts.Add(Int32.Parse(parts[i + 1])); break;
case "D": diamonds.Add(Int32.Parse(parts[i + 1])); break;
case "S": spades.Add(Int32.Parse(parts[i + 1])); break;
default:
break;
}
}
Console.WriteLine("Clubs: {0}", string.Join(" ", clubs));
Console.WriteLine("Hearts: {0}", string.Join(" ", hearts));
Console.WriteLine("Diamonds: {0}", string.Join(" ", diamonds));
Console.WriteLine("Spades: {0}", string.Join(" ", spades));
Console.ReadLine();
}
}
}

getting the best record from a file

I have a file with the following text inside
mimi,m,70
tata,f,60
bobo,m,100
soso,f,30
I did the reading from file thing and many many other methods and functions, but how I can get the best male name and his grade according to the grade.
here is the code I wrote. Hope it's not so long
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace practice_Ex
{
class Program
{
public static int[] ReadFile(string FileName, out string[] Name, out char[] Gender)
{
Name = new string[1];
int[] Mark = new int[1];
Gender = new char[1];
if (File.Exists(FileName))
{
FileStream Input = new FileStream(FileName, FileMode.Open, FileAccess.Read);
StreamReader SR = new StreamReader(Input);
string[] Current;
int Counter = 0;
string Str = SR.ReadLine();
while (Str != null)
{
Current = Str.Split(',');
Name[Counter] = Current[0];
Mark[Counter] = int.Parse(Current[2]);
Gender[Counter] = char.Parse(Current[1].ToUpper());
Counter++;
Array.Resize(ref Name, Counter + 1);
Array.Resize(ref Mark, Counter + 1);
Array.Resize(ref Gender, Counter + 1);
Str = SR.ReadLine();
}
}
return Mark;
}
public static int MostFreq(int[] M, out int Frequency)
{
int Counter = 0;
int Frequent = 0;
Frequency = 0;
for (int i = 0; i < M.Length; i++)
{
Counter = 0;
for (int j = 0; j < M.Length; j++)
if (M[i] == M[j])
Counter++;
if (Counter > Frequency)
{
Frequency = Counter;
Frequent = M[i];
}
}
return Frequent;
}
public static int Avg(int[] M)
{
int total = 0;
for (int i = 0; i < M.Length; i++)
total += M[i];
return total / M.Length;
}
public static int AvgCond(char[] G, int[] M, char S)
{
int total = 0;
int counter = 0;
for (int i = 0; i < G.Length; i++)
if (G[i] == S)
{
total += M[i];
counter++;
}
return total / counter;
}
public static int BelowAvg(int[] M, out int AboveAvg)
{
int Bcounter = 0;
AboveAvg = 0;
for (int i = 0; i < M.Length; i++)
{
if (M[i] < Avg(M))
Bcounter++;
else
AboveAvg++;
}
return Bcounter;
}
public static int CheckNames(string[] Name, char C)
{
C = char.Parse(C.ToString().ToLower());
int counter = 0;
string Str;
for (int i = 0; i < Name.Length - 1; i++)
{
Str = Name[i].ToLower();
if (Str[0] == C || Str[Str.Length - 1] == C)
counter++;
}
return counter;
}
public static void WriteFile(string FileName, string[] Output)
{
FileStream FS = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter SW = new StreamWriter(FS);
for (int i = 0; i < Output.Length; i++)
SW.WriteLine(Output[i]);
}
static void Main(string[] args)
{
int[] Mark;
char[] Gender;
string[] Name;
string[] Output = new string[8];
int Frequent, Frequency, AvgAll, MaleAvg, FemaleAvg, BelowAverage, AboveAverage, NamesCheck;
Mark = ReadFile("c:\\IUST1.txt", out Name, out Gender);
Frequent = MostFreq(Mark, out Frequency);
AvgAll = Avg(Mark);
MaleAvg = AvgCond(Gender, Mark, 'M');
FemaleAvg = AvgCond(Gender, Mark, 'F');
BelowAverage = BelowAvg(Mark, out AboveAverage);
NamesCheck = CheckNames(Name, 'T');
Output [0]= "Frequent Mark = " + Frequent.ToString();
Output [1]= "Frequency = " + Frequency.ToString();
Output [2]= "Average Of All = " + AvgAll.ToString();
Output [3]= "Average Of Males = " + MaleAvg.ToString();
Output [4]= "Average Of Females = " + FemaleAvg.ToString();
Output [5]= "Below Average = " + BelowAverage.ToString();
Output [6]= "Above Average = " + AboveAverage.ToString();
Output [7]= "Names With \"T\" = " + NamesCheck.ToString();
WriteFile("c:\\Output.txt", Output);
}
}
}
Well, I like LINQ (update: excluded via comments) for querying, especially if I can do it without buffering the data (so I can process a huge file efficiently). For example below (update: removed LINQ); note the use of iterator blocks (yield return) makes this fully "lazy" - only one record is held in memory at a time.
This also shows separation of concerns: one method deals with reading a file line by line; one method deals with parsing a line into a typed data record; one (or more) method(s) work with those data record(s).
using System;
using System.Collections.Generic;
using System.IO;
enum Gender { Male, Female, Unknown }
class Record
{
public string Name { get; set; }
public Gender Gender { get; set; }
public int Score { get; set; }
}
static class Program
{
static IEnumerable<string> ReadLines(string path)
{
using (StreamReader reader = File.OpenText(path))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
static IEnumerable<Record> Parse(string path)
{
foreach (string line in ReadLines(path))
{
string[] segments = line.Split(',');
Gender gender;
switch(segments[1]) {
case "m": gender = Gender.Male; break;
case "f": gender = Gender.Female; break;
default: gender = Gender.Unknown; break;
}
yield return new Record
{
Name = segments[0],
Gender = gender,
Score = int.Parse(segments[2])
};
}
}
static void Main()
{
Record best = null;
foreach (Record record in Parse("data.txt"))
{
if (record.Gender != Gender.Male) continue;
if (best == null || record.Score > best.Score)
{
best = record;
}
}
Console.WriteLine("{0}: {1}", best.Name, best.Score);
}
}
The advantage of writing things as iterators is that you can easily use either streaming or buffering - for example, you can do:
List<Record> data = new List<Record>(Parse("data.txt"));
and then manipulate data all day long (assuming it isn't too large) - useful for multiple aggregates, mutating data, etc.
This question asks how to find a maximal element by a certain criterion. Combine that with Marc's LINQ part and you're away.
In the real world, of course, these would be records in a database, and you would use one line of SQL to select the best record, ie:
SELECT Name, Score FROM Grades WHERE Score = MAX(Score)
(This returns more than one record where there's more than one best record, of course.) This is an example of the power of using the right tool for the job.
I think the fastest and least-code way would be to transform the txt to xml and then use Linq2Xml to select from it. Here's a link.
Edit: That might be more work than you'd like to do. Another option is to create a class called AcademicRecord that has properties for the persons name gender etc. Then when you read the file, add to a List for each line in the file. Then use a Sort predicate to sort the list; the highest record would then be the first one in the list. Here's a link.
Your assignment might have different requirements, but if you only want to get "best male name and grade" from a file you described, a compact way is:
public String FindRecord()
{
String[] lines = File.ReadAllLines("MyFile.csv");
Array.Sort(lines, CompareByBestMaleName);
return lines[0];
}
int SortByBestMaleName(String a, String b)
{
String[] ap = a.Split();
String[] bp = b.Split();
// Always rank male higher
if (ap[1] == "m" && bp[1] == "f") { return 1; }
if (ap[1] == "f" && bp[1] == "m") { return -1; }
// Compare by score
return int.Parse(ap[2]).CompareTo(int.Parse(bp[2]));
}
Note that this is neither fast nor robust.

Categories