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;
}
Related
How does this particular recursion works
return (X.charAt(m-1) == Y.charAt(n-1) ? count(X, Y, m-1, n-1) : 0) + count(X, Y, m-1, n)
in the below code?
The below code will return the count of number of times the pattern appears in a given string as a subsequence.
class Subsequence {
public static int count(String X, String Y, int m, int n) {
if (m == 1 && n == 1)
return X.charAt(0) == Y.charAt(0) ? 1 : 0;
if (m == 0)
return 0;
if (n == 0)
return 1;
if (n > m)
return 0;
return (X.charAt(m - 1) == Y.charAt(n - 1) ? count(X, Y, m - 1, n - 1) : 0) + count(X, Y, m - 1, n);
}
public static void main(String[] args) {
String X = "subsequence";//input String
String Y = "sue";// pattern
System.out.print(count(X, Y, X.length(), Y.length()));
}
}
It works as below:
if(X.charAt(m-1) == Y.charAt(n-1))
return count(X, Y, m - 1, n - 1);
else
return 0; //since no match found here
Now, the above code is breakage of the first line of your return statement that uses ternary operator. Don't think that this is the complete break down of this code.
So, once you got this statement, the next step would be call this function again to find any matching characters starting from m- in first string and from n in the pattern string since we need to still match the whole pattern right from the start. However, if we find a match, we are just proceeding to match remaining available characters in both pattern and the string.
But to be honest, there are many better ways to code the pattern matching algorithm as compared to this approach.
You will often find that renaming your variables properly and adding some clarification comments works wonders.
public static int count(String string, String pattern, int stringLength, int patternLength) {
if (stringLength == 1 && patternLength == 1) {
// Two length=1 strings -> if they are equal then they match - obviously.
return (string.charAt(0) == pattern.charAt(0)) ? 1 : 0;
}
if (stringLength == 0) {
// No more string to search - no-match.
return 0;
}
if (patternLength == 0) {
// No more pattern to search - MATCH!
return 1;
}
if (patternLength > stringLength) {
// Can never find a pattern longer than the string.
return 0;
}
return ((string.charAt(stringLength - 1) == pattern.charAt(patternLength - 1)) ?
// Both end with same character - recurse to keep matching.
count(string, pattern, stringLength - 1, patternLength - 1)
// Not match.
: 0)
// ADD any matches further down the string.
+ count(string, pattern, stringLength - 1, patternLength);
}
Sadly the code is wrong somewhere - searching for sue in subsequence prints 7.
I believe it is called a "Ternary Operator", it is another way to do IF statements in a more compact way (ie if you do a load of them at the same time for readability). It has to have somewhere to give the return value (a variable or return statement for example)
As an example it can look like this
boolean test = (condition) ? true : false;
Which is the same as writing
boolean test;
if (condition) {
test = true;
} else {
test = false;
}
CodeHunter's answer is a good example of how the sample code you gave is turned back into an if statement.
What it is doing is:
(Psuedo)
function recursiveCount(stringStart, stringEnd, startLocation, endLocation) {
/* pre-checks */
// Total will be how many times it loops (1 + 1 + 1 + 1 + 1 basically what it is doing)
// If there is no more occurances of that string it adds 0 instead of 1, and the recursion breaks.
return (total + recursiveCount(stringStart, stringEnd, nextStartLocation, nextEndLocation)
}
My assignment is to create a recursive method makeDecimal that when passed a number (that is represented by a String) and its base, converts the number to base 10. You will need to use the method Integer.parseInt(str). (Hint: use substrings.) This method takes a String and returns the integer form of it.
For example, Integer.parseInt("21"); will return the int 21.
Here are some examples of how makeDecimal works:
makeDecimal("11", 2) will return 3.
makeDecimal("100", 4) will return 16.
Here was my attempt at it:
public static double makeDecimal(String number, int base){
int len = number.length();
double f = 0;
if(len <= 0)
return 0;
else{
makeDecimal(number,base);
double temp = Integer.parseInt(number.substring(len - 1, len + 1));
f = f + temp * Math.pow(3, len-1);
}
len--;
return f;
}
However, I get an "overflow error", and I don't know if it even is written correctly.
You are recursing with exactly the same arguments that were passed in. As a result, the call will itself recurse the same way, until the stack overflows. That's not how recursion is supposed to work. Instead, you need to figure out how to do one piece of the problem in the current call and then recurse to do a smaller problem.
In your code, it's not even clear what logic you are using. (What's the point of computing 3len-1?) Try this instead:
If the input string has length 0, the answer is 0 (that part you got right)
Otherwise, take the last digit and parse it in the current base. Then the answer is that value plus base times the value of everything up to but not including the last digit of the input. (Hint: this is a good place to use recursion.)
You should be able to translate that description into the appropriate method calls and use of substring().
Oh, one other thing: there's no reason to be using double values here. Just stick with int variables throughout. You won't be needing Math.pow().
Here is simplest solution using recursion, substring and Integer.parseInt:
public int makeDecimal(String value, int base) {
// exit from recursion
if (value.length() < 1)
return 0;
//parsing last character of string
int charValue = Integer.parseInt(value.substring(value.length() - 1), base);
//calling recursion for string without last character
return makeDecimal(value.substring(0, value.length() - 1), base) * base + charValue;
}
Here's my solution after writing the prototype in Python (if you are interested, I can also include the Python source code):
import java.util.HashMap;
import java.util.Map;
public class MakeDecimal {
public static final Map<Character, Integer> alphabet = buildAlphabetTable();
public static void main(String[] args) {
// System.out.println(alphabet);
System.out.println(makeDecimal("af10bb1", 16));
}
// pos refers to the position of the character in the string.
// For example, if you have the following binary string 100
// then 1 at the left is at position 2,
// the 0 in the middle is at position 1,
// and the right most 0 is at position 0
// (you start counting from the right side).
// In general, you would convert that string in the following way:
// 2^2 * 1 + 2^1 * 0 + 2^0 * 0 = 4
// If the base was n, then you would have
// first * n^{pos + "length of string - 1"} + ... + penultimate * n^{pos + 1} + last * n^{pos}
// Note that pos starts from 0.
private static int makeDecimal(String s, int base, int pos) {
if (s.length() == 0) {
return 0;
} else {
int last = (int) Math.pow(base, pos) * alphabet.get(s.charAt(s.length() - 1));
return makeDecimal(s.substring(0, s.length() - 1), base, pos + 1) + last;
}
}
public static int makeDecimal(String s, int base) {
if (s.length() == 0) {
return 0;
}
if (base < 2 || base > 36) {
throw new IllegalArgumentException("not base >= 2 and base <= 36");
}
return makeDecimal(s.toLowerCase(), base, 0);
}
// Creates a table that maps characters to their decimal value
// the characters can be also '0' or '2' (or any other character number)
// or they can be a character of the English alphabet
private static Map<Character, Integer> buildAlphabetTable() {
Map<Character, Integer> a = new HashMap<>(36);
int i = 0;
for (char c = '0'; c <= '9'; c++, i++) {
a.put(c, i);
}
for (char c = 'a'; c <= 'z'; c++, i++) {
a.put(c, i);
}
return a;
}
}
My solution is based on the following post, which you should definitely read to refresh your ideas on how to convert between bases.
http://www.purplemath.com/modules/numbbase.htm
It does not accept bases that are smaller than 2 or greater than 36. It handles also when you pass English characters in upper case.
Edit: At first I've misted that recursion is obligated for this solution so my original answer without it could me four below.
Here is solution with recursion and without substring and Math.pow:
public double makeDecimal(String value, int base) {
makeDecimal(value, base, value.length() - 1);
}
public double makeDecimal(String value, int base, int index) {
double result = 0;
if (index < 0)
return result;
double charValue = 0;
char currentChar = values.get(Character.toUpperCase(value.charAt(index));
if (currentChar >= 0 && currentChar <= '9') {
charValue = currentChar - '0';
} else if (currentChar >= 'A' && currentChar <= 'Z') {
charValue = currentChar - 'A';
} else {
throw new InvalidValueException("Unsupported character '" + currentChar + "'.");
}
if (charValue >= base) {
throw new InvalidValueException("Wrong character '" + currentChar + "' for base '" base + "'.");
}
return makeDecimal(value, base, index - 1)) * base + charValue;
}
Original Answer: Something like this should work for any base starting from 2 till 36:
private Map<Character, Integer> getCharValues(int base)
{
Map<Character, Integer> values = new HashMap<Character, Integer>();
for (int i = 0; i < base; i++){
if (i < 10) {
values.put('0' + i, i);
} else if (i < 36) {
values.put('A' + i - 10, i);
} else {
throw new InvalidValueException("Base '" + base + "' not supported");
}
}
return values;
}
public double makeDecimal(String value, int base)
{
Map<Character, Integer> charValues = getCharValues(base);
double result = 0;
for (int i = 0; i < value.length(); i++){
result = result * base + charValues.get(Character.toUpperCase(Character.toUpperCase(value.charAt(i))));
}
return result;
}
If you need base more then 36 you can extend char set in method getCharValues. Also it will be a good idea do not create HasMap every time but just store it for maximum base and throw exception if char value exceed given base.
For a programming assigment:
Create a recursive method in java that for example for n = 5 returns
1
.2
..3
...4
....5
...4
..3
.2
1
(let the point be spaces or tabs)this has been quite a headache im just started this course so im in beginner level and so far i have this
public String Esc(int n){
if (n <= 1)
return ""+n;
else
return n + "\n" + Esc(n - 1) + "\n" + n;
}
that returns
5
4
3
2
1
2
3
4
5
so im not even close and im still missing the spaces problem
thanks for helping
What you need is to do what you were doing, except backward. The way I found to do it was to basically have a counter going UP to the number n instead of going DOWN from n to 1.
Like this:
public static String esc(int n) {
return esc(1, n); // start at 1, go to n
}
// i counts from 1 to n and then stops at n
public static String esc(int i, int n) {
if (i == n) {
return getDots(i - 1) + i; // base case
}
else {
return getDots(i - 1) + i + "\n" + esc(i + 1, n) + "\n" + getDots(i - 1) + i;
}
}
// this method just generates n number of dots for the spacing
public static String getDots(int n) {
String dots = "";
for (int i = 0; i < n; i++) {
dots += ".";
}
return dots;
}
public static void main(String[] args) {
System.out.println(esc(5)); // call the function
}
So you can see that I recursively call the function using esc(i + 1, n) instead of n - 1. I'm counting i up by 1 each time until I reach n.
As for the use of the getDots method: The dots in front of each of the number happens to be that number subtract 1. So whenever the number is displayed (which is i), just display i - 1 dots in front of it.
Output:
1
.2
..3
...4
....5
...4
..3
.2
1
Shortest and easiest:
Demo: Press Start
Code ( first call set m to zero - see in the demo):
public static String Esc(int n, int m){
m = m + 1;
String s = "";
for ( int i= 0; i< (m-1); i++ ) s += '.';
if (n == m) return s + m;
return s + m + "\n" + Esc(n,m) + "\n" + s + m;
}
And even shorter:
public static String Esc(int n, int m) {
String s = "";
for (int i= 0; i< (m); i++) s += '.';
return n == m+1 ? s+(m+1) : s+(m+1)+"\n"+ Esc(n,m+1) +"\n"+s+(m+1);
}
And Even Shorter and without a for loop!! Demo: Press Start
public static String Esc(int n, int m) {
String s = new String(new char[m]).replace("\0", ".");
return n == m+1 ? s+(m+1) : s+(m+1)+"\n"+ Esc(n,m+1) +"\n"+s+(m+1);
}
Usage:
Esc(5, 0);
The trick is to use an accumulator.
class Test {
public static String esc(int n, String accum) {
if(n == 1) {
return accum;
}
int nMinusOne = n -1;
return esc(nMinusOne, nMinusOne + "\n" + accum + "\n" + nMinusOne);
}
public static String esc(int n) {
return esc(n, "" + n);
}
public static void main(String args[]) {
System.out.println(esc(5));
}
}
Here is one way to do it.
You pass in your value n twice. The reason is that you use n1 to print from 1 to n, and you then use n2 to print from n to 1. You also pass in a boolean flag that you make true once you switch the printing order.
Further more, you use n2 to reverse the value of n1 when printing such that:
n1 = 5, print 1
n1 = 4, print 2
// ....
This is done by the formula n2 + 1 - n1 as demonstrated bellow.
Since you said in the comments that you cannot use loops, I made the printing of dots into another recursive function.
Here is the result:
public static void printDots(int val, int condition) {
if(val < condition - 1) {
System.out.print(".");
printDots(val + 1, condition);
}
}
public static void Esc(int n1, int n2, boolean reverse) {
int val = (n2 + 1 - n1); // this gives 1 for n, 2 for n-1, 3 for n-2 etc.
if (n1 > 1 && !reverse) { // print from 1 to n
printDots(0, val); // print dots
System.out.println(val);
Esc(n1 - 1, n2, reverse);
} else if (n1 <= n2) { // print from n to 1
reverse = true;
printDots(0, val); // print dots
System.out.println(val);
Esc(n1 + 1, n2, reverse);
}
}
public static void main(String args[]) {
Esc(5, 5, false);
}
If you want to use the exact method signature you stated in your question, you can wrap the method I gave you above inside your method:
void Esc(int n) {
Esc(5, 5, false);
}
And then call Esc(5) from your main(). You can name the methods the same because java supports method overloading
Here is a running example
Output:
1
.2
..3
...4
....5
...4
..3
.2
1
public class Assignment {
private static int top;
public static void main(String[] args) {
top = 5;
recurse("", 1);
}
public static void recurse(String dots, int value) {
System.out.println(dots + value);
if (value == top) return;
recurse(dots + '.', value + 1);
System.out.println(dots + value);
}
}
It executes like this:
recurse("", 1) {
1 print 1
recurse(".", 2) {
.2 print .2
recurse("..", 3) {
..3 print ..3
recurse("...", 4) {
...4 print ...4
recurse("....", 5) {
....5 print ....5
return
}
...4 print ...4
}
..3 print ..3
}
.2 print .2
}
1 print 1
}
Now run it in the debugger to learn how it actually works.
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.
I'm trying to convert an integer to a 7 bit Boolean binary array. So far the code doesn't work:
If i input say integer 8 to be converted, instead of 0001000 I get 1000000, or say 15 I should get 0001111 but I get 1111000. The char array is a different length to the binary array and the positions are wrong.
public static void main(String[] args){
String maxAmpStr = Integer.toBinaryString(8);
char[] arr = maxAmpStr.toCharArray();
boolean[] binaryarray = new boolean[7];
for (int i=0; i<maxAmpStr.length(); i++){
if (arr[i] == '1'){
binaryarray[i] = true;
}
else if (arr[i] == '0'){
binaryarray[i] = false;
}
}
System.out.println(maxAmpStr);
System.out.println(binaryarray[0]);
System.out.println(binaryarray[1]);
System.out.println(binaryarray[2]);
System.out.println(binaryarray[3]);
System.out.println(binaryarray[4]);
System.out.println(binaryarray[5]);
System.out.println(binaryarray[6]);
}
Any help is appreciated.
There's really no need to deal with strings for this, just do bitwise comparisons for the 7 bits you're interested in.
public static void main(String[] args) {
int input = 15;
boolean[] bits = new boolean[7];
for (int i = 6; i >= 0; i--) {
bits[i] = (input & (1 << i)) != 0;
}
System.out.println(input + " = " + Arrays.toString(bits));
}
I would use this:
private static boolean[] toBinary(int number, int base) {
final boolean[] ret = new boolean[base];
for (int i = 0; i < base; i++) {
ret[base - 1 - i] = (1 << i & number) != 0;
}
return ret;
}
number 15 with base 7 will produce {false, false, false, true, true, true, true} = 0001111b
number 8, base 7 {false, false, false, true, false, false, false} = 0001000b
Hints: Think about what happens when you get a character representation that's less than seven characters.
In particular, think about how the char[] and boolean[] arrays "line up"; there will be extra elements in one than the other, so how should the indices coincide?
Actual answer: At the moment you're using the first element of the character array as the first element of the boolean array, which is only correct when you're using a seven-character string. In fact, you want the last elements of the arrays to coincide (so that the zeros are padded at the front not at the end).
One way to approach this problem would be to play around with the indices within the loop (e.g. work out the size difference and modify binaryarray[i + offset] instead). But an even simpler solution is just to left pad the string with zeros after the first line, to ensure it's exactly seven characters before converting it to the char array.
(Extra marks: what do you do when there's more than 7 characters in the array, e.g. if someone passes in 200 as an argument? Based on both solutions above you should be able to detect this case easily and handle it specifically.)
What you get when you do System.out.println(maxAmpStr); is "1000" in case of the 8.
So, you only get the relevant part, the first "0000" that you expected is just ommitted.
It's not pretty but what you could do is:
for (int i=0; i<maxAmpStr.length(); i++)
{
if (arr[i] == '1')
{
binaryarray[i+maxAmpStr.length()-1] = true;
}
else if (arr[i] == '0')
{
binaryarray[i+maxAmpStr.length()-1] = false;
}
}
Since nobody here has a answer with a dynamic array length, here is my solution:
public static boolean[] convertToBinary(int number) {
int binExpo = 0;
int bin = 1;
while(bin < number) { //calculates the needed digits
bin = bin*2;
binExpo++;
}
bin = bin/2;
boolean[] binary = new boolean[binExpo]; //array with the right length
binExpo--;
while(binExpo>=0) {
if(bin<=number) {
binary[binExpo] = true;
number =number -bin;
bin = bin/2;
}else {
binary[binExpo] = false;
}
binExpo--;
}
return binary;
}
The char-array is only as long as needed, so your boolean-array might be longer and places the bits at the wrong position. So start from behind, and when your char-array is finished, fill your boolean-array with 0's until first position.
Integer.toBinaryString(int i) does not pad. For e.g. Integer.toBinaryString(7) prints 111 not 00000111 as you expect. You need to take this into account when deciding where to start populating your boolean array.
15.ToBinaryString will be '1111'
You are lopping through that from first to last character, so the first '1' which is bit(3) is going into binaryArray[0] which I'm assuming should be bit 0.
You ned to pad ToBinaryString with leading zeros to a length of 7 (8 ??)
and then reverse the string, (or your loop)
Or you could stop messing about with strings and simply use bit wise operators
BinaryArray[3] = (SomeInt && 2^3 != 0);
^ = power operator or if not (1 << 3) or whatever is left shift in Java.
public static boolean[] convertToBinary(int b){
boolean[] binArray = new boolean[7];
boolean bin;
for(int i = 6; i >= 0; i--) {
if (b%2 == 1) bin = true;
else bin = false;
binArray[i] = bin;
b/=2;
}
return binArray;
}
public static String intToBinary(int num) {
int copy = num;
String sb = "";
for(int i=30; i>=0; i--) {
sb = (copy&1) + sb;
copy = copy >>>=1;
}
return sb;
}
AND the number with 1
Append the vale to a string
do unsigned right shift
repeat steps 1-3 for i=30..0
String maxAmpStr = Integer.toBinaryString(255);
char[] arr = maxAmpStr.toCharArray();
boolean[] binaryarray = new boolean[20];
int pivot = binaryarray.length - arr.length;
int j = binaryarray.length - 1;
for (int i = arr.length - 1; i >= 0; i--) {
if (arr[i] == '1') {
binaryarray[j] = true;
} else if (arr[i] == '0') {
binaryarray[j] = false;
}
if (j >= pivot)
j--;
}
System.out.println(maxAmpStr);
for (int k = 0; k < binaryarray.length; k++)
System.out.println(binaryarray[k]);
}