Identifying set of integers in strings - java

I'm new to Java, trying to learn more.
How do I identify a contiguous set of integers in a string?
For example, if I have the string "123hh h3ll0 wor1d" the program should output 4 as the answer.
Here's what I've worked on, and as a result, my program outputs 6. I understand why but I don't know how to implement what I want the program to do.
public static void main (String[] args) throws java.lang.Exception
{
String string = "123hh h3ll0 w0rld";
int count = 0;
if (string.isEmpty())
count = 0;
for (int i = 0; i < string.length(); i++)
{
char c = string.charAt(i);
if (Character.isDigit(c))
count++;
}
System.out.println(count);
}

Your program is a good start, but it counts all digits. You need to avoid count++ when you are in a contiguous group of digits. You can do it by adding a boolean flag which you set to true when you see a digit, and then to false when you see a non-digit:
boolean inDigits = false;
for (int i = 0; i < string.length(); i++)
{
char c = string.charAt(i);
if (Character.isDigit(c)) {
if (!inDigits) count++;
inDigits = true;
} else {
inDigits = false;
}
}
Demo 1
A simpler way to find the number of groups is to split on \\d+ (a sequence of one or more digits), count the number of groups you get, and subtract one:
System.out.println(string.split("\\d+").length-1);
Demo 2

Your program counts each occurrence of a digit within the input string; and as there 6 digits; 6 is your result. So no surprises there. You have to understand: if you are interested in sequences of digits, then just checking each character "are you a digit" isn't enough!
If you are interested in the length of the longest sequence, then your "counting" must be enhanced:
While being within a sequence, you keep increasing the "currentSequenceLength" counter
When hitting a non-digit, you stop counting; and you compare the length of the last sequence with the "maximum" that you also have to remember.
That should be enough to get you going; as for sure; the idea is not that we do the homework/learning part for you.

Based on what you stated about contiguous, you want to reset the count every time you are not on a digit and store the maximum count achieved during this process.
Add int currentMaximum = 0 and when a non-digit is read in, check to see if count is greater than currentMaximum and set currentMaximum to count and then set count = 0. This will cause the count to reset at each non-digit and only count up when digits are contiguous.

So your code snippet is simply counting every digit in the string, which you said you knew. So you have to see which situation does it occur that you actually want to count. For contiguous digits, the situation you're looking for is when the current character is a digit, and the next is not. That is when the chain of contiguous digits is broken. I have edited your for loop to use this technique to find the number of contiguous digit sets:
public static void main (String[] args) throws java.lang.Exception {
String string = "123hh h3ll0 w0rld";
int count = 0;
if (string.isEmpty()) {
count = 0;
} else {
for (int i = 0; i < string.length() - 1; i++){
char current = string.charAt(i);
char next = string.charAt(i+1);
if (Character.isDigit(current) && !Character.isDigit(next)){
count++;
}
}
System.out.println(count);
}
}

I would target the numbers in the string via pre-processing OR real time, your problem statement doesn't define a requirement for either, and then refer to the related problem: here and additionally here (which provides a c++ and java sample too).
There's not too much to elaborate on because you haven't set up the problem space to define other factors (more in-depth problem statement by OP would help answers reflect more accurate responses). Try to specify such things as:
does/should it reset when encountering non-digits?
can you use objects like sets?
are you reading in simple test strings or large data amounts?
etc.
Without more info, I think there will be a varying response of answers here.
Cheers

This code will generate count = 6 and group = 4.
enter public static void main (String[] args) throws java.lang.Exception
{
String string = "123hh h3ll0 w0rld";
boolean isGroup = false;
int count = 0;
int group = 0;
if (string.isEmpty()) {
count = 0;
} else {
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (Character.isDigit(c)) {
count++;
if (!isGroup) {
group++;
isGroup = true;
}
} else {
isGroup = false;
}
}
}
System.out.println(count);
System.out.println(group);
}

Related

Finding the nth term in a sequence

I have a sequence, and I am trying to make a program to find the nth term of the sequence.
The sequence is as follows:
1, 11, 21, 1211, 111221, 312211...
In this sequence, each term describes the previous term. For example, "1211" means that the previous term; the previous term is "21" where there is one occurrence of a 2 and then one occurrence of a 1 (=1211). To get the third term, "21," you look at the second term: 11. There are two occurrences of a 1 which gives us "21."
import java.util.*;
class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
System.out.println( Main.num(n-1, "1"));
}
public static String num(int times, String x){
if(times == 0){
return x;
}else{
//System.out.println("meow");
String y = "" + x.charAt(0);
int counter = 0;
for(int i = 1; i < x.length(); i++){
if(x.charAt(i) == x.charAt(i-1)){
counter++;
}else{
y += "" + counter + x.charAt(i-1);
counter = 0;
}
}
return num(times--, y);
}
//return "";
}
}
My code uses recursion to find the nth term. But, it gives us errors :(
First, I start of the method "num" by passing it the number of terms-1 (since the first term is already given) and the first term (1).
In the method num, we start off by using a conditional to establish the base case (when you are done finding the nth term).
If the base case is false, then you find the next term in the sequence.
This is a very cool sequence! I like that it is English based and not mathematical, haha. (Though now I wonder ... is there a formula we could make for the nth term? I'm pretty sure it's impossible or uses some crazy-level math, but just something to think about ...)
In your solution, the recursive logic of your code is correct: after you find each term, you repeat the method with your knew number and find the next term using that element, and end when you have determined the first n elements. Your base case is also correct.
However, the algorithm you developed for determining the terms in the sequence is the issue.
To determine the next element in the sequence, we want to:
Logical Error:
Create a empty variable, y, for your next element. The variable, counter, should not start at 0, however. This is because every element will ALWAYS have an occurrence of at least 1, so we should initialize int counter = 1;
Iterate through the characters in x. (You did this step correctly) We begin at i = 1, because we compare each character to the previous one.
If the current character is equal to the previous character, we increment counter by 1.
Otherwise, we concatenate counter and the character being repeated, to y. Remember, to reinitialize counter to 1, not 0.
Technical Errors:
Once we reach the end of iterating x, we need to concatenate our final counter and character to y, since the else statement for the final characters will never run in our for loop.
This is done with the following code: y += "" + counter + x.charAt(x.length() - 1);
Finally, when you are doing your recursive call, you should do --times instead of times--. The difference between these two parameters is that with your original code, you are post-decrementing. This means the value of times is decreasing after the method call, when we want the decreased value to be sent into the method. To solve this, we need to pre-decrement, by doing --times.
import java.util.*;
class CoolSequence {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
System.out.println(num(n, "1"));
}
public static String num(int times, String x){
if(times == 0){
return x;
}
else{
String y = "";
int counter = 1;
for(int i = 1; i < x.length(); i++){
if(x.charAt(i) == x.charAt(i - 1)){
counter++;
}
else{
y += "" + counter + x.charAt(i - 1);
counter = 1;
}
}
y += "" + counter + x.charAt(x.length() - 1);
return num(--times, y);
}
}
}
Testing:
6
13112221
An alternative approach would be using an iterative method:
import java.util.*;
class CoolSequence2 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
ArrayList<String> nums = new ArrayList<String>();
int n = scan.nextInt();
String val = "1";
for(int i = 0; i < n; i++){
String copy = val;
val = "";
while(!copy.equals("")){
char curr = copy.charAt(0);
int ind = 0;
int cons = 0;
while(ind < copy.length() && curr == copy.charAt(ind)){
cons += 1;
ind += 1;
}
val += String.valueOf(cons) + copy.charAt(cons - 1);
copy = copy.substring(cons);
}
nums.add(val);
}
System.out.println(nums.get(nums.size() - 1));
}
}
6
13112221
In this method, we use a for loop to iterate through n terms. To determine each element, we do a similar method to your logic:
We create an empty string, val, to hold the new element, and store our current element in copy. We also initialize a cons, similar to your counter.
While copy is not empty, we iterate through copy and increment cons until there is an element that is not equal to the next element.
When this occurs, we concatenate cons and the repeated element to val, like in your code. Then, we cut out the repeated elements from copy and continue the process.
We add the new value of val to nums, and keep iterating through the n elements.
I hope these two methods of approaching your problem helped! Please let me know if you have any further questions or clarifications :)
You can use Pattern with backreference.
The regular expression "(.)\\1*" matches any single character ("(.)") and zero or more sequences of the same character ("\\1*"). "\\1" is called a backreference, it refers to the string enclosed in parentheses 1st.
For example, it matches 111, 22 and 1 for 111221.
replaceAll() calls the lambda expression specified by the argument each time it matches. The lambda expression receives a MatchResult and returns a string. The matched string is replaced with the result.
The lambda expression in this case concatenates the length of the matched string (match.group().length()) and the first character (match.group(1)).
static final Pattern SEQUENCE_OF_SAME_CHARACTER = Pattern.compile("(.)\\1*");
static String num(int times, String x) {
for (int i = 0; i < times; ++i)
x = SEQUENCE_OF_SAME_CHARACTER.matcher(x).replaceAll(
match -> match.group().length() + match.group(1));
return x;
}
public static void main(String[] args) {
for (int i = 1; i <= 8; ++i)
System.out.print(num(i - 1, "1") + " ");
}
output:
1 11 21 1211 111221 312211 13112221 1113213211

Write a program which accepts two integers as a minimum and maximum limit and calculates total of how many 1s were their within the limit

For ex:
1) if user input 1 11 then it should print 4.
2) if user input 11 111 then it should print 34.
Do it with Java.util.Scanner. Thats a really basic thing in java. I recommend you to do some research :) Here is an easy tutorial on that:
http://www.homeandlearn.co.uk/java/user_input.html
here an answere anyway:
public static void main(String[] args){
Scanner user_input = new Scanner( System.in );
String anInputString;
anInputString = user_input.next( );
if (anInputString.equals("1 11")){
System.out.println("4")
}
if (anInputString.equals("11 111"){
System.out.println("34")
}
}
edit:
if you want to achieve an output of "4" while your input lies between "1" and "11". Or "34" if its between "10" and "112" you should try this:
public static void main(String[] args){
Scanner user_input = new Scanner( System.in );
int anInputInt;
anInputInt = user_input.nextInt( );
if (0 < anInputInt && anInputInt < 11 ){ //if input is (1-10)
System.out.println("4")
}
if (11 <= anInputInt && anInputInt <= 111){ //if input is (11-111)
System.out.println("34")
}
}
Anyway you should edit your question :D I think many people are happy to help you, but just cant understand your question at all 0.0
finally after I understood what you really want to do:
public static void main(String[] args){
Scanner user_input = new Scanner( System.in );
int anInputInt;
anInputInt = user_input.nextInt( );
if(anInputString < 0){
anInputString = anInputstring*(-1);
}
int oneCount = 0;
//gets all numbers in your specified range
//if you want to start at number "xx" change the value of aNumberInRange likewise
for (int aNumberInRange = 0; aNumberInRange < anInputInt; aNumberInRange++){
String str = String.valueOf(aNumberInRange);
//iterates through every character of an aNumberInRange and counts if a "1" occurs
for(int i = 0; i < str.length(); i++){
char c = str.charAt(i);
if (c == 1){
oneCount++
}
}
}
system.out.println(oneCount);
}
For whoever reads this solution. The client wanted to count all the occurences of the number "1" in a specified range. This should also work with negative Numbers
I strongly advice looking into the math of your problem and come up with a clever algorithm that you then implement. The 1s are far from randomly distributed in a range of numbers that are count up ;-)
However there is always the brute force approach.
(This is just to show a possibility and one of the worst ways to solve the problem)
int count = 0;
for(int i = 1; i<=11; i++)
{
String number = String.valueOf(i);
while(number.contains("1"))
{
number= number.substring(number.indexOf("1")+1);
count ++;
}
}
System.out.println(count);
EDIT:
For those with an interest in better brute force version using log, mod and div (best I could come up with yet ^^):
int count2 = 0;
for(int i = lowerbound; i<=upperbound; i++)
{
int temp = Math.abs(i); //make positive. No negative log
if(temp==0) //beware the log(0) trap
continue;
int length = (int)(Math.log10(temp)+1); //count digits
for(int j = length -1; j>=0 ; j--) //inspect digit for digit
{
if(temp % 10 == 1)
{
count2 ++;
}
temp = temp / 10;
}
}
Tests done with a range from -1000000 to 1000000 measured with nano() (so no units). For CharAt approach see Tom Wellbrock s answer.
Even though log, % and / are quite slow mathematical operations the cost for a String creation is more expensive.
Without java Optimisation: :
SubString: 14000002 time taken:
18351768293
Log: 14000002 time taken:
2895089202
CharAt: 14000002 time taken:
13929667983
With java optimisation (creating Strings becomes a lot cheaper then, especially when they appear twice and all the little tweaks why we love java so much)
SubString:14000002 time taken:
1088103359
Log:14000002 time taken:
568686169
CharAt:14000002 time taken:
741721424

Matching subsequence of length 2 (at same index) in two strings

Given 2 strings, a and b, return the number of the positions where they contain the same length 2 substring. For instance a and b is respectively "xxcaazz" and "xxbaaz" yields 3, since the "xx", "aa", and "az" substrings appear in the same place in both strings.
What is wrong with my solution?
int count=0;
for(int i=0;i<a.length();i++)
{
for(int u=i; u<b.length(); u++)
{
String aSub=a.substring(i,i+1);
String bSub=b.substring(u,u+1);
if(aSub.equals(bSub))
count++;
}
}
return count;
}
In order to fix your solution, you really don't need the inner loop. Since the index should be same for the substrings in both string, only one loop is needed.
Also, you should iterate till 2nd last character of the smaller string, to avoid IndexOutOfBounds. And for substring, give i+2 as second argument instead.
Overall, you would have to change your code to something like this:
int count=0;
for(int i=0; i < small(a, b).length()-1; i++)
{
String aSub=a.substring(i,i+2);
String bSub=b.substring(i,i+2);
if(aSub.equals(bSub))
count++;
}
}
return count;
Why I asked about the length of string is, it might become expensive to create substrings of length 2 in loop. For length n of smaller string, you would be creating 2 * n substrings.
I would rather not create substring, and just match character by character, while keeping track of whether previous character matched or not. This will work perfectly fine in your case, as length of substring to match is 2. Code would be like:
String a = "iaxxai";
String b = "aaxxaaxx";
boolean lastCharacterMatch = false;
int count = 0;
for (int i = 0; i < Math.min(a.length(), b.length()); i++) {
if (a.charAt(i) == b.charAt(i)) {
if (lastCharacterMatch) {
count++;
} else {
lastCharacterMatch = true;
}
} else {
lastCharacterMatch = false;
}
}
System.out.println(count);
The heart of the problem lies with your usage of the substring method. The important thing to note is that the beginning index is inclusive, and the end index is exclusive.
As an example, dissecting your usage, String aSub=a.substring(i,i+1); in the first iteration of the loop i = 0 so this line is then String aSub=a.substring(0,1); From the javadocs, and my explanation above, this would result in a substring from the first character to the first character or String aSub="x"; Changing this to i+2 and u+2 will get you the desired behavior but beware of index out of bounds errors with the way your loops are currently written.
String a = "xxcaazz";
String b = "xxbaaz";
int count = 0;
for (int i = 0; i < (a.length() > b.length() ? b : a).length() - 1; i++) {
String aSub = a.substring(i, i + 2);
String bSub = b.substring(i, i + 2);
if (aSub.equals(bSub)) {
count++;
}
}
System.out.println(count);

Java reading in a string and converting numbers in strings into Integers types

I am trying to take numbers from a users string (if it has numbers) and convert those numbers to their numerical value. I have the following code which takes in user input.
Ex: java Convert "55s" will just output the number 55, which i will store for later usage
{
char Element = 0;
double Sum = 0;
boolean Check = false;
for(String s: args) // taking in user input for command line
{
for (int i = 0; i<s.length(); i++)
{
Check = true;
Element = s.charAt(i); // converting the string into chars
Sum = convert_to_numb (Element, Check);
Check = false;
}
}
The input is a string in which i separate into chars and send it to my conversion functions. The idea i have follows
public static double convert_to_numb (char elem, boolean check) //trying to convert chars to numbers
{
char iter = elem;
double number = 0;
int count = 0;
while (check == true)
{
number = number + (iter - 48) * Math.pow(10,count);
System.out.println(iter);
count ++;
}
return number;
}
Here I am feeding in the chars to see if they're numbers and convert the actual numbers into their integer value. To try to clarify i would like to perform the following task given an example input of "55" covert it to 5*10^1 + 5*10^0 = 55. I would appreciate any help. Thanks.
Alright, I think I might know what you're trying to accomplish, though as others have mentioned it is a little unclear.
To address the code you just posted, I don't think it'll behave the way you expect. For starters, the Boolean variable 'Check' accomplishes nothing at the moment. convert_to_numb is only called while Check is true, so it's redundant.
Additionally, the sum isn't being stored anywhere as you loop through the string. Every time you obtain a sum, it overwrites the previous one.
Your convert_to_numb method is even more troubling; it contains an infinite loop. Since Check is always set to 'true', you essentially have a while(true) loop that will never end.
I'm going to assume that your objective here is to parse whichever Strings are input into the program looking for groups of consecutive digits. Then you want to store these groups of digits as integers, perhaps in an array if you find multiple.
Something like this might do the trick.
{
ArrayList<Integer> discovered = new ArrayList<Integer>();
for (String s : args) {
// contains previous consecutive digits (if any)
ArrayList<Integer> digits = new ArrayList<Integer>();
for (int i = 0; i < s.length(); i++) {
Character c = s.charAt(i);
// add digit to digit array
if (c.isDigit()) {
digits.add(c.getNumericValue())
}
// not a digit, so we clear the digit array
else {
// combine the array to form an integer
if (! digits.isEmpty()) {
int sum = 0;
int counter = 0;
for (Integer i : digits) {
sum += i * Math.pow(10, counter);
counter++;
}
discovered.add(sum);
digits.clear();
}
}
}
}
}
Note the use of ArrayLists and the Integer and Character wrapper classes. These all provide functionality that helps deal with edge-cases. For example, I'm not sure that (iter - 48) part would have worked in all cases.
Something like this:
public static void main(String[] args) {
String string = "55s";
String[] piece = string.split("[\\D]+");
for (int j = 0; j < piece.length; j++) {
if(piece[j].trim().length() > 0) {
System.out.println(piece[j]);
}
}
}
It will split your initial string, the rest you should do yourself.

Why am I getting java.lang.StringIndexOutOfBoundsException?

I want to write a program that prints words incrementally until a complete sentence appears. For example : I need to write (input), and output:
I
I need
I need to
I need to write.
Here is my code:
public static void main(String[] args) {
String sentence = "I need to write.";
int len = sentence.length();
int numSpace=0;
System.out.println(sentence);
System.out.println(len);
for(int k=0; k<len; k++){
if(sentence.charAt(k)!='\t')
continue;
numSpace++;
}
System.out.println("Found "+numSpace +"\t in the string.");
int n=1;
for (int m = 1; m <=3; m++) {
n=sentence.indexOf('\t',n-1);
System.out.println("ligne"+m+sentence.substring(0, n));
}
}
and this is what I get:
I need to write.
16
Found 0 in the string.
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: -1 at
java.lang.String.substring(String.java:1937) at
split1.Split1.main(Split1.java:36) Java Result: 1 BUILD SUCCESSFUL
(total time: 0 seconds)
I don't understand why numSpace doesn't count the occurrences of spaces, nor why I don't get the correct output (even if I replace numSpace by 3 for example).
You don't have a \t character, so indexOf(..) returns -1
You try a substring from 0 to -1 - fails
The solution is to check:
if (n > -1) {
System.out.prinltn(...);
}
Your loop looking for numSpace is incorrect. You are looking for a \t which is a tab character, of which there are none in the string.
Further, when you loop in the bottom, you get an exception because you are trying to parse by that same\t, which will again return no results. The value of n in n=sentence.indexOf('\t',n-1); is going to return -1 which means "there is not last index of what you are looking for". Then you try to get an actual substring with the value of -1 which is an invalid substring, so you get an exception.
You are mistaken by the concept of \t which is an escape sequence for a horizontal tab and not for a whitespace character (space). Searching for ' ' would do the trick and find the whitespaces in your sentence.
This looks like homework, so my answer is a hint.
Hint: read the javadoc for String.indexOf paying attention to what it says about the value returned when the string / character is not found.
(In fact - even if this is not formal homework, you are clearly a Java beginner. And beginners need to learn that the javadocs are the first place to look when using an unfamiliar method.)
The easiest way to solve this I guess would be to split the String first by using the function String.split. Something like this:
static void sentence(String snt) {
String[] split = snt.split(" ");
for (int i = 0; i < split.length; i++) {
for (int j = 0; j <= i; j++) {
if (i == 1 && j == 0) System.out.print(split[j]);
else System.out.printf(" %s", split[j]);
}
}
}
As other people pointed out. You are counting every characters except tabs(\t) as a space. You need to check for spaces by
if (sentence.charAt(k) == ' ')
\t represents a tab. To look for a space, just use ' '.
.indexOf() returns -1 if it can't find a character in the string. So we keep looping until .indexOf() returns -1.
Use of continue wasn't really needed here. We increment numSpaces when we encounter a space.
System.out.format is useful when we want to mix literal strings and variables. No ugly +s needed.
String sentence = "I need to write.";
int len = sentence.length();
int numSpace = 0;
for (int k = 0; k < len; k++) {
if (sentence.charAt(k) == ' ') {
numSpace++;
}
}
System.out.format("Found %s in the string.\n", numSpace);
int index = sentence.indexOf(' ');
while(index > -1) {
System.out.println(sentence.substring(0, index));
index = sentence.indexOf(' ', index + 1);
}
System.out.println(sentence);
}
Try this, it should pretty much do what you want. I figure you have already finished this so I just made the code real fast. Read the comments for the reasons behind the code.
public static void main(String[] args) {
String sentence = "I need to write.";
int len = sentence.length();
String[] broken = sentence.split(" "); //Doing this instead of the counting of characters is just easier...
/*
* The split method makes it where it populates the array based on either side of a " "
* (blank space) so at the array index of 0 would be 'I' at 1 would be "need", etc.
*/
boolean done = false;
int n = 0;
while (!done) { // While done is false do the below
for (int i = 0; i <= n; i++) { //This prints out the below however many times the count of 'n' is.
/*
* The reason behind this is so that it will print just 'I' the first time when
* 'n' is 0 (because it only prints once starting at 0, which is 'I') but when 'n' is
* 1 it goes through twice making it print 2 times ('I' then 'need") and so on and so
* forth.
*/
System.out.print(broken[i] + " ");
}
System.out.println(); // Since the above method is a print this puts an '\n' (enter) moving the next prints on the next line
n++; //Makes 'n' go up so that it is larger for the next go around
if (n == broken.length) { //the '.length' portion says how many indexes there are in the array broken
/* If you don't have this then the 'while' will go on forever. basically when 'n' hits
* the same number as the amount of words in the array it stops printing.
*/
done = true;
}
}
}

Categories

Resources