Badawy
BAN USER
I have a solution for this. We can use only files without loading input file into the memory or modifying it. See below example, I used the existing file without any changes, and I created a temp file for insertion/deletion process.
Algorithm is working as the following:
- If an open parenthesis comes, insert it to the file
- if a close parenthesis comes; check it with the latest one in the temp file. If they are match, delete its open from the temp file, otherwise, the file will be invalid and break.
- After completing this, temp file will be checked. If it has any open or close parenthesis, then this file is invalid file, otherwise, it will be valid file.
I hope the code to come in a good format.
package com.careercup;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import org.junit.Test;
/**
* @author Abouads, Badawy
*
*/
public class CheckParenthesesInFile {
/**
* Arrays for Parentheses
*/
HashMap<Character, Character> mappedSpecialCharacters = new HashMap<>();
Collection<Character> opens = null; // Open Parenthesis
Set<Character> closes = null; // Close Parenthesis
/**
* Initialization of Parentheses arrays
*/
public CheckParenthesesInFile() {
mappedSpecialCharacters.put('}', '{');
mappedSpecialCharacters.put(')', '(');
mappedSpecialCharacters.put(']', '[');
closes = mappedSpecialCharacters.keySet();
opens = mappedSpecialCharacters.values();
}
public boolean check(String filePath) throws IOException {
File file = new File(filePath);
RandomAccessFile current = new RandomAccessFile(file, "r");
// System.out.println(file.);
File tempFile = new File(file.getParent() + "//output.temp");
tempFile.deleteOnExit();
RandomAccessFile temp = new RandomAccessFile(tempFile, "rw");
long mainFilePointer = 0;
long tempFilePointer = 0;
boolean isValid = true;
while ((mainFilePointer = current.read()) != -1) {
char currentCharacter = (char) mainFilePointer;
if (opens.contains(currentCharacter)) {
temp.seek(tempFilePointer);
temp.write(currentCharacter);
tempFilePointer++;
} else if (closes.contains(currentCharacter)) {
tempFilePointer--;
if (tempFilePointer >= 0) {
temp.seek(tempFilePointer);
char lastChar = (char) temp.read();
if (mappedSpecialCharacters.get(currentCharacter) == lastChar) {
temp.seek(tempFilePointer);
temp.write(' ');
} else {
isValid = false;
break;
}
} else {
isValid = false;
break;
}
}
}
current.close();
return isThereParenthesesInFile(temp) && isValid;
}
/**
* Check if the file has any open Parentheses or any close Parentheses
*
* @param tempFile
* @return
* @throws IOException
*/
private boolean isThereParenthesesInFile(final RandomAccessFile file) throws IOException {
file.seek(0);
int read = 0;
boolean isValid = true;
while ((read = file.read()) != -1) {
char ch = (char) read;
if (opens.contains(ch) || closes.contains(ch)) {
isValid = false;
break;
}
}
file.close();
return isValid;
}
@Test
public void testParenthesis() {
try {
// check valid files
assertTrue(check("validateFiles/correctLargefile1.txt")); // file contains [{()()}]
assertTrue(check("validateFiles//correctLargefile2.txt")); // file contains [{(32)(44)565}23232][]{}()
assertTrue(check("validateFiles//correctLargefile3.txt")); // file contains this java class inside it, with valid comments in testParenthesis method
assertTrue(check("validateFiles//correctLargefile4.txt")); // file contains (){}[]{ { { } } } [()[]]
// invalid files
assertFalse(check("validateFiles//incorrectLargefile1.txt"));// file contains [{()()}[
assertFalse(check("validateFiles//incorrectLargefile2.txt"));// file contains [{()()}][{(}()}]
assertFalse(check("validateFiles//incorrectLargefile3.txt")); // file contains this java class inside it, with invalid comments in testParenthesis method
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String args[]) {
}
}
Read character by character from the file and use stack to push and pop parenthesis based on its order in the file. If an open parenthesis comes, add it to the stack, if its closed parenthesis comes, remove its open parenthesis from the stack. If a close parenthesis comes without the existence of an open parenthesis, it will be added to the stack, and it will be invalid example.
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import java.util.Stack;
import org.junit.Test;
/**
* @author Abouads, Badawy
*
*/
public class ParenthesisChecker {
// Mapping Parenthesis
HashMap<Character, Character> mappedSpecialCharacters = new HashMap<>();
Set<Character> opens = null; // Open Parenthesis
Collection<Character> closes = null; // Close Parenthesis
Stack<Character> stringParenthesis = null;// Parenthesis inside string
/**
* initialization
*/
public ParenthesisChecker() {
// TODO Auto-generated constructor stub
mappedSpecialCharacters.put('{', '}');
mappedSpecialCharacters.put('(', ')');
mappedSpecialCharacters.put('[', ']');
opens = mappedSpecialCharacters.keySet();
closes = mappedSpecialCharacters.values();
}
/**
*
* @param filePath
* @return
* @throws IOException
*/
public boolean checkParenthesisInFile(final String filePath) throws IOException {
stringParenthesis = new Stack<>();
FileReader fileReader = null;
boolean result = false;
BufferedReader bufferedReader = null;
try {
fileReader = new FileReader(filePath);
bufferedReader = new BufferedReader(fileReader);
int r = 0;
while ((r = bufferedReader.read()) != -1) {
result = checkParenthesis((char) r); // Read character by character and check it
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
fileReader.close();
bufferedReader.close();
}
return result;
}
public boolean checkParenthesis(final char ch) throws NullPointerException {
boolean passed = true;
if (ch != ' ') {
if (opens.contains(ch)) {
stringParenthesis.push(ch);
} else if (closes.contains(ch)) {
if (!stringParenthesis.isEmpty() && ch == mappedSpecialCharacters.get(stringParenthesis.peek())) {
stringParenthesis.pop();
} else {
stringParenthesis.push(ch);
passed = false;
}
}
}
return passed && stringParenthesis.isEmpty();
}
/**
* Test code
*/
@Test
public void testParenthesis() {
try {
assertFalse(checkParenthesisInFile("D://incorrectLargefile.txt"));
assertTrue(checkParenthesisInFile("D://correctLargefile.txt"));
} catch (IOException ex) {
}
}
}
You can use stack and do the following steps
- If the current character is an open parenthesis like “{“ or “(“ or “[“ , push it to the stack
- If the current character is an close parenthesis like “}” or “)” or “]”
o check the latest value in the stack if it is the closer of the latest element on the stack, pop the latest value from the stack
o Otherwise, break from the loop and this string will be invalid.
- Finally, check if there is any element on the stack that is meaning this string is invalid, otherwise, it is valid.
See the below java example
- Badawy December 20, 2017