need help in algorithm of deterministic finite automata - java

i'm working on an application on deterministic finite automata but there's a problem in algorithm, all the details will be set from user's input. it becomes problem if user inputs details like following
totalStates = 3 //user input
initialState = 1 //user input
finalState = 3 //user input
//transitions created in linked-list
//contains three data members(prevState(int), transition symbol(String), nextState(int))
2->b->1 //user input
1->a->2 //user input
2->b->3 //user input
string = ab
this is a valid string for this automata but not according to my algorithm, there's problem in algo that it changes the states according to transitions indexes. like
for 'a' it works good and change the state from 1 to 2
for 'b' it choose the transition from 2 to 1 not 2 to 3
because 2->b->1 is created before 2->b->3
how to solve this using linked-list( for transitions) and String(for string input) in java. Thanks
complete code is
public boolean match() {
s = str;
current = FiniteAutomata.startState;
for (int t = 0; t < str.length(); t++) {
curFlag = false;
list2 = originalList.head;
while (list2 != null) {
if (current == list2.initialState) {
for (int i = 0; i < s.length(); i++) {
String s2 = delL(s.toCharArray(), i);
if (s2.equals(list2.transitionString)) {
current = list2.finalState;
curFlag = true;
s = delF(s.toCharArray(), i);
}
}
}
if (curFlag) {
break;
}
list2 = list2.next;
}
}
boolean flag = false;
if (s.equals("")) {
for (int i = 0; i < FiniteAutomata.finalStates.length; i++) {
if (current == FiniteAutomata.finalStates[i]) {
flag = true;
}
}
}
if (flag) {
return true;
} else {
return false;
}
}
String delF(char[] temp, int c) {
String s = "";
for (int i = c + 1; i < temp.length; i++) {
s = s + temp[i];
}
return s;
}
String delL(char[] temp, int c) {
String s = "";
for (int i = 0; i <= c; i++) {
s = s + temp[i];
}
return s;
}

Related

How to eliminate a nested for loop to get O(n)?

In the code below I have a double for loop resulting in a time complexity of O^2 in method getResponse(). This code prompts the user for a 10 integer sequence string and an uppercase sensitive pin. It then converts the pin to numbers on a phone pad ie. [ABC] --> 2, [DEF] --> 3. Lastly a response array is generated with each digit of the new phone pin corresponding to indexes of sequence. So input "0123456789","HAM", response = "426"
import java.util.Scanner;
public class Test {
public static final int SEQ_DIGITS = 10;
public static final String ERR_SEQ = "Invalid sequence";
public static final String ERR_PIN = "Invalid PIN";
public static int letterToPhone(char c) {
int phoneNumber = 0;
if (Character.toString(c).matches("[ABC]")) {
phoneNumber = 2;
} else if (Character.toString(c).matches("[DEF]")) {
phoneNumber = 3;
} else if (Character.toString(c).matches("[GHI]")) {
phoneNumber = 4;
} else if (Character.toString(c).matches("[JKL]")) {
phoneNumber = 5;
} else if (Character.toString(c).matches("[MNO]")) {
phoneNumber = 6;
} else if (Character.toString(c).matches("[PQRS]")) {
phoneNumber = 7;
} else if (Character.toString(c).matches("[TUV]")) {
phoneNumber = 8;
} else if (Character.toString(c).matches("[WXYZ]")) {
phoneNumber = 9;
}
return phoneNumber;
}
public static int[] getResponse(String pin, int[] values) {
int[] response = new int[pin.length()];
for(int i = 0; i < pin.length(); i++) {
for (int j = 0; j < values.length; j++) {
int x = letterToPhone(pin.charAt(i));
if(x == j) {
response[i] = values[j];
}
}
}
return response;
}
public static boolean stringIsLengthK(String s, int k) {
boolean isLength = false;
if (s.length() == k) {
isLength = true;
}
return isLength;
}
public static boolean allDigits(String s) {
boolean isDigit = true;
for (int i = 0; i < s.length(); i++) {
if (!(Character.isDigit(s.charAt(i)))) {
isDigit = false;
break;
}
}
return isDigit;
}
public static boolean allUppercaseLetters(String s) {
boolean isUpper = true;
for (int i = 0; i < s.length(); i++) {
if (!(Character.isUpperCase(s.charAt(i)))) {
isUpper = false;
break;
}
}
return isUpper;
}
public static int[] digitStringToIntArray(String s) {
int[] arrayS = new int[s.length()];
for(int i = 0; i < arrayS.length; i++) {
for(int j = 0; j < SEQ_DIGITS; j++) {
if (((int) s.charAt(i) - 48) == j) {
arrayS[i] = j;
}
}
}
return arrayS;
}
public static int countValues(int value, int[] values) {
int count = 0;
for(int i = 0; i < values.length; i++) {
if(value == values[i]) {
count++;
}
}
return count;
}
public static int numPossible(int[] response, int[] values) {
int product = 1;
int[] count = new int[response.length];
for (int i = 0; i < count.length; i++) {
count[i] = countValues(response[i], values);
}
for(int i=0; i<response.length; i++){
product = product * count[i];
}
return product;
}
public static void main(String[] args) {
try (Scanner in = new Scanner(System.in)) {
System.out.printf("Enter value sequence: ");
final String seq = in.nextLine();
System.out.printf("Enter PIN: ");
final String pin = in.nextLine();
if (!(allUppercaseLetters(pin))) {
throw new AssertionError(ERR_PIN);
} else if (!(allDigits(seq)) || !(stringIsLengthK(seq, SEQ_DIGITS))) {
throw new AssertionError(ERR_SEQ);
}
int[] seqArray = new int[SEQ_DIGITS];
seqArray = digitStringToIntArray(seq);
int[] response = new int[SEQ_DIGITS];
response = getResponse(pin, seqArray);
System.out.printf("Response: ");
for (int i = 0; i < response.length; i++) {
System.out.printf("%d", response[i]);
}
System.out.printf("%n");
numPossible(response, seqArray);
} catch (Error e) {
System.out.println(e.getMessage());
}
}
}
I want to be to able to accommodate larger sequence numbers without a scaling of n^2. Is there a way to change the for loop to instead compare the int x = letterToPhone(pin.charAt(i)); value in getResponse() to a range of integers such as "[0-9]"
One easy optimization of constant factors is to move the call to letterToPhone() out of the inner loop.
And yes, you can compare the x value to a range, eliminating the need for the inner loop.
for(int i = 0; i < pin.length(); i++) {
int x = letterToPhone(pin.charAt(i));
if ( (0 <= x) && (x < values.length)) {
response[i] = values[x];
}
}
Another optimization of constant factors would be to replace all the function calls in letterToPhone() with a switch statement. The compiler may choose to optimize that into a table lookup.

When running code, sorting method prints same exact array numbers when the second array should be sorted in ascending or descending order

The code below is in the selectionSorting method which is just a specific way of sorting. I think the problem is somewhere here but I'm not sure how to fix it.
if(orderAscending.isSelected()) {
boolean sorted = false;
int counting = arrayInt.length-1;
int errorCounter = 1;
int tempNum;
while(sorted == false) {
if(errorCounter == 0) {
sorted = true;
}else {
errorCounter = 0;
}
if(arrayInt[counting] < arrayInt[counting - 1] && sorted != true) {
tempNum = arrayInt[counting];
arrayInt[counting] = arrayInt[counting - 1];
arrayInt[counting - 1] = tempNum;
errorCounter++;
counting--;
}
if (counting == 0) {
counting = arrayInt.length-1;
}
}
String sOutput = "";
for(int i = 0; i < arrayInt.length-1; i++) {
sOutput = sOutput + arrayInt[i] + "\n";
}
sortedOutput.setText(sOutput);
Output
Your while loop should only include this code
if(orderAscending.isSelected()) {
boolean sorted = false;
int counting = arrayInt.length-1;
int errorCounter = 1;
int tempNum,secondLoop;
while(counting>0) {
secondLoop=0;
while(secondLoop<=counting){
if(arrayInt[counting] < arrayInt[secondLoop]) {
tempNum = arrayInt[counting];
arrayInt[counting] = arrayInt[secondLoop];
arrayInt[secondLoop] = tempNum;
}
secondLoop++;
}
counting--;
}
String sOutput = "";
for(int i = 0; i < arrayInt.length-1; i++) {
sOutput = sOutput + arrayInt[i] + "\n";
}
sortedOutput.setText(sOutput);

Handling Null issue with .split method & JOP.InputDialog Java

So this is a snippet of code for a uni project im doing fairly new to java so excuse any poor code. One of the restrictions is that the code mustn't have errors on exit / cancel. So i understand that the cancel button on JOptionPane.showInputDialog returns null but it seems the section of 'parts = temp.split(" ")' is for reasons unknown to me blocking input from being null? When i get rid of parts=temp.split() there is no exception thrown when cancel button is selected but then obviously the for loop doesn't work.So what i need to do is for there to be no exception or error's produced upon cancel.Any help would be appreciated! :)
** Edit** We're also forbidden to use catch, try or break any while loops.Must exit with a true / false.
while (X == true && flag == true) {
input = JOptionPane.showInputDialog("Tell me more about " + topics[z]);
String temp = input;
if (input != null) {
flag = true;
}
else if (input == null) {
flag = false;
}
parts = temp.split(" ");
for (int i = 0; i < parts.length; i++) {
for (int x = 0; x < topics.length; x++) {
if (parts[i].equals(topics[x])) {
cut = parts[i];
break;
}
}
}
for (int i = 0; i < topics.length; i++) {
if (cut.equals(topics[i])) {
z = i;
break;
}
}
input = cut;
System.out.print(cut);
System.out.println(z);
X = Arrays.asList(topics[z]).contains(input);
System.out.println(X);
}
You need to write parts = temp.split(" "); inside if (input != null) and make sure parts is initialized before this as well; otherwise you'll get NPE in line parts.length as well.
I'll assume topics is not null:
while (X == true && flag == true) {
input = JOptionPane.showInputDialog("Tell me more about " + topics[z]);
String temp = input;
parts = new String[initialArraySize];
if (input != null) {
parts = temp.split(" ");
flag = true;
}
else if (input == null) {
flag = false;
}
for (int i = 0; i < parts.length; i++) {
for (int x = 0; x < topics.length; x++) {
if (parts[i].equals(topics[x])) {
cut = parts[i];
break;
}
}
}
for (int i = 0; i < topics.length; i++) {
if (cut.equals(topics[i])) {
z = i;
break;
}
}
input = cut;
System.out.print(cut);
System.out.println(z);
X = Arrays.asList(topics[z]).contains(input);
System.out.println(X);
}

Array required but Integer found

I am trying to compare two values present in two different arrays but I end up getting the " Array required but Integer found " compile time error . I am really not able solve this. I have marked the line from where the error was coming. It would be very appreciable if anybody can help me out with this. Here is the code .
public class Banker
{
int proccess, n, allocated[][], need[][], maximum[][], available[], safe[];
boolean done[];
public Banker(int n, int proccess) {
this.n = n;
this.proccess = proccess;
allocated = new int[n][n];
need = new int[n][n];
maximum = new int[n][n];
safe = new int[proccess];
done = new boolean[proccess];
}
public void getSafeSequence() {
int result = 0;
for (int i = 0; i < proccess; ++i) {
result = getLocation();
if (result != -1) {
safe[i] = result;
done[result] = true;
} else {
System.out.println(" No Safe Sequence Exist ");
break;
}
}
if (result != -1)
DisplaySequene();
}
public int getLocation() {
boolean flag = true;
for (int i = 0; i < proccess; ++i) {
if (done[i] != true) {
flag = true;
for (int j = 0; j < n; ++j)
***if (available[i][j] < need[i][j])*** {
flag = false;
break;
}
}
if (flag)
return i;
}
return -1;
}
}
available is one dimensional array so you cannot write available[i][j]. Change it to smh like available[i]
You defined available[] as a one dimensional array and use it with two dimensions available[i][j].

how To reduce execution time of the following program

I have a requirement, in which I have to scan certain files for the match of certain keywords. My keywords list size is around 40000 and all my files have approximately 4000 lines. Also the keyword should not be commented in the file, hence I have to take care of comments as well. The code what I have written to know the occurrence of the keyword is taking around 5 minutes for each file. I don't know what change I can make to reduce the execution time.
The code is as shown below.
for (File fl : files) {
flag = false;
content = FileUtils.readFileToString(fl);
System.out.println(fl.getName());
fileName = fl.getName();
// Object Keywords scanning
keywords = null;
keywords = findKeywordType(fileName);
if (keywords != null) {
Boolean keywordCount = false;
for (String[] key : keywords) {
key[0] = key[1];
}
for (String[] key : keywords) {
Boolean check = false;
if (content.contains(key[0])) {
if (content.contains(key[3] + ".")) {
check = true;
}
if (check) {
continue;
}
if (content.contains(key[3])) {
keywordCount = FindOccurence(fl, key[0], key[3]);
if (keywordCount) {
System.out.println("Writing keywords");
objKwm = new ObjectKeywordMaster();
objKwm.setObjectName(key[0]);
objKwm.setObjectType(key[1]);
objKwm.setObjectOwner(key[2]);
objKwm.setDependentObjectName(key[3]);
objKwm.setDependentObjectType(key[4]);
objKwm.setDependentObjectOwner(key[5]);
objKw.getObjectKeywords().add(objKwm);
}
}
}
}
}
FindOccurrence method code is
private static Boolean FindOccurence(File fl, String objectName, String keyword) throws IOException {
int startComment = 0;
int endComment = 0;
Boolean objCheck = false;
Boolean keyCheck = false;
Boolean check = false;
List line = FileUtils.readLines(fl);
int fileLength = line.size();
int objCount = 0;
int keyCount = 0;
loop:
for (int j = 0; j < fileLength; j++) {
if (line.get(j).toString().contains("/*")) {
startComment = j;
}
if (line.get(j).toString().contains("*/")) {
endComment = j;
}
if (line.get(j).toString().contains(objectName)) {
objCheck = false;
Pattern p = Pattern.compile("\\b" + objectName + "\\b");
Matcher m = p.matcher(line.get(j).toString());
while (m.find()) {
objCheck = true;
objCount++;
}
if (objCheck) {
if (line.get(j).toString().contains("#")) {
int objIndex = line.get(j).toString().indexOf(objectName);
int commentIndex = line.get(j).toString().indexOf("#");
if (objIndex > commentIndex) {
objCount--;
}
} else {
if (line.get(j).toString().contains("--")) {
int objIndex = line.get(j).toString().indexOf(objectName);
int commentIndex = line.get(j).toString()
.indexOf("--");
if (objIndex > commentIndex) {
objCount--;
}
}
}
if ((j >= startComment && j <= endComment)||(j >= startComment && endComment==0)) {
objCount--;
}
}
}
if (line.get(j).toString().contains(keyword)) {
keyCheck = false;
Pattern p = Pattern.compile("\\b" + keyword + "\\b");
Matcher m = p.matcher(line.get(j).toString());
while (m.find()) {
keyCheck = true;
keyCount++;
}
if (keyCheck) {
if (line.get(j).toString().contains("#")) {
int objIndex = line.get(j).toString().indexOf(keyword);
int commentIndex = line.get(j).toString().indexOf("#");
if (objIndex > commentIndex) {
keyCount--;
}
} else {
if (line.get(j).toString().contains("--")) {
int objIndex = line.get(j).toString().indexOf(keyword);
int commentIndex = line.get(j).toString()
.indexOf("--");
if (objIndex > commentIndex) {
keyCount--;
}
}
}
if ((j >= startComment && j <= endComment)||(j >= startComment && endComment==0)) {
keyCount--;
}
}
}
if(objCount > 0 && keyCount >0){
check = true;
break loop;
} else
check = false;
}
return check;
}
}
I have two find occurence of two keywords present in the same list. Please suggest some ways so that I can reduce the execution time.
1) Before to start looking for any keyword, prepare the file content: remove the comments, ... .
2) Split file content in words.
3) Do not loop for each keyword: use a Set who stores all keywords.

Categories