Java Looking for specific letters in a sting - java

I was wondering how to iterate over a string and to check how many hi's come out
For example, if the string is "hihi" the count should output 2.
This is what I have so far
public static int countHi(String str) {
int counter = 0;
for (int i = 0; i < str.length(); i++) {
if (str.substring(i, i + 1) == "h") {
if (str.substring(i, i + 1) == "i") {
counter = counter + 1;
}
}
}
return counter;
}
public static void main(String[] args) {
String str = "hihi";
int i = countHi(str);
System.out.println("number of hi = " + i);
}

You compare instances (like String) with .equals (not ==). However, here you can use == with String.charAt(int). Also, I would start with the second character and compare the character at the current index with i and the previous index with h. Like,
public static int countHi(String str) {
int counter = 0;
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i - 1) == 'h' && str.charAt(i) == 'i') {
counter++;
}
}
return counter;
}
Alternatively, compare the character at the current index with h and the character at the next index with i (but now you need to stop iterating a character earlier). Like,
public static int countHi(String str) {
int counter = 0;
for (int i = 0; i < str.length() - 1; i++) {
if (str.charAt(i) == 'h' && str.charAt(i + 1) == 'i') {
counter++;
}
}
return counter;
}

Here's the easy way:
public static int countHi(String str) {
return split(str, -1).length - 1;
}
Note that you must pass -1 as the second parameter of split(); without it, trailing blanks would be pruned from the result.

For compactness and readability, maybe:
int count = 0;
Matcher matcher = Pattern.compile(“hi”).matcher(string)
while (matcher.find()) {
count++;
}
This approach will work for any Regular Expression pattern, although it won’t be the most efficient.

Related

I am not getting desired output what is the problem in the code

Given a string. Find the longest palindrome subsequence. The string contains an only lowercase letter.
Here, I am creating the array with the length of 26 and keeping track of all lowercase letters (i.e how many times they occur in the string). Finally, I count the number of even letters and if one is odd then (odd-1) is added to it.
public int count(String input1){
int res = 0;
int temp = 0;
char chr [] = input1.toCharArray();
int arr[] = new int[26];
for(int i=0;i<chr.length;i++){
arr[chr[i] - 97]++;
}
for(int val:arr){
if(val%2 != 0) temp++;
if(val%2 ==0){
res=res+val;
}
else{
res = res+(val-1);
}
}
if(temp != 0) res++;
return res;
}
}
it's showing undesired output
It's much easier to understand where is the problem, just split activities in separate methods. E.g. isPalindrome() could be in separate method:
public static int findLongestPalindrome(String str) {
int max = 1;
for (int i = 0; i < str.length(); i++) {
for (int j = str.length() - 1; j > i; j--) {
if (!isPalindrome(str, i, j))
continue;
max = Math.max(max, j - i + 1);
break;
}
}
return max;
}
private static boolean isPalindrome(String str, int i, int j) {
while (i < j)
if (str.charAt(i++) != str.charAt(j--))
return false;
return true;
}

How to count unique characters (only letters and numbers)

// I have a program where I am supposed to count unique characters, only letters and numbers and don't count repeating numbers or letters. However, I have a problem finding out a way for the program not to count spaces and symbols such as "!" "#" "#" "$". So If i type in Hello! I only want the program to say "4", but it says "5" because it counts the exclamation point. Here is my code so far:
public static int countUniqueCharacters(String text1) {
int count = 0;
for (int i = 0; i < text1.length(); i++) {
if (text1.substring(0, i).contains(text1.charAt(i) + ""))
System.out.println();
else
count++;
}
return count;
}
In your else block add a condition that the count will be incremented only if the given character is a letter or a digit.
if (Character.isLetter(text1.charAt(i)) || Character.isDigit(text1.charAt(i))) {
count++;
}
In your example:
public static int countUniqueCharacters(String text1) {
int count = 0;
for (int i = 0; i < text1.length(); i++) {
if (text1.substring(0, i).contains(text1.charAt(i) + "")) {
System.out.println();
} else if (Character.isLetter(text1.charAt(i)) || Character.isDigit(text1.charAt(i))) {
count++;
}
}
return count;
}
here's a sample code written in C# try and understand it. It compares with ascii and adds in a list
string input = Console.ReadLine();//input
List<char> CountedCharacters = new List<char>();
for (int i = 0; i < input.Length; i++)
{ //checking for numerics //checking for alphabets uppercase //checking for alphabets lowercase
if ((input[i] >= 45 && input[i] <= 57) || (input[i] >= 65 && input[i] <= 90) || (input[i] >= 97 && input[i] <= 122))
{
bool AlreadyExists = false;
for (int j = 0; j < CountedCharacters.Count; j++)
{
////checking if already exists
if (CountedCharacters[j]==input[i])
{
AlreadyExists = true;
break;
}
}
////adding in list if doesnt exists
if (!AlreadyExists)
{
CountedCharacters.Add(input[i]);
}
}
}
for (int i = 0; i < CountedCharacters.Count; i++)
{
Console.WriteLine(CountedCharacters[i]);
}
Try this one using regex. You can add and remove the characters you need from the expression to count what you need.
public static int countUniqueCharacters(String text1) {
String newText = text1.replaceAll("[^A-Za-z0-9()\\[\\]]", "");
Set<Character> tempSet = new HashSet<>();
for (char item : newText.toCharArray()) {
tempSet.add(item);
}
return tempSet.size();
}

Check if a character appears more than once in a string using charAt() and loop

The code is giving characters for consecutive appearances and not for non-consecutive repetition of a character in a string. Using function can be easy but I want to use loop and use charAt in it to compare.
int count = 0;
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i)==str.charAt(i+1)) {
count++;
}
return count;
}
Your code will throw IndexOutOfBoundsException.
You need a nested loop, because now you're checking if there are two adjacency equal characters.
Do something like that (I won't show you a solution, but I'll guide you):
for (int i = 0; i < str.length() - 1; i++) {
another loop with index j {
if(str.charAt(i)==str.charAt(j)){
count++;
}
}
}
However, as suggested in comments by #BrianRoach, if you use a Map, you'll get a better solution:
You can have a Character key and a value of Integer that indicates how many times a char appears in the String.
Edit:
After your edit, you only need to change the loop condition to str.length() - 1.
try
int count = 0;
for (int i = 0; i < str.length() - 1; i++) {
for (int j = i + 1; j < str.length; j++) {
if(str.charAt(i)==str.charAt(j)){
count++;
}
}
return count;
}
I know this is late in time, but rather than complex responses I came up with this:
public static boolean isitIsogram(String word){
int count = 0;
char check = ' ';
if(word == "" || word == null){
return false;
}
String newWord = word.toLowerCase();
char [] checkWord = newWord.toCharArray();
for (char i : checkWord){
if(check == i)
return false;
for(char j : checkWord){
if(i == j){
count++;
if(count > 1){
check = i;
}
}
}count = 0;
}
return true;
}
This function would also cater for empty and null string cases

Evaluate a Math Expression given in string form without using API

I want to evaluate an expression like -4-12-2*12-3-4*5 given in a String form without using API as I am a beginner and want to grasp the logic.
Given below is my unsuccessful attempt to this problem which, if you may like, ignore and suggest appropriate logic.And of course your codes are also welcome :-)
public class SolveExpression3 {
static String testcase1 = "-4-12-2*12-3-4*5";
public static void main(String args[]){
SolveExpression3 testInstance= new SolveExpression3();
int result = testInstance.solve(testcase1);
System.out.println("Result is : "+result);
}
public int solve(String str){
int sum = 1;
int num1 = 0;
int num2 = 0;
String num = "";
int len = str.length();
System.out.println(str);
for (int i = len-1 ; i >= 0; i--)
{
char ch = str.charAt(i);
if(ch == '*')
{
String s = "";
num1 = num2 = 0;
//to get the number on left of *
for (int j = i; j >= 0; j--)
{
char c = str.charAt(j);
if(c == '+' || c == '-' || j == 1)
{
num1 = stringToInt(s);
s = "";
break;
}
else
{
s = c + s;
}
}
//to get the number on right of *
for (int j = i; j <= len; j++)
{
char c = str.charAt(j);
if(c == '+' || c == '-' || j == len-1)
{
num2 = stringToInt(s);
s = "";
break;
}
else
{
s = c + s;
}
}
sum = sum + num1*num2;
}
else
{
num = ch + num;
}
}
len = str.length();
for (int i = len-1; i >= 0; i--)
{
char ch = str.charAt(i);
if(ch==' ')
{}
else if(ch=='+')
{
sum = sum + stringToInt(num);
num = "";
}
else if(ch=='-')
{
sum = sum - stringToInt(num);
num = "";
}
else
{
num = ch + num;
}
}
return sum;
}
public int stringToInt(String str)
{
int number=0;
for(int i = 0; i < str.length(); i++)
{
int num = str.charAt(i) - 48;
number = number*10+num;
}
return number;
}
}
found=true;
static String testcase1 = "-4-12-2*12-3-4*5";
Pattern SEGMENT_PATTERN = Pattern.compile("(\\d+(\\.\\d+)?|\\D+)");
/*\\d-means digit,
\\.-point,
+-one or more times,
?-optional and
\\D-non digit ch*/
Matcher matcher = SEGMENT_PATTERN.matcher(testcase1);
while (found) {
boolean Found = matcher.find();
String segment = matcher.group();//representing a number or an operator
if (Character.isDigit(segment.toCharArray()[0])) {
//is digit
}
else {
//is operator
}
}
This a a solution using a patter to determine if you have a number or and operator,u just have to adapt it a little to your case to computing the result.
You can add all the matches found to an array list than traverse it and test the operators and computer the result.
It works for floating numbers too,ex:"it matches 5.10".
I would suggest a different logic for your purpose.
Usually the logic behind programs algorithms is not different from the logic that you will apply if you have to do the task by hand.
For an expression like your example you would usually do:
Find all the *
For each * compute the result of the operation
Repeat steps 1 and 2 for + and -
Try to implement a recursive descent parser, a tutorial depicting how a calculator can be implemented (in Python but the same concepts apply to java) can be found here http://blog.erezsh.com/how-to-write-a-calculator-in-70-python-lines-by-writing-a-recursive-descent-parser/

Evaluate Polynomial String without using regex and API

Given a polynomial with a single variable x, and the value of x as input, compute its value. Examples:
eval("-2x^3+10x-4x^2","3")=-60
eval("x^3+x^2+x","6")=258
Description of issue: In this code I break the string into a substring whenever a +/- is encountered and pass the substring to a function which evaluates single term like "-2x^3". So my code for input = "-2x^3+10x-4x^2" calculates till "-2x^3+10x" only and skips "-4x^2" part.
Can anyone please tell me whats wrong here?
public class EvalPolyX2 {
static String testcase1 = "-2x^3+10x-4x^2";
static String testcase2 = "3";
public static void main(String args[]){
EvalPolyX2 testInstance = new EvalPolyX2();
int result = testInstance.eval(testcase1,testcase2);
System.out.println("Result : "+result);
}
public int eval(String str,String valx){
int sum = 0;
String subStr = "";
if(str.charAt(0) == '-')
{
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i);
len = str.length();
i = 0;
}
}
}
else if(str.charAt(0) != '-')
{
str = '+' + str;
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i);
len = str.length();
i=0;
}
}
}
return sum;
}
public int evalSubPoly(String poly,String valx){
int len = poly.length();
String num = "";
String power = "";
int exp = 0, coeff = 0;
for(int i = 0; i < len; i++)
{
if(poly.charAt(i) == 'x')
{
num = poly.substring(0, i);
coeff = Integer.parseInt(num);
}
if(poly.charAt(i) == '^')
{
power = poly.substring(i+1, len);
exp = Integer.parseInt(power);
}
}
if(power.equals(""))
exp = 1;
System.out.println("coeff="+coeff);
int sum = 1;
int x = Integer.parseInt(valx);
for (int i = 0; i < exp; i++)
{
sum = sum*x;
}
System.out.println("sum="+sum);
sum = sum*coeff;
return sum;
}
}
What's wrong with using regex? You can split the polynomial into monomials, evaluate each, and add all of the results.
private static final Pattern monomial = Pattern
.compile("([+-])?(\\d+)?x(?:\\^(\\d+))?");
public static int eval(String str, String valx) {
Matcher m = monomial.matcher(str);
int x = Integer.parseInt(valx);
int total = 0;
while (m.find()) {
String mul = m.group(2);
int value = (mul == null) ? 1 : Integer.parseInt(m.group(2));
String pow = m.group(3);
value *= (pow == null) ? x : (int) Math.pow(x,
Integer.parseInt(pow));
if ("-".equals(m.group(1)))
value = -value;
total += value;
}
return total;
}
System.out.println(eval("-2x^3+10x-4x^2", "3"));
System.out.println(eval("x^3+x^2+x", "6"));
-60
258
This code replacement should help
if(str.charAt(i) == '-' || str.charAt(i) == '+' || i == (len - 1))
{
if(i == len - 1)
{
i++;
}
...
Though there could be better ways, but I only wanted to show a way out here.
The reason is you are looking for + or - as the delimiter.
But the last part of the expression will not end with either of these but just probably EOL
You need to account for the last term (the if-statement will only trigger when a - or + is found, which there isn't at the end).
One easy way to do this is to replace:
for (int i = 0; i < len; i++)
{
if (str.charAt(i) == '-' || str.charAt(i) == '+')
with:
// v one more iteration
for (int i = 0; i <= len; i++)
{
if (i == len || str.charAt(i) == '-' || str.charAt(i) == '+')
// \------/
// extra condition
The above simply goes on for one more iteration and, on that iteration, always goes into the if-statement, causing the last term to be processed.
You can also simplify
if (str.charAt(0) == '-')
{
// common code
}
else if (str.charAt(0) != '-')
{
str = '+' + str;
// common code
}
To:
if (str.charAt(0) != '-')
{
str = '+' + str;
}
// common code
There's also a bug with handling +. I get a NumberFormatException for this. One way to handle it is to ignore the + between the terms (and not adding a + to the start):
if (i != len && str.charAt(i) == '+')
str = str.substring(i+1);
else
str = str.substring(i);
And you might as well make your functions static and call them directly rather than declaring a new instance of your class.
Test.
The simple answer is that when you do this:
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
the effect is that you're setting subStr to text just before the - or +, and evaluating it. But since there's no - or + at the end of the string, there's no way this logic will evaluate the last term of the polynomial, since it only evaluates substrings that are right before a - or +.
P.S. That's just one problem I noticed. I don't know if the rest of the logic is correct.
When you parse the string, you look for +/- and only stop if you find them. This works for the first two terms, but when you get down to "-4x^2" the loop won't stop because there is no +/-. So in addition to the conditions you have, you need to add code so that when the end of the string is reached, what you have left is the last term. So what you want to have is this
if(str.charAt(0) == '-')
{
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i+1);
len = str.length();
i = 0;
}
}
System.out.println("subStr="+str);
sum += evalSubPoly(str, valx);
}
else if(str.charAt(0) != '-')
{
str = '+' + str;
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i+1);
len = str.length();
i=0;
}
}
System.out.println("subStr="+str);
sum += evalSubPoly(str, valx);
}
I will also throw out the disclaimer that there may be more errors, but this is the major one causing your problem.
EDIT: added change to else if statement and added change mentioned in my comment above
With regular expressions, you can get a more simple solution. And, do you want support for simple constants? Try the next:
public class EvalPolyX2 {
public static void main(String args[]) {
System.out.println("Result: " + eval("x^3+x^2+x", 6));
}
public static int eval(String eq, int val) {
int result = 0;
String mons[] = eq.split("(?=[+-])(?!\\B)");
for (String str : mons) {
str = str.replace("+", "");
if (str.contains("x")) {
double a = 1, b = 1;
String[] comps = str.split("x\\^?");
if (comps.length > 0) {
a = comps[0].isEmpty() ? 1 : Integer.parseInt(comps[0]);
}
if (comps.length > 1) {
b = Integer.parseInt(comps[1]);
}
result += a * Math.pow(val, b);
} else {
result += Integer.parseInt(str);
}
}
return result;
}
}

Categories

Resources