Regular Expressions to count number of ocurrences of a string in Java - java

I'm learning Java as I complete CodingBat exercises, and I want to start using regular expressions to solve some level 2 String problems. I'm currently trying to solve this problem:
Return the number of times that the string "code" appears anywhere in the given string, except we'll accept any letter for the 'd', so "cope" and "cooe" count.
countCode("aaacodebbb") → 1
countCode("codexxcode") → 2
countCode("cozexxcope") → 2
And here is the piece of code I wrote (which doesn't work, and I'd like to know why):
public int countCode(String str) {
int counter = 0;
for (int i=0; i<str.length()-2; i++)
if (str.substring(i, i+3).matches("co?e"))
counter++;
return counter;
}
I'm thinking that maybe the matches method isn't compatible with substring, but I'm not sure.

You need to use the regular expression syntax. In this case you want "co\\we", where \\w means any letter.
BTW you can do
public static int countCode(String str) {
return str.split("co\\we", -1).length - 1;
}

Try using this in the if statement. Unless I'm mixing up Java rules with PHP, then it needs to be +4 rather than +3.
str.substring(i, i+4)

public int countCode(String str) {
int count=0; // created a variable to count the appearance of "coe" in the string because d doesn't matter.
for(int i=0;i<str.length()-3;i++){
if(str.charAt(i)=='c'&&str.charAt(i+1)=='o'&&str.charAt(i+3)=='e'){
++count; // increment count if we found 'c' and 'o' and 'e' in the string.
}
}
return count; // returing the number of count 'c','o','e' appeared in string.
}

public class MyClass {
public static void main(String[] args) {
String str="Ramcodecopecofeacolecopecofeghfgjkfjfkjjcojecjcj BY HARSH RAJ";
int count=0;
for (int i = 0; i < str.length()-3; i++) {
if((str.substring(i, i+4)).matches("co[\\w]e")){
count++;
}
}
System.out.println(count);
}
}

Related

How to check if a String contains 3 digits or more

I'm currently trying to check if a string contains 3 digits or more. If it does, then it is valid. How can I fix it?
System.out.print("Enter a string: "); //111Hello <-- valid
String word = input.nextLine();
boolean numbers = word.matches(".*\\d{3,}");
System.out.println(numbers);
Output:
Invalid
Here are some examples:
Input:
Hello244
Output:
Valid
Input:
3Hello
Output:
Invalid
Input:
6Hello2Hello5
Output:
Valid
This is easy to do using a regular expression, because the set of strings containing at least three digits is a regular language - precisely what regular expressions are designed to recognise.
public boolean hasThreeDigits(String s) {
return s.matches(".*\\d.*\\d.*\\d.*");
}
The regex .*\d.*\d.*\d.* matches three digits with anything before, after or in between.
Let's do this with regular expressions. That doesn't really seem required, but let's assume this is an assignment:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FindDigits {
public static final Pattern DIGIT_PATTERN = Pattern.compile("\\p{Digit}");
private static int countDigits(String input) {
final Matcher m = DIGIT_PATTERN.matcher(input);
int c = 0;
while (m.find()) {
c++;
}
return c;
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
final int c = countDigits(args[i]);
System.out.printf("Input : \"%s\"%nOutput: %s%n", args[i], c >= 3 ? "Valid" : "Invalid");
}
}
}
This answer assumes that the input is a set of strings on the command line. It defines a function to count the occurrences of pattern consisting of a single digit. It could of course stop counting at 3.
I'm mainly posting this because Matcher.find is often overlooked as it doesn't have a convenience method defined in String. It often makes for much easier to read regular expressions as you don't need to define what you are not looking for. Otherwise you're stuck with regular expressions strings such as ".*\\d.*\\d.*\\d.*" which are kind of horrible and do not scale well.
Instead of the while loop you can also use m.results().count() on a later version of the Java runtime. In that case a one-liner would be:
long count = Pattern.compile("\\p{Digit}").matcher(input).results().count();
Why not have a counter and loop over each character and then test if its a digit?
This is pseudo code :
System.out.print("Enter a string: "); //111Hello <-- valid
String word = input.nextLine();
int numberOfDigits = countDigits(word, 3);
if (numberOfDigits) >= 3{//...
int countDigits(String val, int max){
int cnt = 0;
for(int i =0; i < val.length(); i++){
char c = val.charAt(i);
if(Character.isDigit(c){
cnt++;
}
if(cnt == max)return;
}
return cnt;
}
https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isDigit(char)
Maybe not the most elegant solution, but pretty short and straightforward:
System.out.println(input.replaceAll("\\D","").length() > 2);
I prefer kaya3's solution the most

How to get each letter and add them as points with a substring method

I've been trying to create an algorithm where each letter adds points. I don't want to use charAt, I'd like to use the substring method.
My problem is that String letter does not seem to get each letter and the result is always 0.
Is there a way to get each letter and convert it to points?
public class WDLPoints{
public static void main(String[] args){
String word = "LDWWL";
System.out.println(getMatchPoints(word));
}
public static int getMatchPoints(String word) {
int points = 0;
String letter = word.substring(5);
for (int i = 0; i < word.length(); i++) {
if (letter.equals("W")) {
points+=3;
}
else if (letter.equals("D")) {
points+=1;
}
else {
points = 0;
}
}
return points;
}
}
You may try the following changes in your public static int getMatchPoints(String word) method:
for (int i = 0; i < word.length(); i++) {
String letter = word.substring(i, i + 1);
if (letter.equals("W")) {
points+=3;
}
else if (letter.equals("D")) {
points+=1;
}
}
word.substring(i, i + 1) will get a single letter word and will help you compute your score the way you want.
If you want to make it really simple you can just use String.toCharArray() and then iterate over the array of char and check its value:
public static int getMatchPoints(String word) {
int points = 0;
char[] arr = word.toCharArray();
for (char letter : arr) {
if (letter == 'W') {
points += 3;
}
else if (letter == 'D') {
points += 1;
}
}
return points;
}
I also removed your else statement because that was just setting the value to 0 if there is any other letter in the loop. I think you intended it to be points += 0 which does nothing, so it can just be removed.
Example Run:
Input:
String word = "LDWWL";
Output:
7
Note: I am aware you might not be allowed to use this solution, but I thought it would be good info on the possibilities since it does not technically use charAt()
Also I'd like to point out you misunderstand what substring(5) does. This will return all characters after the position of 5 as a single String, it does not separate the String into different characters or anything.
You will find that your variable letter is always the empty String. Here's a better way of doing things:
class WDLPoints
{
public static void main(String[] args)
{
String word = "LDWWL";
System.out.println(getMatchPoints(word));
}
// We have only one method to encode character values, all in one place
public static int getValueForChar(int c)
{
switch((char)c)
{
case 'W': return 3;
case 'D': return 1;
default: return 0; //all non-'W's and non-'D's are worth nothing
}
}
public static int getMatchPoints(String word)
{
// for all the characters in the word
return word.chars()
// get their integer values
.map(WDLPoints::getValueForChar)
// and sum all the values
.sum();
}
}
Assuming your string represents a football teams performance of the last 5 games, you could keep it simple and readable with something like:
public static int getMatchPoints(String word) {
String converted = word.replace('W', '3').replace('D', '1').replace('L', '0');
return converted.chars().map(Character::getNumericValue).sum();
}
This converts your example input "LDWWL" to "01330" and sums each char by getting its numeric value.

Instances and classes syntax

So... I understand the idea of one main method and then being able to call multiple classes. That we can refer to one directly in order to run different scenarios. AKA use it if it is needed. Static is for one instance while main is overarching
Questions:
1. Where i have placed the bar there is a return; which is used to get me out of this instance. However, it is telling me i need a String. Which makes sense because the method and the output must match?
I have attempted:
1.to return solely the int value
2.to convert the int to string using-String.valueOf(special);
Where is the error?
import java.util.Scanner;
public class Overall{
public static void main(String[] argc){
Scanner input = new Scanner(System.in);
int i = 0;
int containsLowerCase = 0;
System.out.println(" Please give me a string that has a combination of lower, upper, digits and special characters");
String s1 = input.next();
System.out.println(s1);
}
public static String isSpecial (String input){
int special = 0;
int i =0;
for(i=0;i< input.length(); i++){
char c = input.charAt(i);
if (c=='#' || c=='$' || c== '*' || c== '&')
special++;
String.valueOf(special);
}
return special;
_________________________________________________________
^ ONLY FOCUSING ON UPPER HALF ISSUES ^
public static String print (String input){
System.out.println(s1);
}
public static int isDigit (int input){
int digit = 0;
for(i=0;i< input.length(); i++){
char c = imput.charAt(i);
if (character.isDigit(s1.charAt(i))){
isDigit++;
}
return isDigit++;
}
}
public static int isLower (int input){
int digit = 0;
for(i=0;i< input.length(); i++){
char c = imput.carAt(i);
if (character.isLowerCase(s1.charAt(i))){
isLower++;
}
}
}
public static int isUpper (int input){
int digit = 0;
for(i=0;i< input.length(); i++){
char c = imput.carAt(i);
if (character.isUpperCase(s1.charAt(i))){
isUpper++;
}
}
}
}
You return special which is an int, you need to define a new String variable and return that or simply return String.valueOf(special);.
You called the String.valueOf(int) which will convert an int to a String but you need to place the return value of that method in a String variable.
Example: String newStringVariable = String.valueOf(special);
Return String.valueOf(number)
public static String isSpecial (String input){
int special = 0;
int i =0;
for(i=0;i< input.length(); i++){
char c = input.charAt(i);
if (c=='#' || c=='$' || c== '*' || c== '&')
special++;
}
return String.valueOf(special);
I will try to mention all your mistakes, and tell you why it is wrong and what it has ro be like.
First, lets begin with your isSpecial method:
You count the number of times a special character is in your String. Most of its code is right, but I think you wanted return type of int not of String. See, the type you write before the name of the method, in this case String, is what type of Object the method will return. In your method you count the number of times a certain event happens, so you want to return that number to later calculate with that or something else.
The return statement has to be in the method body, and when it is reached, the current method takes that value and gives it back to the call of it. Afterwards the method exits, so after a return this method ended and the program continues where you called that method. Take following code:
public class Test {
public static void main (String [] args){
String testText = "This was written on 2.03.2017";
int numbers = countNumeric (testText);
System.out.println ("The text containes "+ numbers +" numbers");
}
public static int countNumeric (String text){
int count = 0;
for (int i = 0; i < text.length; i++){
if (Character.isDigit (text.charAt (i))
count++;
}
return count;
}
When executing this method, java creates a new String, then passes that String to the countNumeric method, where count is incremented by one for each digit character in the String. Then countNumeric returns the count. The program jumps back to the main method and there takes the return value of countNumeric and puts it into the variable numbers, then it prints that.
Also you seem to have a problem using String.valueOf. String.valueOf is a method, which takes a number and converts it to a string. But since you declared special as int, you cannot store a String in it (and maybe want to use it later on). So to convert a number to a String, you have to create a new variable of type String, like in this simple example:
int number = 123;
String text = String.valueOf (number);
//do something with text
So most of your errors are due to missing returns or wrong return type. Also the reurn in your isDigit method is in the for loop, so it will only look at the first character of the String.
I hope I could help you, and would suggest you to look for a good java step by step tutorial, since you don't seem very familiar with programming.

How to count number of letters in sentence

I'm looking for simple way to find the amount of letters in a sentence.
All I was finding during research were ways to find a specific letter, but not from all kinds.
How I do that?
What I currently have is:
sentence = the sentence I get from the main method
count = the number of letters I want give back to the main method
public static int countletters(String sentence) {
// ....
return(count);
}
You could manually parse the string and count number of characters like:
for (index = 1 to string.length()) {
if ((value.charAt(i) >= 'A' && value.charAt(i) <= 'Z') || (value.charAt(i) >= 'a' && value.charAt(i) <= 'z')) {
count++;
}
}
//return count
A way to do this could stripping every unwanted character from the String and then check it's length. This could look like this:
public static void main(String[] args) throws Exception {
final String sentence = " Hello, this is the 1st example sentence!";
System.out.println(countletters(sentence));
}
public static int countletters(String sentence) {
final String onlyLetters = sentence.replaceAll("[^\\p{L}]", "");
return onlyLetters.length();
}
The stripped String looks like:
Hellothisisthestexamplesentence
And the length of it is 31.
This code uses String#replaceAll which accepts a Regular Expression and it uses the category \p{L} which matches every letter in a String. The construct [^...] inverts that, so it replaces every character which is not a letter with an empty String.
Regular Expressions can be expensive (for the performance) and if you are bound to have the best performance, you can try to use other methods, like iterating the String, but this solution has the much cleaner code. So if clean code counts more for you here, then feel free to use this.
Also mind that \\p{L} detects unicode letters, so this will also correctly treat letters from different alphabets, like cyrillic. Other solutions currently only support latin letters.
SMA's answer does the job, but it can be slightly improved:
public static int countLetters(String sentence) {
int count = 0;
for (int i = 0; i < sentence.length; i ++)
{
char c = Character.toUpperCase(value.charAt(i));
if (c >= 'A' && c <= 'Z')
count ++;
}
return count;
}
This is so much easy if you use lambda expression:
long count = sentence.chars().count();
working example here: ideone
use the .length() method to get the length of the string, the length is the amount of characters it contains without the nullterm
if you wish to avoid spaces do something like
String input = "The quick brown fox";
int count = 0;
for (int i=0; i<input.length(); i++) {
if (input.charAt(i) != ' ') {
++count;
}
}
System.out.println(count);
if you wish to avoid other white spaces use a regex, you can refer to this question for more details
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
String str = sc.nextLine();
int count = 0;
for (int i = 0; i < str.length(); i++) {
if (Character.isLetter(str.charAt(i)))
count++;
}
System.out.println(count);
}
}

Count Occurence of Needle String in Haystack String, most optimally?

The Problem is simple Find "ABC" in "ABCDSGDABCSAGAABCCCCAAABAABC" without using String.split("ABC")
Here is the solution I propose, I'm looking for any solutions that might be better than this one.
public static void main(String[] args) {
String haystack = "ABCDSGDABCSAGAABCCCCAAABAABC";
String needle = "ABC";
char [] needl = needle.toCharArray();
int needleLen = needle.length();
int found=0;
char hay[] = haystack.toCharArray();
int index =0;
int chMatched =0;
for (int i=0; i<hay.length; i++){
if (index >= needleLen || chMatched==0)
index=0;
System.out.print("\nchar-->"+hay[i] + ", with->"+needl[index]);
if(hay[i] == needl[index]){
chMatched++;
System.out.println(", matched");
}else {
chMatched=0;
index=0;
if(hay[i] == needl[index]){
chMatched++;
System.out.print("\nchar->"+hay[i] + ", with->"+needl[index]);
System.out.print(", matched");
}else
continue;
}
if(chMatched == needleLen){
found++;
System.out.println("found. Total ->"+found);
}
index++;
}
System.out.println("Result Found-->"+found);
}
It took me a while creating this one. Can someone suggest a better solution (if any)
P.S. Drop the sysouts if they look messy to you.
How about:
boolean found = haystack.indexOf("ABC") >= 0;
**Edit - The question asks for number of occurences, so here's a modified version of the above:
public static void main(String[] args)
{
String needle = "ABC";
String haystack = "ABCDSGDABCSAGAABCCCCAAABAABC";
int numberOfOccurences = 0;
int index = haystack.indexOf(needle);
while (index != -1)
{
numberOfOccurences++;
haystack = haystack.substring(index+needle.length());
index = haystack.indexOf(needle);
}
System.out.println("" + numberOfOccurences);
}
If you're looking for an algorithm, google for "Boyer-Moore". You can do this in sub-linear time.
edit to clarify and hopefully make all the purists happy: the time bound on Boyer-Moore is, formally speaking, linear. However the effective performance is often such that you do many fewer comparisons than you would with a simpler approach, and in particular you can often skip through the "haystack" string without having to check each character.
You say your challenge is to find ABC within a string. If all you need is to know if ABC exists within the string, a simple indexOf() test will suffice.
If you need to know the number of occurrences, as your posted code tries to find, a simple approach would be to use a regex:
public static int countOccurrences(string haystack, string regexToFind) {
Pattern p = Pattern.compile(regexToFind);
Matcher m = p.matcher(haystack); // get a matcher object
int count = 0;
while(m.find()) {
count++;
}
return count;
}
Have a look at http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
public class NeedleCount
{
public static void main(String[] args)
{
String s="AVBVDABCHJHDFABCJKHKHF",ned="ABC";
int nedIndex=-1,count=0,totalNed=0;
for(int i=0;i<s.length();i++)
{
if(i>ned.length()-1)
nedIndex++;
else
nedIndex=i;
if(s.charAt(i)==ned.charAt(nedIndex))
count++;
else
{
nedIndex=0;
count=0;
if(s.charAt(i)==ned.charAt(nedIndex))
count++;
else
nedIndex=-1;
}
if(count==ned.length())
{
nedIndex=-1;
count=0;
totalNed++;
System.out.println(totalNed+" needle found at index="+(i-(ned.length()-1)));
}
}
System.out.print("Total Ned="+totalNed);
}
}
Asked by others, better in what sense? A regexp based solution will be the most concise and readable (:-) ). Boyer-Moore (http://en.wikipedia.org/wiki/Boyer–Moore_string_search_algorithm) will be the most efficient in terms of time (O(N)).
If you don't mind implementing a new datastructure as replacement for strings, have a look at Tries: http://c2.com/cgi/wiki?StringTrie or http://en.wikipedia.org/wiki/Trie
If you don't look for a regular expression but an exact match they should provide the fastest solution (proportional to length of search string).
public class FindNeedleInHaystack {
String hayStack="ASDVKDBGKBCDGFLBJADLBCNFVKVBCDXKBXCVJXBCVKFALDKBJAFFXBCD";
String needle="BCD";
boolean flag=false;
public void findNeedle() {
//Below for loop iterates the string by each character till reaches max length
for(int i=0;i<hayStack.length();i++) {
//When i=n (0,1,2... ) then we are at nth character of hayStack. Let's start comparing nth char of hayStach with first char of needle
if(hayStack.charAt(i)==needle.charAt(0)) {
//if condition return true, we reach forloop which iterates needle by lenghth.
//Now needle(BCD) first char is 'B' and nth char of hayStack is 'B'. Then let's compare remaining characters of needle with haystack using below loop.
for(int j=0;j<needle.length();j++) {
//for example at i=9 is 'B', i+j is i+0,i+1,i+2...
//if condition return true, loop continues or else it will break and goes to i+1
if(hayStack.charAt(i+j)==needle.charAt(j)) {
flag=true;
} else {
flag=false;
break;
}
}
if(flag) {
System.out.print(i+" ");
}
}
}
}
}
Below code will perform exactly O(n) complexity because we are looping n chars of haystack. If you want to capture start and end index's of needle uncomment below commented code. Solution is around playing with characters and no Java String functions (Pattern matching, IndexOf, substring etc.,) are used as they may bring extra space/time complexity
char[] needleArray = needle.toCharArray();
char[] hayStackArray = hayStack.toCharArray();
//java.util.LinkedList<Pair<Integer,Integer>> indexList = new LinkedList<>();
int head;
int tail = 0;
int needleCount = 0;
while(tail<hayStackArray.length){
head = tail;
boolean proceed = false;
for(int j=0;j<needleArray.length;j++){
if(head+j<hayStackArray.length && hayStackArray[head+j]==needleArray[j]){
tail = head+j;
proceed = true;
}else{
proceed = false;
break;
}
}
if(proceed){
// indexList.add(new Pair<>(head,tail));
needleCount++;
}
++tail;
}
System.out.println(needleCount);
//System.out.println(indexList);

Categories

Resources