Java: Wildcard Pattern Matching - java

I have been trying to solve the Wildcard pattern matching and I have found a working solution in the below link:
http://www.geeksforgeeks.org/wildcard-character-matching/
I have written an Equivalent java code for the C code given in the above link, which is:
public class wildcard
{
public static void main(String[] args)
{
test("g*ks", "geeks");
//test("g*k", "gee");
//test("c*d*", "cad");
}
static boolean matches(String format, String data)
{
if (format.length() == 0 && data.length() == 0)
{
return true;
}
if ((format.charAt(0) == '*' && format.charAt(1) != 0 && data.length() == 0) && (format.length() != 0 && data.length() != 0))
{
return false;
}
if ((format.charAt(0) == '?' || format.charAt(0) == data.charAt(0)) && (format.length() != 0 && data.length() != 0))
{
return matches(format.substring(1), data.substring(1));
}
if ((format.charAt(0) == '*')&& (format.length() != 0 && data.length() != 0))
{
return matches(format.substring(1), data) || matches(format, data.substring(1));
}
return false;
}
static void test(String first, String second)
{
System.out.println(matches(first, second));
}
}
On Execution, a String out of bounds Exception is thrown, which is:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.String.charAt(String.java:658)
at wildcard.matches(wildcard.java:29)
at wildcard.matches(wildcard.java:36)
at wildcard.matches(wildcard.java:42)
at wildcard.matches(wildcard.java:42)
at wildcard.matches(wildcard.java:36)
at wildcard.test(wildcard.java:52)
at wildcard.main(wildcard.java:16)
I can see that this exception occurs at the CharAt() method, is there any other way to make this work??

:)
First I noticed that the code && (format.length() != 0 && data.length() != 0) is not on the original code from the page you provide and are causing conflicts with your algorithm so I remove it and it looks like this:
static boolean matches(String format, String data) {
if (format.length() == 0 && data.length() == 0) {
return true;
}
if (format.charAt(0) == '*' && format.charAt(1) != 0 && data.length() == 0) {
return false;
}
if (format.charAt(0) == '?' || format.charAt(0) == data.charAt(0)) {
return matches(format.substring(1), data.substring(1));
}
if (format.charAt(0) == '*') {
return matches(format.substring(1), data) || matches(format, data.substring(1));
}
return false;
}
The problems I talked about are in the second condition you have data.length() == 0 and in the code I remove was data.length() != 0, so that condition was always false because the length cannot be 0 and not 0 at the same time.
I discovered two problems. The first one was that some cases like matches("ge?ks*", "geeksforgeeks") end up with having a single wildcard at the format and crashed on if (format.charAt(0) == '*' && format.charAt(1) != 0 && data.length() == 0) because of format.charAt(1). To solve this I add the next code to the algorithm:
if (format.length() == 1 && format.charAt(0) == '*')
return true;
The other problem was when the format was empty but still have data and solve it with:
if (format.length() == 0 && data.length() > 0)
return false;
The final algorithm looks like this:
static boolean matches(String format, String data) {
if (format.length() == 0 && data.length() == 0)
return true;
if (format.length() == 1 && format.charAt(0) == '*')
return true;
if (format.length() == 0 && data.length() > 0)
return false;
if (format.charAt(0) == '*' && format.charAt(1) != 0 && data.length() == 0)
return false;
if (format.charAt(0) == '?' || format.charAt(0) == data.charAt(0))
return matches(format.substring(1), data.substring(1));
if (format.charAt(0) == '*')
return matches(format.substring(1), data) || matches(format, data.substring(1));
return false;
}

Related

Reverse loop TicTacToe

I've got loop:
for (int i = 0; i<3; i++){
System.out.println(i);
}
output:
0
1
2
I need to reverse this loop to output:
2
1
0
I need it because I work on TicTacToe Java game.
Here is my code for check win:
static boolean checkWin(char dot) {
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
if (map[0][i] == dot && i == 2) {
return true;
}
if (map[1][i] == dot && i == 2) {
return true;
}
if (map[2][i] == dot && i == 2) {
return true;
}
if (map[i][0] == dot && i == 2) {
return true;
}
if (map[i][1] == dot && i == 2) {
return true;
}
if (map[i][2] == dot && i == 2) {
return true;
}
if (map[i][i] == dot && i == 2) {
return true;
}
if (map[i][0] == dot && i == 2) {
return true;
}
}
}
return false;
}
last thing that I need to refactor this method:
static boolean checkWin(char dot) {
if (map[0][0] == dot && map[0][1] == dot && map[0][2] == dot) {
return true;
}
if (map[1][0] == dot && map[1][1] == dot && map[1][2] == dot) {
return true;
}
if (map[2][0] == dot && map[2][1] == dot && map[2][2] == dot) {
return true;
}
if (map[0][0] == dot && map[1][0] == dot && map[2][0] == dot) {
return true;
}
if (map[0][1] == dot && map[1][1] == dot && map[2][1] == dot) {
return true;
}
if (map[0][2] == dot && map[1][2] == dot && map[2][2] == dot) {
return true;
}
if (map[0][0] == dot && map[1][1] == dot && map[2][2] == dot) {
return true;
}
if (map[0][2] == dot && map[1][1] == dot && map[2][0] == dot) {
return true;
}
return false;
}
}
I almost done it.
Last thing that i need refactor this part of code:
if (map[0][2] == dot && map[1][1] == dot && map[2][0] == dot) {
return true;
}
to something like
if (map[i][0] == dot && i == 2) {
return true;
}
Main question is here:
for (int i = 0; i<3; i++){
System.out.println(i);
}
output:
0
1
2
I need to reverse this loop to output:
2
1
0
to feel this last part:
if (map[i][0] == dot && i == 2) {
return true;
}
i need to feel this last condition with values 2 1 0
if (map[i][insert here] == dot && i == 2) {
return true;
}
Please Help.
If all you want to do is reverse the loop output, you can just invert what you're doing in the for loop
for (int i = 2; i>=0; i--){
System.out.println(i);
}
output:
2
1
0
As a quick example.

Java && || operators precedent

I need help with one if condition in java code
public class Main
{
public static void main(String[] args) {
String sHeaderStatus = "1";
Boolean hasButton = false;
Boolean editableLineStatus =true;
String sFrom = "REQ";
int canChangeSupplier = 0;
if ((sHeaderStatus.equals("1") || canChangeSupplier == 1 &&
(sHeaderStatus.equals("10") || sHeaderStatus.equals("14") || sHeaderStatus.equals("85") || sHeaderStatus.equals("86") || sHeaderStatus.equals("87"))
|| hasButton && editableLineStatus && !sHeaderStatus.equals("85")) || sFrom.equals("APPROVAL")) {
String valdiaton ="true11";
System.out.println(valdiaton);
}
}
result is true11
public class Main
{
public static void main(String[] args) {
String sHeaderStatus = "1";
Boolean hasButton = false;
Boolean editableLineStatus =false; //changed this one to false
String sFrom = "REQ";
int canChangeSupplier = 0;
if ((sHeaderStatus.equals("1") || canChangeSupplier == 1 &&
(sHeaderStatus.equals("10") || sHeaderStatus.equals("14") || sHeaderStatus.equals("85") || sHeaderStatus.equals("86") || sHeaderStatus.equals("87"))
|| hasButton && editableLineStatus && !sHeaderStatus.equals("85")) || sFrom.equals("APPROVAL")) {
String valdiaton ="true11";
System.out.println(valdiaton);
}
}
result is still true11
I am not able to understood the issue.
Per my understanding...
sHeaderStatus.equals("1") || canChangeSupplier == 1 // gave true
(sHeaderStatus.equals("10") || sHeaderStatus.equals("14") || sHeaderStatus.equals("85") || sHeaderStatus.equals("86") || sHeaderStatus.equals("87"))
|| hasButton // gave false
become true && false && true && true
Similarly second code would become true && false && false &&true
Am not sure how this become true and below line printed.
&& happens before ||
Write the code like this
if (
(
sHeaderStatus.equals("1")
|| canChangeSupplier == 1 && (sHeaderStatus.equals("10") || sHeaderStatus.equals("14") || sHeaderStatus.equals("85") || sHeaderStatus.equals("86") || sHeaderStatus.equals("87"))
|| hasButton && editableLineStatus && !sHeaderStatus.equals("85")
)
|| sFrom.equals("APPROVAL")
)
You can see that you always will have (something) || false with the values given.
And changing only editableLineStatus will modify only the operator "grouping" for hasButton && editableLineStatus && !sHeaderStatus.equals("85").
However, regardless of what you change that to, you have sHeaderStatus.equals("1"), which is true, resulting in logic of
(true || (false && false) || (false && true/false && true)) || false
which, in total, is true, therefore entering the conditional

Sorting using collections for multiple parameter with null values

I wanted to sort list of records in my using multiple comparators.
It contains null values as well for some fields.
I used java collections, to sort it, but it works only for one filed which is places at top.
My code:
Collections.sort(userListResult, new Comparator<UserDto>()
{
#Override
public int compare(UserDto userDto1, UserDto userDto2)
{
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() != null && userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()) != 0) {
return userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate());
}
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() == null) {
return -1;
}
if (userDto1.getLastLoginDate() == null && userDto2.getLastLoginDate() != null) {
return 1;
}
if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() != null && userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate()) != 0) {
return userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate());
}
if (userDto1.getLastActionDate() == null && userDto2.getLastActionDate() == null) {
return 0;
}
if (userDto1.getLastActionDate() == null && userDto2.getLastActionDate() != null) {
return 1;
}
if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() == null) {
return -1;
}
if (userDto1.getLastName() != null && userDto2.getLastName() != null && userDto1.getLastName().compareTo(userDto2.getLastName()) != 0) {
return userDto1.getLastName().compareTo(userDto2.getLastName());
}
if (userDto1.getLastName() != null && userDto2.getLastName() == null) {
return -1;
}
if (userDto1.getLastName() == null && userDto2.getLastName() != null) {
return 1;
}
if (userDto1.getFirstName().compareTo(userDto2.getFirstName()) != 0) {
return userDto1.getFirstName().compareTo(userDto2.getFirstName());
}
if (userDto1.getFirstName() != null && userDto2.getFirstName() == null) {
return -1;
}
if (userDto1.getFirstName() == null && userDto2.getFirstName() != null) {
return 1;
}
return 0;
}
});*/
I wanted to sort descending of LastLoginDate, LastActionDate. Either or both fields might be null in some cases.
And ascending of names. And to display all other null field values(LastLoginDate, LastActionDate) at last.
But when i sort, with this code it takes only the first defined method to sort.
Example, if i have 3 records having same, "LastLoginDate" then it should check sort with "LastActionDate" values. But its not sorted with this logic.
So i added another algorithm to sort, since some fields has null values it is not properly sorted.
My second logic:
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() != null && userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()) != 0) {
compareLastLoginDate = userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate());
}
if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() != null && userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate()) != 0) {
compareLastActionDate = userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate());
}
if (userDto1.getLastName() != null && userDto2.getLastName() != null && userDto1.getLastName().compareTo(userDto2.getLastName()) != 0) {
compareLastName = userDto1.getLastName().compareTo(userDto2.getLastName());
}
if (compareLastLoginDate == 0) {
return ((compareLastActionDate == 0) ? compareLastName : compareLastActionDate);
}
else {
return compareLastLoginDate;
}
Here i am getting the integer values to compare it "compareLastActionDate, compareLastName, compareLastLoginDate".
I used simple date format to filter the list.
Here is my working code,
public int compare(UserDto userDto1, UserDto userDto2) {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() != null && userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()) != 0) {
String Date1 = format.format(userDto1.getLastLoginDate());
String Date2 = format.format(userDto2.getLastLoginDate());
if (Date1.equals(Date2)) {
if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() != null && userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate()) != 0) {
String Date3 = format.format(userDto1.getLastActionDate());
String Date4 = format.format(userDto2.getLastActionDate());
if (Date3.equals(Date4)) {
if (userDto1.getLastName() != null && userDto2.getLastName() != null && userDto1.getLastName().compareTo(userDto2.getLastName()) != 0) {
return userDto1.getLastName().compareTo(userDto2.getLastName());
}
} else {
return userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate());
}
}
} else {
return userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate());
}
}
if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() == null) {
return -1;
}
if (userDto1.getLastLoginDate() == null && userDto2.getLastLoginDate() != null) {
return 1;
}
if (userDto1.getLastLoginDate() == null && userDto2.getLastLoginDate() == null) {
return userDto1.getLastName().compareTo(userDto2.getLastName());
} }
I would recommend you to use the java8 comparators, it provides some helpful methods to compare based in multiple attributes with thenComparing().
If you don't want to / can't use, try two wrap part of that repetitive code in one or multiple custom Comparator or in a helper method.
Here, for simplicity, the following helper method is used (in java8 you can use method references):
public static <R extends Comparable<? super R>> int nullSort(R r1, R r2,
boolean ascending,
boolean nullsFirst) {
R rs1 = ascending ? r1 : r2, rs2 = ascending ? r2 : r1;
if (rs1 != null && rs2 != null) return rs1.compareTo(rs2);
else if (r1 == null && r2 == null) return 0;
else if (r1 == null) return (nullsFirst ? -1 : 1);
else return (nullsFirst ? 1 : -1);
}
In your method, you could use this nullSort() method, to check first for lastLoginDate descending and nulls last (false, false), then lastActionDate again descending and nulls last.
A difference with your comparator is that you stop evaluating here when both are null. It would be better that when lastLoginDate and lastActionDate are nulls you keep ordering by lastName and firstName. If you don't want this, you can add if (result == 0) return 0; after the second if in the method below.
Then after the dates are compared, you compare lastName and then firstName both ascending and nulls last (true, false).
#Override
public int compare(UserDto dto1, UserDto dto2) {
int result;
if ((result = nullSort(dto1.getLastLoginDate(), dto2.getLastLoginDate(),
false, false)) != 0) return result;
if ((result = nullSort(dto1.getLastActionDate(), dto2.getLastActionDate(),
false, false)) != 0) return result;
if ((result = nullSort(dto1.getLastName(), dto2.getLastName(),
true, false)) != 0) return result;
if ((result = nullSort(dto1.getFirstName(), dto2.getFirstName(),
true, false)) != 0) return result;
return 0;
}

Java Multi-Dimensional Arrays in a Method

I'm knew with multi-dimensional arrays and I kind of know the basics but I'm stuck on combining them into a boolean method. In this case, I'm trying to find out how I can make this method simplified which will function as:
Comparing one array with a location (row:column) to another array (with the same location).
If all locations from both arrays match, it should return true.
The method below works with what I have for my code but I want to know the proper way on how to not "hard code" the numbers single handedly. Would I need to use a nested for loop for comparing both arrays?
Thanks for the assistance~
public static boolean gameIsWon(int[][] workingPuzzle, int[][] solvedPuzzle)
{
if (workingPuzzle[0][0] == solvedPuzzle[0][0] &&
workingPuzzle[0][1] == solvedPuzzle[0][1] &&
workingPuzzle[0][2] == solvedPuzzle[0][2] &&
workingPuzzle[0][3] == solvedPuzzle[0][3] &&
workingPuzzle[0][4] == solvedPuzzle[0][4] &&
workingPuzzle[0][5] == solvedPuzzle[0][5] &&
workingPuzzle[0][6] == solvedPuzzle[0][6] &&
workingPuzzle[0][7] == solvedPuzzle[0][7] &&
workingPuzzle[0][8] == solvedPuzzle[0][8] &&
workingPuzzle[1][0] == solvedPuzzle[1][0] &&
workingPuzzle[1][1] == solvedPuzzle[1][1] &&
workingPuzzle[1][2] == solvedPuzzle[1][2] &&
workingPuzzle[1][3] == solvedPuzzle[1][3] &&
workingPuzzle[1][4] == solvedPuzzle[1][4] &&
workingPuzzle[1][5] == solvedPuzzle[1][5] &&
workingPuzzle[1][6] == solvedPuzzle[1][6] &&
workingPuzzle[1][7] == solvedPuzzle[1][7] &&
workingPuzzle[1][8] == solvedPuzzle[1][8] &&
workingPuzzle[2][0] == solvedPuzzle[2][0] &&
workingPuzzle[2][1] == solvedPuzzle[2][1] &&
workingPuzzle[2][2] == solvedPuzzle[2][2] &&
workingPuzzle[2][3] == solvedPuzzle[2][3] &&
workingPuzzle[2][4] == solvedPuzzle[2][4] &&
workingPuzzle[2][5] == solvedPuzzle[2][5] &&
workingPuzzle[2][6] == solvedPuzzle[2][6] &&
workingPuzzle[2][7] == solvedPuzzle[2][7] &&
workingPuzzle[2][8] == solvedPuzzle[2][8] &&
workingPuzzle[3][0] == solvedPuzzle[3][0] &&
workingPuzzle[3][1] == solvedPuzzle[3][1] &&
workingPuzzle[3][2] == solvedPuzzle[3][2] &&
workingPuzzle[3][3] == solvedPuzzle[3][3] &&
workingPuzzle[3][4] == solvedPuzzle[3][4] &&
workingPuzzle[3][5] == solvedPuzzle[3][5] &&
workingPuzzle[3][6] == solvedPuzzle[3][6] &&
workingPuzzle[3][7] == solvedPuzzle[3][7] &&
workingPuzzle[3][8] == solvedPuzzle[3][8] &&
workingPuzzle[4][0] == solvedPuzzle[4][0] &&
workingPuzzle[4][1] == solvedPuzzle[4][1] &&
workingPuzzle[4][2] == solvedPuzzle[4][2] &&
workingPuzzle[4][3] == solvedPuzzle[4][3] &&
workingPuzzle[4][4] == solvedPuzzle[4][4] &&
workingPuzzle[4][5] == solvedPuzzle[4][5] &&
workingPuzzle[4][6] == solvedPuzzle[4][6] &&
workingPuzzle[4][7] == solvedPuzzle[4][7] &&
workingPuzzle[4][8] == solvedPuzzle[4][8] &&
workingPuzzle[5][0] == solvedPuzzle[5][0] &&
workingPuzzle[5][1] == solvedPuzzle[5][1] &&
workingPuzzle[5][2] == solvedPuzzle[5][2] &&
workingPuzzle[5][3] == solvedPuzzle[5][3] &&
workingPuzzle[5][4] == solvedPuzzle[5][4] &&
workingPuzzle[5][5] == solvedPuzzle[5][5] &&
workingPuzzle[5][6] == solvedPuzzle[5][6] &&
workingPuzzle[5][7] == solvedPuzzle[5][7] &&
workingPuzzle[5][8] == solvedPuzzle[5][8] &&
workingPuzzle[6][0] == solvedPuzzle[6][0] &&
workingPuzzle[6][1] == solvedPuzzle[6][1] &&
workingPuzzle[6][2] == solvedPuzzle[6][2] &&
workingPuzzle[6][3] == solvedPuzzle[6][3] &&
workingPuzzle[6][4] == solvedPuzzle[6][4] &&
workingPuzzle[6][5] == solvedPuzzle[6][5] &&
workingPuzzle[6][6] == solvedPuzzle[6][6] &&
workingPuzzle[6][7] == solvedPuzzle[6][7] &&
workingPuzzle[6][8] == solvedPuzzle[6][8] &&
workingPuzzle[7][0] == solvedPuzzle[7][0] &&
workingPuzzle[7][1] == solvedPuzzle[7][1] &&
workingPuzzle[7][2] == solvedPuzzle[7][2] &&
workingPuzzle[7][3] == solvedPuzzle[7][3] &&
workingPuzzle[7][4] == solvedPuzzle[7][4] &&
workingPuzzle[7][5] == solvedPuzzle[7][5] &&
workingPuzzle[7][6] == solvedPuzzle[7][6] &&
workingPuzzle[7][7] == solvedPuzzle[7][7] &&
workingPuzzle[7][8] == solvedPuzzle[7][8] &&
workingPuzzle[8][0] == solvedPuzzle[8][0] &&
workingPuzzle[8][1] == solvedPuzzle[8][1] &&
workingPuzzle[8][2] == solvedPuzzle[8][2] &&
workingPuzzle[8][3] == solvedPuzzle[8][3] &&
workingPuzzle[8][4] == solvedPuzzle[8][4] &&
workingPuzzle[8][5] == solvedPuzzle[8][5] &&
workingPuzzle[8][6] == solvedPuzzle[8][6] &&
workingPuzzle[8][7] == solvedPuzzle[8][7] &&
workingPuzzle[8][8] == solvedPuzzle[8][8]
)
return true;
else
return false;
}
You need to learn about loops.
And about storing a two-dimensional matrix in a one-dimensional array using index mapping (which is easier to handle than a two-dimensional array).
But in this particular case:
return java.util.Arrays.deepEquals(workingPuzzle, solvedPuzzle);
Use nested for loops based on the array lengths.
public static boolean gameIsWon(int[][] workingPuzzle, int[][] solvedPuzzle) {
if(workingPuzzle.length != solvedPuzzle.length) {
return false;
}
for(int i = 0; i < workingPuzzle.length; i++) {
if(workingPuzzle[i].length != solvedPuzzle[i].length) {
return false;
}
for(int j = 0; j < workingPuzzle[i].length; j++) {
if(workingPuzzle[i][j] != solvedPuzzle[i][j]) {
return false;
}
}
}
return true;
}

Check which (combinations) of parameters are null

Suppose I have 4 variables
String a;
String b;
String c;
String d;
I want to check if individual variable or combination of variable is not Null and act accordingly.
For example one way to do this is using if-else this way
if(a!=null && b == null && c == null && d == null) {
//doSomething }
else if(a==null && b!= null && c == null && d == null) {
//doSomething }
else if(a==null && b!= null && c == null && d == null) {
//doSomething }
else if(a==null && b== null && c != null && d == null) {
//doSomething }
......
//Similarly combination of two variables
if(a!=null && b != null && c == null && d == null) {
//doSomething }
else if(a!=null && b== null && c != null && d == null) {
//doSomething }
else if(a!=null && b== null && c == null && d != null) {
//doSomething }
......
//and so on
//Similarly combination of three variables
if(a!=null && b != null && c != null && d == null) {
//doSomething }
else if(a!=null && b== null && c != null && d != null) {
//doSomething }
else if(a!=null && b== null && c == null && d != null) {
//doSomething }
....
How to achieve this kind of situation Switch even don't accept null
I thought of using queue as it dont allow null values but i need to have a key for the variable so that I can get the value and manipulate something. help will be appreciated
You could build an additional variable to achieve this a with switch statement:
int switchvar = 0;
if (a == null) {switchvar += 1;}
if (b == null) {switchvar += 10;}
if (c == null) {switchvar += 100;}
if (d == null) {switchvar += 1000;}
and then you can use
switch (switchvar) {
case(1): //only a ==null
...
case(101): //a == null and c == null
....
case(1011): //a,b,d null
....
case(1111): // all variables null
}

Categories