I was asked this question on a technical interview. Question is: given a target, and an array of strings, return an array that contains all strings with ONLY one difference to the target.
For example if target is cat, catt, caT, caa, ca, at <-- are all only one difference. And conversely, cat, cattt, dog, flower, c <-- are not one difference and should not be returned.
oneDiff(String target, String[] a) ...
My approach was:
ans = []
for all element e in the array
count -> 0
if absoulte(e's length - target length) > 1
continue
endif
for all character c in e
scan through, increment count if difference is found.
endfor
if (count == 1)
continue
else
add e to ans
endfor
return ans
But the interviewer wasnt happy with what's above. Anyone has any efficient/clever ideas?
Thanks
As mentioned by zubergu Levenshtein distance will solve your problem. You can find Levenshtein distance in java here.
Edit: Since you tagged it as java you can run the following java code:
public class Levenshtein {
public static int distance(String a, String b) {
a = a.toLowerCase();
b = b.toLowerCase();
// i == 0
int [] costs = new int [b.length() + 1];
for (int j = 0; j < costs.length; j++)
costs[j] = j;
for (int i = 1; i <= a.length(); i++) {
// j == 0; nw = lev(i - 1, j)
costs[0] = i;
int nw = i - 1;
for (int j = 1; j <= b.length(); j++) {
int cj = Math.min(1 + Math.min(costs[j], costs[j - 1]), a.charAt(i - 1) == b.charAt(j - 1) ? nw : nw + 1);
nw = costs[j];
costs[j] = cj;
}
}
return costs[b.length()];
}
public static void main(String [] args) {
String comparison = "cat";
String [] data = { "cattt", "catt", "caT", "caa", "ca", "at" };
for (int i = 0; i < data.length; i++)
System.out.println("distance(" + comparison + ", " + data[i] + ") = " + distance(comparison, data[i]));
}
}
If you run the code you will see the following output:
distance(cat, cattt) = 2
distance(cat, catt) = 1
distance(cat, caT) = 0
distance(cat, caa) = 1
distance(cat, ca) = 1
distance(cat, at) = 1
If the distance is 0 or 1 then its acceptable.
Related
I have to create an N * M matrix and fill it up with values between 0 and 9. One of the values should be "A" which is the starting point of the graph, and I should find the shortest path to the value "B" (both of these are generated at a random position of the matrix). If the value is 0 it counts as an obstacle, and 2 < N, M < 100.
I have to print out the exact route of the shortest graph and the total cost of it. Also, the problem has to be solved by Dijkstra's algorithm.
I've haven't gotten past filling up the Matrix. I store the values in a 2D String array, but I think I should use different arrays or maybe Maps for storing the positions of key values such as the start and endpoint. I've been thinking on this for 2 days now because I'm a total noob in Java and not much better at programming in general. I'm mainly looking for guidance on how to store the datas and what should I actually store in order to get to the end because I think I overcomplicate the problem.
This is the matrix generating part of the code.
int N = ThreadLocalRandom.current().nextInt(3,7);
int M = ThreadLocalRandom.current().nextInt(3,7);
int J = ThreadLocalRandom.current().nextInt(0,(Math.min(N, M))/2);
int K = 0;
int aPosX = ThreadLocalRandom.current().nextInt(0,N);
int aPosY = ThreadLocalRandom.current().nextInt(0,M);
int bPosX = ThreadLocalRandom.current().nextInt(0,N);
int bPosY = ThreadLocalRandom.current().nextInt(0,M);
String[][] matrix = new String[N][M];
int[][] map = new int[N][M];
int shortestPath = 10;
int currentPosX,currentPosY;
int shortestPosX, shortestPosY;
public void generateMatrix(){
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
K = ThreadLocalRandom.current().nextInt(0,10);
matrix[i][j] = String.valueOf(K);
}
}
}
public void createStartAndFinish(){
matrix[aPosX][aPosY] = "A";
matrix[bPosX][bPosY] = "B";
}
}
This part finds the lowest cost adjacent tiles and steps on them but id does generate an out of bounds exception. I'm also aware that it has nothing to do with Dijkstra algorithm but this is my starting point.
public void solveMatrix(){
visited[aPosX][aPosY] = true;
currentPosX = aPosX;
currentPosY = aPosY;
while (!matrix[currentPosX - 1][currentPosY].equals("B") ||
!matrix[currentPosX + 1][currentPosY].equals("B") ||
!matrix[currentPosX][currentPosY - 1].equals("B") ||
!matrix[currentPosX][currentPosY + 1].equals("B")) {
if(currentPosX > 0) {
if(!visited[currentPosX - 1][currentPosY] && Integer.parseInt(matrix[currentPosX - 1][currentPosY]) < shortestPath) {
shortestPath = Integer.parseInt(matrix[currentPosX - 1][currentPosY]);
shortestPosX = currentPosX - 1;
shortestPosY = currentPosY;
}
}
if(currentPosX + 1 < N){
if(!visited[currentPosX + 1][currentPosY] && Integer.parseInt(matrix[currentPosX + 1][currentPosY]) < shortestPath) {
shortestPath = Integer.parseInt(matrix[currentPosX + 1][currentPosY]);
shortestPosX = currentPosX + 1;
shortestPosY = currentPosY;
}
}
if(currentPosY > 0){
if(!visited[currentPosX][currentPosY - 1] && Integer.parseInt(matrix[currentPosX][currentPosY - 1]) < shortestPath) {
shortestPath = Integer.parseInt(matrix[currentPosX][currentPosY - 1]);
shortestPosX = currentPosX;
shortestPosY = currentPosY - 1;
}
}
if(currentPosY - 1 < M){
if(!visited[currentPosX][currentPosY + 1] && Integer.parseInt(matrix[currentPosX][currentPosY + 1]) < shortestPath) {
shortestPath = Integer.parseInt(matrix[currentPosX][currentPosY + 1]);
shortestPosX = currentPosX;
shortestPosY = currentPosY + 1;
}
}
visited[shortestPosX][shortestPosY] = true;
currentPosX = shortestPosX;
currentPosY = shortestPosY;
System.out.println(shortestPosX + " " + shortestPosY + " " + shortestPath);
shortestPath = 10;
}
}
I have this question I am trying to solve. I have tried coding for the past 4 hours.
An integer is defined to be a Smart number if it is an element in the infinite sequence
1, 2, 4, 7, 11, 16 …
Note that 2-1=1, 4-2=2, 7-4=3, 11-7=4, 16-11=5 so for k>1, the kth element of the sequence is equal to the k-1th element + k-1. For example, for k=6, 16 is the kth element and is equal to 11 (the k-1th element) + 5 ( k-1).
Write function named isSmart that returns 1 if its argument is a Smart number, otherwise it returns 0. So isSmart(11) returns 1, isSmart(22) returns 1 and isSmart(8) returns 0
I have tried the following code to
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
// TODO Auto-generated method stub
int x = isSmart(11);
System.out.println(x);
}
public static int isSmart(int n) {
int[] y = new int[n];
int j = 0;
for (int i = 1; i <= n; i++) {
y[j] = i;
j++;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i <= y.length; i++) {
int diff = 0;
y[j] = y[i+1] - y[i] ;
y[i] = diff;
}
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
When I test it with 11 it is giving me 0 but it shouldn't. Any idea how to correct my mistakes?
It can be done in a simpler way as follows
import java.util.Arrays;
public class IsSmart {
public static void main(String[] args) {
int x = isSmart(11);
System.out.println("Ans: "+x);
}
public static int isSmart(int n) {
//------------ CHECK THIS LOGIC ------------//
int[] y = new int[n];
int diff = 1;
for (int i = 1; i < n; i++) {
y[0] =1;
y[i] = diff + y[i-1];
diff++;
}
//------------ CHECK THIS LOGIC ------------//
System.out.println(Arrays.toString(y));
for (int i = 0; i < y.length; i++) {
if(n == y[i])
return 1;
}
return 0;
}
}
One of the problems is the way that your populating your array.
The array can be populated as such
for(int i = 0; i < n; i++) {
y[i] = (i == 0) ? 1 : y[i - 1] + i;
}
The overall application of the function isSmart can be simplified to:
public static int isSmart(int n) {
int[] array = new int[n];
for(int i = 0; i < n; i++) {
array[i] = (i == 0) ? 1 : array[i - 1] + i;
}
for (int i = 0; i < array.length; i++) {
if (array[i] == n) return 1;
}
return 0;
}
Note that you don't need to build an array:
public static int isSmart(int n) {
int smart = 1;
for (int i = 1; smart < n; i++) {
smart = smart + i;
}
return smart == n ? 1 : 0;
}
Here is a naive way to think of it to get you started - you need to fill out the while() loop. The important thing to notice is that:
The next value of the sequence will be the number of items in the sequence + the last item in the sequence.
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
System.out.println(isSmart(11));
}
public static int isSmart(int n) {
ArrayList<Integer> sequence = new ArrayList<Integer>();
// Start with 1 in the ArrayList
sequence.add(1);
// You need to keep track of the index, as well as
// the next value you're going to add to your list
int index = 1; // or number of elements in the sequence
int nextVal = 1;
while (nextVal < n) {
// Three things need to happen in here:
// 1) set nextVal equal to the sum of the current index + the value at the *previous* index
// 2) add nextVal to the ArrayList
// 3) incriment index by 1
}
// Now you can check to see if your ArrayList contains n (is Smart)
if (sequence.contains(n)) { return 1; }
return 0;
}
}
First think of a mathematical solution.
Smart numbers form a sequence:
a0 = 1
an+1 = n + an
This gives a function for smart numbers:
f(x) = ax² + bx + c
f(x + 1) = f(x) + x = ...
So the problem is to find for a given y a matching x.
You can do this by a binary search.
int isSmart(int n) {
int xlow = 1;
int xhigh = n; // Exclusive. For n == 0 return 1.
while (xlow < xhigh) {
int x = (xlow + xhigh)/2;
int y = f(x);
if (y == n) {
return 1;
}
if (y < n) {
xlow = x + 1;
} else {
xhigh = x;
}
}
return 0;
}
Yet smarter would be to use the solution for x and look whether it is an integer:
ax² + bx + c' = 0 where c' = c - n
x = ...
I was playing around with this and I noticed something. The smart numbers are
1 2 4 7 11 16 22 29 ...
If you subtract one you get
0 1 3 6 10 15 21 28 ...
0 1 2 3 4 5 6 7 ...
The above sequence happens to be the sum of the first n numbers starting with 0 which is n*(n+1)/2. So add 1 to that and you get a smart number.
Since n and n+1 are next door to each other you can derive them by reversing the process.
Take 29, subtract 1 = 28, * 2 = 56. The sqrt(56) rounded up is 8. So the 8th smart number (counting from 0) is 29.
Using that information you can detect a smart number without a loop by simply reversing the process.
public static int isSmart(int v) {
int vv = (v-1)*2;
int sq = (int)Math.sqrt(vv);
int chk = (sq*(sq+1))/2 + 1;
return (chk == v) ? 1 : 0;
}
Using a version which supports longs have verified this against the iterative process from 1 to 10,000,000,000.
I am creating a program that will take a wordlist of 5 000 strings and find the shortest path from one string to another. For example abc -> bac could print "abc, bbc, bac".
I am pretty sure about what I want to do, the only thing I'm not completely sure about is what datastructure should represent my wordlist. The goal is for the search(BFS) to run as fast as possible, so to sacrifice some space is no problem. I am thinking either a BST or an adjacency list, but since I'm no expert at datastrutcutres' timecomplexity I want to be certain before I start adjusting my code. Can anyone recommend one of the structures over the other? Or have I perhaps missed a datastructure that is an obvious alternative for this?
Looks like what you are looking for is the Levenshtein distance, here is the Rosetta code implementation, you should be able to change it to suit your need:
public class Levenshtein {
public static int distance(String a, String b) {
a = a.toLowerCase();
b = b.toLowerCase();
// i == 0
int [] costs = new int [b.length() + 1];
for (int j = 0; j < costs.length; j++)
costs[j] = j;
for (int i = 1; i <= a.length(); i++) {
// j == 0; nw = lev(i - 1, j)
costs[0] = i;
int nw = i - 1;
for (int j = 1; j <= b.length(); j++) {
int cj = Math.min(1 + Math.min(costs[j], costs[j - 1]), a.charAt(i - 1) == b.charAt(j - 1) ? nw : nw + 1);
nw = costs[j];
costs[j] = cj;
}
}
return costs[b.length()];
}
public static void main(String [] args) {
String [] data = { "kitten", "sitting", "saturday", "sunday", "rosettacode", "raisethysword" };
for (int i = 0; i < data.length; i += 2)
System.out.println("distance(" + data[i] + ", " + data[i+1] + ") = " + distance(data[i], data[i+1]));
}
}
So here is my code to the above question. I am curious to know why the code doesn't work in all scenarios such as:
System.out.println(stringMatch("aabbccdd", "abbbxxd")); // Should be 1, but was 3
System.out.println(stringMatch("aaxxaaxx", "iaxxai")); // Should be 3, but was 5
System.out.println(stringMatch("iaxxai", "aaxxaaxx")); // Should be 3, but was 5
public int stringMatch(String a, String b) {
int counter = 0;
for (int i = 0; i < a.length() - 1; i++) {
for (int j = 0; j < b.length() - 1; j++) {
String aSub = a.substring(i, i + 2);
String bSub = b.substring(j, j + 2);
if (aSub.equals(bSub)) {
counter++;
}
}
}
return counter;
}
As Ashu mentioned, your program is actually calculating the number of strings which are the same of length two.
Take the first example you mentioned..
aabbccdd, abbbxxd
So your for loops are structured in a way where the 'aa' substring is being compared with each two letter substring in the second string 'abbbxxd'
In the end you have ab matching with ab, bb matching with bb, bb with bb again,
(since you have 3 b's in the second string) and therefore you get 3 as the output, when really it should be 1, since only one bb is matched to the same position (third and fourth letters)
The question asks you to put two Strings next to each other and check on how many positions they have the same set of two characters (be careful that they can overlop). In other words:
aabbccdd aaxxaaxx iaxxai
abbbxxd iaxxai aaxxaaxx
--^^---- (1) -^^^^--- (3) -^^^^--- (3)
(bb) (ax, xx, xa) (ax, xx, xa)
As you can hopefully see, you need only one loop to do this, since you're always comparing the same indices of String a and String b. But your code has 2 loops. What is does is check if any two characters of String a are anywhere in String b:
for string "aabbccdd":
Iteration i1: Iteration i2: Iteration i3: Iteration i4: etc...
abbbxxd abbbxxd abbbxxd abbbxxd
aa (0) ab (1) bbb (2) bc (0)
You need to get rid of the first loop and then fix your loop to run until the 2 before the end of the shortest String so you don't get an ArrayIndexOutOfBoundsException:
public int stringMatch(String a, String b) {
int counter = 0;
for(int i = 0; ((i < a.length() - 2) && (i < b.length() -2)); i++){
String aSub = a.substring(i, i + 2);
String bSub = b.substring(i, i + 2);
if(aSub.equals(bSub)){
counter++;
}
}
return counter;
}
Thanks Faaiz Haque for spotting the error in my for statement! Both statements must be true for the loop to keep running, not either.
One error is < ?.length() - 2 as the iteration is for i+2 < length().
public static int stringMatch(String a, String b) {
int counter = 0;
for (int i = 0; i < a.length() - 1; i++) {
for (int j = 0; j < b.length() - 1; j++) {
String aSub = a.substring(i, i + 2);
String bSub = b.substring(j, j + 2);
if (aSub.equals(bSub)) {
System.out.println(aSub);
counter++;
}
}
}
return counter;
}
public static void main(String[] args) {
System.out.print(stringMatch("aabbccdd", "abbbxxd"));
System.out.println("****");
System.out.println(stringMatch("aaxxaaxx", "iaxxai"));
System.out.println("****");
System.out.println(stringMatch("iaxxai", "aaxxaaxx"));
}
Use the above code to generate the substring matches. The output generated is following:
ab
bb
bb
3
****
ax
xx
xa
ax
xx
5
****
ax
ax
xx
xx
xa
5
Which is, in turn, a correct output as per your code. If you want a unique count for the matched substrings, you can try to insert substrings in a set and return the size of the set as the output of your function.
Firstly you should find greater string :
String tempA = "";
String tempB = "";
if (a.length() > b.length()){
tempA = a;
tempB = b;
}else{
tempA = b;
tempB = a;
}
Then you need control some special cases such as when i equals aTemp.length()-1 or j equals bTemp.length()-1.In this cases aTemp.substring(i, i + 2); and bTemp.substring(j, j + 2); statements occur errors.
i should iterate until aTemp.length()-2
j should iterate until bTemp.length()-2
You need to store finded position to avoid duplicate counting (I did is by using ArrayList)
For this example : stringMatch("iaxxai", "aaxxaaxx")
The answer must be 3 :
ax : iaxxai aaxxaaxx
xx : iaxxai aaxxaaxx
xa : iaxxai aaxxaaxx
public static int stringMatch(String a, String b) {
ArrayList<String> list = new ArrayList<String>();
int counter = 0;
String tempA = "";
String tempB = "";
if (a.length() > b.length()){//to find the bigger string
tempA = a;
tempB = b;
}else{
tempA = b;
tempB = a;
}
for(int i = 0; i < tempA.length() - 2; i++){
for(int j = 0; j < tempB.length() - 2; j++){
String aSub;
String bSub;
if (i == tempA.length() - 2){//when i == tempA.length() - 2 you need to take the substring(i to end of the string)
aSub = tempA.substring(i);
}else{
aSub = tempA.substring(i, i + 2);
}
if (j == tempB.length() - 2){
bSub = tempB.substring(j);
}else{
bSub = tempB.substring(j, j + 2);
}
if(aSub.equals(bSub) && list.indexOf(aSub) == -1 ){//list.indexOf(aSub) == -1 means there is no element in the list
list.add(aSub);//or bSub
counter++;
}
}
}
return counter;
}
I'm trying to implement the CYK algorithm based on wikipedia pseudocode. When I test the string "a b" for the grammar input:
S->A B
A->a
B->b
It gives me false, and I think it should be true. I have an arraylist called AllGrammar that contains all the rules. For the example above it would contain:
[0]: S->A B[1]: A->a[2]: B->bFor the example S->hello and the input string hello it gives me true as it should. More complex tests (more productions) gives me false :S
public static boolean cyk(String entrada) {
int n = entrada.length();
int r = AllGrammar.size();
//Vector<String> startingsymbols = getSymbols(AllGrammar);
String[] ent = entrada.split("\\s");
n = ent.length;
System.out.println("length of entry" + n);
//let P[n,n,r] be an array of booleans. Initialize all elements of P to false.
boolean P[][][] = initialize3DVector(n, r);
//n-> number of words of string entrada,
//r-> number of nonterminal symbols
//This grammar contains the subset Rs which is the set of start symbols
for (int i = 1; i < n; i++) {
for(int j = 0; j < r; j++) {
String[] rule = (String[]) AllGrammar.get(j);
if (rule.length == 2) {
if (rule[1].equals(ent[i])) {
System.out.println("entrou");
System.out.println(rule[1]);
P[i][1][j + 1] = true;
}
}
}
}
for(int i = 2; i < n; i++) {
System.out.println("FIRST:" + i);
for(int j = 1; j < n - i + 1; j++) {
System.out.println("SECOND:" + j);
for(int k = 1; k < i - 1; k++) {
System.out.println("THIRD:" + k);
for(int g = 0; g < r; g++) {
String[] rule = (String[]) AllGrammar.get(g);
if (rule.length > 2) {
int A = returnPos(rule[0]);
int B = returnPos(rule[1]);
int C = returnPos(rule[2]);
System.out.println("A" + A);
System.out.println("B" + B);
System.out.println("C" + C);
if (A!=-1 && B!=-1 && C!=-1) {
if (P[j][k][B] && P[j + k][i - k][C]) {
System.out.println("entrou2");
P[j][i][A] = true;
}
}
}
}
}
}
}
for(int x = 0; x < r; x++) {
if(P[1][n][x]) return true;
}
return false;
}
As compared to the CYK algorithm:
you have indexing starting at 1, but the arrays would appear to start at 0
the function returnpos() is not defined, and it's not obvious what it does.
It would seem the problems could be fairly basic in the the use of indexes. If you are new to the language, you might want to get a refresher.