Im trying to write a method that takes in an ID of the form "xxxx-xxxx" (x being any number 1-9) and checks to see if the ID entered is valid. For example, 1111-1111 would be valid, but 111p-1111 or 11111-1111 would not be. However, after I have written this method, it comes out as true even when the ID is of the form 111p-1111.
public static boolean idCheck(String ID){
char[] idChar = ID.toCharArray();
boolean firstHalf = false;
boolean secHalf = false;
for (int i = 0; i < 5; ++i){//Check first half
if ((idChar[i] > 47 && idChar[i] < 58)){//Checks ascii vals to see if valid ID
firstHalf = true;
}
}
for (int i = 5; i < idChar.length; ++i){//Check second half
if ((idChar[i] > 47 && idChar[i] < 58)){//Checks ascii vals to see if valid ID
secHalf = true;
}
}
//If all values are valid, returns true.
if (firstHalf == true && secHalf == true && idChar[4] == '-' && ID.length() == 9){
return true;
}
return false;
}
Using a regular expression would be much simpler in this case:
\d{4}-\d{4}
In Java:
static boolean idCheck(String id) {
return id.matches("\\d{4}-\\d{4}");
}
If you're unfamiliar with regular expressions, here's an explanation:
\d Match a digit 0-9
{4} Repeat last token 4 times (matches 4 digits)
- Match a hyphen literally
\d Match a digit 0-9
{4} Repeat last token 4 times (matches 4 digits)
Your if statements only look at one number to determine if it sets the boolean to true. So if any of the numbers in each half are valid, the boolean will be set to true.
You are probably better off using regular expressions. regexr.com is a great resource to get started! :)
Something like:
[1-9]{4}-[1-9]{4} (You can also use \d)
You only check if there is at least one character that matches, not if any of the input characters are failing.
To have a quick solution that is easy to understand for any Java developer after you you could use a Regex and check if your input matches:
public static boolean idCheck(String id){
return Pattern.matches("\\d{4}-\\d{4}", id);
}
If you want to keep your way of checking you should start with true booleans and check if they stay true.
boolean firstHalf = true;
boolean secHalf = true;
and therefrom use firstHalf &= true for your updates and use a else{ firstHalf = false; } branch.
To keep your method I would prefer to always back out fast if you know the result:
public static boolean idCheck(String id)
{
//check length
if (id.length() != 9)
return false;
char[] idChar = id.toCharArray();
//check for dash
if (idChar[4] != '-')
return false;
//check first half
for (int i = 0; i < 5; ++i)
{
if (!(idChar[i] > 47 && idChar[i] < 58))
return false;
}
//check second half
for (int i = 5; i <= 10; ++i)
{
if (!(idChar[i] > 47 && idChar[i] < 58))
return false;
}
}
Related
I am writing a function that compares the number of vowels in the first half of a string and compares it with the second half, and returns a boolean based on if the number is equal.
Example:
Input: "book"
Output: true
because bo | ok, numVowels = 1, one 'o' in both halves.
My code that works is here
class Solution {
public boolean halvesAreAlike(String s) {
Set<Character> set = new HashSet<>(Arrays.asList('a','e','i','o','u','A','E','I','O','U'));
int vowelCount = 0, length = (s.length()%2 == 0) ? s.length()/2 : s.length()/2+1;
boolean pastHalf = false;
for (int i = 0; i < s.length(); i++) {
if (i == length) pastHalf = true;
if (pastHalf && set.contains(s.charAt(i))) vowelCount--;
else if (!pastHalf && set.contains(s.charAt(i))) vowelCount++;
}
return vowelCount == 0;
}
}
In the if (i == length) pastHalf = true; line, I am checking to see if I have hit the middle of the String. This is a simple boolean. I changed it to this ternary pastHalf = (i == length) ? true : false; and the output was wrong for the test case Ieai. Does anyone know why? I believe that the statements are equivalent.
if (i == length) pastHalf = true;
is most definitely NOT the same as
pastHalf = (i == length) ? true : false
In the first case, pastHalf is changed only when i is exactly equal to length, so as you iterate beyond length, pastHalf remains true.
In the second, at each iteration pastHalf is reset, so pastHalf is true only when i is exactly equal to length.
Other improvements:
length = (s.length()+1) % 2; // Think about this one carefully
and
if (set.contains(s.charAt(i)))
vowelCount += pastHalf ? -1 : +1;
Example:
I have a boolean array with N boolean inside. Which is the most efficient way to determine there are more than continuous M true flags, in the array?
Write some thing like (bA=booleanArray, for M=3)
(bA[0] && bA[1] && bA[2]) || (bA[1] && bA[2] && bA[3]) || ...
is really ugly.
And this can not be done with a VERY-LONG dynamic length array with dynamic least true flags to meet need. And maybe inefficient with few and scattered true?
Use a loop and a counter:
int count = 0;
for (boolean x: theArray){
if (x) {
count++;
if (count >= n) return true; // n is the count we are looking for
} else { count = 0; }
}
return false;
This is one approach, that allows for adjusting the number of consecutive entries, and the array is not fixed in length. The method hasConsecutiveTrue will loop over the array, looking for a value of true. If found, it increments the counter, otherwise sets it to 0. If the counter matches the expected amount, it returns true. Otherwise, it will return false. EDIT: based upon a comment, make so it will throw an IllegalArgumentException for an attempt to find <= 0 consecutive numbers, or if the input array is null/empty.
public static void main(String[] args)
{
int consecutive = 3;
boolean[] ba = new boolean[] { true, false, true, true, true, false};
System.out.println("found: " + hasConsecutiveTrue(ba, consecutive));
}
private static boolean hasConsecutiveTrue(boolean[] ba, int consecutive) throws IllegalArgumentException
{
// we will not attempt to process if the input <= 0; if 0 should return
// true, then modify the conditional statement as appropriate
if (consecutive <= 0) {
throw new IllegalArgumentException("Invalid input for consecutive: " +
consecutive);
}
if (ba == null || ba.length < 1) {
throw new IllegalArgumentException("No array to check!");
}
int count = 0;
boolean found = false;
for (boolean b : ba) {
count = ( b ? count + 1 : 0);
if (count == consecutive) {
found = true;
break;
}
}
return found;
}
Here's one using BitSet: if you're able to start with a BitSet, it will almost certainly be more efficient. If you have to convert from a boolean[] or byte[], it might not be.
// BitSet bits = BitSet.valueOf(bA);
int i = bits.nextSetBit(0);
while (i > -1 && i < bits.length()) {
int nextFalse = bits.nextClearBit(i);
if (nextFalse - nextTrue > N) return true;
i = bits.nextSetBit(nextFalse) + 1;
}
return false;
One option is to use a string with T + F in the location to determine the true/false setting of your array. Then use contains.
Example:
String booleanArray = "TTFFTFTFTFTTTFFT";
if ( !booleanArray.contains("TTT") ) // Pattern was found.
Given a string, does "xyz" appear in the middle of the string? To
define middle, we'll say that the number of chars to the left and
right of the "xyz" must differ by at most one. This problem is harder
than it looks.
My solution works without the second last line except for one condition: if str="xyx"
Is it possible to modify the for loop to take this into account...I'm struggling with understanding why it doesn't.
My solution does work I'm just trying to get a better understanding of what I'm doing. I know I could add it into the first if statement but I want to know why it doesn't work without it.
public boolean xyzMiddle(String str) {
for (int i=0;i<str.length()-3;i++) {
if (str.substring(i,i+3).equals("xyz")) {
String front =str.substring(0,i);
String end = str.substring(i+3);
int a =Math.abs(front.length() -end.length());
if (a<=1) return true;
}
}
if (str.equals("xyz")) return true;
return false;
I think i remember this question - it's this question from Codingbat, I believe. Excellent web site, learned a lot from that site back when I started programming. There's absolutely no reason to use a loop, though.
public boolean xyzMiddle(String str) {
boolean result = false;
int i = str.length()/2 -1;
if (str.length() >= 3 && (str.substring(i, i+3).equals("xyz") || (str.length()%2 == 0 && str.substring(i-1, i+2).equals("xyz")) )) {
result = true;
}
return result;
}
So, let's walk through this and why it works. Firstly, str.length() >= 3, because if the string isn't at least as long as "xyz", there's no way it can contain "xyz".
There are two main cases to this problem, we need to think of. The string can have an even or an uneven length. In the uneven case, it's easy:
The Uneven case
AAAxyzAAA // length = 9
012345678 // the indexes
^ // that's the middle, which can be calculated by length/2
// (since this is an integer divison, we disregard whatever comes after the decimal point)
So to get the start of the xyz-substring, we simply subtract one from this number - which is exactly what i is doing:
AAAxyzAAA // length = 9
012345678 // the indexes
i // i = length/2-1 = 3
So if str.substring(i, i+3) is xyz, we can return true!
The Even Case
Now, this can be a bit more tricky, since there is no true "middle" of the string. In fact, two indexes could be called the middle, so we have two sub-cases:
AAAAAAAA // length = 8
01234567 // the indexes
^^ // Which one is the true middle character?
In fact, the middle would be between index 3 and 4. However, we are performing integer divisions, length/2 is always the largest (rightmost) of the two possible "middles". And since we calculate i using the middle, the same as in the uneven case applies - str.substring(i, i+3) could be considered the middle part of the string.
AAAxyzAA
01234567
^^^ // str.substring(i, i+3)
i
But suppose our string was AAxyzAAA - that could also be considered the middle part of the string. So we need to move our substring check "to the left" - so we subtract 1 from it.
AAxyzAAA
01234567
^^^ // str.substring(i-1, i+2)
i // i is still at "the old" location
So is it even or not?
To check whether the string is even or uneven, we use the modulo operator, %. The easiest way to think of what it does is "what would be left over after i divided with this number?". So 3 % 2 would be 1. In our case, we want to make sure that the number is divisible by 2 with nothing left over - because that means it was an even number. Therefore, we need to check whether str.length() % 2 == 0 before we make our "move-to-the-left" check. If not, we could risk going out of bounds on the string. If the string was 3 characters long, and we moved one to the left... we would check the substring starting at index -1, and that doesn't make a lot of sense.
Put it all together, and there you go!
I'd say something as simple as:
public void test() {
test("Hello", "ll");
test("Hello", "He");
test("Hello", "el");
test("Hello", "lo");
test("Hello", "Hell");
test("Hello", "ello");
test("Hello", "Hello");
test("Hell", "He");
test("Hell", "el");
test("Hell", "ll");
}
private void test(String s, String p) {
System.out.println(p + (inMiddle(s, p) ? " in " : " not in ") + s);
}
// Is the pattern in the middle of the string.
public static boolean inMiddle(String s, String p) {
int d = s.length() - p.length();
return at(s, p, d / 2) || ((d & 1) == 1 && at(s, p, (d / 2) + 1));
}
private static boolean at(String s, String p, int i) {
return i >= 0 && i < s.length() && s.substring(i).startsWith(p);
}
Results look correct to me:
ll in Hello
He not in Hello
el in Hello
lo not in Hello
Hell in Hello
ello in Hello
Hello in Hello
He not in Hell
el in Hell
ll not in Hell
I have confirmed that this matches Tobias' solution exactly when p = "xyz".
public boolean xyzMiddle(String str) {
int len = str.length();
if (len < 3){ return false; }
int even = (len+1)%2;
int mid = len/2;
return str.substring(mid-1-even, mid+2).contains("xyz");
}
The simplest I could come up with:
public boolean xyzMiddle(String str) {
str = " " + str + " ";
int even = (str.length()+1)%2;
int mid = (str.length())/2;
str = str.substring(mid-1-even, mid+2);
return str.contains("xyz");
}
public boolean xyzMiddle(String str) {
int len = str.length();
if(len < 3) {return false;}
if(len==3 && str.equals("xyz")) {return true;}
int index = middleIndex(str);
String left = str.substring(0,index) ;
String right= str.substring(index+3) ;
//Return based on the difference by at most 1
return (Math.abs(left.length()-right.length()) <=1);
}
public int middleIndex(String str) {
int middleLen = (str.length())/2;
int index= 0;
//Find an index that could be in the middle of the string with
// "xyz"
for(int i=middleLen-2; i < middleLen; i++ ) {
if(str.substring(i, i+3).equals("xyz") ) {
index= i;
}
}
return index;
}
public boolean xyzMiddle(String str) {
if (str.length() >= 3)
{
// if odd
if (str.length() % 2 == 1)
{
//axyzb
//01234
//length = 5; 5 is odd.
//length / 2 = 2;
//2 minus 1 = 1
//1 is where xyz starts
//aaxyzbb
//0123456
//length = 7; 7 is odd.
//length / 2 = 3;
//3 minus 1 = 2
//2 is where xyz starts.
//....
//This pattern works with all odd numbers.
if (str.substring((str.length() / 2) - 1, ((str.length() / 2) - 1) + 3).equals("xyz"))
{
return true;
}
else
{
return false;
}
}
//if even
else
{
//for evens that occur with a larger amount before "xyz" than after
//axyz
//0123
//length = 4; 4 is even;
//4 - 1 = 3;
//3 / 2 = 1
//1 is where xyz starts.
//aaxyzb
//012345
//length = 6; 6 is even;
//6 - 1 = 5;
//5 / 2 = 2
//2 is where xyz starts.
//...
//This pattern works for all even numbers where there is a larger amount of characters before the xyz.
if (str.substring((str.length() - 1) / 2, ((str.length() - 1) / 2) + 3).equals("xyz"))
{
return true;
}
//For the cases where there are more characters after "xyz" than before.
//xyzb
//0123
//length = 4; 4 is even;
//4 - 1 = 3;
//3 / 2 = 1
//1 - 1 = 0;
//xyz starts at 0;
//axyzbb
//012345
//length = 6; 6 is even;
//6 - 1 = 5;
//5 / 2 = 3;
//2 - 1 = 1;
//xyz starts at 1;
//...
//The pattern continues onwards for all cases where there are more characters after xyz than before.
else if (str.substring((((str.length() - 1) / 2) - 1), (((str.length() - 1) / 2) -1) + 3).equals("xyz"))
{
return true;
}
//If there is no instance of xyz in these areas.
else
{
return false;
}
}
}
// If our string is less than 3 in length.
else
{
return false;
}
}
public boolean xyzMiddle(String str) {
return str.length()>2 && str.length()%2==1 && str.substring((str.length()-1)/2-1,(str.length()/2+1)+1).contains("xyz") || str.length()>2 && str.length()%2==0 && (str.substring(str.length()/2-2,str.length()/2+1).contains("xyz") || str.substring(str.length()/2-1,str.length()/2+2).contains("xyz"));
}
public boolean xyzMiddle(String str) {
int index = str.indexOf("x");
if(index < 0)
return false;
while(index >=0 && (index+3 <= str.length()) ){
if(str.substring(index,index+3).equals("xyz") && Math.abs(str.substring(0,index).length() - str.substring(index+3).length()) <=1)
return true;
index = str.indexOf("x",index+1);
}
return false;
}
This is what I have so far, I managed to reach here with several hours of work. The problem with my code is that if i give it a string "abcefg" it will verify the first two characters and returns it as true. I want the code to do it for all of my characters. I thought that putting the limit as x.length() would do the thing, but for some reason, it won't work.
public static boolean ConsecutiveCheckerAscending(String x) {
x = x.toLowerCase();
for (int i = 0; i < x.length() - 1; i++) {
if ((int)x.charAt(i) + 1 != ((int)x.charAt(i + 1)))
{
return false;
}
}
return true;
}
public static boolean ConsecutiveCheckerDescending(String x) {
x = x.toLowerCase();
for (int i = 0; i < x.length() - 1; i++) {
if((int)x.charAt(i) - 1 != ((int)x.charAt(i + 1)))
{
return false;
}
}
return true;
}
You have a variety of issues here.
Firstly, you can eventually go out of bounds with the charAt(i + 1) calls (check your loop condition).
Secondly, how can you possibly return true in the body of the for-loop? You haven't checked all of the characters yet!
I think you're making this overly complicated, though. All you need to do in order to check that two contiguous (i.e. next to each other in the string) characters are consecutive is
Math.abs(s.charAt(i) - s.charAt(i + 1)) == 1
You actually don't even need a cast. What we're doing is checking that the "distance" between the two characters is 1.
Just apply that to every contiguous pair of characters in the string, and return false if it isn't satisfied somewhere along the line. If you exit the loop without ever returning false, you can return true.
You cannot know for sure if the string is consecutive until the end of the method, so you cannot return true in the middle. At most you can return false when you find that string is not consecutive.
To give more advice, what do you mean by "consecutive"? Is adgkm consecutive? Looking at the current code it would look like it; all you check is the order of the characters. Is abcdcbcd consecutive? Usually "consecutive" means there are no gaps.
In both if and else statements you having return statement, So the method will return after first check. You have to give return only for the exit condition. don't give for both if and else
Wrote it in a rush, but it'd look something like this.-
public static boolean ConsecutiveChecker(String x) {
boolean consecutive = true;
x = x.toLowerCase();
for (int i = 0; i < x.length() - 1; i ++) {
if ((int) x.charAt(i) + 1 != ((int) x.charAt(i + 1))) {
consecutive = false;
break;
}
}
return consecutive;
}
So im working on java codingbat and this is the question:
Given a string, look for a mirror image (backwards) string at both the beginning and end of the given string.
In other words, zero or more characters at the very begining of the given string, and at the very end of the string in reverse order (possibly overlapping).
For example:
the string "abXYZba" has the mirror end "ab". mirrorEnds("abXYZba") → "ab" mirrorEnds("abca") → "a" mirrorEnds("aba") → "aba" .
My code passed all the test except for the other test, which is not specified. I dont know what's wrong with it.
public String mirrorEnds(String string) {
String input = string, mirror = "";
int length = string.length();
for (int n = 0; n < (length+1) / 2; n++) {
if (input.charAt(n) != input.charAt(length - n - 1)) {
break;
}else if(length%2 == 1 && n == (length - 1)/2){
// System.out.println("length/2 = " );
return input;
}
else {
mirror += input.charAt(n);
}
}
return mirror;
}
You were correct in not needing to go though the entire word, but your logic is more complex than it needs to be, making it harder to find and fix the problem. The root cause of the test failure is in the last return statement. It must return string if the loop completes without breaking. You can fix your code by changing break; to return mirror; and changing the last return mirror; to return input;
The test that is failing is one like this:
mirrorEnds("abba") -> "abba"
A much simpler version of your code can be created like this:
public String mirrorEnds(String string) {
int len = string.length();
for (int i=0; i < len/2; ++i)
if (string.charAt(i) != string.charAt(len - 1 - i))
return string.substring(0, i);
return string;
}
mirrorEnds("abba")?
Anyways, I'm sure you could come up with a better question name than "some weird stuff"...
Since you are dividing n by 2 in your loop termination condition, it will end when halfway through the word. This is enough to tell the word is a palindrome, but not enough to build your output correctly. You have a condition handling palindrome with odd numbers of letter, but not even numbers of letters. I believe the failing test will be of the form "abba", where I believe what you have will return "ab", instead of "abba".
If you change you loop to:
for (int n = 0; n < length; n++) {
I believe it should be doing what you want. This also makes the short circuit case unnecessary, so:
for (int n = 0; n < length; n++) {
if (input.charAt(n) != input.charAt(length - n - 1)) {
break;
}
else {
mirror += input.charAt(n);
}
}
The first test I tried was with the string "abba" which fails. It returns ab, and not abba. As femtoRgon mentioned, you're not going through the entire word, which may some times be necessary. femtoRgon's solution works, as well as taking a slightly different approach to iterating through the word as follows:
public String mirrorEnds(String string) {
boolean matches = true;
StringBuilder mirrorEnd = new StringBuilder();
int index = 0;
while (matches && index < string.length()) {
if (string.charAt(index) == string.charAt(string.length() - index - 1))
mirrorEnd.append(string.charAt(index));
else
matches = false;
index++;
}
return mirrorEnd.toString();
}
public String mirrorEnds(String string) {
String comp="";
for(int i=0; i<string.length(); i++){
if(string.charAt(i)==string.charAt(string.length()-(i+1)))
comp= comp+ string.charAt(i);
else break;
}
return comp;
}