Hey I am writing a calculator script in Java.
I am currently stuck trying to find out a way to find if any of the characters in a sting are in an ArrayList.
For example:
I have to have the input as a String I pass this string into a method of which has access to an array list with the operators and operands in it. How can I make sure that the string only contains the operands and operators within this array list?
Thanks, Ciaran
Here is the code that I have so far with the input being passed in..
import java.util.*;
public class stringCalculator {
private String[] operators = {"+","-","/","*"};
public stringCalculator(String userinput){
System.out.println(userinput);
public boolean checkInput(){
}
}
}
Here is the new code.
import java.util.*;
public class stringCalculator {
private String userinput;
HashSet<String> op = new HashSet<String>();
public stringCalculator(String userinput){
this.userinput = userinput;
//System.out.println(userinput);
HashSet<String> op = new HashSet<String>();
op.add("+");
op.add("-");
op.add("*");
op.add("/");
this.op = op;
System.out.println(op);
}
public void checkTheInput(){
System.out.println(userinput);
}
public boolean checkInput(){
return op.contains(userinput);
}
}
Edited to meet requirement as per comments
To return true if a string contains only -+/* or digits:
public boolean checkInput(String input) {
return input.matches("[-+/*0-9]+");
}
This uses a regular expression to assert that the string contains only the specified characters. A breakdown of the regex:
[...] is a character class, which lists the characters allowed
+ means "one or more of the preceding expression" (in this case the character class)
Note that the minus sign in a character class is for a range of characters, eg 0-9 means 0123456789. However, when a minus is used either first of last in a character class, it means a literal minus (not a range).
Another note about String.matches() - it must match the whole string to return true. This is different from many other languages, where the similar method/function would return true if part of the string matches.
So, you want to take out the numbers, and then check if the remaining characters are all contained in opereators. Assuming your input String is not too long, I'd suggest you use a HashSet instead of String[] for operators. This way, you can use the [contains(Object)][1] method (which will be O(1) instead of O(n)) for anything that's not a number in your String.
As validation goes, however, you'll still have to check for much more, such as: "4++5/-3", where the operands are valid, but the overall expression isn't.
If you want to calculate expressions such as:
(3+4)*5
(which is in INFIX format). it is not very wise to read the string straightly. you should first convert the input to POSTFIX or Reverse Polish format like:
34+5*
This can be done reading characters one by one and using a stack. In that case you can check the characters on the fly one by one storing operators in a Set or Map.
I would recommend having a look at http://en.wikipedia.org/wiki/Reverse_Polish_notation for POSTFIX format and http://www.softwareandfinance.com/Java/Infix_Postfix_Converter.html
for example conversion code.
Related
My result after passing the value "A2A" - which should return false
I want to check that a three character string matches the format 12A. The first two must be a digit and the 3rd must be a letter.
The string "A2A" must therefore return false.
What is happening here and how stupid am I being?
I've tried various ways of doing this and nothing seems to work.
Just use String#matches() here with a regular expression:
public boolean validate(String input) {
return input.matches("[0-9]{2}[A-Za-z]");
}
I have a quite simple question here is that i have a string 0-1000
say str = "0-1000"
I successfully extract 0 and 1000 by using str.split("-")
Now, I am assigned to check the number because i am noticed that those two numbers can be a negative.
If I continue str.split("-"), then I will skip the negative sign as well.
Could anyone suggest methods for me?
Since String.split() uses regular expressions to split, you could do something like this:
String[] nos = "-1000--1".split("(?<=\\d)-";
This means you split at minus characters that follow a digit, i.e. must be an operator.
Note that the positive look-behind (?<=\d) needs to be used since you only want to match the minus character. String.split() removes all matching separators and thus something like \d- would remove digits as well.
To parse the numbers you'd then iterate over the array elements and call Integer.valueOf(element) or Integer.parseInt(element).
Note that this assumes the input string to be valid. Depending on what you want to achieve, you might first have to check the input for a match, e.g. by using -?\d--?\d to check whether the string is in format x-y where x and y can be positive or negative integers.
You can use regex like this :Works for all cases
public static void main(String[] args) {
String s = "-500--578";
String[] arr = s.split("(?<=\\d)-"); // split on "-" only if it is preceeded by a digit
for (String str : arr)
System.out.println(str);
}
O/P:
-500
-578
I am working on password enhancement and client wants a password that does not have consecutive letters ie: 123, 234.
I have figured out that you can declare strings that you want to match in regex like (012|123|234|345|456|567|678|789|890) and made it as the regex sequence.
This sequence is separated from the other sequences for easy reading.
The problem is, I cannot match the password with the pattern even if I included 123 or 234 in the password character.
I've read that regex cannot detect 123 as consecutive numbers, but as a string, can it do so?
If you have a limited sequence of characters following one another you can use a Pattern, .find() on a matcher on your input and just invert the test:
// Only the alternation is needed, no need for the capture
private static final Pattern PATTERN
= Pattern.compile("012|123|234|345|456|567|678|789|890");
// ...
if (PATTERN.matcher(input).find())
// fail: illegal sequence found
But if you want to detect that code points follow one another you have to use character functions:
final CharBuffer buf = CharBuffer.wrap(input);
int maxSuccessive = 0;
int successive = 0;
char prev = buf.get();
char next;
while (buf.hasRemaining()) {
next = buf.get();
if (next - prev == 1)
successive++;
else {
maxSuccessive = Math.max(maxSuccessive, successive);
successive = 0;
}
prev = next;
}
// test maxSuccessive
Note however that this will test successive characters according to "canonical ordering", not collation. In some locales, for instance, what is immediately after a is A, not b.
More generally, if you want to test for password requirements and constraint evolves, you are better off splitting things a bit. For instance, consider this:
public interface PasswordChecker
{
boolean isValid(final String passwd);
}
Implement this interface for each of your checks (for instance, length, presence/absence of certain characters, etc), and when you do check for a password, have a List of checkers; the password is invalid if one checker returns false:
private final List<PasswordChecker> checkers = ...;
// then
for (final PasswordChecker checker: checkers)
if (!checker.isValid(passwd))
return false;
return true;
If you use Guava, you can forget about PasswordChecker and use Predicate<String>.
If you're only dealing with these strings of digits that you want to exclude, you can achieve this using a negative lookahead assertion:
^(?!.*(012|123|234|345|456|567|678|789|890))<regex>
where <regex> is the actual regex you're using to match the password, and (?!...) is the lookahead that asserts it's impossible to match that string in your regex.
If you're asking about any increasing sequence of characters, then regex is not the right tool for this. You would have to do that programmatically.
I am trying to create a String[] which contains only words that comprise of certain characters. For example I have a dictionary containing a number of words like so:
arm
army
art
as
at
attack
attempt
attention
attraction
authority
automatic
awake
baby
back
bad
bag
balance
I want to narrow the list down so that it only contains words with the characters a, b and g. Therefore the list should only contain the word 'bag' in this example.
Currently I am trying to do this using regexes but having never used them before I can't seem to get it to work.
Here is my code:
public class LetterJugglingMain {
public static void main(String[] args) {
String dictFile = "/Users/simonrhillary/Desktop/Dictionary(3).txt";
fileReader fr = new fileReader();
fr.openFile(dictFile);
String[] dictionary = fr.fileToArray();
String regx = "able";
String[] newDict = createListOfValidWords(dictionary, regx);
printArray(newDict);
}
public static String[] createListOfValidWords(String[] d, String regex){
List<String> narrowed = new ArrayList<String>();
for(int i = 0; i<d.length; i++){
if(d[i].matches(regex)){
narrowed.add(d[i]);
System.out.println("added " + d[i]);
}
}
String[] narrowArray = narrowed.toArray(new String[0]);
return narrowArray;
}
however the array returned is always empty unless the String regex is the exact word! Any ideas? I can post more code if needed...I think I must be trying to initialise the regex wrong.
The narrowed down list must contain ONLY the characters from the regex.
Frankly, I'm not an expert in regexes, but I don't think it's the best tool to do what you want. I would use a method like the following:
public boolean containsAll(String s, Set<Character> chars) {
Set<Character> copy = new HashSet<Character>();
for (int i = 0; i < s.length() && copy.size() < chars.size(); i++) {
char c = s.charAt(i);
if (chars.contains(c)) {
copy.add(c);
}
}
return copy.size() == chars.size();
}
The regex able will match only the string "able". However, if you want a regular expression to match either character of a, b, l or e, the regex you're looking for is [able] (in brackets). If you want words containing several such characters, add a + for repeating the pattern: [able]+.
The OP wants words that contain every character. Not just one of them.
And other characters are not a problem.
If this is the case, I think the simiplest way would be to loop through the entire string, character by character, and check to see if it contains all of the characters you want. Keep flags to check and see if every character has been found.
If this isn't the case.... :
Try using the regex:
^[able]+$
Here's what it does:
^ matches the beginning of the string and $ matches the end of the string. This makes sure that you're not getting a partial match.
[able] matches the characters you want the string to consist of, in this case a, b, l, and e. + Makes sure that there are 1 or more of these characters in the string.
Note: This regex will match a string that contains these 4 letters. For example, it will match:
able, albe, aeble, aaaabbblllleeee
and will not match
qable, treatable, and abled.
A sample regex that filters out words that contains at least one occurrence of all characters in a set. This will match any English word (case-insensitive) that contains at least one occurrence of all the characters a, b, g:
(?i)(?=.*a)(?=.*b)(?=.*g)[a-z]+
Example of strings that match would be bag, baggy, grab.
Example of strings that don't match would be big, argument, nothing.
The (?i) means turns on case-insensitive flag.
You need to append as many (?=.*<character>) as the number of characters in the set, for each of the characters.
I assume a word only contains English alphabet, so I specify [a-z]. Specify more if you need space, hyphen, etc.
I assume matches(String regex) method in String class, so I omitted the ^ and $.
The performance may be bad, since in the worst case (the characters are found at the end of the words), I think that the regex engine may go through the string for around n times where n is the number of characters in the set. It may not be an actual concern at all, since the words are very short, but if it turns out that this is a bottleneck, you may consider doing simple looping.
How can I identify strings containing more digits than non-digits using regular expression (Pattern) in Java? Thank you.
That's not a regular language, and thus it cannot be captured by a vanilla regex. It may be possible anyway, but it will almost certainly be easier not to use a regex:
public static boolean moreDigitsThanNonDigits(String s) {
int diff = 0;
for(int i = 0; i < s.length(); ++i) {
if(Character.isDigit(s.charAt(i))) ++diff;
else --diff;
}
return diff > 0;
}
You won't be able to write a regexp that does this. But you already said you're using Java, why not mix in a little code?
public boolean moreDigitsThanNonDigits(String input) {
String nonDigits = input.replace("[0-9]","");
return input.length() > (nonDigits.length * 2);
}
Regular expressions are conceptually not able to preform such a task. They are equivalent to formal languages or (regular) automatons. They have no notion of memory (or a stack), so they cannot count the occurences of symbols. The next extension in terms of expressiveness are push-down automatons (or stack machines), which correspond to context free grammars. Before writing such a grammer for this task, using a method like the moreDigitsThanNonDigits above would be appropriate.
As already mentioned the language in question is not regular and cannot be detected using a regular expression.
I'll give you one more way of counting the number of digits and number of non-digits in a string using regex!!
You can use the String.replaceAll method to delete all non-digits in the input string. The length of the resultant string will be the number of digits in the input.
Similarly you can delete all the digits in the input string and the length of the resultant string will be the number of non-digits in the input string.
public static boolean test(String str) {
int numDigits = str.replaceAll("\\D","").length();
int numNonDigits = str.replaceAll("\\d","").length();
return numDigits > numNonDigits;
}
Ideone Link
I'm not sure that using regular expressions would be the best solution here.
regex alone can't (since they don't count anything); but if you want to use them then just use two replacements: one that strips out all the digits and one that only keeps them. then compare string lengths of the results.
of course, i'd rather use Dave's answer.