Problem with output of mergesort algorithm - c#

this code gives output but it has one problem that is when user write 5,6 in textbox1 and 7,8 in textbox3 it output 5,6.i know the problem is that when the elements of an array ends,it doesnt print the rest elements of other array,i commented on line of problem.
edited:i used textbox1 and textbox3 for getting the elements of the arrays that user wants to merge
private void button3_Click(object sender, EventArgs e)
{
string[] source = textBox1.Text.Split(',');
string[] source1 = textBox3.Text.Split(',');
int[] nums2 = new int[8];
int[] nums = new int[source.Length];
for (int i = 0; i < source.Length; i++)
{
nums[i] = Convert.ToInt32(source[i]);
}
int[] nums1 = new int[source1.Length];
for (int j = 0; j < source1.Length; j++)
{
nums1[j] = Convert.ToInt32(source1[j]);
}
int x = 0;
int y = 0;
int z = 0;
while (x < nums.Length && y < nums1.Length)
{
if (nums[x] < nums1[y])
{
nums2[z] = nums[x];
x++;
}
else
{
nums2[z] = nums1[y];
y++;
}
z++;
}////----->>it works untill here
while (x > nums.Length)///this mean when the elements of nums end,out the rest of the elements in other textbox but it doesnt do anything,whats the problem ?
{
if (y <= nums1.Length)
{
nums2[z] = nums1[y];
z++;
y++;
}
}
while (y > nums1.Length)
{
if (x <= nums.Length)
{
nums2[z] = nums[x];
z++;
x++;
}
}
string merge = "";
foreach (var n in nums2)
merge += n.ToString() + ",";
textBox4.Text = merge;
}

Do (remove your last while)
while (x < nums.Length)
{
nums2[z] = nums[x];
z++;
x++;
}
while (y < nums1.Length)
{
nums2[z] = nums1[y];
z++;
y++;
}
because you are not aware which array items remained, also your current code doesn't work anyway, because y is not related to nums and vise verse.
Edit: I copy past first while into second while, fix it, remove your last while loops (2 while with if in them) and replace this.

Both your conditions on while (x > nums.Length) and while (y > nums1.Length) don't make sense, since this will never happen.
In the block before, you increment x and y as long as they are smaller than nums.Length or nums1.Length. Therefore those will never become larger (at most equal), thus both conditions will always be false and the "remaining" items will not be merged in.
Note that there are other things wrong in your mergesort implementation, but that's not in the scope of your specific question I guess.

Related

Magic square array filled with random numbers doesn't accept even numbers

I found this code that i need for an assigment, but it only reads odd numbers and i need it to read even numbers too, but i don't know whats wrong. I need it to make the random magic squares go from 1 to 10.
Still very much a beginner and don't understand functions yet, please let me know if there is a way to dolve this.
using System;
class GFG
{
// Function to generate odd sized magic squares
static void generateSquare(int n)
{
int[,] magicSquare = new int[n, n];
// Initialize position for 1
int i = n / 2;
int j = n - 1;
// One by one put all values in magic square
for (int num = 1; num <= n * n;)
{
if (i == -1 && j == n) // 3rd condition
{
j = n - 2;
i = 0;
}
else
{
// 1st condition helper if next number
// goes to out of square's right side
if (j == n)
j = 0;
// 1st condition helper if next number is
// goes to out of square's upper side
if (i < 0)
i = n - 1;
}
// 2nd condition
if (magicSquare[i, j] != 0)
{
j -= 2;
i++;
continue;
}
else
// set number
magicSquare[i, j] = num++;
// 1st condition
j++;
i--;
}
// print magic square
Console.WriteLine("The Magic Square for " + n
+ ":");
Console.WriteLine("Sum of each row or column "
+ n * (n * n + 1) / 2 + ":");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
Console.Write(magicSquare[i, j] + " ");
Console.WriteLine();
}
}
// driver program
public static void Main()
{
Console.WriteLine("Value of n: ");
int n = int.Parse(Console.ReadLine());
// Works only when n is odd
generateSquare(n);
}
}
Step through the program with a debugger. Using n = 2 as an example, on your second loop through the for loop you get to this with i = 1 and j = 1:
if (magicSquare[i, j] != 0)
{
j -= 2;
i++;
continue;
}
And that makes i = 2 on the next loop through. Because there is no 2 index in the array you have created, it crashes when it gets to this same check the next loop.
Presumably odd numbers are working because they are getting floored on division (in the case of n = 5 -> i = 2).
That should be enough to point you in the right direction.

how can I draw a triangle of asterisks using the while statement?

here is the (not working code) and it should print the shape below but its not :
static void Main(string[] args)
{
int i = 1;
int k = 5;
int h = 1;
while (i <= 5)
{
Console.WriteLine("");
while (k > i)
{
Console.Write(" ");
k--;
}
while (h <= i)
{
Console.Write("**");
h++;
}
i++;
}
Console.ReadLine();
}
but when I try to do the same using the while statement the shape gets totally messed up.
any help ?
You have to declare k and h within the loop:
static void Main(string[] args)
{
int i = 1;
while (i <= 5)
{
int k = 5;
int h = 1;
Console.WriteLine("");
while (k > i)
{
Console.Write(" ");
k--;
}
while (h <= i)
{
Console.Write("**");
h++;
}
i++;
}
Console.ReadLine();
}
With your current solution, after first outer loop iteration, inner loops do nothing.
int NumberOfLines = 5;
int count = 1;
while (NumberOfLines-- != 0)
{
int c = count;
while (c-- != 0)
{
Console.Write("*");
}
Console.WriteLine();
count = count + 2;
}
That's it, simplest implementation.
The problem is that i, k and h are initialised before the outermost loop is entered. Within the outer loop k and h are altered by the inner loops. On the second execution of the outer loop k and h have the same values as were left after running the inner loops previously. As i increments in the outer loop, the k loop will not be entered and the h loop will only run once.
Think about what values h and k should have inside the outermost loop on the second execution.
I'll not solve for you just will give you hint only:
Use 3 loop statements
1. for line change
2. for spaces (reverse loop)
3. for printing * (odd series in this case) i.e. 2n-1
check in third while statement h <= 2*i - 1;
and print only one * in place of **
Check here:
http://ideone.com/xOB2OI
Actually I've done this via 'for' loop, z is height and x is equal to length of side.
Isosceles triangle (x>z):
public void Print(int x, int z)
{
var peakStart = x;
var peakEnd = x;
for (int i = 0; i < z; i++)
{
for (int j = 0; j < 2 * x + 1; j++)
{
if (peakStart < 1.5 * x && j >= peakStart && j <= peakEnd)
Console.Write("*");
else
Console.Write(" ");
}
peakStart--;
peakEnd++;
Console.WriteLine("");
}
}

forward and backward search algorithm on an array

I'm working on a simple algorithm problem for practice and i'm trying to figure out why on about 20 percent of test cases it fails. The problem is thus, given an array of ints find the average of all valid ints in the array.
An int is valid if
It is greater than or equal to -273
at least one of the previous two or next two ints are two points away from the current one
if the int is invalid it should not be included in calculating the average. Also, I don't believe the problem wants the solution to be cyclic (not sure though just thought about it while writing this so will try) i.e. if you are at the first int array[0], then there are no previous two ints as opposed to the last two being the previous two in a cyclic array.
my strategy is summed up in the code below:
public double averageTemperature(int[] measuredValues)
{
Queue<int> qLeft = new Queue<int>(2);
Queue<int> qRight = new Queue<int>(2);
double sum = 0d;
int cnt = 0;
for (int i = 0; i < measuredValues.Length; i++)
{
if (measuredValues[i] < -273)
continue;
if (qLeft.Count == 3)
qLeft.Dequeue();
for (int j = i + 1; j < measuredValues.Length; j++)
{
if (qRight.Count == 2)
{
break;
}
qRight.Enqueue(measuredValues[j]);
}
if (b(qLeft, qRight, measuredValues[i]) == true)
{
sum += measuredValues[i];
cnt++;
qLeft.Enqueue(measuredValues[i]);
}
qRight.Clear();
}
if (cnt > 0)
return sum / cnt;
return -300.0;
}
bool b(Queue<int> a, Queue<int> b, int c)
{
foreach (int q in a)
{
if (Math.Abs(q - c) <= 2)
return true;
}
foreach (int w in b)
{
if (Math.Abs(w - c) <= 2)
return true;
}
return false;
}
However, my strategy fails for this test case
{-13, 12, -14, 11, -15, 10, -16, 9, -17, 8, -18, 7, 6, -19, 5, -400, -400, 4, -390, -300, -270, 3, -12, 3, 2}
I don't understand why. I'm i missing something obvious? i know they're might be another more efficient way of solving this but i don't want to try them until i know why my "naive" way does not work.
Well I finally figured out why thanks to you guys. Here is my revised code for those who may find it helpful:
public double averageTemperature(int[] measuredValues)
{
Queue<int> qLeft = new Queue<int>(2);
Queue<int> qRight = new Queue<int>(2);
double sum = 0d;
int cnt = 0;
for (int i = 0; i < measuredValues.Length; i++)
{
if (qLeft.Count == 3)
qLeft.Dequeue();
for (int j = i + 1; j < measuredValues.Length; j++)
{
if (qRight.Count == 2)
{
break;
}
qRight.Enqueue(measuredValues[j]);
}
if (isValid(qLeft, qRight, measuredValues[i]) == true)
{
sum += measuredValues[i];
cnt++;
}
qLeft.Enqueue(measuredValues[i]);
qRight.Clear();
}
if (cnt > 0)
return sum / cnt;
return -300.0;
}
bool isValid(Queue<int> a, Queue<int> b, int c)
{
foreach (int q in a)
{
if (c >=-273 && Math.Abs(q - c) <= 2)
return true;
}
foreach (int w in b)
{
if (c >=-273 && Math.Abs(w - c) <= 2)
return true;
}
return false;
}
try starting at the same point in the nested for() loop when comparing. like this: what do you get when you run it?
public double averageTemperature(int[] measuredValues)
{
Queue<int> qLeft = new Queue<int>(2);
Queue<int> qRight = new Queue<int>(2);
double sum = 0d;
int cnt = 0;
for (int i = 0; i < measuredValues.Length; i++)
{
if (measuredValues[i] < -273)
continue;
if (qLeft.Count == 3)
qLeft.Dequeue();
for (int j = 0; j < measuredValues.Length; j++)
{
if (qRight.Count == 2)
{
break;
}
qRight.Enqueue(measuredValues[j]);
}
if (b(qLeft, qRight, measuredValues[i]) == true)
{
sum += measuredValues[i];
cnt++;
qLeft.Enqueue(measuredValues[i]);
}
qRight.Clear();
}
if (cnt > 0)
return sum / cnt;
return -300.0;
}
bool b(Queue<int> a, Queue<int> b, int c)
{
foreach (int q in a)
{
if (Math.Abs(q - c) <= 2)
return true;
}
foreach (int w in b)
{
if (Math.Abs(w - c) <= 2)
return true;
}
return false;
}
is it adding one each direction to put you two away like you were before?
You are enqueuing into qLeft only when the current value in the array is valid, but this is not right. You need to enqueue into qLeft at each iteration of the outer for-loop that is being controlled by i.
See the following code:
for (int i = 0; i < measuredValues.Length; i++)
{
if (measuredValues[i] < -273)
continue;
if (qLeft.Count == 3)
qLeft.Dequeue();
for (int j = i + 1; j < measuredValues.Length; j++)
{
if (qRight.Count == 2)
{
break;
}
qRight.Enqueue(measuredValues[j]);
}
if (b(qLeft, qRight, measuredValues[i]) == true)
{
sum += measuredValues[i];
cnt++;
}
qLeft.Enqueue(measuredValues[i]); // YOU NEED TO ENQUEUE INTO qLeft EACH TIME REGARDLESS OF IT IS VALID OR INVALID
qRight.Clear();
}

Two Dimensional List Loop

I am looping through a List<List<Shape>> object and checking if the horizontally and vertically adjacent objects are the same:
for (int x = 0; x < grid.Columns.Count; x++)
{
for (int y = 0; y < grid.Columns[x].Count; y++)
{
if (y != grid.Columns[x].Count - 1)
{
if (grid.Columns[x][y].Column == grid.Columns[x][y + 1].Column)
{
if (!shapesToDestroy.Contains(grid.Columns[x][y]))
{
shapesToDestroy.Add(grid.Columns[x][y]);
}
if (!shapesToDestroy.Contains(grid.Columns[x][y + 1]))
{
shapesToDestroy.Add(grid.Columns[x][y + 1]);
}
}
}
if (x != grid.Columns.Count - 1)
{
if (grid.Columns[x][y].Column == grid.Columns[x + 1][y].Column)
{
if (!shapesToDestroy.Contains(grid.Columns[x][y]))
{
shapesToDestroy.Add(grid.Columns[x][y]);
}
if (!shapesToDestroy.Contains(grid.Columns[x + 1][y]))
{
shapesToDestroy.Add(grid.Columns[x + 1][y]);
}
}
}
}
}
However, I always seem to get a ArgumentOutOfRange on
if (grid.Columns[x][y].Column == grid.Columns[x][y + 1].Column)
and
if (grid.Columns[x][y].Column == grid.Columns[x + 1][y].Column)
Before indexing these, I am performing a check as you can see to make sure that I do not get a ArgumentOutOfRange, but here I am. When I look at the index which is being + 1, it appears to be well under the size of the collection.
Can anyone see the obvious mistake and where I am going horribly wrong?
UPDATE
I updated the code by changing the checks for X and Y to:
if (x < grid.Columns.Count - 1)
and
if (y < grid.Columns[x].Count - 1)
I still get the same error.
FYI - The size of the collection is always the same. The size is: X = 5 and Y = 10
if (x != grid.Columns.Count - 1)
should be
if (x < grid.Columns.Count - 1)
since y is iterated from 0 to the maximum index of the list the operation
grid.Columns[x][y + 1]
will attempt to access an element with a higher index than what is currently in the list. If you want to keep the code above you should change the loop to only iterate to
for (int x = 0; x < grid.Columns.Count-1; x++)
{
for (int y = 0; y < grid.Columns[x].Count-1; y++)
{
}
}
I tried running your code, and i think you could get the functionality that you are looking for stripping it down to:
for (int x = 0; x < grid.Count; x++)
{
for (int y = 0; y < grid[x].Count; y++)
{
if (grid[x].Count > y && grid[x][y] == grid[x][y + 1])
{
if (!shapesToDestroy.Contains(grid[x][y]))
{
shapesToDestroy.Add(grid[x][y]);
}
if (!shapesToDestroy.Contains(grid[x][y + 1]))
{
shapesToDestroy.Add(grid[x][y + 1]);
}
}
if (grid.Count > x && grid[x+1].Count > y && grid[x][y] == grid[x + 1][y])
{
if (!shapesToDestroy.Contains(grid[x][y]))
{
shapesToDestroy.Add(grid[x][y]);
}
if (!shapesToDestroy.Contains(grid[x + 1][y]))
{
shapesToDestroy.Add(grid[x + 1][y]);
}
}
}
}
EDIT
Could also remove the second if in both of the cases since you have already tested that they are equal, doesn't really matter though since it won't change the result. Would just improve performance a tiny bit
it seems that your if condition does not seems correct
Try this
if (y < grid.Columns[x].Count - 1)
instead of
if (y != grid.Columns[x].Count - 1)
Probably your arrays are jagged. And the individual subarrays do not have the same length.
That could be a reason for getting an ArgumentOutOfRange-Exception in:
if (grid.Columns[x][y].Column == grid.Columns[x + 1][y].Column)
Why not use a foreach loop? then you won't have problems with the array out of bounds? Unless you are going for speed. You can use and then nest them as above.
foreach (int key in values.Keys)
{
Console.WriteLine("{0} is assigned to key: {1}", values[key], key);
}

Matrix Row - QuickSort recursion problem

I've adapted QuickSort Method to sort Array's Row.
Here's the code:
That one works fine
static void QuickSort(int lowBound, int highBound, int[] a)
{
int temp = 0;
int x = random.Next(lowBound, highBound);
int pivot = a[x];
int i = lowBound;
int j = highBound;
do
{
while (a[i] < pivot) i++;
while (pivot < a[j]) j--;
if (i <= j)
{
temp = a[i]; //changes an element smaller than the pivot...
a[i] = a[j];//... with the greater one
a[j] = temp;
i++; j--;
}
}
while (i <= j);
if (lowBound < j) { QuickSort(lowBound, j, a); }//recursion
if (i < highBound){ QuickSort(i,highBound, a); }
}
Here's the problematic method
static void QuickSortMatrix(int[,] a)
{
int n = a.GetLength(0);
int m = a.GetLength(1);
for (int i = 0; i < n; i++)
{
QuickSortRow(0, m - 1, i, a);
}
for (int j = 0; j < m; j++)
{
QuickSortRow(0, n - 1, j, a);
}
}
static void QuickSortRow(int lowBound, int highBound, int row, int[,] a)
{
int temp = 0;
int x = random.Next(lowBound, highBound);
int pivot = a[row,x];
int p = lowBound;
int q = highBound;
do
{
while (a[row,p] < pivot) p++;
while (pivot < a[row,q]) q--;
if (p <= q)
{
temp = a[row,p];
a[row,p] = a[row,q];
a[row,q] = temp;
p++; q--;
}
}
while (p <= q);
if (lowBound < q) { QuickSortRow(lowBound, q, row, a); }
if (p < highBound) { QuickSortRow(p, highBound,row, a); }
}
At first when the "for" loop is executed everything's ok bur for some reason when executed recursively the row that should be constant when calling the method goes outside the matrix boundaries.
Here's my array and rows reaches value of 4
int[,] matrix =
{
{7,8,9,10,11,5},
{3,6,4,16,22,4},
{7,9,17,8,3,21},
{24,7,11,19,3,4}
};
I hope my explanation was clear enough.
Could anybody advise me? What I'm missing here?
Thank you for your kind help!
BR
Stephan
n is the number of rows in the matrix (4)
m is the number of columns in the matrix (6)
In your second loop you are going 0..m and passing that value to the row parameter. It blows up because there are more columns in the matrix than rows. i.e. It tries to read matrix[4, 0].
Note: as far as I can tell you don't need the second loop because your rows are already sorted after the first loop. Remove that and it won't throw an exception.

Categories