C# Dynamic programming conversion - c#

Hi I have a task to convert exponential code into linear, but I have no idea how to do it. Could you give me any tips or point me in the right direction?
Here's the code:
int F (int m, int n)
{
if(n == 0)
{
return m;
}
else if(m == 0 && n > 0)
{
return n;
}
else
{
int[] array = { 1 + F(m - 1, n), 1 + F(m, n - 1), D(m, n) + F(m - 1, n - 1) };
return array.Min();
}
}
int D(int i, int f)
{
if(x[i] == y[f])
{
return 1;
}
else
{
return 0;
}
}
Update:
Am I going in the right direction? So far it works only with m=0,1,2 and n=0,1,2. How do I fill all the values if let's say, I give m = 10 and n = 20?
int Fdp(int m, int n)
{
fdin[m, 0] = m;
for(int i = 0; i <= n; i++)
{
fdin[0, i] = n;
}
if (n == 0)
{
return m;
}
else if (m == 0 && n > 0)
{
return n;
}
else
{
int[] temp = { 1 + fdin[m-1, n], 1+ fdin[m,n-1], D(m,n) + fdin[m-1,n-1] };
fdin[m, n] = temp.Min();
return temp.Min();
}
}

Solved it.
static int Fdp(int m, int n)
{
for (int i = 0; i <= m; i++)
{
fdin[i, 0] = i;
for (int j = 1; j <= n; j++)
{
if(i == 0)
{
fdin[i, j] = j;
}
else
{
int[] temp = new int[] { 1 + fdin[i - 1, j], 1 + fdin[i, j - 1], D(i, j) + fdin[i - 1, j - 1] };
fdin[i, j] = temp.Min();
}
}
}
return fdin[m,n];
}

Related

Binary Insertion Sort using recursion - working for one array and not another?

Doing a Binary Insertion Sort and my recursion is backfiring on me when I return my array. When I use the array : { 3, 1, 2, 4 } I get back 1,2,3,4.
When I use the array : { 3, 7, 2, 4 } the recursion causes a StackOverflow.
Where am I going wrong?
p.s Sorry about the console.writelines in my code it helps me check whats going on as I develop
The C# code is per the following snippet:
int[] a = new int[] { 3, 1, 2, 4 }; //Array to be sorted
int MiddlePointer = 0;
int LeftPointer = 0;
int RightPointer = 0;
int i = 1; //First number is 'sorted' so focus on second number
BinaryInsertSort(a, MiddlePointer, LeftPointer, RightPointer, i);
void BinaryInsertSort(int[] a, int MiddlePointer, int LeftPointer, int RightPointer, int i)
{
if (i == a.Length) //This should EXIT the algorithm once all of the numbers are sorted
{
return;
}
if (MiddlePointer == 0 & LeftPointer == 0 & RightPointer == 0) //If this is the first iteration, only the first number is 'sorted' and all of the pointers are the same
{
if (a[i] > a[MiddlePointer]) //If the next number is higher then just raise the RightPointer
{
RightPointer = i;
}
else //If the next number is lower, the 'sorted' values need to be 'shifted' one place to the right
{
RightPointer = i;
int temp = a[i];
for (int j = RightPointer; j > LeftPointer; j--)
{
a[j] = a[j - 1];
}
a[LeftPointer] = temp;
}
// i++; //At this point one number has been sorted
}
else
{
a = Testing(a, MiddlePointer, LeftPointer, RightPointer, i);
}
foreach (int x in a)
{
Console.WriteLine(x);
}
Console.ReadLine();
i++;
BinaryInsertSort(a, MiddlePointer, LeftPointer, RightPointer, i);
}
int[] Testing(int[] a, int MiddlePointer, int LeftPointer, int RightPointer,int i) //This method should find the space where the number should be inserted and return the updated array
{
if(MiddlePointer == RightPointer & RightPointer == LeftPointer)
{
Console.WriteLine($"{a[i]} has not been found");
if (a[i] > a[MiddlePointer])
{
RightPointer = i;
}
else
{
RightPointer = i;
int temp = a[i];
for (int j = RightPointer; j > 0; j--)//move up values
{
a[j] = a[j - 1];
}
a[LeftPointer] = temp;
}
}
else if (a[i] > a[MiddlePointer])
{
Console.WriteLine($"{a[i]} is greater than {a[MiddlePointer]}");
LeftPointer = MiddlePointer + 1;
MiddlePointer = (LeftPointer + RightPointer) / 2;
Testing(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (a[i] < a[MiddlePointer])
{
Console.WriteLine($"{a[i]} is less than {a[MiddlePointer]}");
RightPointer = MiddlePointer - 1;
MiddlePointer = (LeftPointer + RightPointer) / 2;
Testing(a, MiddlePointer, LeftPointer, RightPointer, i);
}
return a;
}
Basically I went back to scratch and did a binary search first. This really helped in my previous attempt so I really made sure this worked before moving onto binary insertion sort. From this point I modified the code bit by bit and tried loads of different data sets to see if anything changed. Using breakpoints really helped. I needed to go through and 'follow' the changing variables to see where errors were being made. I also used Console.ReadLine and Console.WriteLine to follow where my logic was ending up. There are many loops in this code and the biggest problem was when I was using the recursion. I was using the recursion to find the 'gap' were the number should be inserted, this was the moment all of the pointers were the same. These pointers needed to constantly be updated and changed at the right moments. This was the most challenging part of the sort.
int i = 1;
int MiddlePointer = 0;
int LeftPointer = 0;
int RightPointer = 0;
BinaryInsertionSort.SortList(UnsortedNumberList, MiddlePointer, LeftPointer, RightPointer, i);
public void SortList(int[] a, int MiddlePointer, int LeftPointer, int RightPointer, int i)
{
if (i == a.Length)
{
Console.Write("Sorted list: ");
for (int x = 0; x < a.Length; x++) //output sorted list
{
if (x == a.Length - 1)
{
Console.Write($"{a[x]}");
}
else
{
Console.Write($"{a[x]}, ");
}
}
return;
}
if (a[MiddlePointer] == a[i])
{
RightPointer = i;
int temp = a[i];
for (int j = i; j > MiddlePointer + 1; j--)
{
a[j] = a[j - 1];
}
a[MiddlePointer + 1] = temp;
LeftPointer = 0;
MiddlePointer = i / 2;
i++;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (MiddlePointer == RightPointer & RightPointer == LeftPointer)
{
if (a[i] > a[MiddlePointer])
{
RightPointer = i;
int temp = a[i];
for (int j = i; j > MiddlePointer + 1; j--)
{
a[j] = a[j - 1];
}
a[MiddlePointer + 1] = temp;
}
else //If the next number is lower, the 'sorted' values need to be 'shifted' one place to the right
{
RightPointer = i;
int temp = a[i];
for (int j = i; j > MiddlePointer; j--)
{
a[j] = a[j - 1];
}
a[MiddlePointer] = temp;
}
LeftPointer = 0;
MiddlePointer = i / 2;
i++;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (a[i] > a[MiddlePointer])
{
LeftPointer = MiddlePointer + 1;
if (LeftPointer > RightPointer)
{
LeftPointer = RightPointer;
}
MiddlePointer = (LeftPointer + RightPointer) / 2;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (a[i] < a[MiddlePointer])
{
RightPointer = MiddlePointer - 1;
if (RightPointer < 0)
{
RightPointer = 0;
}
MiddlePointer = (LeftPointer + RightPointer) / 2;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
}
}
UnsortedNumberList is an array of numbers. At first the pointers point at the first number at Array position 0. When the pointers are equal to each other then the position where the number is inserted has been found. From this point evaluate if the next number is higher or lower that this optimum position. Numbers will have to be juggled about hence the for loops with int j and variable temp. I hope this helps anyone else doing merge sort in the future.

Sequence of marching chars in 2 strings

I have to write searching algorithm, For example I have to compare str="giorgi" to str2="grigol". I'm trying to find longest matching sequence of chars, so that the order of chars is the same and string which I should get is "grg"... with this c# code I'm getting "grig".
int k=0;
string s="";
string str = "giorgi";
string str2 = "grigol";
for(int i=0;i<str.Length;i++)
{
for (int j = k; j < str2.Length; j++)
{
if (str[i] == str2[j])
{
s += str2[k];
k++;
goto endofloop;
}
}
endofloop:;
}
Console.WriteLine(s);
The solution:
using System;
class GFG
{
/* Returns length of LCS for X[0..m-1], Y[0..n-1] */
static int lcs( char[] X, char[] Y, int m, int n )
{
int [,]L = new int[m+1,n+1];
/* Following steps build L[m+1][n+1]
in bottom up fashion. Note
that L[i][j] contains length of
LCS of X[0..i-1] and Y[0..j-1] */
for (int i = 0; i <= m; i++)
{
for (int j = 0; j <= n; j++)
{
if (i == 0 || j == 0)
L[i, j] = 0;
else if (X[i - 1] == Y[j - 1])
L[i, j] = L[i - 1, j - 1] + 1;
else
L[i, j] = GFG.max(L[i - 1, j], L[i, j - 1]);
}
}
return L[m, n];
}
static int max(int a, int b)
{
return (a > b)? a : b;
}
}
And now the program to test it:
public static void Main()
{
String s1 = "giorgi";
String s2 = "grigol";
char[] X=s1.ToCharArray();
char[] Y=s2.ToCharArray();
int m = X.Length;
int n = Y.Length;
Console.Write("Length of LCS is" + " " +lcs( X, Y, m, n ) );
}
}

2d array to 1d array C#

I've got two algorithms converting random 2d arrays (m х n or m х m) to 1d array. I'm wondering if there is a way to make them work als in the opposite direction and convert the result to 1d array saving the order of numbers. Here is the full code of my program and a picture to see how both of my algorithms work.enter image description here
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using static System.Math;
namespace MyProgram
{
public class Program
{
public static void Main(string[] args)
{
Console.Write("Enter number of rows:");
int n = int.Parse(Console.ReadLine());
Console.Write("Enter number of columns:");
int m = int.Parse(Console.ReadLine());
int[] arr1 = new int[n * m];
int[,] arr2 = new int[n, m];
int choice;
do
{
Console.WriteLine("Select option:");
Console.WriteLine("\t1: Diagonal");
Console.WriteLine("\t2: Spiral");
Console.WriteLine("\t3: Exit");
Console.Write("Your selection: ");
choice = int.Parse(Console.ReadLine());
switch (choice)
{
case 1:
{
SetArray(arr2);
PrintArray(arr2);
Diagonal(arr2, arr1);
PrintArray(arr1);
break;
}
case 2:
{
SetArray(arr2);
PrintArray(arr2);
Spiral(arr2, arr1);
PrintArray(arr1);
break;
}
}
Console.WriteLine();
Console.WriteLine();
} while (choice != 5);
}
static void Diagonal(int[,] array2, int[] array1)
{
int k = 0;
int row = 0;
int col = 0;
while (k < array1.Length)
{
array1[k] = array2[row, col];
if ((row + col) % 2 == 0)
{
if ((row == 0) && (col != array2.GetLength(1) - 1)) { col++; }
else
{
if (col == array2.GetLength(1) - 1) { row++; }
else { row--; col++; }
}
}
else
{
if ((col == 0) && (row != array2.GetLength(0) - 1)) { row++; }
else
{
if (row == array2.GetLength(0) - 1) { col++; }
else { row++; col--; }
}
}
k += 1;
}
}
private static void Spiral(int[,] array2, int[] array1)
{
int lengthX = array2.GetLength(0);
int lengthY = array2.GetLength(1);
int Product = lengthX * lengthY;
int CorrectY = 0;
int CorrectX = 0;
int Count = 0;
while (lengthX > 0 && lengthY > 0)
{
for (int j = CorrectY; j < lengthY && Count < Product; j++)
{
array1[Count] = array2[CorrectX, j];
Count++ ;
}
CorrectX++;
for (int i = CorrectX; i < lengthX && Count < Product; i++)
{
array1[Count] = array2[i, lengthY - 1];
Count++ ;
}
if (lengthY > 0 && lengthX > 0) lengthY-- ;
else break;
for (int j = lengthY - 1; j >= CorrectY && Count < Product; j--)
{
array1[Count] = array2[lengthX - 1, j];
Count++ ;
}
if (lengthY > 0 && lengthX > 0) lengthX-- ;
else break;
for (int i = lengthX - 1; i >= CorrectX && Count < Product; i--)
{
array1[Count] = array2[i, CorrectY];
Count++ ;
}
CorrectY++;
}
}
public static void SetArray(int[,] arr)
{
Random r = new Random();
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
arr[i, j] = r.Next(11, 99);
}
}
}
public static void SetArray(int[] arr)
{
Random r = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr[i] = r.Next(11, 99);
}
}
public static void PrintArray(int[] arr)
{
Console.Write("print 1d array:");
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i] + " ");
}
Console.WriteLine();
}
public static void PrintArray(int[,] arr)
{
Console.WriteLine("print 2d array:");
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
Console.Write(arr[i, j] + " ");
}
Console.WriteLine();
}
}
}
}
Actually what you are asking is quite easy. Just change your algorithm methods to receive int rows, int cols and delegate like this
delegate void Apply(int row, int col, int index);
Then replace arr2.GetLength(0) with rows, arr2.GetLength(1) with cols, and array element assignments with delegate call.
Here is the updated Diagonal method (you can do the same with the other):
static void Diagonal(int rows, int cols, Apply action)
{
int k = 0;
int row = 0;
int col = 0;
int length = rows * cols;
while (k < length)
{
action(row, col, k);
if ((row + col) % 2 == 0)
{
if ((row == 0) && (col != cols - 1)) { col++; }
else
{
if (col == cols - 1) { row++; }
else { row--; col++; }
}
}
else
{
if ((col == 0) && (row != rows - 1)) { row++; }
else
{
if (row == rows - 1) { col++; }
else { row++; col--; }
}
}
k += 1;
}
}
and the usage:
SetArray(arr2);
PrintArray(arr2);
Diagonal(n, m, (r, c, i) => arr1[i] = arr2[r, c]);
PrintArray(arr1);
// Inverse
var arr3 = new int[n, m];
Diagonal(n, m, (r, c, i) => arr3[r, c] = arr1[i]);
PrintArray(arr3);
This seems to be working for me for backward Diagonal:
static void BackwardDiagonal(int[,] array2, int[] array1) {
int k = 0;
int row = 0;
int col = 0;
while (k < array1.Length) {
array2[row, col] = array1[k]; // just swap sides of the assignment...
if ((row + col) % 2 == 0) {
if ((row == 0) && (col != array2.GetLength(1) - 1)) { col++; } else {
if (col == array2.GetLength(1) - 1) { row++; } else { row--; col++; }
}
} else {
if ((col == 0) && (row != array2.GetLength(0) - 1)) { row++; } else {
if (row == array2.GetLength(0) - 1) { col++; } else { row++; col--; }
}
}
k += 1;
}
}
For backward Spiral:
private static void BackwardSpiral(int[,] array2, int[] array1)
{
int lengthX = array2.GetLength(0);
int lengthY = array2.GetLength(1);
int Product = lengthX * lengthY;
int CorrectY = 0;
int CorrectX = 0;
int Count = 0;
while (lengthX > 0 && lengthY > 0)
{
for (int j = CorrectY; j < lengthY && Count < Product; j++)
{
array2[CorrectX, j] = array1[Count]; // just swap sides of the assignment...
Count++ ;
}
CorrectX++;
for (int i = CorrectX; i < lengthX && Count < Product; i++)
{
array2[i, lengthY - 1] = array1[Count];
Count++ ;
}
if (lengthY > 0 && lengthX > 0) lengthY-- ;
else break;
for (int j = lengthY - 1; j >= CorrectY && Count < Product; j--)
{
array2[lengthX - 1, j] = array1[Count];
Count++ ;
}
if (lengthY > 0 && lengthX > 0) lengthX-- ;
else break;
for (int i = lengthX - 1; i >= CorrectX && Count < Product; i--)
{
array2[i, CorrectY] = array1[Count];
Count++ ;
}
CorrectY++;
}
}
I also added this to the switch statement to implement it:
case 4:
{
SetArray(arr2);
PrintArray(arr2);
Diagonal(arr2, arr1);
PrintArray(arr1);
int[,] arr3 = new int[n, m]; // new blank array to fill with arr1
BackwardDiagonal(arr3, arr1); // fill arr3 from backward Diagonal algorithm
PrintArray(arr3);
break;
}
case 5:
{
SetArray(arr2);
PrintArray(arr2);
Spiral(arr2, arr1);
PrintArray(arr1);
int[,] arr3 = new int[n, m]; // new blank array to fill with arr1
BackwardSpiral(arr3, arr1); // fill arr3 from backward Spiral algorithm
PrintArray(arr3);
break;
}
While you're at it, also make sure to have } while (choice != 3); at the end of your do loop so that you can exit the program!

How to process an array correctly

Here's the part 1 of my question, if you wanna check the background of this question :
Detecting brackets in input string
Forgive me if the title doesn't match, since I also confused how to name it appropriately to picture my problem. If anyone knows a more appropriate title, feel free to edit.
So, given below code (my own code) :
private const int PARTICLE_EACH_CHAR = 4;
/*ProcessBarLines : string s only contains numbers, b, [, and ]*/
private int ProcessBarLines(Canvas canvas, string s, int lastLineAboveNotation)
{
List<int> bracket = new List<int>();
List<int> other = new List<int>();
int currentCloseNumber = 0;
int currentOpenNumber = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == '[')
{
bracket.Add(i);
currentOpenNumber++;
if (i - 1 > 0 && s[i - 1] != '[')
{
currentOpenNumber = 1;
}
}
else if (s[i] == ']')
{
bracket.Add(i);
currentCloseNumber++;
if (i + 1 >= s.Length || s[i + 1] != ']' || currentOpenNumber == currentCloseNumber)
{
int min = bracket.Count - (currentCloseNumber * 2);
int max = bracket[bracket.Count - 1];
List<int> proc = new List<int>();
int firstIndex = -1;
int lastIndex = -1;
for (int ii = 0; ii < other.Count; ii++)
{
if (other[ii] > min && other[ii] < max)
{
proc.Add(other[ii]);
if (firstIndex == -1)
{
firstIndex = ii;
lastIndex = ii;
}
else
{
lastIndex = ii;
}
}
}
double leftPixel = firstIndex * widthEachChar;
double rightPixel = (lastIndex * widthEachChar) + widthEachChar;
DrawLine(canvas, currentCloseNumber, leftPixel,
rightPixel, lastLineAboveNotation * heightEachChar / PARTICLE_EACH_CHAR);
lastLineAboveNotation += currentCloseNumber - 1;
currentOpenNumber -= currentCloseNumber;
currentCloseNumber = 0;
}
}
else
{
other.Add(i);
}
}
return lastLineAboveNotation + 1;
}
Here's the test cases :
Picture 1 & 2 is the correct answer, and picture 3 is the wrong answer. Picture 3 should have a line, just like inverted from number 2, but, apparently, (if you look closely) the line is drawn on the right, but it should be on the left to be correct (above 0).
I figured, the problem is, I'm quite sure on the "min". Since it doesn't give the correct starting value.
Any idea on this? Feel free to clarify anything. It's used for writing numeric musical scores.
Btw, DrawLine() just meant to draw the line above the numbers, it's not the problem.
Finally! I found it!
private int ProcessBarLines(Canvas canvas, string s, int lastLineAboveNotation)
{
List<int> bracket = new List<int>();
List<int> other = new List<int>();
int currentCloseNumber = 0;
int currentOpenNumber = 0;
int space = 0;
for (int i = 0; i < s.Length; i++)
{
if (s[i] == '[')
{
bracket.Add(i);
currentOpenNumber++;
if (i - 1 > 0 && s[i - 1] != '[')
{
currentOpenNumber = 1;
}
}
else if (s[i] == ']')
{
bracket.Add(i);
currentCloseNumber++;
if (i + 1 >= s.Length || s[i + 1] != ']' || currentOpenNumber == currentCloseNumber)
{
int min = bracket[Math.Max(bracket.Count - ((currentCloseNumber * 2) + space), 0)];
int max = bracket[bracket.Count - 1];
space = max - min - 1;
List<int> proc = new List<int>();
int firstIndex = -1;
int lastIndex = -1;
for (int ii = 0; ii < other.Count; ii++)
{
if (other[ii] > min && other[ii] < max)
{
proc.Add(other[ii]);
other[ii] = -1;
if (firstIndex == -1)
{
firstIndex = ii;
lastIndex = ii;
}
else
{
lastIndex = ii;
}
}
}
double leftPixel = firstIndex * widthEachChar;
double rightPixel = (lastIndex * widthEachChar) + widthEachChar;
DrawLine(canvas, currentCloseNumber, leftPixel,
rightPixel, lastLineAboveNotation * heightEachChar / PARTICLE_EACH_CHAR);
lastLineAboveNotation += 1;
currentOpenNumber -= currentCloseNumber;
currentCloseNumber = 0;
}
}
else
{
other.Add(i);
}
}
return lastLineAboveNotation + 1;
}
If someone got a more efficient code, please let us know!

What am I doing wrong in this C# mergesort algorithm?

For a school assignment, I have to implement mergesort.
I've used this code to do the trick:
static int[] MergeSort(int[] C)
{
int left = 0;
int right = C.Length;
int middle = (left + right) / 2;
int[] A, B;
A = new int[middle];
B = new int[middle];
if (C.Length == 0 || C.Length == 1)
{
return C;
}
else
{
for (int i = left; i < middle; i++)
{
A[i] = C[i];
B[i] = C[middle + i];
}
MergeSort(A);
MergeSort(B);
return Merge(A, B, C);
}
}
static int[] Merge(int[] A, int[] B, int[] C)
{
int i, j, k;
i = j = k = 0;
int n = A.Length;
int m = B.Length;
int c = C.Length;
int middle = C.Length / 2;
while (i < n && j < m)
{
if (A[i] < B[j])
{
C[k] = A[i];
i++;
}
else
{
C[k] = B[j];
j++;
}
k++;
if (i == n)
{
for (int b = i; b < B.Length; b++)
{
C[middle + b] = B[b];
}
}
else
{
for (int a = i; a < A.Length; a++)
{
C[middle + a] = A[a];
}
}
}
return C;
}
It does not work for a lot of different rows though. I've already debugged and checked if there was something wrong with constraints, but I can't seem to find the problem.
Thanks in advance!
The first thing I spot is how you split the array into two:
A = new int[middle];
B = new int[middle];
If the length is not even, you will be leaving out the last item. You should have:
A = new int[middle];
B = new int[right - middle];
Then you would use separate loops for them, as they can be different in length:
for (int i = left; i < middle; i++) {
A[i - left] = C[i];
}
for (int i = middle; i < right; i++) {
B[i - middle] = C[i];
}
In addition to Guffa answer, you should edit the code of the Merge method like this:
while (i < n && j < m)
{
if (A[i] < B[j])
{
C[k] = A[i];
i++;
}
else
{
C[k] = B[j];
j++;
}
k++;
}
if (i == n)
{
for (int b = j; b < B.Length; b++)
{
C[k++] = B[b];
}
}
else
{
for (int a = i; a < A.Length; a++)
{
C[k++] = A[a];
}
}
While loop block should end right after k++ and in first for loop you should initialize b with j instead of i. Also, watch out for the index of the next element of the C array, it is k, not necessarily middle + a or b.

Categories

Resources