I am doing codingbat as practice for an upcoming quiz that I have. I am doing the recursion problems using recursion, but my teacher said that I should be able to do them using other loops. I figured that I should use for loops as they achieve are easily able to achieve the same result.
But I am having trouble converting the recursion to a for loop.
This is the problem:
Given a string and a non-empty substring sub, compute recursively the number of times that sub appears in the string, without the sub strings overlapping.
strCount("catcowcat", "cat") → 2
strCount("catcowcat", "cow") → 1
strCount("catcowcat", "dog") → 0
This is the code I am trying to use:
public int strCount(String str, String sub) {
int number = 0;
for (int i = 0; i >= str.length() - 1; i++) {
if (str.substring(i, sub.length()).equals(sub)) {
number += 1;
}
}
return number;
}
When I return, everything returns as 0.
In your for loop when you say
i >= str.length() - 1
the loop is never entered, because you are testing that i is greater than the allowed length (and it isn't). You need something like
i <= str.length() - 1
or
i < str.length()
Also, number += 1; can be written as number++;
One of the details you missed is "without the sub strings overlapping". This problem calls for a while loop, rather than a for loop, since the index will be incremented by different amounts, depending on whether there is a match or not.
Here's executable code to test whether or not the strCount method works correctly.
package com.ggl.testing;
public class StringCount {
public static void main(String[] args) {
StringCount stringCount = new StringCount();
System.out.println(stringCount.strCount("catcowcat", "cat"));
System.out.println(stringCount.strCount("catcowcat", "cow"));
System.out.println(stringCount.strCount("catcowcat", "dog"));
}
public int strCount(String str, String sub) {
int count = 0;
int length = str.length() - sub.length();
int index = 0;
while (index <= length) {
int substringLength = index + sub.length();
if (str.substring(index, substringLength).equals(sub)) {
count++;
index += sub.length();
} else {
index++;
}
}
return count;
}
}
Related
I have reversed the string and have a for loop to iterate through the reversed string.
I am counting characters and I know I have a logic flaw, but I cannot pinpoint why I am having this issue.
The solution needs to return the length of the last word in the string.
My first thought was to iterate through the string backward (I don't know why I decided to create a new string, I should have just iterated through it by decrementing my for loop from the end of the string).
But the logic should be the same from that point for my second for loop.
My logic is basically to try to count characters that aren't whitespace in the last word, and then when the count variable has a value, as well as the next whitespace after the count has counted the characters of the last word.
class Solution {
public int lengthOfLastWord(String s) {
int count = 0;
int countWhite = 0;
char ch;
String reversed = "";
for(int i = 0; i < s.length(); i++) {
ch = s.charAt(i);
reversed += ch;
}
for(int i = 0; i < reversed.length(); i++) {
if(!Character.isWhitespace(reversed.charAt(i))) {
count++;
if(count > 1 && Character.isWhitespace(reversed.charAt(i)) == true) {
break;
}
}
}
return count;
}
}
Maybe try this,
public int lengthOfLastWord(String s) {
String [] arr = s.trim().split(" ");
return arr[arr.length-1].length();
}
Another option would be to use index of last space and calculate length from it:
public int lengthOfLastWord(String string) {
int whiteSpaceIndex = string.lastIndexOf(" ");
if (whiteSpaceIndex == -1) {
return string.length();
}
int lastIndex = string.length() - 1;
return lastIndex - whiteSpaceIndex;
}
String.lastIndexOf() finds the start index of the last occurence of the specified string. -1 means the string was not found, in which case we have a single word and length of the entire string is what we need. Otherwise means we have index of the last space and we can calculate last word length using lastIndexInWord - lastSpaceIndex.
There are lots of ways to achieve that. The most efficient approach is to determine the index of the last white space followed by a letter.
It could be done by iterating over indexes of the given string (reminder: String maintains an array of bytes internally) or simply by invoking method lastIndexOf().
Keeping in mind that the length of a string that could be encountered at runtime is limited to Integer.MAX_VALUE, it'll not be a performance-wise solution to allocate in memory an array, produced as a result of splitting of this lengthy string, when only the length of a single element is required.
The code below demonstrates how to address this problem with Stream IPA and a usual for loop.
The logic of the stream:
Create an IntStream that iterates over the indexes of the given string, starting from the last.
Discard all non-alphabetic symbols at the end of the string with dropWhile().
Then retain all letters until the first non-alphabetic symbol encountered by using takeWhile().
Get the count of element in the stream.
Stream-based solution:
public static int getLastWordLength(String source) {
return (int) IntStream.iterate(source.length() - 1, i -> i >= 0, i -> --i)
.map(source::charAt)
.dropWhile(ch -> !Character.isLetter(ch))
.takeWhile(Character::isLetter)
.count();
}
If your choice is a loop there's no need to reverse the string. You can start iteration from the last index, determine the values of the end and start and return the difference.
Just in case, if you need to reverse a string that is the most simple and efficient way:
new StringBuilder(source).reverse().toString();
Iterative solution:
public static int getLastWordLength(String source) {
int end = -1; // initialized with illegal index
int start = 0;
for (int i = source.length() - 1; i >= 0; i--) {
if (Character.isLetter(source.charAt(i)) && end == -1) {
end = i;
}
if (Character.isWhitespace(source.charAt(i)) && end != -1) {
start = i;
break;
}
}
return end == -1 ? 0 : end - start;
}
main()
public static void main(String[] args) {
System.out.println(getLastWord("Humpty Dumpty sat on a wall % _ (&)"));
}
output
4 - last word is "wall"
Firstly, as you have mentioned, your reverse string formed is just a copy of your original string. To rectify that,
for (int i = s.length() - 1; i >= 0; i--) {
ch = s.charAt(i);
reversed += ch;
}
Secondly, the second if condition is inside your first if condition. That is why, it will never break ( because you are first checking if character is whitespace, if it is, then you are not going inside the if statement, thus your second condition of your inner if loop will never be satisfied).
public class HW5 {
public static void main(String[] args) {
String s = "My name is Mathew";
int count = lengthOfLastWord(s);
System.out.println(count);
}
public static int lengthOfLastWord(String s) {
int count = 0;
int countWhite = 0;
char ch;
String reversed = "";
System.out.println("original string is----" + s);
for (int i = s.length() - 1; i >= 0; i--) {
ch = s.charAt(i);
reversed += ch;
}
System.out.println("reversed string is----" + reversed);
for (int i = 0; i < reversed.length(); i++) {
if (!Character.isWhitespace(reversed.charAt(i)))
count++;
if (count > 1 && Character.isWhitespace(reversed.charAt(i)) == true) {
break;
}
}
return count;
}
}
=
and the output is :
original string is----My name is Mathew
reversed string is----wehtaM si eman yM
6
Another way to go about is : you use the inbuilt function split which returns an array of string and then return the count of last string in the array.
I'm doing this specific exercise here:
Question:
Given a non-empty string and an int N, return the string made starting with char 0, and then every Nth char of the string. So if N is 3, use char 0, 3, 6, ... and so on. N is 1 or more.
e.g:
everyNth("Miracle", 2) → "Mrce"
My code:
public String everyNth(String str, int n) {
int a = 0; String result= "";
for (int i=0;i<str.length();i++) {
if (str.charAt(i) % n == 0) {
result = result + str.charAt(i);
a++;
}
}
return result;
}
I can't figure out how to fix my code given what my plan was:
1. Move result to String result
2. Run a loop and only move the data if modular = 0
But instead of getting Mrce, I'm getting rl
I don't need an easier solution, I just want to understand what is going on wrong and how to make it work.
Exercise Ref: https://codingbat.com/prob/p196441
I don't know how to advise you without telling you the answer, which is fairly simple. You want every nth character. So this,
if (str.charAt(i) % n == 0) {
should just be
if (i % n == 0) {
With just that change (and your provided input), I get (as expected)
Mrce
However, we can indeed make it easier by incrementing by n on each loop iteration. Thus eliminating the need for testing if i is divisible by n. We can also make the method static. And I would prefer a StringBuilder. Like,
public static String everyNth(String str, int n) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i += n) {
sb.append(str.charAt(i));
}
return sb.toString();
}
Hey I have to create a method where I have to calculate pi to a passed term (a) using the leibiniz sequence. This is what I have so far
public static double calculatePi(int a){
double oddNum=1;
double pi=0;
for(int x=0; x<a; x++){
if(x%2==0)
pi=pi+(4/oddNum);
else
pi=pi-(4/oddNum);
oddNum=oddNum+2;
}
return pi;
}
I also need help writing a method that accepts a passed string and a (x)term. In the method it will add a "#" every x letters. So if its passed (sundae, 2) it will return su#nd#ae#. I have most of it down but theres a logical error that doesnt allow something like (cats, 3) to compile.
public static String addPounds(String s, int x){
String a="";
for(int i=0; i<s.length(); i=i+x){
a=(a+s.substring(i,i+x)+"#");
}
return a;
}
Thanks so much!
Your pi method is working fine.
You should change the other one to this. I have written it a little bit different so you get the logic easily.
public static String addPounds(String s, int x){
String a = "";
//starting from 1 so i can do mod division easily
for(int i = 1; i <= s.length(); i++){
//check if next # has to be placed at the end
if(i + 1 > s.length() && (i + 1) % x == 0){
a += "#";
//check if next # has to be placed somewhere inside the string
}else if(i % x == 0){
a += s.charAt(i - 1);
a += "#";
//oherwise just add the char at i-1
}else {
a += s.charAt(i - 1 );
}
}
return a;
}
Your addPounds method throws a StringIndexOutOfBoundsException with your given example (cats,3).
for(int i=0; i<s.length(); i=i+x){
a=(a+s.substring(i,i+x)+"#");
}
In the first execution of this for-loop, your variable 'a' will correctly be "Cat#". But now it goes wrong.
The variable 'i' gets increased to 3. And now you want to get a substring starting from the index 3 and ending with the index 6. The String "Cats" is only 4 letters, therefore the IndexOutOfBoundsException.
I guess the easiest way to solve your problem would be inserting a if else statement like this:
for(int i=0; i<s.length(); i=i+x){
if(s.length()>=i+x){
a=(a+s.substring(i,i+x)+"#");
}
else{
a= a+s.substring(i);
}
}
I've looked at a few different stack questions and googled, but nothing I've read really has dealt with reversal of integers, but just strings.
So right now my code may or may not work at all, and it may be the dumbest thing you've ever seen, and that's okay and corrections are welcomed, but from what I hope my code will be doing is going through 100 - 999 multiplying the two ints and then checking whether it's palindromic or not. The if with reverse.equals(sum) is totally pseudocode and obviously won't work, however I can't figure out how to do a check for a palindromic int. Is there a simple way to do this? I've read some pretty lengthy and complicated ways, but I'm sure there's gotta be a simple way. Maybe not. :/. Anyway, here's my code.
public class PalandromicNum {
public static void main(String[] args){
int numOne = 100;
int numTwo = 100;
int toteVal;
int counter = 1000;
int sum = 0;
int finalSum = 0;
for(int i=0; i<counter; i++){
toteVal = numOne * numTwo;
numTwo++;
if(numTwo == 999){
numOne++;
numTwo = 100;
}
if(toteVal < sum){
sum += toteVal;
if(reverse.equals(sum)){
finalSum = sum;
System.out.println(finalSum);
}
}
}
}
}
Thanks again in advance!
This is on my phone so sorry for any errors.
Convert your number to a String and:
public static boolean isPalindrome(String str)
{
// base recursive case
if (str.length <= 1) {
return true;
}
// test the first and last characters
char firstChar = str.charAt(0);
char lastChar = str.charAt(str.length - 1) // subtract 1 as indexes are 0 based
if (!firstChar.equals(lastChar)) {
return false;
}
// if the string is longer than 2 chars and both are equal then recursively call with a shorter version
// start at 2nd char, end at char before last
return isPalindrome(str.substring(1,str.length);
}
Reversing integers is quite easy. Remember mod 10 gives u last digit. Loop over it, chopping off last digit of the number one at a time and adding it to reverse to new number. Then its matter of simple integer equality
int rev = 0;
int n = sum;
while(n)
{
rev = rev*10 + n%10;
n /= 10;
}
if(sum==rev)
//palindrome
else
//no no no no.
You can create a function named isPalindrome to check whether a number is a palindrome.
Use this function in your code.
You just need to pass the number you want to check into this function.
If the result is true, then the number is a palindrome.
Else, it is not a palindrome.
public static boolean isPalindrome(int number) {
int palindrome = number; // copied number into variable
int reverse = 0;
while (palindrome != 0) {
int remainder = palindrome % 10;
reverse = reverse * 10 + remainder;
palindrome = palindrome / 10;
}
// if original and reverse of number is equal means
// number is palindrome in Java
if (number == reverse) {
return true;
}
return false;
}
}
I believe that this code should help you out if you are trying to find out how many palindromes are between 100-999. Of course, it will count palindromes twice since it looks at both permutations of the palindromes. If I were you I would start creating methods to complete a majority of your work as it makes debugging much easier.
int total = 100;
StringBuilder stringSumForward;
StringBuilder stringSumBackward;
int numberOfPals = 0;
for(int i = 100; i < 999; i++){
for(int j = 100; j < 999; j++){
total = i * j;
stringSumForward = new StringBuilder(String.valueOf(total));
stringSumBackward = new StringBuilder(String.valueOf(total)).reverse();
if(stringSumForward.toString().equals(stringSumBackward.toString())){
numberOfPals++;
}
}
}
In this task i need to get the Hamming distance (the Hamming distance between two strings of equal length is the number of positions at which the corresponding symbols are different - from Wikipedia) between the two strings sequence1 and sequence2.
First i made 2 new strings which is the 2 original strings but both with lowered case to make comparing easier. Then i resorted to using the for loop and if to compare the 2 strings. For any differences in characters in these 2 pair of string, the loop would add 1 to an int x = 0. The returns of the method will be the value of this x.
public static int getHammingDistance(String sequence1, String sequence2) {
int a = 0;
String sequenceX = sequence1.toLowerCase();
String sequenceY = sequence2.toLowerCase();
for (int x = 0; x < sequenceX.length(); x++) {
for (int y = 0; y < sequenceY.length(); y++) {
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else if (sequenceX.charAt(x) != sequenceY.charAt(y)) {
a += 1;
}
}
}
return a;
}
So does the code looks good and functional enough? Anything i could to fix or to optimize the code? Thanks in advance. I'm a huge noob so pardon me if i asked anything silly
From my point the following implementation would be ok:
public static int getHammingDistance(String sequence1, String sequence2) {
char[] s1 = sequence1.toCharArray();
char[] s2 = sequence2.toCharArray();
int shorter = Math.min(s1.length, s2.length);
int longest = Math.max(s1.length, s2.length);
int result = 0;
for (int i=0; i<shorter; i++) {
if (s1[i] != s2[i]) result++;
}
result += longest - shorter;
return result;
}
uses array, what avoids the invocation of two method (charAt) for each single char that needs to be compared;
avoid exception when one string is longer than the other.
your code is completely off.
as you said yourself, the distance is the number of places where the strings differ - so you should only have 1 loop, going over both strings at once. instead you have 2 nested loops that compare every index in string a to every index in string b.
also, writing an if condition that results in a+=0 is a waste of time.
try this instead:
for (int x = 0; x < sequenceX.length(); x++) { //both are of the same length
if (sequenceX.charAt(x) != sequenceY.charAt(x)) {
a += 1;
}
}
also, this is still a naive approach which will probbaly not work with complex unicode characters (where 2 characters can be logically equal yet not have the same character code)
public static int getHammingDistance(String sequenceX, String sequenceY) {
int a = 0;
// String sequenceX = sequence1.toLowerCase();
//String sequenceY = sequence2.toLowerCase();
if (sequenceX.length() != sequenceY.length()) {
return -1; //input strings should be of equal length
}
for (int i = 0; i < sequenceX.length(); i++) {
if (sequenceX.charAt(i) != sequenceY.charAt(i)) {
a++;
}
}
return a;
}
Your code is OK, however I'd suggest you the following improvements.
do not use charAt() of string. Get char array from string using toCharArray() before loop and then work with this array. This is more readable and more effective.
The structure
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else if (sequenceX.charAt(x) != sequenceY.charAt(y)) {
a += 1;
}
looks redundant. Fix it to:
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else {
a += 1;
}
Moreover taking into account that I recommended you to work with array change it to something like:
a += seqx[x] == seqY[x] ? 0 : 1
less code less bugs...
EDIT: as mentionded by #radai you do not need if/else structure at all: adding 0 to a is redundant.