problems trying to convert c sharp code into java - java

i'm try find most similar string in a array, and i found a code in c sharp that is this one
public static int LevenshteinDistance(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
Console.WriteLine(cost);
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
return d[n, m];
}
and i'm trying to convert it into java but i get 1 error this is my code in java
public static int LevenshteinDistance(String s, String t)
{
int n = s.length();
int m = t.length();
int[][] d = new int[n + 1][ m + 1];
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1])? 0 : 1;
d[i][ j] = Math.min(
Math.min(d[i - 1][ j] + 1, d[i][ j - 1] + 1),
d[i - 1][ j - 1]+cost );
}
}
return d[n] [m];
}
i get the error in this line of code
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
the error that i have is "Array is required,but string found" this is what i have in my main
String []ray ={"food","drinks","stuffs"};
String fa="drink";
for (int i = 0; i < ray.length; i++)
{
System.out.print(LevenshteinDistance(fa, ray[i]));
}
i would appreciate any help

Use t.charAt(j-1) == s.charAt(i-1) as to access characters (letters) in string You cannot access them directly via index (brackets []).
int cost = (t.charAt(j - 1) == s.charAt(i - 1))? 0 : 1;

You are accessing the strings as arrays here with the [] array operator:
t[j - 1] == s[i - 1]
to get the nth char of a string, instead use .charAt(n)
so in this case change it to:
t.charAt(j - 1) == s.charAt(i - 1)
the same applies to the rest of the code.

Related

How can i print path to matrix path in java?

code is here
public class MatrixPath {
public static void main(String[] args) throws FileNotFoundException {
int m[][], c[][];
int set;
Scanner scan = new Scanner(new File("hw9_1.text"));
set = scantiness();
m = new int[set][set];
c = new int[set][set];
for (int i = 0; i < set; i++) {
for (int j = 0; j < set; j++) {
m[i][j] = scan.nextInt();
}
}
c[0][0] = m[0][0];
System.out.println(set);
for (int i = 0; i < set; i++) {
for (int j = 0; j < set; j++) {
System.out.print(m[i][j] + " ");
}
System.out.println();
}
System.out.println(path(m, set - 1, set - 1, c));
}
private static int path(int[][] m, int i, int j, int[][] c) {
if (i == 0 && j == 0) {
return c[0][0];
}
if (i == 0) {
c[i][j] = (c[0][j - 1] != 0) ? (c[0][j - 1] + m[0][j]) : (path(m, 0, j - 1, c) + m[0][j]);
return c[i][j];
}
if (j == 0) {
c[i][j] = (c[i - 1][0] != 0) ? (c[i - 1][0] + m[i][0]) : (path(m, i - 1, 0, c) + m[i][0]);
return c[i][j];
}
int A = (c[i - 1][j] != 0) ? (c[i - 1][j]) : (path(m, i - 1, j, c));
int B = (c[i][j - 1] != 0) ? (c[i][j - 1]) : (path(m, i, j - 1, c));
int C = (c[i - 1][j - 1] != 0) ? (c[i - 1][j - 1]) : (path(m, i - 1, j - 1, c));
c[i][j] = Math.max(A, Math.max(B, C)) + m[i][j];
System.out.print("(" + i + " " + j + ")");
return c[i][j];
}
}
I used the translator.
Code that utilizes dynamic programming to find the matrix path at its maximum value.
I can get the maximum value by executing the current code.
Text documents leverage the following:
4
1 1 1 1
2 -3 1 -5
-1 2 3 1
1 1 4 1
I want to track the path of the matrix to get the maximum value.
like this ->
max : 13
path : 0 0 > 1 0 > 2 1 > 2 2 > 3 2 > 3 3
Do I need to add a new method?
Or is it possible with the existing code?

Wagner Fischer algorithm + display steps

I made an implementation of Wagner Fischer algorithm in java with input cost, but I want to display all steps.
I search but can't find any idea.After a long time I tried to keep each transformation in matrix alongside cost and to go through back to first solution then reverse it... is this a good idea, if it is, how should I set condition?
kitten -> sitting
1.replace k with s
2.keep i
3.keep t
4.keep t
5.replace t
6.add g
I tried to make function for display steps and can't figure out how to solve it.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Principal {
static int c1, c2, c3;
static String word1, word2;
public static void main(String[] args) throws FileNotFoundException {
Scanner data_in = new Scanner(new File("data.in"));
word1 = data_in.next();
word2 = data_in.next();
c1 = data_in.nextInt();
c2 = data_in.nextInt();
c3 = data_in.nextInt();
System.out.printf("\nInsert: %s, Delete: %s, Replace: %s\n", c1, c2, c3);
System.out.printf("\nLevenstheinDistance: %s", LevenshteinDistance(word1, word2, c1, c2, c3));
}
private static int LevenshteinDistance(String str1, String str2, int InsCost, int DelCost, int ReplCost)
{
if(word1.length() == 0)
return InsCost*str1.length();
if(word2.length() == 0)
return DelCost*str2.length();
int substitutionCost = ReplCost;
if(ReplCost > InsCost + DelCost)
ReplCost = InsCost + DelCost;
Solution[][] ManageSol = new Solution[str1.length()+1][str2.length()+1];
for(int i = 0; i <= str1.length(); i++)
{
for(int j = 0; j <= str2.length(); j++){
ManageSol[i][j] = new Solution();
}
}
System.out.printf("\nLungime str1: %s", str1.length());
System.out.printf("\nLungime str2: %s", str2.length());
for(int i = 0; i <= str1.length(); i++)
{
for (int j = 0; j <= str2.length(); j++)
{
if (i == 0)
ManageSol[i][j].solution = j;
else if (j == 0)
ManageSol[i][j].solution = i;
else if (str1.charAt(i - 1) == str2.charAt(j - 1))
{
substitutionCost = 0;
ManageSol[i][j].ecqualTo(minimum(
ManageSol[i][j - 1].solution + InsCost,
ManageSol[i - 1][j].solution + DelCost,
ManageSol[i - 1][j - 1].solution + substitutionCost));
System.out.printf("\nManagerSol[%s, %s]: ch1: %s, ch2: %s", i, j, str1.charAt(i - 1), str2.charAt(j - 1));
}
else
{
substitutionCost = 1;
ManageSol[i][j].ecqualTo(minimum(
ManageSol[i][j - 1].solution + InsCost,
ManageSol[i - 1][j].solution + DelCost,
ManageSol[i - 1][j - 1].solution + substitutionCost));
System.out.printf("\nManagerSol[%s, %s]: ch1: %s, ch2: %s", i, j, str1.charAt(i - 1), str2.charAt(j - 1));
}
}
}
System.out.printf("\n");
path(ManageSol, str1.length(), str2.length(), str1, str2);
System.out.printf("\n");
for(int i = 0; i <= str1.length(); i++)
{
for (int j = 0; j <= str2.length(); j++)
{
System.out.printf("[%s,%s]:(%s,%s) ", i, j, ManageSol[i][j].solution, ManageSol[i][j].operation);
}
System.out.printf("\n");
}
return ManageSol[str1.length()][str2.length()].solution;
}
static int minimum(int x, int y)
{
if(x >= y)
return x;
return y;
}
static Solution minimum(int Ins, int Del, int Replace)
{
Solution solution = null;
if(Ins <= Del && Ins <= Replace)
{
solution = new Solution();
solution.operation = 1;
solution.solution = Ins;
return solution;
}
else if(Del <= Ins && Del <= Replace)
{
solution = new Solution();
solution.operation = 2;
solution.solution = Del;
return solution;
}
else
{
solution = new Solution();
solution.solution = Replace;
solution.operation = 0;
return solution;
}
}
//my failure, function that should display steps
static void path(Solution[][] ManagerSol, int i, int j, String str1, String str2)
{
if(ManagerSol[i][j].operation == 0)
{
System.out.printf("\nReplace %s -> %s", str1.charAt(i-1), str2.charAt(j-1));
if(i > 1 && j > 1)
path(ManagerSol, i-1,j-1, str1, str2);
}
if(ManagerSol[i][j].operation == 1)
{
System.out.printf("\nAdd %s on position %s", str2.charAt(j-1), i-1);
if(j > 1)
path(ManagerSol, i,j-1, str1, str2);
}
if(ManagerSol[i][j].operation == 2)
{
System.out.printf("\nDelete %s", str1.charAt(i-1));
if(j > 1)
path(ManagerSol, i-1,j, str1, str2);
}
}
}
Output for kitten to sitting:
[0,0]:(0,3) [0,1]:(1,3) [0,2]:(2,3) [0,3]:(3,3) [0,4]:(4,3) [0,5]:(5,3) [0,6]:(6,3) [0,7]:(7,3)
[1,0]:(1,3) [1,1]:(1,0) [1,2]:(2,1) [1,3]:(3,1) [1,4]:(4,1) [1,5]:(5,1) [1,6]:(6,1) [1,7]:(7,1)
[2,0]:(2,3) [2,1]:(2,2) [2,2]:(1,0) [2,3]:(2,1) [2,4]:(3,1) [2,5]:(4,1) [2,6]:(5,1) [2,7]:(6,1)
[3,0]:(3,3) [3,1]:(3,2) [3,2]:(2,2) [3,3]:(1,0) [3,4]:(2,1) [3,5]:(3,1) [3,6]:(4,1) [3,7]:(5,1)
[4,0]:(4,3) [4,1]:(4,2) [4,2]:(3,2) [4,3]:(2,2) [4,4]:(1,0) [4,5]:(2,1) [4,6]:(3,1) [4,7]:(4,1)
[5,0]:(5,3) [5,1]:(5,2) [5,2]:(4,2) [5,3]:(3,2) [5,4]:(2,2) [5,5]:(2,0) [5,6]:(3,1) [5,7]:(4,1)
[6,0]:(6,3) [6,1]:(6,2) [6,2]:(5,2) [6,3]:(4,2) [6,4]:(3,2) [6,5]:(3,2) [6,6]:(2,0) [6,7]:(3,1)
In general your idea is correct. It's even simpler than that. You don't need to store any additional information.
You can go backwards (starting from the end of the given strings) and use your dynamic programming values in the following way:
If one of the indices is 0, there is only one way to go.
Otherwise, you can look at 3 possible transitions "backwards" (from (i, j) to (i - 1, j - 1), (i - 1, j) and (i, j - 1)) and choose the one which yields the actual value for (i, j). If there are several possible options, you can choose any of them.
Once you know where to go from the given pair of positions, the operation is uniquely determined.
I'm not versed in Java but here is an illustration in JavaScript:
var a = 'kitten',
b = 'sitting';
var m = new Array(a.length + 1);
for (var i=0; i<m.length; i++){
m[i] = new Array(b.length + 1);
for (var j=0; j<m[i].length; j++){
if (i === 0) m[i][j] = j;
if (j === 0) m[i][j] = i;
}
}
for (var i=1; i<=a.length; i++){
for (var j=1; j<=b.length; j++){
// no change needed
if (a[i - 1] === b[j - 1]){
m[i][j] = m[i - 1][j - 1];
// choose deletion or insertion
} else {
m[i][j] = Math.min(m[i - 1][j], m[i][j - 1], m[i - 1][j - 1]) + 1;
}
}
}
console.log('a: ' + JSON.stringify(a));
console.log('b: ' + JSON.stringify(b));
var i = a.length,
j = b.length,
steps = '';
while (i !== 0 && j !== 0){
if (a[i - 1] === b[j - 1]){
steps = 'no change; ' + steps;
i--;
j--;
} else if (m[i - 1][j] < m[i][j - 1]){
steps = 'delete \'' + a[i - 1] + '\'; ' + steps;
i--;
} else if (m[i - 1][j] === m[i][j - 1]){
steps = 'replace \'' + a[i - 1] + '\' with \'' + b[j - 1] + '\'; ' + steps;
i--;
j--;
} else {
steps = 'insert \'' + b[j - 1] + '\'; ' + steps;
j--;
}
}
if (i === 0 && j > 0){
steps = 'insert first ' + j + ' elements from b; ' + steps;
} else if (j === 0 && i > 0){
steps = 'delete first ' + i + ' elements from a; ' + steps;
}
console.log('\n' + steps[0].toUpperCase() + steps.substr(1));
console.log('\nMatrix:\n');
for (var i in m){
console.log(JSON.stringify(m[i]));
}

Index Outside of Bounds on Stock Maximization Algorithm

I have the following code translated as best I could from Java to C#:
public double maxProfit(double[] prices, int K)
{
if (K == 0 || prices.Length == 0)
{
return 0;
}
var dp = new double[K + 1, prices.Length];
for (int i = 1; i < K + 1; i++)
{
double maxDiff = -prices[0];
for (int j = 1; j < prices.Length; j++)
{
dp[i, j] = Math.Max(dp[i, j - 1], prices[j] + maxDiff);
maxDiff = Math.Max(maxDiff, dp[i - 1, j] - prices[j]);
}
}
printTrans(dp, prices, K);
return dp[K, prices.Length - 1];
}
public void printTrans(double[,] dp, double[] prices, int K)
{
int i = K - 1;
int j = prices.Length;
var priceList = new List<double>();
while (true)
{
if (i == 0 || j == 0)
{
break;
}
if (dp[i, j] == dp[i, j - 1])
{
j = j - 1;
}
else
{
priceList.Add(j);
double maxDiff = dp[i, j] - prices[j];
for (int z = j - 1; z >= 0; z--)
{
if (dp[i - 1, z] - prices[z] == maxDiff)
{
i = i - 1;
j = z;
priceList.Add(j);
break;
}
}
}
}
while (priceList.Count > 0)
{
Console.WriteLine("Buy # " + prices[priceList.IndexOf(0)]);
Console.WriteLine("Sell # " + prices[priceList.IndexOf(0)]);
}
}
Error occurs in the second method on lines:
if (dp[i, j] == dp[i, j - 1])
and
for (int z = j - 1; z >= 0; z--)
{
if (dp[i - 1, z] - prices[z] == maxDiff)
I am getting an Index was outside the bounds of the array. error. I understand what this error means but I have no clue on my to fix it. It took me quite a bit to understand the first part of this code but for the second part, I am at a loss.
Also what is the C# equivalent of the Java pollFirst() method?
Probably this line is the cause
public void printTrans(double[,] dp, double[] prices, int K)
{
int i = K - 1;
int j = prices.Length; // <=== this line is the cause
its causing the j to refer an index outside the bounds of the 2D array.
If you have ported from java recheck your java code.
Either make that line
int j = prices.Length - 1;
Or you need to make changes to how you create your array
var dp = new double[K + 1, prices.Length]; // <-- prices.Length would have to change here

Longest Common Subsequences of 2 Arrays of Bytes

I wanted to compare the LCS of two files from their binary, therefore i used the usual LCS source code, and using the GenStr command to change the bytes of the file to String first.
The problem is, I received memory out of bound error because comparing String has limit, therefore i am planning to use array that stores the bytes then compare it. Is it possible to use LCS algorithm to compare two arrays of bytes?
EDIT:
public static byte[] Compare(byte[] x, byte[] y) {
int i, j;
final int x_length = x.length;
final int y_length = y.length;
int n = 2048;
int m = 2048;
// D[i][j] = direction, L[i][j] = Length of LCS
int[][] D = new int[n + 1][m + 1];
byte[][] L = new byte[n + 1][m + 1]; // { 1, 2, 3 }
// D[i][0] = 0 for 0<=i<=n
// D[0][j] = 0 for 0<=j<=m
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
if (x[i - 1] == y[j - 1]) {
D[i][j] = D[i - 1][j - 1] + 1;
L[i][j] = 1;
} else if (D[i - 1][j] >= D[i][j - 1]) {
D[i][j] = D[i - 1][j];
L[i][j] = 2;
} else {
D[i][j] = D[i][j - 1];
L[i][j] = 3;
}
}
}
// Backtrack
ByteArrayOutputStream lcs = new ByteArrayOutputStream();
i = n;
j = m;
while (i != 0 && j != 0) {
switch (L[i][j]) {
case 1: // diagonal
lcs.write(x[i - 1]); // Unreversed LCS
--i;
--j;
break;
case 2: // up
--i;
break;
case 3: // backward
--j;
break;
}
}
byte[] result = lcs.toByteArray();
// Reverse:
for (i = 0, j = result.length - 1; i < j; ++i, --j) {
byte b = result[i];
result[i] = result[j];
result[j] = b;
}
return result;
//While not end of file
while(n < x_length && m < y_length){
if(n+2048 < x.length){
n = n+2048;
} else {
n = x.length;
}
if(m+2048 < y.length){
m = m+2048;
} else {
m = y.length;
}
// D[i][j] = direction, L[i][j] = Length of LCS
int[][] D_new = new int[n + 1][m + 1];
byte[][] L_new = new byte[n + 1][m + 1]; // { 1, 2, 3 }
// D[i][0] = 0 for 0<=i<=n
// D[0][j] = 0 for 0<=j<=m
for (i = i+2048; i <= n; i++) {
for (j = j+2048; j <= m; j++) {
if (x[i - 1] == y[j - 1]) {
D_new[i][j] = D_new[i - 1][j - 1] + 1;
L_new[i][j] = 1;
} else if (D_new[i - 1][j] >= D_new[i][j - 1]) {
D_new[i][j] = D_new[i - 1][j];
L_new[i][j] = 2;
} else {
D_new[i][j] = D_new[i][j - 1];
L_new[i][j] = 3;
}
}
}
// Backtrack
ByteArrayOutputStream lcs_next = new ByteArrayOutputStream();
i = n;
j = m;
while (i != 0 && j != 0) {
switch (L[i][j]) {
case 1: // diagonal
lcs_next.write(x[i - 1]); // Unreversed LCS
--i;
--j;
break;
case 2: // up
--i;
break;
case 3: // backward
--j;
break;
}
}
byte[] result_new = lcs_next.toByteArray();
// Reverse:
for (i = 0, j = result_new.length - 1; i < j; ++i, --j) {
byte b = result_new[i];
result_new[i] = result_new[j];
result_new[j] = b;
}
return result_new;
Arrays.fill(D_new, null);
Arrays.fill(L_new, null);
Arrays.fill(result_new, null);
lcs_next.reset();
}
}
I tried, but haven't been able to check if this can be used or not, because of some errors.
Questions:
how do you append the lcs in line (return result) and line (return result_new)?
how do you clear the array so i can use it over and over again with different input?
(Array.fill(D_new, null) and Array.fill(L_new, null) doesn't work)?
Thank you in advance
There's nothing to stop you using a byte array instead. This will use half the memory of an int array, but the maximum length of it will be the same: Integer.MAX_VALUE. If you're running out of RAM, but not hitting the length limit, then this might save you.
If these are coming from files, then that's what you should be doing anyway. You really shouldn't be reading them in as entire strings. Read them byte by byte.
But the right way to do this if the files are huge (more than 2GB) is to process the files as you go, rather than reading them in beforehand, and also using a file to store the LCS data that you're creating. The nice thing about the algorithm is that all the access is localised: you scan the input files sequentially (so you don't gain anything from reading them in in advance); and you write the arrays fairly close to sequentially, by only considering the previous and current rows when you calculate a new value (so you don't gain much by having them in RAM either).
Doing it like this will allow you to scale the files arbitrarily. CPU time will then be the deciding factor. The disk cache will give you close to the same performance you'd get by reading the files in first and doing it from RAM.
A conversion without algorithmic consideration.
In java new initializes to 0 / 0.0 / false / null.
On the other hand prepending to lcs cannot be done out-of-the-box. However reversing an array is simple.
public static byte[] compare(byte[] x, byte[] y) {
int i, j;
final int n = x.length;
final int m = y.length;
/* D[i][j] = direction, L[i][j] = Length of LCS */
int[][] D = new int[n + 1][m + 1];
byte[][] L = new byte[n + 1][m + 1]; // { 1, 2, 3 }
/* D[i][0] = 0 for 0<=i<=n */
/* D[0][j] = 0 for 0<=j<=m */
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
if (x[i - 1] == y[ - 1]) {
D[i][j] = D[i - 1][j - 1] + 1;
L[i][j] = 1;
} else if (D[i - 1][j] >= D[i][j - 1]) {
D[i][j] = D[i - 1][j];
L[i][j] = 2;
} else {
D[i][j] = D[i][j - 1];
L[i][j] = 3;
}
}
}
/* Backtrack */
ByteArrayOutputStream lcs = new ByteArrayOutputStream();
i = n;
j = m;
while (i != 0 && j != 0) {
switch (L[i][j]) {
case 1: /* diagonal */
lcs.write(x[i - 1]); // We want lcs reversed though.
--i;
--j;
break;
case 2: /* up */
--i;
break;
case 3: /* backward */
--j;
break;
}
}
byte[] result = lcs.toByteArray();
// Reverse:
for (i = 0, j = result.length - 1; i < j; ++i, --j) {
byte b = result[i];
result[i] = result[j];
result[j] = b;
}
return result;
}

longest common subsequence printdDiff

Just a quick question about the longest Common subsequence algorithm.
I have done the part where you need to generate the subsequence as follow:
public int[][] lcsLength(char[] input1, char[] input2) {
int[][] opt = new int[M][N];
for (int i = 1; i < input1.length; i++) {
for (int j = 1; j < input2.length; j++) {
if (input1[i] == input2[j]) {
opt[i][j] = opt[i - 1][j - 1] + 1;
} else {
opt[i][j] = Math.max(opt[i][j - 1], opt[i - 1][j]);
}
}
}
return opt;
}
and the printDiff function as follow:
private static void printDiff(int[][] opt,String x,String y,int i, int j) {
if(i>0 &&j>0 && x.charAt(i-1)==y.charAt(j-1)){
printDiff(i-1,j-1);
System.out.println(x.charAt(i-1));
}
else{
if(j>0&&(i==0||opt[i][j-1]>=opt[i-1][j])){
printDiff(i-1,j-1);
System.out.println("-"+y.charAt(j-1));
}
else if(i>0&&(j==0|| opt[i][j-1]<=opt[i-1][j])){
printDiff(i-1,j-1);
System.out.println(x.charAt(i-1));
}
}
}
And then if I use this as parameters:
String input1="ABCDE"
String input2="ACDC"
int i=input1.length()
int j=input2.length()
after generating the opt matrix with lcsLength() I wish that printdiff woul give me :
ABCDE-
A-CD-C
but instead I get:
ABCDE-
ABCD-C
any ideas on what I did wrong would help me a lot
Thanks
Laurent
From wiki:
function printDiff(C[0..m,0..n], X[1..m], Y[1..n], i, j)
if i > 0 and j > 0 and X[i] = Y[j]
printDiff(C, X, Y, i-1, j-1)
print " " + X[i]
else if j > 0 and (i = 0 or C[i,j-1] ≥ C[i-1,j])
printDiff(C, X, Y, i, j-1)
print "+ " + Y[j]
else if i > 0 and (j = 0 or C[i,j-1] < C[i-1,j])
printDiff(C, X, Y, i-1, j)
print "- " + X[i]
else
print ""
This line:
else if(i>0&&(j==0|| opt[i][j-1]<=opt[i-1][j])){
Should be:
else if(i>0&&(j==0|| opt[i][j-1]<opt[i-1][j])){
(change <= to just <)
Don't know if it's a related issue, but I think your LCS code should be:
public int[][] lcsLength(char[] input1, char[] input2) {
int[][] opt = new int[input1.length+1][input2.length+1];
for (int i = 1; i <= input1.length; i++) {
for (int j = 1; j <= input2.length; j++) {
if (input1[i-1] == input2[j-1]) {
opt[i][j] = opt[i - 1][j - 1] + 1;
} else {
opt[i][j] = Math.max(opt[i][j - 1], opt[i - 1][j]);
}
}
}
return opt;
}

Categories