Codingbat sameStarChar exercise - java

I'm having trouble with this codingbat exercise:
Returns true if for every * (star) in the string, if there are chars both immediately before and after the star, they are the same.
sameStarChar("xyyzz") // true
sameStarChar("xyzzz") // false
sameStarChar("xaaz") // true
The right answer is:
public boolean sameStarChar(String str) {
for (int i = 1; i < str.length() - 1; i++) {
if (str.charAt(i) == '*' && str.charAt(i - 1) != str.charAt(i + 1)) {
return false;
}
}
return true;
}
What I wrote is:
public boolean sameStarChar(String str) {
for (int i = 1; i < str.length() - 1; i++) {
if (str.substring(i, i + 1) == "*" && str.substring(i - 1, i) != str.substring(i + 1, i + 2)) {
return false;
}
}
return true;
}
I'm having trouble understanding the substring and charAt methods.

Instructions:
Returns true if for every '*' (star) in the string, if there are chars both immediately before and after the star, they are the same.
sameStarChar("xy*yzz") → true
sameStarChar("xy*zzz") → false
sameStarChar("*xa*az") → true
Pseudocode:
Loop over every character from 1 to length-1. If the character is an asterisk and the character before it is different from the one after, return false. Otherwise if when you reach the end, return true.
Code:
public boolean sameStarChar(String str){
int len = str.length();
for(int x = 1; x < len-1; x++){
if (str.charAt(x) == '*' && str.charAt(x-1) != str.charAt(x+1)){
return false;
}
}
return true;
}
Comments:
It's a linear time O(n) operation.

str.charAt() is easier to read and understand in this case.
Also, your substring solution should be more like
if (str.substring(i, i + 1).equals("*") &&
!str.substring(i - 1, i).equals(str.substring(i + 1, i + 2))){
//etc.
}
Substring returns a string, and to compare the literal sting value you have to use the .equals() method.

Instead, I count the number of '*' and number of pairs that are matched and check if they both are equal and return true.
public boolean sameStarChar(String str) {
int count=0, noOfPairs=0;
for(int i=1; i<str.length()-1;i++){
if(str.charAt(i)=='*') count++;
if(str.charAt(i)=='*' && str.charAt(i+1)==str.charAt(i-1)) noOfPairs++;
}
if(count==noOfPairs) return true;
return false;
}

Another solution to look at...
public boolean sameStarChar(String str) {
if(str.length()==0) return true;
if(str.length()==1 && str.contains("*")) return true;
if(!str.contains("*")) return true;
int i = 0;
boolean result = false;
while(i<str.length()-1){
if(i!=0 && str.charAt(i) == '*' && str.charAt(i-1) == str.charAt(i+1)){
result = true;
}else if(i!=0 && str.charAt(i) == '*' && str.charAt(i-1) != str.charAt(i+1)){
result = false;
}else if(str.charAt(i) == '*'){
result = true;
}
i++;
}
return result;
}

A version which does not iterate over each individual character in the string by using indexOf(int ch, int fromIndex)
public boolean sameStarChar(String str) {
int i=0;
int l=str.length();
for(i=str.indexOf("*",i);i!=-1;i=str.indexOf("*",i+1))
{
if(i==0 || i==l-1) //saves the program from accessing an out of bounds Index
continue;
else
{
if(str.charAt(i-1)!=str.charAt(i+1));
return false;
}
}
return true;
}

Related

Leetcode 9. Palindrome Number

I am trying to do this converting the integer to a string.
Inside the if clause, if I used s.charAt(i) == s.charAt(j) first then i++, j--, I couldn't pass the test of input = 121, I got false instead of true. But if I put s.charAt(i) != s.charAt(j) first, then accepted.
Wrong answer:
class Solution {
public boolean isPalindrome(int x) {
String s = String.valueOf(x); //n
int l = s.length();
int i = 0;
int j = l - 1;
while (i <= j) {
if (s.charAt(i) == s.charAt(j)) {
i++;
j--;
}
return false;
}
return true;
}
Accepted answer:
class Solution {
public boolean isPalindrome(int x) {
String s = String.valueOf(x); //n
int l = s.length();
int i = 0;
int j = l - 1;
while (i <= j) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
i++;
j--;
}
return true;
}
}
What did I miss?
The wrong solution returns false in any case and the correct solution only returns false when s.charAt(i) != s.charAt(j) is true.
If you want to skip return false; in the first code, you either need to move it into an else clause or use continue; in the if clause in order to directly jump to the next loop iteration.

Checking whether an expression is a valid formula

Recursion Question: A formula is defined as a string
containing positive single digits numbers, variables, and operations
(such that: +,-,/,*,%). In addition, the string doesn't contain space
bars. Each operation between two numbers or variables is separated
with brackets - "()".
Valid formulas would be: ((6+x)*(4+2)), (((9*4)+(x+8))*(6-5)), 6,
(3+1), etc...
Invalid formulas would be: -6, (1+*(x+2)*(1-6)), ( (6+x)), 10,
2+x, (33+3), ((1+2)), etc...
Write a boolean recursion function which gets a string - "s" and
returns true if he is a valid formula, and false otherwise.
The code has to be written via java.
My attempt: I have tried the following, putting in mind that the number of "(" is less equal to the number of ")", however, it doesn't right since: "((1+2))" isn't a valid formula. So I have written the following:
public static boolean isFormula(String s) {
return calc(s, 0, 0, 0, 0);
}
public static boolean calc(String s, int oc, int l, int r, int g) {
if (s == "") {
return (oc <= 1 && (l == r));
}
char c = s.charAt(0);
char e = s.charAt(s.length() - 1);
if (g == 0) {
if (!(op(s))) return false;
else {
return calc(s, oc, l, r, g + 1);
}
}
if (c == '(') {
return calc(s.substring(1), oc, l + 1, r, g);
} else if (c == ')') {
return calc(s.substring(1), oc, l, r + 1, g);
} else if ((c >= '0' && c <= '9') || c == 'x') {
if (oc <= 1) {
return calc(s.substring(1), 0, l, r, g);
}
} else if ((c == '+' || c == '-' || c == '*' || c == '/')) {
return calc(s.substring(1), oc + 1, l, r, g);
}
return false;
}
public static boolean op(String s) {
int count = 0;
if (s.charAt(0) == '+' || s.charAt(0) == '-' || s.charAt(0) == '*' || s.charAt(0) == '/') {
count++;
}
String d = s.replace("(", "");
if (d.charAt(0) == '+' || d.charAt(0) == '-' || d.charAt(0) == '*' || d.charAt(0) == '/') {
count++;
}
d = d.replace(")", "");
d = d.replace("+", ",");
d = d.replace("-", ",");
d = d.replace("*", ",");
d = d.replace("/", ",");
String[] words = d.split(",");
int sum = words.length;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '+' || s.charAt(i) == '-' || s.charAt(i) == '/' || s.charAt(i) == '*') {
count++;
}
}
if (s.contains(" ")) return false;
return (count <= sum - 1);
}
Thoughts:
I find this question very complex, and I don't know how to arrange the code, because it doesn't seem that my way is correct and and it is so messy. I will be glad for some help. I put a lot of effort into writing this post. Thank you!
Try this.
static final Pattern DIGIT_OR_X = Pattern.compile("[\\dx]");
static final Pattern OPERATION = Pattern.compile("\\([\\dx][+*/%-][\\dx]\\)");
public static boolean isFormula(String s) {
while (true) {
if (DIGIT_OR_X.matcher(s).matches())
return true;
String rep = OPERATION.matcher(s).replaceAll("x");
if (rep.equals(s))
return false;
s = rep;
}
}
Test cases:
assertTrue(isFormula("((6+x)*(4+2))"));
assertTrue(isFormula("(((9*4)+(x+8))*(6-5))"));
assertTrue(isFormula("6"));
assertTrue(isFormula("(3+1)"));
assertFalse(isFormula("-6"));
assertFalse(isFormula("(1+*(x+2)*(1-6))"));
assertFalse(isFormula("( (6+x))"));
assertFalse(isFormula("10"));
assertFalse(isFormula("2+x"));
assertFalse(isFormula("(33+3)"));
assertFalse(isFormula("((1+2))"));
Or you can also do it without regular expression.
static boolean isFormula(String s) {
return new Object() {
int index = 0;
boolean match(String expects) {
if (index >= s.length() || expects.indexOf(s.charAt(index)) < 0)
return false;
++index;
return true;
}
boolean formula() {
if (match("0123456789x"))
return true;
return match("(")
&& formula() && match("+-*/%") && formula()
&& match(")");
}
boolean parse() {
return formula() && index >= s.length();
}
}.parse();
}

Java maze solving issue

so I've been asked to solve a maze in a recursive java function, but I stumble into an issue that the recursive function doesnt seem to switch the correct path into '*'.
Any help would be appreciated.
public class Maze
{
/**
* This is only an example,
* you can change this to test other cases but don't forget to submit the work with this main.
* #param args
*/
public static void main(String[] args)
{
int M = 4;
int N = 4;
char[][] maze = {{'1','0','0','0'},{'1','1','0','0'},{'0','1','1','1'},{'0','0','0','1'}};
if (findPath(maze, 0,0))
printMaze(maze);
else
System.out.println("No solution");
}
private static void printMaze(char[][] maze)
{
for (int i = 0; i < maze.length; i++)
{
for (int j = 0; j < maze[0].length; j++)
{
System.out.print(maze[i][j] +" ");
}
System.out.println();
}
}
// you should implement this function
private static boolean findPath(char[][] maze, int i, int j)
{
if ((i+1 > maze.length) || (j+1 > maze[i].length))
return false;
else
{
if (maze[i][j] == 1)
{
maze[i][j] = '*';
if (maze[i+1][j] == 1)
{
return findPath(maze, i+1, j);
}
if (maze[i][j+1] == 1)
{
return findPath(maze, i, j+1);
}
}
}
return true;
}
}
You're missing quotes around the 1 at
if (maze[i][j] == 1)
should be
if (maze[i][j] == '1')
The number 1 and the character representing the number 1 are two different things in Java (and in any other statically typed language), so you can't check if they're equal like that.
I doubt that the code will find all paths then though, since you don't seem to be searching left and up at all.
Use this code:
private static boolean findPath(char[][] maze, int i, int j)
{
if (maze[i][j] == 1)
{
maze[i][j] = '*';
if ((i+1 > maze.length && maze[i+1][j] == '1' && findPath(maze, i+1, j))
{
return true;
}
if ((j+1 > maze[i].length) && maze[i][j+1] == '1' && findPath(maze, i, j+1))
{
return true;
}
if (i>=1 && maze[i-1][j] == '1' && findPath(maze, i-1,j)){
return true;
}
if(j>=1 && maze[i][j-1] == '1' && findPath(maze, i,j-1)){
return true;
}
}
return false;
}

Solution of twoTwo riddle on codingBat in Java

The question is about Solving this problem from codingBat in Java.
Problem Statement:
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
First of all going by the problem statement that every 2 that appears in the array is next to another 2. then
do you think as suggested the outcome for the first inputs shown above
should be true?
twoTwo({4, 2, 2, 3}) → true
Because as I see it it the first 2 itself that appears in the array is next to 4 not 2
am I confused or it's a wrongly stated question? I had to grapple with the problem to somehow get the right code to crack the problem as below but it seems a hotch potch:
public boolean twoTwo(int[] nums) {
if(nums.length==0)
{
return true;
}
if(nums.length==1)
{
return !(nums[0]==2);
}
if((nums.length==2))
{
if((nums[1]==2)&&(nums[0]==2))
return true;
else
return false;
}
for(int i=0;i+2<nums.length;i++)
{
if((nums[i]!=2)&&(nums[i+1]==2)&&(nums[i+2]!=2))
return false;
}
if((nums[nums.length-2]!=2)&&(nums[nums.length-1]==2))
return false;
return true;
}
Any efficient alternate solutions are welcome.
Thanks!
Here's how I would do it. It's a bit easier to follow I think:
public boolean twoTwo(int[] nums)
{
for (int i=0; i<nums.length; i++)
{
if (nums[i] != 2)
continue;
if (i >= 1 && nums[i-1] == 2)
continue;
if (i < (nums.length-1) && nums[i+1] == 2)
continue;
return false;
}
return true;
}
The solution I got to the problem is below:
public boolean twoTwo(int[] nums) {
final int length = nums.length;
for (int i = 0; i < length;){
int count = 0; // Used to count following 2's
while(i < length && nums[i++] == 2){
count++;
}
if(count == 1){ // No adjacent 2's! Set doesn't work.
return false;
}
}
return true; // Didn't come across a lone 2
}
The way that I handle this, is that I count all the adjacent 2's. If the count is not 1, we are good. This means that there was either no 2 at that index, or a group of 2's was present. This holds, since we traverse the array in a single direction.
A good thing about this solution is that it will work for an array of any size. Note that it would have a linear complexity, even though 2 loops are present. They both just traverse using the same index value, only ever sweeping over the array once.
If at any time we find a 2, then check the following only to find there are 0 following 2's (denoted by count), we return false.
public boolean twoTwo(int[] nums) {
for (int i=0; i<nums.length; i++) {
if(nums[i] == 2) { //If current number is 2
if (
// if prev or next is not 2 return true
!(i-1>=0 && nums[i-1] == 2) &&
!(i+1<nums.length && nums[i+1] == 2)
) { return false; }
}
}
return true;
}
For the sake of simplicity and clean code, this code forces the check
i-1>=0 and i+1<nums.length in every iteration.
This can be avoided by iterating from (1...nums.length-1) and checking the edge cases separately.
I know this is an old question, but I came up with a new solution. Short, and with no complicated conditionals.
public boolean twoTwo(int[] nums) {
int position = -2;
boolean result = true;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 2) {
result = position == i - 1;
position = i;
}
}
return result;
}
Next to means either before or after. Loop through each number and check the values before and after to see if there's an adjacent 2. The special cases are when you're checking the 1st and last element because there won't be an element before or after to check.
public boolean twoTwo(int[] nums) {
if(nums.length == 1 && nums[0] == 2)
return false;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 2) {
if(i == 0) { // check the next element
if(nums[i+1] != 2)
return false;
}
else if(i == (nums.length - 1)) { // check the previous element
if(nums[i-1] != 2)
return false;
}
else { // check both
if(nums[i+1] != 2 && nums[i-1] != 2)
return false;
}
}
}
return true;
}
Here is mine solution to two two's problem. I think my solution is clear i.e. understandable.
package codingbat.array2;
public class TwoTwo
{
public static void main(String[] args)
{
}
public boolean twoTwo(int[] nums)
{
boolean twoTwo = true;
for (int i = 0; i < nums.length; i++)
{
if (2 == nums[i])
{
if (i > 0 && 2 == nums[i - 1]
|| nums.length > i+1 && 2 == nums[i+1])
{
twoTwo = true;
i++;
}
else
{
twoTwo = false;
break;
}
}
}
return twoTwo;
}
}
public boolean twoTwo(int[] nums) {
for(int i = 0 ; i < nums.length; i++ ) {
int count = 0;
if(nums[i] == 2 ) {
while(i+1 < nums.length && nums[i+1] == 2 ) {
count ++;
i++;
}
if (count == 0 ) {
return false;
}
}
}
return true;
}
public boolean twoTwo(int[] nums) {
for(int i = 0;i<nums.length;i++)
if(nums[i]==2 && !isTwoBeforeOrAfter(nums,i))
return false;
return true;
}
private boolean isTwoBeforeOrAfter(int[] nums,int i){
return i+1<nums.length && nums[i+1]==2 || i-1>=0 && nums[i-1]==2;
}
public boolean twoTwo(int[] nums) {
float two = 0;
double count = 0;
for (int i = 0; i < nums.length; i++) {
if (i < nums.length - 2 && nums[i] == 2 && nums[i + 1] == 2 && nums[i + 2] == 2) {
return true;
}
if (i < nums.length - 1 && nums[i] == 2 && nums[i + 1] == 2) {
count++; //count the pair
}
if (nums[i] == 2) {
two++;
}
}
return ((count * 2) == two);
//each pair contain 2 ,two"s .so pair*2=total two counts
//count
}
public boolean twoTwo(int[] nums) {
boolean two = false;
boolean result = true;
for (int i=0; i<nums.length; i++) {
if (nums[i] == 2) {
if (two) {
result = true;
} else {
result = false;
}
two = true;
} else {
two = false;
}
}
return result;
}
Here's my solution. Enjoy.
public boolean twoTwo(int[] nums)
{
//If the length is 2 or more
if (nums.length >= 2)
{
//If the last char is a 2, but the one before it is not a char, we return false;
if (nums[nums.length - 1] == 2 && nums[nums.length - 2] != 2)
{
return false;
}
//If larger than three, we create a for loop to test if we have any 2s that are alone.
if (nums.length >= 3)
{
for (int i = 1; i < nums.length-1; i++)
{
//If we find a two that is alone, we return false;
if ((nums[i] == 2) && (nums[i-1] != 2 && nums[i+1] != 2))
{
return false;
}
}
}
//If we don't return false, we return true;
return true;
}
//If we have less than two characters, we return true if the length is 0, or \
//One the one number there is not a 2.
else
{
return ((nums.length == 0) || !(nums[0] == 2));
}
}
public boolean twoTwo(int[] nums) {
int len = nums.length;
Boolean check = false;
int count = 0;
for(int i=0; i<len ; i++){
if(nums[i]==2){
count++;
if((i<len-1 && nums[i+1]==2) || (i>0 && nums[i-1]==2)) check = true;
else check = false;
}
}
if(count==0) check = true;
return check;
}
public boolean twoTwo(int[] nums) {
int count = 0;
for (int i = 0; i < nums.length; i++)
if (nums[i] == 2) count++;
else if (count == 1) return false;
else count = 0;
return count != 1;
}
Every time we encounter a 2, we increase the counter of consecutive 2s.
When it's not a 2 — but the counter indicates that there was a single 2 before it —, we know we've found a lonely 2.
Otherwise the search continues, resetting the 2-counter.
easy to understand)
static boolean twoTwo(int[] nums) {
int len = nums.length;
boolean result = true;
boolean found = false;
for(int i=0; i<len; i++){
//if it not 2, no meaning to go true other if-s
if(nums[i] !=2) {found = false; continue;}
// if current element is 2 and found is true(last element is 2)
if(nums[i] ==2 && found) result = true;
// if current element is 2, but last element not
if(nums[i] ==2 && !found){
found = true;
result = false;
}
}
return result;
}
This might be easier to follow if the other suggestions confuse you..
public boolean twoTwo(int[] nums) {
int len = nums.length;
if(len == 0) return true; // no 2's to worry about
if(len == 1) return nums[0] != 2; // make sure it's not a single 2
for(int i = 1; i < len -1; i++){ // loop for each except edge cases
if(nums[i] == 2 && nums[i-1] != 2 && nums[i+1] != 2) return false; // check surrounding
}
if(nums[len - 1] == 2) return nums[len - 2] == 2; //if last num is 2 check for 2 before it
return true; // made it here it's true
}
that one was tough for me... here's mine:
public boolean twoTwo(int[] nums) {
boolean two = false, res = true;
for (int i : nums) {
if (i == 2) {
if (two)
res = true;
else {
two = true;
res = false;
}
} else {
two = false;
}
}
return res;
}
One more alternative. Here is the main idea:
Convert array into String. Add a character different from "2" at the beginning and end of the string, to avoid going out of bounds.
Look for standalone "2" - if element of the string is equal to 2, check whether chars immediately before and after are also equal to "2". If they are it means that not all "2" are adjacent, and therefore method returns false.
public boolean twoTwo(int[] nums) {
// convert array to string
String text = "";
for (int i = 0; i < nums.length; i++) {
text += String.valueOf(nums[i]);
}
text = " " + text + " ";
// find standalone "2"
for (int i = 1; i < text.length() - 1; i++) {
if (text.charAt(i) == '2' && text.charAt(i - 1) != '2' && text.charAt(i + 1)
!= '2') {
return false;
}
}
return true;
}

java controle upper and lowercase in 2 String

I want to check if every character in a string is the inverse of the other character in the second. By inverse I mean uppercase and lowercase.
For example these strings:
Ahh7h
aHH7H
The result will be true
I wrote this code but the result is always false. Why?
public boolean checkString(String serverString, String clientString) {
if (serverString.length() != clientString.length())
return false;
else
for (int i = 0; i < clientString.length(); i++) {
if ((clientString.charAt(i) >= '0' && clientString.charAt(i) <= '9')
&& (clientString.charAt(i) != serverString.charAt(i)))
return false;
else if (clientString.charAt(i) >= 'A'
&& clientString.charAt(i) <= 'Z') {
if ((int) clientString.charAt(i) != ((int) serverString
.charAt(i) + 32))
return false;
} else if (clientString.charAt(i) >= 'a'
&& clientString.charAt(i) <= 'z') {
if ((int) clientString.charAt(i) != ((int) serverString
.charAt(i) - 32))
return false;
}
}
return true;
}
You could "invert" one string using: How can I invert the case of a String in Java? and then use Strings .equals method to compare them.
Method from How can I invert the case of a String in Java? included for completeness:
public static String reverseCase(String text)
{
char[] chars = text.toCharArray();
for (int i = 0; i < chars.length; i++)
{
char c = chars[i];
if (Character.isUpperCase(c))
{
chars[i] = Character.toLowerCase(c);
}
else if (Character.isLowerCase(c))
{
chars[i] = Character.toUpperCase(c);
}
}
return new String(chars);
}
You've switched the + 32 and the - 32.
By the way, it's a lot easier to use methods like:
Character.isDigit
Character.isLowerCase
Character.isUpperCase
Character.toLowerCase
Character.toUpperCase

Categories

Resources