Reporting progress of a LINQ query with background worker, how? - c#

I am exprementing an application which prints out all the possible multiplies of integers in an array that equals size of the array:
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
int progress = 0;
int toCheck = int.Parse(textBox2.Text); //Number to check for
int[] array = new int[toCheck];
//Fill the array
for (int i = 0; i < toCheck; i++)
{
array[i] = i;
bgw.ReportProgress(progress);
progress += 1;
}
var result =
from i1 in array
from i2 in array
where i1 * i2 == toCheck
let square = i1 * i2
select new { i1, i2, square }; //how to report progress here?
foreach (var res in result)
{
textBox1.Text += res.i1 + " * " + res.i2 + " = " + res.square + Environment.NewLine;
bgw.ReportProgress(progress);
progress += 1;
}
}
The linq query itself is very time consuming specially if a big number should be checked for. Is there a way to report the progress of the linq query? Or I should leave linq and do this old-school mode?
Update
This is my whole code. The progressbard does not fill after it got half-full. The first half is when the array is being created, the second part is when code tries to perform the linq query (That is why I think the reporting should be done in the linq query!) pardon my stupidity!!!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace BGWorkerTest
{
public partial class Form1 : Form
{
private PerformanceCounter cpuCounter;
private PerformanceCounter ramCounter;
string[] diagnosticInfo = new string[2] { string.Empty, string.Empty };
int toCheck = 0;
StringBuilder sb;
public Form1()
{
InitializeComponent();
//Diagnostics
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
ramCounter = new PerformanceCounter("Memory", "Available KBytes");
}
private string[] GetDiagnostics()
{
diagnosticInfo[0] = string.Format("{0:0.##}", cpuCounter.NextValue()) + "%";
diagnosticInfo[1] = ramCounter.NextValue() + "MB";
return diagnosticInfo;
}
private void timerStStr_Tick(object sender, EventArgs e)
{
string[] temp = new string[2] { "", ""};
temp = GetDiagnostics();
ststrLabelCpu.Text = temp[0];
ststrLabelMem.Text = temp[1];
}
private void button1_Click(object sender, EventArgs e)
{
ststrProgBar.Minimum = 0;
ststrProgBar.Maximum = 0;
toCheck = int.Parse(textBox2.Text);
ststrProgBar.Minimum = 0;
ststrProgBar.Maximum = toCheck * 2;
ststrProgBar.Step = 1;
//Starts the backgroundworker process asynchronously
bgw.RunWorkerAsync();
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
int progress = 0;
int[] array = new int[toCheck + 1];
for (int i = 0; i < toCheck + 1; i++)
{
array[i] = i;
bgw.ReportProgress(progress);
progress += 1;
}
var result =
from i1 in array
from i2 in array
where i1 * i2 == toCheck
let square = i1 * i2
select new { i1, i2, square };
sb = new StringBuilder();
foreach (var res in result)
{
sb.AppendLine(res.i1 + " * " + res.i2 + " = " + res.square);
bgw.ReportProgress(progress);
progress += 1;
Application.DoEvents();
}
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ststrProgBar.PerformStep();
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("Operation Cancelled");
}
else
{
MessageBox.Show("Operation Completed");
textBox1.Text = sb.ToString();
}
}
}
}

var result =
from int i1 in array
from int i2 in array
where i1 * i2 == toCheck
let square = getSquare(i1,i2)
select new { i1, i2, square };
And then create the method:
public static int getSquare(int i, int i2)
{
Console.WriteLine("busy {0}", i);
return i * i2;
}
just change Console.WriteLine("busy {0}", i); to whatever you want to report

You could try this:
private static IEnumerable<T> ActAsEnumerated<T>(this IEnumerable<T> source, Action<T> act)
{
foreach(var t in source)
{
act(t);
yield return t;
}
}
Usage could be something like:
var pairs = from i1 in array from i2 in array select new { int1 = i1, int2 = i2 };
var reportPairs = pairs.ActAsEnumerated(p => { bgw.ReportProgress(progress); progress += 1; });
var result =
from pair in reportPairs
where pair.int1 * pair.int2 == toCheck
let square = pair.int1 * pair.int2
select new { pair.int1, pair.int2, square };
which is really not very pretty. Really, I think you'd be better off doing this in a non-Linq fashion.

Related

Returning Fibonacci series c#

I need to make a method that returns the nth integer in the fibonacci series, the code that I wrote (edited) did not work, could anyone guide me in my for loop section. I need to use a webform and return the fibonacci series to a specific point.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
{
public partial class Default : System.Web.UI.Page
{
int i, temp;
public void Page_Load(object sender, EventArgs e)
{
}
public int Fibonacci(int x)
{
if (x == 0)
{
return 1;
}
if (x == 1)
{
return 1;
}
else
{
return (Fibonacci(x - 2) + Fibonacci(x - 1));
}
}
public void btSubmit_Click(object sender, EventArgs e)
{
// getting input from user
int num = Convert.ToInt32(txtInput.Text);
// logic for fibonacci series
for (i = 0; i < num; i++)
{
lblResult.Text = Fibonacci(i).ToString();
}
}
}
}
First of all, we, usually, assume
F(0) = 0,
F(1) = 1,
...
F(N) = F(N - 1) + F(N - 2)
See https://oeis.org/A000045
If you want a serie, let's implement a serie (with a help of IEnumerable<T> and yield return):
using System.Linq;
...
//TODO: do you really want int as a return type? BigInteger seems to be a better choice
public static IEnumerable<int> Fibonacci() {
int n_2 = 1; // your rules; or start Fibonacci from 1st, not 0th item
int n_1 = 1;
yield return n_2;
yield return n_1;
while (true) {
int n = n_2 + n_1;
yield return n;
n_2 = n_1;
n_1 = n;
}
}
Having a generator we can easily take num first Fiboncacci numbers (Linq Take):
lblResult.Text = string.Join(", ", Fibonacci().Take(num));
In case num == 7 we'll get
1, 1, 2, 3, 5, 8, 13
If you want an individual item - ElementAt (index is zero based):
// 8
lblResult.Text = Fibonacci().ElementAt(5).ToString();
You can use an integer array to keep the Fibonacci numbers until n and returning the nth Fibonacci number:
public int GetNthFibonacci_Ite(int n)
{
int number = n - 1; //Need to decrement by 1 since we are starting from 0
int[] Fib = new int[number + 1];
Fib[0]= 0;
Fib[1]= 1;
for (int i = 2; i <= number;i++)
{
Fib[i] = Fib[i - 2] + Fib[i - 1];
}
return Fib[number];
}
and then you can call it like this:
GetNthFibonacci_Ite(7);
and it retuns 7th fibonacci number
Your mistake is that you overwrite the Text, rather then add to it. Change it to lblResult.Text += Fibonacci(i).ToString() to append.
Do however note that appending a lot of text from a Loop to a GUI Element is a problematic opreation. You incur a massive overhead reading and writing GUI Elemetns. It does not mater if you only do it once per user Triggered event, but from a loop you will notice it quickly.
It might be better to build the sequence in the code behind, then dispaly it in one go. I even wrote a example code to showcase that issues:
using System;
using System.Windows.Forms;
namespace UIWriteOverhead
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int[] getNumbers(int upperLimit)
{
int[] ReturnValue = new int[upperLimit];
for (int i = 0; i < ReturnValue.Length; i++)
ReturnValue[i] = i;
return ReturnValue;
}
void printWithBuffer(int[] Values)
{
textBox1.Text = "";
string buffer = "";
foreach (int Number in Values)
buffer += Number.ToString() + Environment.NewLine;
textBox1.Text = buffer;
}
void printDirectly(int[] Values){
textBox1.Text = "";
foreach (int Number in Values)
textBox1.Text += Number.ToString() + Environment.NewLine;
}
private void btnPrintBuffer_Click(object sender, EventArgs e)
{
MessageBox.Show("Generating Numbers");
int[] temp = getNumbers(10000);
MessageBox.Show("Printing with buffer");
printWithBuffer(temp);
MessageBox.Show("Printing done");
}
private void btnPrintDirect_Click(object sender, EventArgs e)
{
MessageBox.Show("Generating Numbers");
int[] temp = getNumbers(1000);
MessageBox.Show("Printing directly");
printDirectly(temp);
MessageBox.Show("Printing done");
}
}
}
As another commenter mentioned, you may want to go to some form of Multitasking too. Indeed my first Multitasking learnign experience was a Fibbonacci/Prime Number checker. They are good learning examples for that.
Use the method for Fibonacci:
public int Fibonacci(int n)
{
int a = 0;
int b = 1;
for (int i = 0; i < n; i++)
{
int temp = a;
a = b;
b = temp + b;
}
return a;
}
And replace:
lblResult.Text = Fibonacci(i).ToString();
To:
lblResult.Text += Fibonacci(i).ToString();

Windows Forms Application that sorts a list of random number by using the Gnome Sort algorithm

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
FillArray();
}
private void FillArray() { Random rnd = new Random();
for (int i = 0; i < 29; i++) { myArray[i] = rnd.Next(1, 100); } }
// Array of random integers
static int max = 29;
int[] myArray = new int[max];
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnOne_Click(object sender, EventArgs e)
{
int temp = 0;
for (int outer = 0; outer < max; outer++)
{
for (int i = 0; i < max - 1; i++)
{
if (myArray[i] > myArray[i + 1])
{
// Swap routine
temp = myArray[i + 1];
myArray[i + 1] = myArray[i];
myArray[i] = temp;
}
ShowArray();
Thread.Sleep(100);
}
}
}
private void ShowArray()
{
listBox1.Items.Clear();
for (int i = 0; i < max; i++)
{
listBox1.Items.Add(myArray[i]);
}
}
}
}
// Hi, I'm trying to complete this but having trouble. Not sure if I am even going the right way about it. Any help would be appreciated. Here's the question:
Create a Windows Forms Application that sorts a list of random number by using
the Gnome Sort algorithm. The program must use an Array of 29 integers. After
each iteration the program must display the Array.
Important: The swap routine must be in a separate method that uses arguments
to pass and return two Array elements.
This one is quick and dirty from your code. I start the gnome sort in a new task, so that the GUI not freezed during sorting. And ShowArray will be called using Invoke to avoid CrossThreadException. Take a look first:
// Array of random integers
private const int MAX = 29;
private readonly int[] myArray = new int[MAX];
private void btnOne_Click(object sender, EventArgs e)
{
FillArray();
// Using Task to avoid GUI freeze
Task.Factory.StartNew(() =>
{
for (var outer = 0; outer < MAX; outer++)
{
for (var inner = 0; inner < MAX - 1; inner++)
{
if (myArray[inner] > myArray[inner + 1])
{
Swap(ref myArray[inner + 1], ref myArray[inner]);
}
ShowArray();
Thread.Sleep(50);
}
}
});
}
private void FillArray()
{
var random = new Random();
for (var i = 0; i < MAX; i++)
{
myArray[i] = random.Next(1, 100);
}
}
private void ShowArray()
{
// Using Invoke to avoid CrossThreadException
Invoke(new MethodInvoker(delegate
{
listBox1.Items.Clear();
for (var i = 0; i < MAX; i++)
{
listBox1.Items.Add(myArray[i]);
}
}));
}
private static void Swap(ref int var1, ref int var2)
{
var temp_value = var1;
var1 = var2;
var2 = temp_value;
}

Thread safe assigning of the returned result of a threaded function to a variable

I have a function that takes a variable as a parameter and returns a calculated result. That function splits up into other functions each doing their own calculation. I need the function to run multi threaded.
My code:
for (int i = 0; i < pic.Width; i++)
{
for (int k = 0; k < pic.Height; k++)
{
var localK = k;
var localI = i;
Image bestPic;
new Thread(() =>
{
bestPic = new Bitmap(getBestPic(argb));//THIS IS WHERE THE WRONG VALUES ARE ASSIGNED BECAUSE OF CROSS THREADING
lock (thisLock)
{
g.DrawImage(bestPic, localI * bestPic.Width, localK * bestPic.Height, bestPic.Width, bestPic.Height);
}
}).Start();
}
}
All I need is the function getBestPic to run multi threaded. But how do I run the function getBestPic multi threaded and make the assigning of the returned result to the bestPic variable atomic?
My entire program if needed: This is a montage program.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;
namespace test
{
public partial class Form1 : Form
{
private static readonly Object thisLock = new Object();
private Graphics g;
private Bitmap returnImg;
private Bitmap pic;
private int done = 0;
private int pictureWidthAndLength = 200;
private string inputPicName = "test";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DateTime dtStart = DateTime.Now;
pic = new Bitmap(inputPicName + ".jpg");
//MessageBox.Show(pic.GetPixel(1,1).ToArgb().ToString());
//MessageBox.Show(pic.Width.ToString() + " x " + pic.Height.ToString());
returnImg = new Bitmap(pic.Width * pictureWidthAndLength, pic.Height * pictureWidthAndLength);
using (g = Graphics.FromImage(returnImg))
{
Color clr;
int[] argb = new int[4];
for (int i = 0; i < pic.Width; i++)
{
for (int k = 0; k < pic.Height; k++)
{
clr = pic.GetPixel(i, k);
argb[0] = clr.A;
argb[1] = clr.R;
argb[2] = clr.G;
argb[3] = clr.B;
var localK = k;
var localI = i;
Image bestPic;
if (cbxthreading.Checked)
{
new Thread(() =>
{
bestPic = new Bitmap(getBestPic(argb));
lock (thisLock)
{
g.DrawImage(bestPic, localI * bestPic.Width, localK * bestPic.Height, bestPic.Width, bestPic.Height);
done++;
}
}).Start();
}
else
{
//Single threaded
bestPic = new Bitmap(getBestPic(argb));
g.DrawImage(bestPic, localI * pictureWidthAndLength, localK * pictureWidthAndLength, pictureWidthAndLength, pictureWidthAndLength);
}
//MessageBox.Show(getBestPic(argb));
}
}
if (cbxthreading.Checked)
{
int loopNum = pic.Width * pic.Height;
while (done < loopNum) { }
}
}
DateTime dtEnd = DateTime.Now;
MessageBox.Show((dtEnd - dtStart).ToString());
}
//Get picture that is best suited to replace pixel
private string getBestPic(int[] argb)
{
int numOfpics = 5;
int[] currentBest = new int[2];
currentBest[0] = 255;
currentBest[1] = 150;
for (int i = 0; i < numOfpics; i++)
{
int compare = compareARGB(getAverageRGB(new Bitmap((i + 1).ToString()+".jpg")), argb);
if (compare < currentBest[0])
{
currentBest[0] = compare;
currentBest[1] = i + 1;
}
}
return currentBest[1].ToString() + ".jpg";
}
// smaller the value, closer the camparison
private int compareARGB(int[] one, int[] two)
{
int [] tmp = new int[4];
tmp[0] = Convert.ToInt32(Math.Abs(one[0] - two[0]));
tmp[1] = Convert.ToInt32(Math.Abs(one[1] - two[1]));
tmp[2] = Convert.ToInt32(Math.Abs(one[2] - two[2]));
tmp[3] = Convert.ToInt32(Math.Abs(one[3] - two[3]));
return (tmp[0] + tmp[1] + tmp[2] + tmp[3]);
}
//return int arry with size 4 containing the argb values
private int[] getAverageRGB(Bitmap img)
{
Color clr;
int aplha = 0;
int red = 0;
int green = 0;
int blue = 0;
for (int i = 0; i < img.Width; i++)
{
for (int k = 0; k < img.Height; k++)
{
clr = img.GetPixel(i, k);
aplha += clr.A;
red += clr.R;
green += clr.G;
blue += clr.B;
}
}
aplha = aplha / (img.Width * img.Height);
red = red / (img.Width * img.Height);
green = green / (img.Width * img.Height);
blue = blue / (img.Width * img.Height);
int[] re = new int[] {aplha,red,green,blue};
return re;
}
private void button2_Click(object sender, EventArgs e)
{
returnImg.Save(inputPicName+".bmp");
MessageBox.Show("Done!");
}
}
}
The single thread functionality works, but takes long. The multi threaded functionality also finishes in a third of the time of the single threaded, but the result is not correct.
getBestPic() method runs multi-thread as I understand. But the problem is the argb parameter. You initialize it ones and then overwrite its values in for loops.argb is reference type, so only the reference is passed to getBestPic(), so it's referenced values get changed while processed in getBestPic().
I would try to pass it by Value or move int[] argb = new int[4];line to the inside of the second for loop, so you every time initialize new variable. More on passing reference type params here.
Just create a copy of the Value of your argb in the getBestPic() method and use it instead of using the original one
private string getBestPic(int[] argb)
{
int[] argbCopy = argb.ToArray();
int numOfpics = 5;
int[] currentBest = new int[2];
currentBest[0] = 255;
currentBest[1] = 150;
for (int i = 0; i < numOfpics; i++)
{
int compare = compareARGB(getAverageRGB(new Bitmap((i + 1).ToString()+".jpg")), argbCopy);
if (compare < currentBest[0])
{
currentBest[0] = compare;
currentBest[1] = i + 1;
}
}
return currentBest[1].ToString() + ".jpg";
}

get the value from the dictionary

I am working with Round Robin (RR). I am building random Round-Robin value. I get the time for the RR randomly. In the first run it shows me the current values that i have in the list. but when it goes to run for the second time it just say the index is not presented in the dictionary key. I am trying to fix this problem I have add the time and the quantum tim that the algorithm reduce the value from the dictionary and return back to the dictionary it the value is > 0.
Dictionary<int, int> waytosave = new Dictionary<int, int>();
List<int> randomListxCoor = new List<int>();
List<int> randomListyCoor = new List<int>();
int xCoor;
int yCoor;
Random coor = new Random();
Random setTimeRandom = new Random();
int randomTimeSetting;
int NodeIndex = 0;
Graphics graphDraw;
Graphics drawLine;
int TimeToProcess = 0;
string NodeName = "";
int QuantumTime = 1;
int TotalRouterTime = 0;
int NextNodeToProcess = 0;
public Form1()
{
InitializeComponent();
this.graphDraw = this.panel1.CreateGraphics();
this.drawLine = this.panel1.CreateGraphics();
}
private void btnRun_Click(object sender, EventArgs e)
{
int nodesNumber = (int)this.numNodes.Value;
SolidBrush getNodesDrawn = new SolidBrush(Color.LightYellow);
for (int x = 1; x <= nodesNumber; x++)
{
xCoor = coor.Next(0, 700);
yCoor = coor.Next(0, 730);
if (!randomListxCoor.Contains(xCoor))
{
randomListxCoor.Add(xCoor);
}
if (!randomListyCoor.Contains(xCoor))
{
randomListyCoor.Add(yCoor);
}
randomTimeSetting = setTimeRandom.Next(1, 10);
//Draw the line from main Node to the other Nodes
Pen linePen = new Pen(Color.DarkMagenta, 2);
drawLine.DrawLine(linePen, 350, 360, xCoor, yCoor);
drawLine = this.panel1.CreateGraphics();
graphDraw.FillEllipse(getNodesDrawn, xCoor - 5, yCoor - 5, 15, 12);
//Add the values t the Dictionaries and the List.
waytosave.Add(x, randomTimeSetting);
}
}
private void btnRunTIme_Click(object sender, EventArgs e)
{
this.QuantumTime = (int)this.numQuanrum.Value;
this.ComputeTotalNodeTime();
this.timerRoundRobin.Enabled = true;
}
private void timerRoundRobin_Tick(object sender, EventArgs e)
{
this.NodeIndex = this.GetNextNodeToProcess();
if (this.NodeIndex >= 0)
{
this.waytosave[this.NodeIndex] -= this.QuantumTime;
here at this point it getting crashed. I tried to fixed the number of iteration but if i change the number of iterations it will not go through all the values in the dictionary.
if (this.waytosave[this.NodeIndex] < 0)
{
this.waytosave[this.NodeIndex] = 0;
}
this.NodeName = this.NodeIndex.ToString();
this.TimeToProcess = this.waytosave[this.NodeIndex];
this.txtOutput.Text += "\r\r\n" + " Time Remaining: "
+ this.TimeToProcess
+ "Router name: "
+ this.NodeName;
}
else
{
this.timerRoundRobin.Enabled = false;
this.txtOutput.Text += "\r\r\n" + " Ends x " + TotalRouterTime.ToString();
return;
}
}
private int GetNextNodeToProcess()
{
int NextNodeIndex = -1;
if (NextNodeToProcess >= this.waytosave.Count)
{ NextNodeToProcess = 0; }
for (int i = NextNodeToProcess; i < this.waytosave.Count; i++)
{
if (this.waytosave[i] > 0)
{
NextNodeIndex = i;
break;
}
}
NextNodeToProcess++;
return NextNodeIndex;
}
private void ComputeTotalNodeTime()
{
this.TotalRouterTime = 0;
foreach (KeyValuePair<int, int> item in this.waytosave)
{
this.TotalRouterTime += item.Value;
this.txtOutput.Text += "\r\r\n" + " Time Remaining: "
+ item.Value
+ "Router name: "
+ item.Key;
}
}
I am trying to fix this value from days but i have no success. the problem that in cannot read the first value from the dictionary. How can I solve this problem. Can you please give me some Hence.

matching characters in strings in visual C#

I'm working on visual C#
to calculate the word error rate
I have one textbox for the refrence which is the correct sentance
and one for the hypothesis which is wrong one.
in order to calculate WER I need to calculate :
substitution : the word that has been changed which was my first question
Insert : the words that had been inserted in the sentence
Deleted: the words that had been deleted from the original sentence
For EX:
refrence: This is a NPL program.
hypothesis: it is an NPL cool.
it: substitution
is: correct
an :substitution
NPL:correct
program: deleted
cool: inserted
I tried the algorithm that dasblinkenlight proposed ( thank you so much by the way )
I worked but there is a runtime error I couldn't figure it out, in line
int x= Compute(buffer[j], buffer_ref[i]);
Index was outside the bounds of the array.
and here is my code :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
string [] hyp = new string[20];
string [] refrence = new string[20];
string [] Anser= new string[20];
string[] buffer = new string[20];
string[] buffer_ref = new string[20];
int count = 0; // number of words
string ref2=" " ;
string hyp2 = " ";
string Anser2 = " ";
string buffer2 = " ";
int corecct_c=0;
int corecct_d = 0;
int corecct_i = 0;
//====================================================================
public Form1()
{
InitializeComponent();
for (int i = 0; i <= 19; ++i)
{
hyp[i] = null;
buffer[i] = null;
}
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
refrence = this.textBox2.Text.Split(' ');
buffer_ref = this.textBox2.Text.Split(' ');
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
hyp = this.textBox1.Text.Split(' ');
buffer = this.textBox1.Text.Split(' ');
//hyp = this.textBox1.Text;
// fname1.Add(this.textBox1.Text);
}
public void correct(string[] R)
{
for (int i = 0; (i <= 19) && (R[i] != "."); ++i)
{
if (buffer[i] == refrence[i])
{ buffer[i] = "0";
buffer_ref[i] = "0";
corecct_c = corecct_c + 1;
Anser[i] = "C";
}
}
}
// function that compute 2 strings
public static int Compute(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
// Step 1
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
// Step 2
for (int i = 0; i <= n; d[i, 0] = i++)
{
}
for (int j = 0; j <= m; d[0, j] = j++)
{
}
// Step 3
for (int i = 1; i <= n; i++)
{
//Step 4
for (int j = 1; j <= m; j++)
{
// Step 5
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
// Step 6
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
// Step 7
return d[n, m];
}
public void sub(){
for (int j = 0;j<=19;j++)
{
if (buffer[j].IndexOf("0") != -1)
{
for (int i = 0; i <= 19; i++)
{
if (buffer_ref[j].IndexOf("0") != -1)
{
int x= Compute(buffer[j], buffer_ref[i]);
if (x > 3)
{
buffer[j] = "0";
Anser[j] = "S";
}
}//end if
}
}//end if
}//end for
}// end fun
private void button1_Click(object sender, EventArgs e)
{
correct(refrence);
sub();
for (int i = 0; (i <= 19) && (refrence[i] != "."); ++i)
{
//loop intialize
ref2 = ref2 + " " + refrence[i];
hyp2 = hyp2 + " " + hyp[i];
Anser2 = Anser2 + " " + Anser[i];
buffer2 = buffer2 + " " + buffer[i];
count++;
}
listBox1.Items.Add(" Refrence :" + ref2);
listBox1.Items.Add(" HYp :" + hyp2);
listBox1.Items.Add(" Anser:" + Anser2);
listBox1.Items.Add(" buffer:" + buffer2);
listBox1.Items.Add(count);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
private void label2_Click(object sender, EventArgs e)
{
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}
can you help me please ?
There is a built-in way to test if two lines are identical, but there is no built-in way to tell if two lines are similar. You need to implement an algorithm that measures string similarity, such as the Levenshtein Distance - a very common Edit Distance algorithm. Lines with small edit distance can be declared similar depending on some threshold specific to your requirements.
You'll need to use an algorithm that compares the "distance" between two strings:
The closeness of a match is measured in terms of the number of
primitive operations necessary to convert the string into an exact
match. This number is called the edit distance between the string and
the pattern. The usual primitive operations are:
insertion: cot → coat
deletion: coat → cot
substitution: coat → cost

Categories

Resources