I'm new to programming (taking a class) and I'm not sure how to accomplish this one task.
"Ignoring case, find the last occurrence of an ‘a’ in the input and remove all of the characters following it. In the case where there are no ‘a’s in the word, remove all but the first two characters (reminder: do not use if statements or loops). At the end of the now truncated word, add a number that is the percentage that the length of the truncated word is of the length of the original word; this percentage should be rounded to the closest integer value."
I'll be fine with the percentage part, but I'm not sure how to do the first part.
How do I remove only after the last occurrence of 'a'?
If there is no 'a' how do I cut it off after the first two letters without using an if statement?
I'm assuming its to be done using string manipulation and various substrings, but I'm not sure how the criteria for the substrings should be made.
Remember, Java newbie! I don't know a lot of fancy coding techniques yet.
Thank you!
String#toLowerCase - remove all case from the String
String#lastIndexOf will tell you where the last occurrence of the specified String occurs, will return -1 if there is no occurrence, this is important.
String#subString will allow you to generate a new String based on a sub element of the current String
Math#max, Math#min
Given String input, consider the following as a possible starting point:
int indexOfSmallA = input.lastIndexOf('a');
int indexOfBigA = input.lastIndexOf('A');
int beginIndex = Math.max(indexOfSmallA, indexOfBigA);
// if not found, begin at 2 or end of input, else begin after last 'a'
beginIndex = (beginIndex == -1) ? Math.min(2, input.length()) : beginIndex + 1;
String result = input.substring(beginIndex);
For finding the last occurence of 'a' or 'A' you can use...
int index = Math.max(str.lastIndexOf('a'),str.lastIndexOf('A'));
index = (index==-1)?Math.min(2,str.length()):index+1;
Once you get the index you can use the following to remove the characters after it...
str.substring(0,index);
Related
Got something for you all.
As the title of the problem suggests, I am trying to implement a non-array, non-looping, recursive method to find the alphabetically last letter in a string.
I think that I understand the nature of the problem I'm trying to solve, but I don't know how to start with the base case and then the recursion.
Can anyone be willing to solve this problem?
In this case, I would like the following code:
//Method Definition
public static String findZenithLetter(String str) {
//Put actual working Java code that finds the alphabetically last letter of the desired string here.
//Use recursion, not loops! :)
//Don't use arrays! ;)
}
//Driver Code
System.out.println(findZenithLetter("I can reach the apex, at the top of the world."));
//Should print the String "x" if implemented properly
I have tried to attempt numerous, but currently failed ways of solving this problem, including but not limited to:
Sorting the string by alphabetical order then finding the last letter of the new string, excluding punctuation marks.
Using the compareTo() method to compare two letters of the string side by side, but that has yet to work as I am so tempted to use loops, not recursion. I need a recursive method to solve this, though. :)
In the end, the best piece of code that I've written for this problem was just a drawn-out way to compute just the last character of a string and not actually THE alphabetically last character.
This is quite simple. All you need is just iterate (in the recursion of course), and check all characters int he string with local maximum.
public static char findZenithLetter(String str) {
return findZenithLetter(str, 0, 'a');
}
private static char findZenithLetter(String str, int i, char maxCh) {
if (i >= str.length())
return maxCh;
char ch = Character.toLowerCase(str.charAt(i));
if (Character.isLetter(ch))
maxCh = ch > maxCh ? ch : maxCh;
return findZenithLetter(str, i + 1, maxCh);
}
Nibble off the first character at each recursion, returning the greater of it and the greatest found in the rest of the input:
public static String findZenithLetter(String str) {
if (str.isEmpty()) {
return ""; // what's returned if no letters found
}
String next = str.substring(0, 1);
String rest = findZenithLetter(str.substring(1));
return Character.isLetter(next.charAt(0)) && next.compareToIgnoreCase(rest) > 0 ? next : rest;
}
See live demo.
The check for Character.isLetter() prevents non-letter characters, which may be "greater than" letters being returned.
If no letters are found, a blank is returned.
I have a java string containing n number of characters.
How do I extract the LAST few characters from that string?
I found this piece of code online that extracts the first few, but I dont understand it so I cant modify it.
Can anyone help me with this?
String upToNCharacters = s.substring(0, Math.min(s.length(), n));
Try,
String upToNCharacters = s.substring(s.length()-lastCharNumber);
That piece of code does exactly the opposite of what you want. Now let's see why and how we can modify it.
Quick solution
You can modify the code as follows to do what you want:
String lastNchars = s.substring( Math.max(0, s.length()-n));
Explanation
According to the official documentation, Java String class has a special method called substring().
The signature of the method is the following (with overload):
public String substring(int beginIndex, int endIndex))
public String substring(int beginIndex)
The first method accepts 2 parameters as input:
beginIndex: the begin index of the substring, inclusive.
endIndex: the end index of the substring, exclusive.
The second overload will automatically consider as endIndex the length of the string, thus returning "the last part"
Both methods return a new String Object instance according to the input parameters just described.
How do you pick up the right sub-string from a string? The hint is to think at the strings as they are: an array of chars. So, if you have the string Hello world you can logically think of it as:
[H][e][l][l][o][ ][w][o][r][l][d]
[0]...............[6]......[9][10]
If you choose to extract only the string world you can thus call the substring method giving the right "array" indexes (remember the endIndex is exclusive!):
String s = "Hello world";
s.substring(6,11);
In the code snippet you provided, you give a special endIndex:
Math.min(s.length(), n);
That is exactly up to the n th char index taking into account the length of the string (to avoid out of bound conditions).
What we did at the very beginning of this answer was just calling the method and providing it with the beginning index of the substring, taking into account the possible overflow condition if you choose a wrong index.
Please note that any String Object instance can take advantage of this method, take a look at this example, for instance:
System.out.println("abc");
String cde = "cde";
System.out.println("abc" + cde);
String c = "abc".substring(2,3);
String d = cde.substring(1, 2);
As you see even "abc", of course, has the substring method!
Have a look at the substring documentation, Basically what it does is, it returns a substring of the string on which it is called, where substring from the index specified by the first parameter and the ends at the second parameter.
So, to get the last few characters, modify the begin index and the end index to the values you need. There is also another version of this method which takes only one parameter, just the begin index, which might be useful for you.
String lastNchars = s.substring(s.length()-n);
One of the String.substring() overloads takes one parameter - the index of the starting index. From that, you can easily implement your function :
String lastFew(String s, int number) {
if (number > s.length()) {
throw new IllegalArgumentException("The string is too short!");
} else return s.substring(s.length()-number);
}
I'm new to Java. I thought I would write a program to count the occurrences of a character or a sequence of characters in a sentence. I wrote the following code. But I then saw there are some ready-made options available in Apache Commons.
Anyway, can you look at my code and say if there is any rookie mistake? I tested it for a couple of cases and it worked fine. I can think of one case where if the input is a big text file instead of a small sentence/paragraph, the split() function may end up being problematic since it has to handle a large variable. However this is my guess and would love to have your opinions.
private static void countCharInString() {
//Get the sentence and the search keyword
System.out.println("Enter a sentence\n");
Scanner in = new Scanner(System.in);
String inputSentence = in.nextLine();
System.out.println("\nEnter the character to search for\n");
String checkChar = in.nextLine();
in.close();
//Count the number of occurrences
String[] splitSentence = inputSentence.split(checkChar);
int countChar = splitSentence.length - 1;
System.out.println("\nThe character/sequence of characters '" + checkChar + "' appear(s) '" + countChar + "' time(s).");
}
Thank you :)
Because of edge cases, split() is the wrong approach.
Instead, use replaceAll() to remove all other characters then use the length() of what's left to calculate the count:
int count = input.replaceAll(".*?(" + check + "|$)", "$1").length() / check.length();
FYI, the regex created (for example when check = 'xyz'), looks like ".*?(xyz|$)", which means "everything up to and including 'xyz' or end of input", and is replaced by the captured text (either `'xyz' or nothing if it's end of input). This leaves just a string of 0-n copies the check string. Then dividing by the length of check gives you the total.
To protect against the check being null or zero-length (causing a divide-by-zero error), code defensively like this:
int count = check == null || check.isEmpty() ? 0 : input.replaceAll(".*?(" + check + "|$)", "$1").length() / check.length();
A flaw that I can immediately think of is that if your inputSentence only consists of a single occurrence of checkChar. In this case split() will return an empty array and your count will be -1 instead of 1.
An example interaction:
Enter a sentence
onlyme
Enter the character to search for
onlyme
The character/sequence of characters 'onlyme' appear(s) '-1' time(s).
A better way would be to use the .indexOf() method of String to count the occurrences like this:
while ((i = inputSentence.indexOf(checkChar, i)) != -1) {
count++;
i = i + checkChar.length();
}
split is the wrong approach for a number of reasons:
String.split takes a regular expression
Regular expressions have characters with special meanings, so you cannot use it for all characters (without escaping them). This requires an escaping function.
Performance String.split is optimized for single characters. If this were not the case, you would be creating and compiling a regular expression every time. Still, String.split creates one object for the String[] and one object for each String in it, every time that you call it. And you have no use for these objects; all you want to know is the count. Although a future all-knowing HotSpot compiler might be able to optimize that away, the current one does not - it is roughly 10 times as slow as simply counting characters as below.
It will not count correctly if you have repeating instances of your checkChar
A better approach is much simpler: just go and count the characters in the string that match your checkChar. If you think about the steps you need to take count characters, that's what you'd end up with by yourself:
public static int occurrences(String str, char checkChar) {
int count = 0;
for (int i = 0, l = str.length(); i < l; i++) {
if (str.charAt(i) == checkChar)
count++;
}
return count;
}
If you want to count the occurrence of multiple characters, it becomes slightly tricker to write with some efficiency because you don't want to create a new substring every time.
public static int occurrences(String str, String checkChars) {
int count = 0;
int offset = 0;
while ((offset = str.indexOf(checkChars, offset)) != -1) {
offset += checkChars.length();
count++;
}
return count;
}
That's still 10-12 times as fast to match a two-character string than String.split()
Warning: Performance timings are ballpark figures that depends on many circumstances. Since the difference is an order of magnitude, it's safe to say that String.split is slower in general. (Tests performed on jdk 1.8.0-b28 64-bit, using 10 million iterations, verified that results were stable and the same with and without -Xcomp, after performing tests 10 times in same JVM instances.)
Can anyone let me know why this wordsearch method doesn't work - the returned value of count is 0 everytime I run it.
public int wordcount(){
String spaceString = " ";
int count = 0;
for(int i = 0; i < this.getString().length(); i++){
if (this.getString().substring(i).equals(spaceString)){
count++;
}
}
return count;
}
The value of getString = my search string.
Much appreciated if anyone can help - I'm sure I'm prob doing something dumb.
Dylan
Read the docs:
The substring begins with the character at the specified index and extends to the end of this string.
Your if condition is only true once, if the last character of the string is a space. Perhaps you wanted charAt? (And even this won't properly handle double spaces; splitting on whitespace might be a better option.)
Because substring with only one argument returns the sub string starting from that index till the end of the string. So you're not comparing just one character.
Instead of substring define spaceString as a char, and use charAt(i)
this.getString().substring(i) -> this returns a sub string from the index i to the end of the String
So for example if your string was Test the above would return Test, est, st and finally t
For what you're trying to do there are alternative methods, but you could simple replace
this.getString().substring(i)
with
spaceString.equals(this.getString().charAt(i))
An alternative way of doing what you're trying to do is:
this.getString().split(spaceString)
This would return an array of Strings - the original string broken up by spaces.
Read the documentation of the method you are using:
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int)
I.e. the count will be non zero only if you have a space on the end of your string
Using substring as you are will not work. If the value of getString() is "my search string" every iteration through the loop with have substring(i) return:
my search string
y search string
search string
search string
earch string
arch string
rch string
ch string
h string
string
string
tring
ring
ing
ng
g
Notice none of those equals " ".
Try using split.
public int countWords(String s){
return s.split("\\s+").length;
}
Change
if (this.getString().substring(i).equals(spaceString))
to
if (this.getString().charAt(i) == ' ')
this.getString().substring(i) returns a string from the index of (i) to the end of the string.
Example: for i=5, it will return "rown cow" from the string "the brown cow". This functionality isn't what you need.
If you pepper System.out.println() throughout your code (or use the debugger), you will see this.
I think it would be better to use something like String.split() or charAt(i).
By the way, even if you fix your code by counting spaces, it will not return the correct value for these conditions: "my dog" (word count=2) and "cow" (word count=1). There is also a problem if there are more than one space between words. ALso, this will produce a word cound of three:
" the cow ".
Alright so here is my problem. Basically I have a string with 4 words in it, with each word seperated by a #. What I need to do is use the substring method to extract each word and print it out. I am having trouble figuring out the parameters for it though. I can always get the first one right, but the following ones generally have problems.
Here is the first piece of the code:
word = format.substring( 0 , format.indexOf('#') );
Now from what I understand this basically means start at the beginning of the string, and end right before the #. So using the same logic, I tried to extract the second word like so:
wordTwo = format.substring ( wordlength + 1 , format.indexOf('#') );
//The plus one so I don't start at the #.
But with this I continually get errors saying it doesn't exist. I figured that the compiler was trying to read the first # before the second word, so I rewrote it like so:
wordTwo = format.substring (wordlength + 1, 1 + wordLength + format.indexOf('#') );
And with this it just completely screws it up, either not printing the second word or not stopping in the right place. If I could get any help on the formatting of this, it would be greatly appreciated. Since this is for a class, I am limited to using very basic methods such as indexOf, length, substring etc. so if you could refrain from using anything to complex that would be amazing!
If you have to use substring then you need to use the variant of indexOf that takes a start. This means you can start look for the second # by starting the search after the first one. I.e.
wordTwo = format.substring ( wordlength + 1 , format.indexOf('#', wordlength + 1 ) );
There are however much better ways of splitting a string on a delimiter like this. You can use a StringTokenizer. This is designed for splitting strings like this. Basically:
StringTokenizer tok = new StringTokenizer(format, "#");
String word = tok.nextToken();
String word2 = tok.nextToken();
String word3 = tok.nextToken();
Or you can use the String.split method which is designed for splitting strings. e.g.
String[] parts = String.split("#");
String word = parts[0];
String word2 = parts[1];
String word3 = parts[2];
You can go with split() for this kind of formatting strings.
For instance if you have string like,
String text = "Word1#Word2#Word3#Word4";
You can use delimiter as,
String delimiter = "#";
Then create an string array like,
String[] temp;
For splitting string,
temp = text.split(delimiter);
You can get words like this,
temp[0] = "Word1";
temp[1] = "Word2";
temp[2] = "Word3";
temp[3] = "Word4";
Use split() method to do this with "#" as the delimiter
String s = "hi#vivek#is#good";
String temp = new String();
String[] arr = s.split("#");
for(String x : arr){
temp = temp + x;
}
Or if you want to exact each word... you have it already in arr
arr[0] ---> First Word
arr[1] ---> Second Word
arr[2] ---> Third Word
I suggest that you've a look at the Javadoc for String before you proceed further.
Since this is your homework, I'll give you a couple of hints and maybe you can solve it yourself:
The format for subString is public void subString(int beginIndex, int endIndex). As per the javadoc for this method:
Returns a new string that is a substring of this string. The substring
begins at the specified beginIndex and extends to the character at
index endIndex - 1. Thus the length of the substring is
endIndex-beginIndex.
Note that if you've to use this method, understand that you'll have to shift your beginIndex and endIndex each time because in your situation, you'll have multiple words that are separated by #.
However if you look closely, there's another method in String class that might be helpful to you. That's the public String[] split(String regex) method. The javadoc for this one states:
Splits this string around matches of the given regular expression.
This method works as if by invoking the two-argument split method with
the given expression and a limit argument of zero. Trailing empty
strings are therefore not included in the resulting array.
The split() method looks pretty interesting for your case. You can split your String with the delimiter that you have as the parameter to this method, get the String array and work with that.
Hope this helps you to understand your problem and get started towards a solution :)
Since this is a home work, it may be better to have try to write it your self. But I will give a clue.
Clue:
The indexOf method has another overload: int indexOf(int chr,
int fromIndex) which find the first character chr in the string
from the fromIndex.
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html
From this clue, the program will look something like this:
Find the index of the first '#' from the start of the string.
Extract the word from 0th character to that index.
Find the index of the first '#' from the character AFTER the first '#'.
Extract the word from the first '#' that index.
... Just do it until you get 4 words or the string ends.
Hope this helps.
I don't know why you're forced to use String#substring, but as others have mentioned, it seems like the wrong method for the kind of functionality you need.
String#split(String regex) is what you would use for such a problem, or, if your input sequence is something you don't control, I would suggest you look at the overloaded method String#split(String regex, int limit); this way you can impose a limit on the amount of matches you make, controlling your resulting array.