twoTwo challenge

Hi,

I am working on below challenge

http://codingbat.com/prob/p102145

Psedo code description of approach :
1. Loop throguh given array
2. check if array element 2 with adjacent one also 2
3. if yes return true
4. if no return false

I wrote my code as below
public boolean twoTwo(int[] nums) {
  boolean result=false;
  for(int i=0;i<nums.length-1;i++){
    if((nums[i]==nums[i+1])||(nums[i]==nums[i-1])){
      result=true;
      
    }
    else{
      result=false;
    }
  }
  return result;
 
}

Open in new window




I am not passing all tests as below and failing edge cases
Expected      Run            
twoTwo([4, 2, 2, 3]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2, 2, 4]) → true      true      OK      
twoTwo([2, 2, 4, 2]) → false      false      OK      
twoTwo([1, 3, 4]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([1, 2, 2, 3, 4]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([1, 2, 3, 4]) → false      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2, 2]) → true      true      OK      
twoTwo([2, 2, 7]) → true      true      OK      
twoTwo([2, 2, 7, 2, 1]) → false      false      OK      
twoTwo([4, 2, 2, 2]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2, 2, 2]) → true      true      OK      
twoTwo([1, 2]) → false      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2]) → false      false      OK      
twoTwo([1]) → true      false      X      
twoTwo([]) → true      false      X      
twoTwo([5, 2, 2, 3]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2, 2, 5, 2]) → false      false      OK      
other tests
X      
Your progress graph for this problem

How to improve my design, approach, code? please advise
LVL 7
gudii9Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gudii9Author Commented:
public boolean twoTwo(int[] nums) {
  boolean result=false;
  for(int i=1;i<nums.length-1;i++){
    if((nums[i]==nums[i+1])||(nums[i]==nums[i-1])){
      result=true;
      
    }
    else{
      result=false;
    }
  }
  return result;
 
}

Open in new window


above approach of starting at index 1 fixed some test cases as below
Expected      Run            
twoTwo([4, 2, 2, 3]) → true      true      OK      
twoTwo([2, 2, 4]) → true      true      OK      
twoTwo([2, 2, 4, 2]) → false      false      OK      
twoTwo([1, 3, 4]) → true      false      X      
twoTwo([1, 2, 2, 3, 4]) → true      false      X      
twoTwo([1, 2, 3, 4]) → false      false      OK      
twoTwo([2, 2]) → true      false      X      
twoTwo([2, 2, 7]) → true      true      OK      
twoTwo([2, 2, 7, 2, 1]) → false      false      OK      
twoTwo([4, 2, 2, 2]) → true      true      OK      
twoTwo([2, 2, 2]) → true      true      OK      
twoTwo([1, 2]) → false      false      OK      
twoTwo([2]) → false      false      OK      
twoTwo([1]) → true      false      X      
twoTwo([]) → true      false      X      
twoTwo([5, 2, 2, 3]) → true      true      OK      
twoTwo([2, 2, 5, 2]) → false      false      OK      
other tests
X      

But not sure on how to handle index 0 element
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Ok, a few pointers to get you started...

  • Your code does NOT contain the number 2 anywhere, that would be a first clue as to something wrong
  • You don't need to check both AHEAD and BEHIND the current index, just check AHEAD. You don't need to check behind because you would have just compared those two numbers in the previous loop iteration
  • Look at the structure of your if/else inside the loop, it will ALWAYS set the result variable to either true or false. This means that anything it does in the initial loop iterations, will ALWAYS be overwritten in later loop iterations, ie. the last loop iteration and ONLY the last iteration will determine the result


Maybe, stating the problem in a different light might help. This is how I might read the problem...

Always return TRUE except if we find ANY 2 that does NOT have an adjacent 2.

I've bolded a few keyword for these reasons... The default return value is TRUE, and only if you find a particular condition do we return false. Also, we only need to find ANY 2 not adjacent to another 2, which means as soon as we find the first 2 that isn't adjacent to another 2, we can stop processing right there and return false, because nothing else in the input could change what we want to return. Finally the main condition that we are looking for is where a 2 does NOT have an adjacent 2, that should help you with your code.


Try thinking about the pseudo-code again, and then when you have that nailed down, then we can look at the code.
0
rrzCommented:
mccarl has posted some good points. I used some of them to create my code.  
public boolean twoTwo(int[] nums) {
	boolean result = true;
        int consecutiveTwos = 0;
        for(int num: nums){
		if(num == 2){ // found a two
			if(consecutiveTwos > 0){ // found twos adjacent to each other
				consecutiveTwos++;
                                result = true;
                        }
			else{ // found a single two
				consecutiveTwos = 1;
				result = false; 
			}
		}  
		else{ // found a number that was not a two 
			if(consecutiveTwos == 1){ // there was a single two
				result = false;
				break; // break out of for loop
			}
			else{
				consecutiveTwos = 0; // reset variable 
			}
		}
	}
        return result;
}

Open in new window

0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

gudii9Author Commented:
twoTwo([1, 3, 4]) → true      false      X

i thought above should be true as there is no 2 following next to other 2

Given an array of ints, return true if every 2 that appears in the array is next to another 2.

twoTwo([4, 2, 2, 3]) → true
twoTwo([2, 2, 4]) → true
twoTwo([2, 2, 4, 2]) → false

or as challenge did not talk about below i should just blindly assume it is always true?

twoTwo([1, 3, 4])
0
rrzCommented:
The challenge  was stated as
Given an array of ints, return true if every 2 that appears in the array is next to another 2.
 
I assumed that if there was not any two in the array, then we would return true.
or as challenge did not talk about below i should just blindly assume it is always true?

 twoTwo([1, 3, 4])]
Yes, I think that is what they had in mind. That is what the tests confirm.
0
gudii9Author Commented:
public boolean twoTwo(int[] nums) {
  boolean result=false;
  for(int i=1;i<nums.length-1;i++){
    if( (nums[i]==2) && (nums[i]==nums[i+1])||(nums[i]==nums[i-1])){
      result=true;
      
    }
    else{
      result=false;
    }
  }
  return result;
 
}

Open in new window


changed my code as above and failing 5 tests
Expected      Run            
twoTwo([4, 2, 2, 3]) → true      true      OK      
twoTwo([2, 2, 4]) → true      true      OK      
twoTwo([2, 2, 4, 2]) → false      false      OK      
twoTwo([1, 3, 4]) → true      false      X      
twoTwo([1, 2, 2, 3, 4]) → true      false      X      
twoTwo([1, 2, 3, 4]) → false      false      OK      
twoTwo([2, 2]) → true      false      X      
twoTwo([2, 2, 7]) → true      true      OK      
twoTwo([2, 2, 7, 2, 1]) → false      false      OK      
twoTwo([4, 2, 2, 2]) → true      true      OK      
twoTwo([2, 2, 2]) → true      true      OK      
twoTwo([1, 2]) → false      false      OK      
twoTwo([2]) → false      false      OK      
twoTwo([1]) → true      false      X      
twoTwo([]) → true      false      X      
twoTwo([5, 2, 2, 3]) → true      true      OK      
twoTwo([2, 2, 5, 2]) → false      false      OK      
other tests
X      

i am not clear how to handle below logic


or as challenge did not talk about below i should just blindly assume it is always true?
 twoTwo([1, 3, 4])]


tried else if() but not working
0
gudii9Author Commented:
public boolean twoTwo(int[] nums) {
  boolean result=false;
  for(int i=0;i<nums.length-1;i++){
    if( (nums[i]==2) && (nums[i]==nums[i+1])||(nums[i]==nums[i-1])){
      result=true;
      
    }
    else{
      result=false;
    }
  }
  return result;
 
}

Open in new window


if i start for loop with i=0 edge cases failing

Expected      Run            
twoTwo([4, 2, 2, 3]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2, 2, 4]) → true      true      OK      
twoTwo([2, 2, 4, 2]) → false      false      OK      
twoTwo([1, 3, 4]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([1, 2, 2, 3, 4]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([1, 2, 3, 4]) → false      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2, 2]) → true      true      OK      
twoTwo([2, 2, 7]) → true      true      OK      
twoTwo([2, 2, 7, 2, 1]) → false      false      OK      
twoTwo([4, 2, 2, 2]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2, 2, 2]) → true      true      OK      
twoTwo([1, 2]) → false      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2]) → false      false      OK      
twoTwo([1]) → true      false      X      
twoTwo([]) → true      false      X      
twoTwo([5, 2, 2, 3]) → true      Exception:java.lang.ArrayIndexOutOfBoundsException: -1 (line number:4)      X      
twoTwo([2, 2, 5, 2]) → false      false      OK      
other tests
X      
Your progress graph for this problem
0
rrzCommented:
I don't think you will be successful with your present approach to solving this problem. I think trying to keep track of indexes is too difficult. It is unnecessary. In my code above here, I created the variable "consecutiveTwos" to keep track of the twos as I looped through the array using the for loop.
Also, you should reread mccarl's suggestions.
0
gudii9Author Commented:
int consecutiveTwos = 0;
        for(int num: nums){
		if(num == 2){ // found a two
			if(consecutiveTwos > 0){ // found twos adjacent to each other

Open in new window


below is always 0 right and always false as we are initializing to 0 as  int consecutiveTwos = 0;?
if(consecutiveTwos > 0){ // found twos adjacent to each other[/code]
0
rrzCommented:
below is always 0 right and always false as we are initializing to 0 as  int consecutiveTwos = 0;?

No, it is not always 0.  
If a first two is found then it will execute the line
consecutiveTwos = 1;

Open in new window

 On a subsequent pass through the loop, if another two is found then
consecutiveTwos > 0

Open in new window

will be true
0
rrzCommented:
It is probably clearer this way.
public boolean twoTwo(int[] nums) {
  		boolean result = true;
        int consecutiveTwos = 0;
        for(int num: nums){
			if(num == 2){ // found a two
				if(consecutiveTwos == 0){ // found a single two
				  consecutiveTwos = 1;
				  result = false;			
                }
				else{ //  found twos adjacent to each other     
 					consecutiveTwos++;
                    result = true;
				}
			}  
			else{ // found a number that was not a two 
				if(consecutiveTwos == 1){ // there was a single two
					result = false;
					break; // break out of for loop
				}
				else{
					consecutiveTwos = 0; // reset variable 
				}
			}
		}
        return result;
}

Open in new window

0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Since we are posting code blindly, this is how I would do it...

public boolean twoTwo(int[] nums) {
  for (int i = 0; i < nums.length; i++) {
    if (nums[i] == 2) {
      if (i == (nums.length - 1) || nums[++i] != 2) {
        return false;
      }
      while (i < nums.length && nums[i] == 2) {
        i++;
      }
    }
  }
  return true;
}

Open in new window


Basic description...

We only need to care if we find a 2, if it is at the end of the array or there is no 2 following it, return false. If it was followed by a 2, the "while" loop skips however many 2's are next to each other (so that it caters for 2, 2 and 2, 2, 2, 2, 2 in the same way)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Or another version that may make it easier to understand...

public boolean twoTwo(int[] nums) {
  for (int i = 0; i < nums.length; i++) {
    if (accessArray(nums, i) == 2) {
      if (accessArray(nums, i - 1) != 2 && accessArray(nums, i + 1) != 2) {
        return false;
      }
    }
  }
  return true;
}

private int accessArray(int[] arr, int index) {
  return index >= 0 && index < arr.length ? arr[index] : 0;
}

Open in new window

0
gudii9Author Commented:
We only need to care if we find a 2, if it is at the end of the array or there is no 2 following it, return false. If it was followed by a 2, the "while" loop skips however many 2's are next to each other (so that it caters for 2, 2 and 2, 2, 2, 2, 2 in the same way)
private int accessArray(int[] arr, int index) {
  return index >= 0 && index < arr.length ? arr[index] : 0;
}

what above method does?

for (int i = 0; i < nums.length; i++) {
    if (accessArray(nums, i) == 2) {
      if (accessArray(nums, i - 1) != 2 && accessArray(nums, i + 1) != 2) {
        return false;
      }
    }
  }

Open in new window


above verifies if given number at i index is 2 if true check if last indexed element not 2 and next i+1 element not 2 then return false

all other cases true?
0
gudii9Author Commented:
public boolean twoTwo(int[] nums) {
  for (int i = 0; i < nums.length; i++) {
    if (nums[i] == 2) {
      if (i == (nums.length - 1) || nums[i++] != 2) {
        return false;
      }
      while (i < nums.length && nums[i] == 2) {
        i++;
      }
    }
  }
  return true;
}

Open in new window


instead of ++i if i take i++ i am failing 2 test cases as below. i wonder why(just because increment is after assigment?)
Expected	Run		
twoTwo([4, 2, 2, 3]) → true	true	OK	
twoTwo([2, 2, 4]) → true	true	OK	
twoTwo([2, 2, 4, 2]) → false	false	OK	
twoTwo([1, 3, 4]) → true	true	OK	
twoTwo([1, 2, 2, 3, 4]) → true	true	OK	
twoTwo([1, 2, 3, 4]) → false	true	X	
twoTwo([2, 2]) → true	true	OK	
twoTwo([2, 2, 7]) → true	true	OK	
twoTwo([2, 2, 7, 2, 1]) → false	true	X	
twoTwo([4, 2, 2, 2]) → true	true	OK	
twoTwo([2, 2, 2]) → true	true	OK	
twoTwo([1, 2]) → false	false	OK	
twoTwo([2]) → false	false	OK	
twoTwo([1]) → true	true	OK	
twoTwo([]) → true	true	OK	
twoTwo([5, 2, 2, 3]) → true	true	OK	
twoTwo([2, 2, 5, 2]) → false	false	OK	
other tests
OK	

Open in new window

0
rrzCommented:
Mr. Wolfe,
Where can we read EE policy?
Where can we discuss policy?  Do we still have the  "Community Support"  topic area? I could not find it.
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
instead of ++i if i take i++ i am failing 2 test cases as below. i wonder why(just because increment is after assigment?)

Yes, i++ and ++i are a little bit different in how they work, they are called post-increment operator and pre-increment operator (respectively). To understand, run this code somewhere...

int i,j;

i = 3;
j = i++;
System.out.println("i = " + i + "     j = " + j);

i = 3;
j = ++i;
System.out.println("i = " + i + "     j = " + j);

Open in new window


As you can see the operator does the same thing to i, in that it will increment it so the new value is 4 in both cases. The difference is in what that expression evaluates to. Because we are assigning the result to j, we get to see what happens.

In the first case, the post-increment operator, the value that was in i gets assigned to j first, and THEN i gets incremented, ie. the increment happens AFTER the value gets assigned to j (the word "post" means "after").

In the second case, the pre-increment operator, the value that was in i gets incremented FIRST, and THEN the new value gets assigned to j, ie. the increment happens BEFORE the value gets assigned to j (the word "pre" means "before").


So in the code above, because we are not only doing the incrementing of i, but we are using that expression as the index in the array, then it matters whether the increment happens before or after we use the value to index the array...

If i = 2, then...
nums[i++]   -   Means get the value of nums at index 2 and then increment i to be 3.
nums[++i]   -   Means increment i to be 3 and then get the value of nums at index 3.

So, yes, it changes the logic of the code that I wrote and definitely would change the test results.
0
rrzCommented:
@Mr. Wolfe, thank you for responding.
I am confused by your addition of
 / Self study  
I don't see any mention of it in  "Experts Exchange Terms of Use". In section 6p; "Code of Conduct" there is the phrase "academic honesty"  but gudii9  is(to use your term) "Self Study".   I think we should let him decide how he wants to learn.  His unorthodox way of learning does frustrate a lot of us but maybe that is our problem.      


@gudii9  
I admire your  energy and your  thirst for knowledge.
One lesson to learn from this challenge should be the excellent point made by mccarl
we only need to find ANY 2 not adjacent to another 2 ... and return false
  compare that to the challenge given by CodingBat
Given an array of ints, return true if every 2 that appears in the array is next to another 2.

You should see the logical equivalency of those two statements.
0
gudii9Author Commented:
I think we should let him decide how he wants to learn.

I am learning a lot from all the experts. All the questions i am asking are for self study only. Explaining and understanding a technical challenge without code is almost next to impossible. Every challenge has n number of approaches and going through each expert code approach opens up new perspective towards that area. I personally prefer solutions with code rather than solutions without code which saves so much  of time for me and and to experts.
0
rrzCommented:
I personally prefer solutions with code rather than solutions without code which saves so much  of time for me and and to experts.
I agree. I definitely agree.  That is the way I like to learn.  I think having a bunch of solutions from a bunch of people is a very valuable  resource. Given such a resource, I study each and every approach and try to learn how each contributor thinks.  My favorite example is
 https://www.experts-exchange.com/questions/20263076/Most-elegant-solution-for-creating-a-star.html    
In that discussion, the author(nebeker) created a challenge for the community. The competition was healthy. It was very educational and FUN for everybody involved .  Maybe it is a technique that you could consider using.
0
gudii9Author Commented:
sure, I will check that link.
0
gudii9Author Commented:
public boolean twoTwo(int[] nums) {
		
		boolean result=true;

		for (int i = 0; i < nums.length; i++) {
			if (nums[i] == 2) {
				int count = 0;
				for (int k = i; k < nums.length; k++) {
					if (nums[k] == 2)
						count++;
					else
						break;
				}
				i = i+count;
				if (count < 2)
					result=false;
			}
		}
		return result;
	}

Open in new window


above also passes all tests
0
gudii9Author Commented:
public boolean twoTwo(int[] nums) {
  for (int i = 0; i < nums.length; i++) {
    if (nums[i] == 2) {
      if (i == (nums.length - 1) || nums[++i] != 2) {
        return false;
      }
      while (i < nums.length && nums[i] == 2) {
        i++;
      }
    }
  }
  return true;
}

Select all
 
Open in new window

Basic description...

We only need to care if we find a 2, if it is at the end of the array or there is no 2 following it, return false. If it was followed by a 2, the "while" loop skips however many 2's are next to each other (so that it caters for 2, 2 and 2, 2, 2, 2, 2 in the same way)

Open in new window


now above solution is clear
0
gudii9Author Commented:
public boolean twoTwo(int[] nums) {
  for (int i = 0; i < nums.length; i++) {
    if (accessArray(nums, i) == 2) {
      if (accessArray(nums, i - 1) != 2 && accessArray(nums, i + 1) != 2) {
        return false;
      }
    }
  }
  return true;
}

private int accessArray(int[] arr, int index) {
  return index >= 0 && index < arr.length ? arr[index] : 0;
}


i was not clear on above. please advise
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
i was not clear on above. please advise

Ok, so, in a few of the other code examples, a lot of the code is there to deal with bounds of the array, ie. the start and the end, and dealing with these specially to avoid your ArrayIndexOutOfBoundsException.

So what the above method does, is provide a view of the array that pads before the start and after the end with ZERO. So an array with 1, 2, 3 looks like, ... 0, 0, 0, 1, 2, 3, 0, 0, 0, 0 ... However, the 0 index still points to the first element, ie. 1 and the length of the array is still 3. So now we just do a standard loop and check if the number is 2, check if both numbers on either side are NOT 2 and if so, return false.
0
gudii9Author Commented:
is this good idea to use above approach for all array chalenges as i quite often get array out of bound exceptin?


what are we doing in these 2 if loops?

if (accessArray(nums, i) == 2) {//check to see if nums[i] is 2 or not?
      if (accessArray(nums, i - 1) != 2 && accessArray(nums, i + 1) != 2) {////check to see if nums[i-1] is not 2 and nums[i+1] os not 2 by calling that method which does some padding?
        return false;
      }
    }

Open in new window

0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
I think it reads pretty well, and I've already stated this... check the last sentence of my last post. But it is again...

If the value we are looking at (based on i) is a 2 and the value before is NOT a 2 and the value after is NOT a 2, then return false. Or in different words, if the value pointed at by i is a 2 that is surrounded by non-2, return false.
0
gudii9Author Commented:
If the value we are looking at (based on i) is a 2 and the value before is NOT a 2 and the value after is NOT a 2, then return false. Or in different words, if the value pointed at by i is a 2 that is surrounded by non-2, return false.

make sense..all other cases return true
0
gudii9Author Commented:
pads before the start and after the end with ZERO.

pads with how many zero's before and after?
0
gudii9Author Commented:
return index >= 0 && index < arr.length ? arr[index] : 0;

if index >= 0 && index < arr.length is true then return arr[index]
otherwise if false then return 0?
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
if index >= 0 && index < arr.length is true then return arr[index]
otherwise if false then return 0?

Exactly!

pads with how many zero's before and after?

An infinite number... It is not really padding the array at all, it just APPEARS as though it is. ie. you can ask for     accessArray(nums, -12568234969986234)      and it will still return 0. Theoretically, all you need is 1 ZERO at the start and 1 at the end, because you only ever do i - 1 and i + 1, but that would actually be harder to code for than what I did above.
0
gudii9Author Commented:
if index >= 0 && index < arr.length is true then return arr[index] otherwise if false then return 0?

Exactly!

 otherwise if false means when index<0 (index can never be less than zero right?
 it is 0 or more always in arrays?
and also index>arr.length then it is false so return 0?
is sounds bit complicated to me somehow?
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.