I'm trying to write a recursive method in Java that will take two arrays of int and return true/false if the first array represent a pattern of the second array, in that way - (the pattern array accept 0, 1 or 2. 0 represent one or two digits number, 1 represent one digit numbers and 2 represent two digits numbers. so if I send {2, 3, 57} and {1, 0, 2} it will return true. if i put {2, 555, 57} and {1, 0, 2} it will return false. also, if i put {2,3,573**,4,34,35}** and {1, 0, 2} i still need to get true, since part of the array represnt the pattern.
i came up with this:
private static boolean match(int [] a, int [] pattern, int i, int j, int c, int subArr)
{
if(a.length < pattern.length)
return false;
else if(pattern.length == 0)
return true;
else if(pattern.length == a.length && check(a, pattern, i, j))
return true;
else if(check(a, pattern, i++, j++))
{
return check(a, pattern, i, j);
}
else return false;
}
private static boolean check(int [] a, int [] pattern, int i, int j)
{
if(pattern[j] == 1 && (checkDigits(a[i]) == 1))
{
return true;
}
else if(pattern[j] == 2 && checkDigits(a[i]) == 2)
{
return true;
}
else if(pattern[j] == 0 &&(checkDigits(a[i]) == 1 || checkDigits(a[i]) == 2 )){
return true;
}
else return false;
}
private static int checkDigits(int k){
int length = (int)(Math.log10(k)+1);
return length;
}
the match method is doing all the checks. the check methode is checking the pattern and checkDigits the number of digits.
My problem is with 3 digits numbers. if i put for exemple { 2, 123, 54 } and {1, 0, 2} I get true and not false. I belive the problem is in the check method but I can't locate the problem.
Check this code I wrote right now, I added comments to the code, and if you run it. I wrote some text on the console to explain to you how it's working. So at the end when you want to use it, just remove the system.out.print
public class ArrayPattern {
static int numbers[] = {1,10,20,3,30};
static int pattern[] = {0,0,2,2};
public static void main(String[] args) {
System.out.println(isPattern(0, 0));
}
/**
* Recursive method that checks for the pattern. If it fails to match pattern starting from index i, it
* tries starting from index i+1
* */
public static boolean isPattern(int index, int consec){
// If all pattern values where matched consecutively
if(consec == pattern.length)
return true;
// If the numbers ended and the pattern wasn't found
if(index == numbers.length)
return false;
// If the current number matches the pattern, check the next number at index + 1
if(checkPattern(pattern[consec], numbers[index])){
System.out.println(pattern[consec] +" => "+ numbers[index]);
return isPattern(index+1, consec+1);
}
// If the pattern was not found, starting from a specific index. Start from the next index to check if the pattern can be found
System.out.println(String.format("\nFailed to match pattern, try starting from index: %d\n", (index - consec + 1)));
return isPattern(index - consec + 1, 0);
}
/**
* Just chesk the pattern:
* 0 => 1 or 2 digits.
* 1 => 1 digit.
* 2 => 2 digits
*/
public static boolean checkPattern(int pattern, int value){
String sValue = String.format("%d", value);
switch (pattern) {
case 0:
return sValue.length() <= 2;
default:
return sValue.length() == pattern;
}
}
}
A truly recursive solution might be the following:
import java.util.Arrays;
public class Checker {
//0 represent one or two digits number,
//1 represent one digit numbers and
//2 represent two digits numbers
public boolean match(int [] a, int [] pattern, int i, int j)
{
if(pattern.length == 0) return true;
if(pattern.length == a.length) {
return check(a, pattern);
} else {
return false;
}
}
//recursive function
private boolean check(int [] a, int [] pattern) {
boolean firstDigitCheck = false;
switch (pattern[0]) {
case 0: firstDigitCheck = checkDigits(a[0]) <3;break; // 1 or 2
case 1: firstDigitCheck = checkDigits(a[0]) <2;break; // 1
case 2: firstDigitCheck = checkDigits(a[0]) ==2;break// 2
default:break;//not important (we trust the pattern format)
}
if (a.length==1) {//base step (array of dimension 1)
return firstDigitCheck;
} else {//recursive step on the left-truncated arrays
return firstDigitCheck && check(Arrays.copyOfRange(a, 1, a.length), Arrays.copyOfRange(pattern, 1, pattern.length));
}
}
public int checkDigits(int k){
int length = (int)(Math.log10(k)+1);
return length;
}
}
If I understand your question, then the element in array, "a", at index 'j' can have a certain number of digits based on the number at the element at index 'j' in pattern.
You could accomplish this with a for loop;
boolean result = true;
int [...] a = ...
int [...] pattern = ...
for (int j = 0; j < a.length(); j++) {
if (result) {
if (pattern[j] = 0) {
if (a[j].toString().length() > 2) {
result = false;
}
} else if (pattern[j] = 1) {
if (a[j].toString().length() != 1) {
result = false;
}
} else if (pattern[j] = 2) {
if (a[j].toString().length() != 2) {
result = false;
}
}
}
}
That should get the job done, or something similar.
I am a little unclear with your code. But it can be done in a simpler way using a for loop.
The basic algorithm you need to follow would be:
j=0
for(i = 0 to a.length){
if number of digits(a[i]) == pattern[j] {
j++
}
}
if j == pattern.length
print its a match
else
it is not.
This small piece of code will work for every case.
Instead of the for loop, just call it every time.
Related
Problem:
Find the maximum length of contagious subarray with repeated elements.
eg:
[1 2 2 2 3 3 5 1 8] - answer is 3 since 2 repeated 3 times is the max repeated times.
[1 2] - answer is 1
[1 2 2 3 3] - answer is 2
But the recursive function should only have list as the argument. int findMaxContagiousRepeatedLength(List<Integer> list)
What I've tried:
class Answer
{
public static int findMaxContagiousRepeatedLength(List<Integer> nums, int currentCount, int latestNumber)
{
if (nums.isEmpty())
return 0;
if (nums.get(0) == latestNumber) {
return Math.max(currentCount+1, findMaxContagiousRepeatedLength(nums.subList(1, nums.size()), currentCount+1, nums.get(0)));
} else {
return findMaxContagiousRepeatedLength(nums.subList(1, nums.size()), 1, nums.get(0));
}
}
public static void main(String[] args)
{
Integer[] nums = { 1,2,1,1,1,1,1,2,3,2,3,1,2,2};
System.out.println("Max length: " +
findMaxContagiousRepeatedLength(Arrays.asList(nums), 0, nums.length == 0 ? -1 : nums[0]));
}
}
The above does work, but doesn't meet the requirement of argument restriction.
Please help me figure out if it's possible to have a solution where recursive function only have list as the argument.
Best solution
Use your Function
public static int findMaxContagiousRepeatedLength(List<Integer> nums, int currentCount, int latestNumber)
{
if (nums.isEmpty())
return 0;
if (nums.get(0) == latestNumber) {
return Math.max(currentCount+1, findMaxContagiousRepeatedLength(nums.subList(1, nums.size()), currentCount+1, nums.get(0)));
} else {
return findMaxContagiousRepeatedLength(nums.subList(1, nums.size()), 1, nums.get(0));
}
}
and make a second Function which calls your function with default parameters
public static int findMaxContagiousRepeatedLength(List<Integer> nums)
{
return findMaxContagiousRepeatedLength(Arrays.asList(nums), 0, nums.length == 0 ? -1 : nums[0]);
}
Now you can call the second function which calls the first function with default parameters!
First, this problem is best solved by just going through the list.
But if you must use recursion with List<Integer> as the only parameter you may use the below:
public static int findMaxContiguousRepeatedLength(List<Integer> nums) {
if (nums.isEmpty()) {
return 0;
}
Iterator<Integer> it = nums.iterator();
Integer start = it.next();
int len = 1, pos = 1;
while (it.hasNext()) {
Integer curr = it.next();
if (curr == start) {
pos++;
len++;
} else {
break;
}
}
return Math.max(len, findMaxContiguousRepeatedLength(nums.subList(pos,nums.size())));
}
If you're allowed to (temporarily) modify the list, the below approach would also work:
public static int findMaxContiguousRepeatedLength(List<Integer> nums) {
if (nums.isEmpty()) {
return 0;
}
// carve out repeated chunk from back
Integer back = nums.remove(nums.size() - 1);
int repeats = 1;
while(!nums.isEmpty() && nums.get(nums.size() - 1) == back) {
nums.remove(nums.size() - 1);
repeats++;
}
int res = Math.max(repeats, findMaxContiguousRepeatedLength(List<Integer> nums));
while(repeats) { // restore
repeats--;
nums.add(back);
}
return res;
}
So the exercise is:
Using recursion only (no loops)
Find if there is sub ground of numbers that are equal to the given number in an array and follow the rule.
Let's say I have this array, I give the function a number for sum and it must adhere to this rule:
you cannot repeat the same number, and you can't sum 3 numbers in a row (can't do i+1 and i+2)
int[] a = {5,4,2,1,3};
So in this case:
num 8 = true (4+3+1) ( 5+3)
num 11 = false (4+5+2 are 3 but are three in a row) (5+2+1+3 also three in a row)
My attempt is:
public static boolean sumRule(int[] a , int num){
if (num == 0){
return true;
} else {
return sumRule(a,num,0,a.length);
}
}
private static boolean sumRule(int[] a, int num, int low,int high){
if(low >= high || low < 0){
return false;
}
if (a[low] == -1){
return false;
}
if(a[low] == num || num-a[low] == 0 ){
return true;
}
int temp = a[low];
a[low] = -1;
return sumRule(a,num,low,high) || sumRule(a,num-temp,low+3,high) || sumRule(a,num-temp,low+1,high) ;
}
But when I send 11 to this, it still returns true, anyone has an idea what am i missing here?
Thanks,
I have the full code answer below, and here's the explanation:
Essentially you need to break this problem down to a recurrence. What that means is, you look at the choice at each step (i.e. whether to use a number or not in the sum) and recursively calculate both options.
The base case:
If num == 0 then we know it's true. But if num != 0 and the array has length 0, then we know it's false
Recursive case:
We check if the first number in the array is less than or equal to num. If not, then we can't use it. So we do a recursive call with all the same parameters except the array is now the original array minus the first number
If we CAN use the number (i.e. a[0] <= num) then the true answer might use this or it may not use it. We make a recursive call for each case, and return true if either of the recursive calls return true.
The consecutive number rule:
This is easy to enforce. We add a parameter called 'left' which tells us the number of elements we can consecutively take from the beginning of the array. To start with, left is 2 because at most we can take 2 consecutive numbers. Then in the cases where we DO use the first number in the array in our sum, we decrement left. If we don't use the first number in the array, we reset left to 2. In the cases where left becomes 0, we have no choice but to skip the current number at the top of the array.
class Main {
public static void main(String[] args) {
int[] a = new int[] {5,4,2,1,3};
System.out.println(sumRule(a, 8));
System.out.println(sumRule(a, 11));
}
public static boolean sumRule(int[] a , int num){
if (num == 0){
return true;
} else {
return sumRule(a,num,2);
}
}
private static boolean sumRule(int[] a, int num, int left){
if (num == 0) {
return true;
}
if (a.length == 0) {
return false;
}
int[] a_new = new int[a.length-1];
for (int i = 1; i < a.length; i++) a_new[i-1] = a[i];
if (left == 0) {
return sumRule(a_new, num, 2);
}
boolean using_a0 = false;
if (a[0] <= num) {
using_a0 = sumRule(a_new, num-a[0], left-1);
}
boolean not_using_a0 = sumRule(a_new, num, 2);
return (not_using_a0 || using_a0);
}
}
Edit - A variation on the code above without copying the array:
class Main {
public static void main(String[] args) {
int[] a = new int[] {5,4,2,1,3};
System.out.println(sumRule(a, 8));
System.out.println(sumRule(a, 11));
}
public static boolean sumRule(int[] a , int num){
if (num == 0){
return true;
} else {
return sumRuleNoLoop(a,num,2,0);
}
}
private static boolean sumRuleNoLoop(int[] a, int num, int left, int startIdx){
if (num == 0) {
return true;
}
if (startIdx >= a.length) {
return false;
}
if (left == 0) {
return sumRuleNoLoop(a, num, 2, startIdx+1);
}
boolean using_a0 = false;
if (a[startIdx] <= num) {
using_a0 = sumRuleNoLoop(a, num-a[startIdx], left-1, startIdx+1);
}
boolean not_using_a0 = sumRuleNoLoop(a, num, 2, startIdx+1);
return (not_using_a0 || using_a0);
}
}
First thing you can add is a check to see not 3 numbers in a row being added. Also replacing a number in the array with -1 would have unintended side effects within recursive calls. Below is something I have. You can ignore the index param I have used to see the values used.
Explanation:
The recursive sumRule method divides the problem into two parts:
First part takes the value of current index and adds with the sum of values starting from next index.
Second part assumes, current value can’t be taken for the sum. It only checks if there is a sum within the subset starting from next value of the array.
In the method, lastIndex is keeping track of the index of last value picked up for the sum. So, in the first call the value is 0, 1 in second and so on.
(start - lastIndex <= 1 ? consecutive + 1 : 1) is to check whether value of consecutive should be increased or not. consecutive = 1 means, current value is added to the sum.
public static boolean sumRule(int[] a, int num) {
if (num == 0) {
return true;
} else {
return sumRule(a, num, 0, 0, 0, 0, "");
}
}
public static boolean sumRule(final int[] a, int num, int sum, int start, int consecutive, int lastIndex,
String index) {
if (consecutive == 3) {
return false;
}
if (sum == num) {
System.out.println(index);
return true;
}
if (start >= a.length) {
return false;
}
return sumRule(a, num, sum + a[start], start + 1, (start - lastIndex <= 1 ? consecutive + 1 : 1), start,
index + ", " + start) || sumRule(a, num, sum, start + 1, consecutive, lastIndex, index);
}
Here is my implementation. It contains comments explaining what the different parts do.
public class RecurSum {
/**
* Determines whether 'sum' equals 'target'.
*
* #param arr - its elements are summed
* #param sum - sum of some elements in 'arr'
* #param target - required value of 'sum'
* #param index - index in 'arr'
* #param consecutive - number of consecutive indexes summed to ensure don't exceed 3
* #param start - starting element in 'arr' which is used for back-tracking
*
* #return "true" if 'sum' equals 'target'
*/
private static boolean sumRule(int[] arr, int sum, int target, int index, int consecutive, int start) {
if (sum == target) {
return true;
}
else {
if (index >= arr.length) {
// if we have reached last element in 'arr' then back-track and start again
if (start < arr.length) {
return sumRule(arr, 0, target, start + 1, 0, start + 1);
}
// we have reached last element in 'arr' and cannot back-track
return false;
}
else {
consecutive++;
if (consecutive == 3) {
// skip 3rd consecutive element (because of the rule)
consecutive = 0;
return sumRule(arr, sum, target, index + 2, consecutive, start);
}
else {
if (sum + arr[index] > target) {
// recursive call but don't add current element of 'arr'
return sumRule(arr, sum, target, index + 1, 0, start);
}
// recursive call: add current element of 'arr' to 'sum' and proceed to next element
return sumRule(arr, sum + arr[index], target, index + 1, consecutive, start);
}
}
}
}
public static void main(String[] args) {
int[] arr = new int[]{5, 4, 2, 1, 3};
// initial call to recursive method with target = 11 (eleven)
System.out.println(sumRule(arr, 0, 11, 0, 0, 0));
// initial call to recursive method with target = 8
System.out.println(sumRule(arr, 0, 8, 0, 0, 0));
}
}
I am buidling an app called Thirty Throws in Android and I am completely stuck
with my validation.
In Thirty Throws you have the scores 4, 5, 6 ,7, 8, 9, 10, 11, 12 and 6 dice.
Each turn consists of 3 throws and the user can choose the dice he wish to keep between every throw.
Example say that the user has thrown 4,4,3,5,1,5 then he can choose the score 11 because 4 + 4 +3 = 11 and 5 + 1 + 5 = 11 or if the user has thrown 2,2,2 he can choose 6.
I'm struggling with validating the score. The code I have at the moment manage to validate most. What am I missing?
I've been looking at some recursive solution here but they seem no to be what I am looking for since I have to return a boolean.
public static boolean isValidResult(ArrayList<Integer> score, int selectedPoints)
{
ArrayList<Integer> notReadyNumbers = new ArrayList<>();
for (int i: score) {
if (i == selectedPoints) {
continue;
}
if (CalcSum(notReadyNumbers) + i == selectedPoints) {
notReadyNumbers.clear();
} else {
boolean isDone = false;
if (notReadyNumbers.size() > 0) {
for (int z: notReadyNumbers) {
if (z + i == selectedPoints) {
isDone = true;
}
}
}
if (isDone) {
notReadyNumbers.clear();
} else {
notReadyNumbers.add(i);
}
}
}
return notReadyNumbers.size() == 0 ? true : false;
}
You should take all possible numbers from any position. So in order to take all possible result you may use permutation of these numbers to serialise the numbers. Another way is to use bit-masking with recursion.
Here is a solution of your problem. (Based on bit-masking and recursion).
public static boolean isValidResult(ArrayList<Integer> score, int selectedPoints)
{
return canMakeValid(score, selectedPoints, 0, 0); // first 0 is for masking, second 0 is for summation.
}
public static boolean canMakeValid(ArrayList<Integer> score, int selectedPoints, int mask, int sum)
{
if(sum > selectedPoints) return false;
sum %= selectedPoints;
int sz = score.size();
if(mask == ((1<<sz)-1)) {
if(sum == 0) return true;
return false;
}
boolean ret = false;
for(int i = 0; i < sz; i++) {
if((mask&(1<<i)) == 0) {
ret = ret | canMakeValid(score, selectedPoints, mask | (1<<i), sum + score.get(i));
}
}
return ret;
}
You can learn about bit-masking from this link: https://discuss.codechef.com/t/a-small-tutorial-on-bitmasking/11811/3
Indeed there are some recursive solutions.
public static boolean isValidResult(List<Integer> score, int selectedPoints) {
score.sort();
return isValidResultRec(score, selectedPoints, 0);
}
/**
* #param scoreI the first position to consider to add or not add.
*/
private static boolean isValidResultRec(List<Integer> score, int selectedPoints, int scoreI) {
while (!score.isEmpty() && scoreI < score.size()) {
int index = Collections.binarySearch(score, selectedPoints);
if (index >= 0) {
return true;
}
// Now ~index is the insert position;
// i >= ~index are values > selectedPoints.
score = score.subList(~index, score.size());
for (int i = scoreI; i < ~index; ++i) {
int value = score[i]; // value < selectedPoints.
score.remove(i); // Do step.
if (isValidResultRec(score, selectedPoints - value, scoreI + 1) {
return true;
}
score.add(i, value); // Undo step.
}
}
return false;
}
Here sorting is used; using decreasing order, Comparator.reversed(), or a for --i would take larger steps.
The recursion should either add the ith dice value or not.
The code here can be written nicer.
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;
}
I want to tell if an array of integers is alternating.
in JAVA.
For example:
a[]={1,-1,1,-1,1,-1} --> true
a[]={-1,1,-1,1,-1} --> true
a[]={1,-4,1-6,1} --> true
a[]={1,1,1,14,5,3,2} --> false
I have started to write some code that uses flags. For example if the current_is_positive=0 and else = 1, but I'm not getting anywhere. What is a good way to achieve this effect?
I think you mean alternating in sign, i.e. positive number, negative number, positive number, etc.?
You could use the following strategy:
Skip the first element.
For every other element, compare its sign with the sign of the previous element:
If they're different, the sequence is still alternating upto now - you should continue.
If they're the same sign, the sequence is not alternating. You can stop processing at this point.
As this sounds like a homework assignment, I'll leave it upto you to write the appropriate code in Java.
Here my solution:
This checks that element n+1 is the inverse of the element n.
public static void main(String[] args) {
int[] ints = {1, -1, 2, -1};
System.out.println(new Example().isArrayAlternating(ints));
}
public boolean isArrayAlternating(int[] ints) {
if (ints == null || ints.length % 2 != 0) {
return false;
}
for (int i = 0; i < ints.length - 1; i++) {
if (ints[i] != ints[i + 1]*(-1)) {
return false;
}
}
return true;
}
If you only wanted to check for positive number, negative number...n times, without paying attention to value:
public static void main(String[] args) {
int[] ints = {1, -1, 2, -1};
System.out.println(new Example().isArrayAlternating(ints));
}
public boolean isArrayAlternating(int[] ints) {
if (ints == null || ints.length % 2 != 0) {
return false;
}
for (int i = 0; i < ints.length - 1; i++) {
if (ints[i] >= 0 && ints[i + 1] >= 0 || ints[i] <= 0 && ints[i + 1] <= 0) {
return false;
}
}
return true;
}
You can simply check if all items are equal to the item two steps back. I don't know what language you are using, but for example using C# you could do it like this:
bool alternating = a.Skip(2).Where((n, i) => a[i] == n).Count() == a.Length - 2;
Edit:
So you want to check if the sign of the values are alternating, not the values?
Then just check the sign against the previous item:
bool alternating = a.Skip(1).Where((n,i) => Math.Sign(n) == -Math.Sign(a[i])).Count() == a.Length-1;
boolean prevPositive = arr[0] > 0, error = false;
for (int i = 1; i < arr.length; ++i) {
boolean current = arr[i] > 0;
if (current != prevPositive) {
current = prevPositive;
} else {
error = true;
break;
}
}
if (error)
System.out.println("No");
else
System.out.println("Yes");
private enum SIGN {
POSITIVE, NEGATIVE
};
public static boolean isAlternating(int... ints) {
SIGN last = null;
for (int i : ints) {
if (i >= 0) {
if (last == null) {
last = SIGN.POSITIVE;
} else {
if (last == SIGN.POSITIVE) {
return false;
} else {
last = SIGN.POSITIVE;
}
}
} else {
if (last == null) {
last = SIGN.NEGATIVE;
} else {
if (last == SIGN.NEGATIVE) {
return false;
} else {
last = SIGN.NEGATIVE;
}
}
}
}
return true;
}
Run through the array from index 1 till the end.
At each index, evaluate (a[i] > 0) == (a[i-1] > 0). If this is true, then your array is not alternating.
If you make it till the end without concluding it is not alternating, then it is alternating :)
Run a loop, from first index to maximum possible with a step of 2, to check for same sign.
Then again a loop, from 2nd index to maximum possible with a step of 2, to check for opposite sign, but all same.
So, loop from index - 0, 2, 4, 6, ...
then loop from index - 1, 3, 5, 7, ...
Then check that the multiplication of every number in both loop with the first number in that iteration should be positive.
int a[]={1,-1,1,-1,1,-1};
boolean alternating = true;
for (int i = 0; i < a.length; i = i + 2) {
if (a[i] * a[0] > 0) {
} else {
alternating = false;
}
}
for (int i = 1; i < a.length; i = i + 2) {
if (a[i] * a[1] > 0) {
} else {
alternating = false;
}
}
if (alternating) {
System.out.println("Array is alternating");
} else
System.out.println("Array is not alternating");
}
For i = 2 to n
check whether A[i-1] && A[i] are with diff sign..
in C++; return ((A[i-1] ^ A[i]) < 0).
Same explained here : http://www.youtube.com/watch?v=Z59REm2YKX0
EDIT
If an integer is negative, then the high order bit is 1. Otherwise, it's 0. You can check if two integers have different signs by XORing them together. If the signs are different, then the high order bit of the result will be 1. If they're the same, then the high order bit will be 0. Thus,
A XOR B < 0 is equivalent to "A and B have different signs"
Peter Ruderman