Counting unique characters in a string - java

So i have been trying to make a code that counts the number of words in a string which was pretty easy. I'm running into problems when im trying to make it count the number of unique characters in a string. The program compiles and runs it doesn't display the number of Unique characters. Adding a System.out.println(countOfUniqueChars); below return doesn't work.
Here's the code:
public class Uniquechar{
public static void main(String[] args) {
String s = "Jag vet inte vad jag heter idag";
String[] parts = s.split(" ");
int wordcount = parts.length;
System.out.println("The number of words is" + wordcount);
countUniqueCharacters(s);
}
public static int countUniqueCharacters(String s) {
String lowerCase = s.toLowerCase();
char characters[] = lowerCase.toCharArray();
int countOfUniqueChars = s.length();
for (int i = 0; i < characters.length; i++) {
if (i != lowerCase.indexOf(characters[i])) {
countOfUniqueChars--;
}
}
return countOfUniqueChars;
}

Try this:
s = s.replace(" ", ""); // If you don't want to count space
char[] chars = s.toCharArray();
Set<Character> uniqueChars = new HashSet<>();
for (char c : chars) {
uniqueChars.add(c);
}
System.out.println(c.size());

Just print the method call, it prints the result.
System.out.println(countUniqueCharacters(s));
Adding a System.out.println(countOfUniqueChars); below return doesn't work.
It won't work. Because the code after return statement is unreachable. Perhaps you can do it just before return.
System.out.println(countOfUniqueChars);
return countOfUniqueChars;

You can do System.out.println(countUniqueCharacters(s)); in the main method, to output the return value of your method. After a return, you cannot add more code. I did it for you and the output is 12, so it seems to be that there is also something wrong with your algorithm.
int uniqeCharsCount = countUniqueCharacters(s);
System.out.println("The number of uniqe chars is " + uniqeCharsCount);
Output: 12
Your algorithm:
Actually you are checking every char, if this char is one more time in the string before. But you should also check if the char is anywhere in the string after the current index. You can fix it if you change your if condition to if (i != lowerCase.indexOf(characters[i]) || i != lowerCase.lastIndexOf(characters[i]))
Output of the fixed version: 3 (n, h, r)

I would recommend using a Set to retain only uniques, then count its size, instead of iterating:
public static int countUniqueCharacters(String s) {
String lowerCase = s.toLowerCase();
char characters[] = lowerCase.toCharArray();
Set<Character> uniques = new HashSet<Character>();
for (char c: characters) {
uniques.add(c);
}
return uniques.size();
}

if (i != lowerCase.indexOf(characters[i])) {
countOfUniqueChars--;
}
This is wrong. Your lowerCase string is lowercase, so any uppercase letters in characters[i] will have an index of -1 in lowerCase (will be calculated as a non-unique character). You can fix this by using indexOf(lowerCase.charAt(i));

A good way to count the number of characters would be eliminating repetitions. The ideia is get the first character, then find next occurrences and replace by nothing, once you do that you can count the unique characters.
public static int countUniqueCharacters(String s) {
String lowerCase = s.toLowerCase();
///Get the first char of lowerCase
String firstChar = lowerCase.substring(0,1);
//Take off the first char
String subS = lowerCase.substring(1);
///replace all chars equals to first char
String replacedSubS = subS.replace(firstChar, "");
/// Now, call method again to calculate size
/// of the substring with first char
// replaced by blank char
return 1+countUniqueCharacters(replacedSubS);
}
This method worked for me, take a look. You may do that in two lines, but i thought it's better be detailed here.

Adding a System.out.println(countOfUniqueChars); below return doesn't work.
That is expected behavior because return means that flow of control will be returned from method to place where this method was invoked. This means that code after return will not be executed, so in situation like
return countOfUniqueChars;
System.out.println(countOfUniqueChars);
System.out.println(countOfUniqueChars); would be dead code.
You could try printing value before you return it like
System.out.println(countOfUniqueChars);
return countOfUniqueChars;
or simply print returned value in main method like
int count = countUniqueCharacters(s);
System.out.println(count);
or using this one-liner
System.out.println(countUniqueCharacters(s));
BTW since Java 8 your code can look like
s.toLowerCase().chars().distinct().summaryStatistics().getCount()
or if you want to skip spaces you can add
s.toLowerCase().replace(" ","").chars().distinct().summaryStatistics().getCount()

public static int countUniqueCharacters(String s) {
char [] input=s.toCharArray();
Set<Character> charset=new HashSet<>();
for (int i = 0; i < input.length; i++) {
charset.add(input[i]);
}
return charset.size();
}

Related

What is the best way to replace a letter with the letter following it in the alphabet in Java?

I'm a programming newbie and I am doing a coderbyte exercise that says "
Replace every letter in the string with the letter following it in the alphabet (ie. c becomes d, z becomes a)"
i'm thinking of the following methods:
declare a string called "abcdefghijklmnopqrstuvxyz" and compare each string's char index position with the alphabet's index position, and then just bring the alphabet char that is located at the i+1 index location. But I don't know how it would work from z to a.
I've seen some techniques using ASCII values for every char but I've never done that before and not sure how it works
convert the given string into a char[] array, but then I'm not sure how I would tell the system to get me the next alphabet char
What would be the easiest way to do this?
EDIT
this is my code so far, but it doesn't work.
import java.util.*;
import java.io.*;
class Main {
public static String LetterChanges(String str) {
// code goes here
String alphabet = "abcdefghijklmnopqrstuvwxyz";
String newWord = "";
for (int i = 0; i < str.length(); i++){
for (int j = 0; j < alphabet.length(); i++){
if (str[i] == alphabet[i]){
if (alphabet[i+1].isVowel()){
newWord = newWord + toUpperCase(alphabet[i+1]);
}
else{
newWord = newWord + alphabet[i+1];
}
}
}
}
return str;
}
public static void main (String[] args) {
// keep this function call here
Scanner s = new Scanner(System.in);
System.out.print(LetterChanges(s.nextLine()));
}
}
Can't I ask for the index position of a Char that is a part of a String? in C I could do that.
Other than that not sure why it doesn't work.
I would definitely go with method 1.
I believe what you're looking for is the indexOf method on a String.
First of, I would create a method that given a character finds the next letter in the alphabet and return that. This could be done by finding the letter in your alphabet string and then fetch the letter at index+1. As you also pointed out you would need to take care of the edge case to turn 'z' into 'a', could by done with an if-statement or by having an extra letter 'a' at the end of your alphabet string.
Now all that remains to do is create a loop that runs over all characters in the message and calls the previously made method on that character and constuct a new string with the output.
Hope this helps you figure out a solution.
Assuming that there would be only lower case English letters in the given String the most performant way would be to add +1 to every character, and use either if-statement checking whethe the initial character was z or use the modulo operator % as #sp00m has pointed out in the comment.
Performing a search in the alphabetic string (option 1 in your list) is redundant, as well extracting array char[] from the given string (option 3).
Checking the edge case:
public static String shiftLetters(String str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char next = str.charAt(i);
if (next == 'z') result.append('a'); // checking the edge case
else result.append((char) (next + 1));
}
return result.toString();
}
Applying modulo operator:
public static String shiftLetters(String str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char next = (char) ((str.charAt(i) - 'a' + 1) % 26 + 'a');
result.append(next);
}
return result.toString();
}
main()
public static void main(String[] args) {
System.out.println(shiftLetters("abc"));
System.out.println(shiftLetters("wxyz"));
}
Output:
bcd // "abc"
xyza // "wxyz"

Counting the number of specific occurrences in a java String

I am attempting to solve a problem where I create a method that counts the number of occurrences of capital and lowercase ("A" or "a") in a certain string. I have been working on this problem for a week now, and the main error that I am receiving is that "char cannot be dereferenced". Can anyone point me in the correct direction on this Java problem? Thank you.
class Main{
public static int countA (String s)
{
String s1 = "a";
String s2 = "A";
int count = 0;
for (int i = 0; i < s.length; i++){
String s3 = s.charAt(i);
if (s3.equals(s1) || s3.equals(s2)){
count += 1;
}
else{
System.out.print("");
}
}
}
//test case below (dont change):
public static void main(String[] args){
System.out.println(countA("aaA")); //3
System.out.println(countA("aaBBdf8k3AAadnklA")); //6
}
}
try a simpler solution
String in = "aaBBdf8k3AAadnklA";
String out = in.replace ("A", "").replace ("a", "");
int lenDiff = in.length () - out.length ();
Also as #chris mentions in his answer, the String could be converted to lowercase first and then only do a single check
the main error that I am receiving is that "char cannot be
dereferenced"
change this:
s.length // this syntax is incorrect
to this:
s.length() // this is how you invoke the length method on a string
also, change this:
String s3 = s.charAt(i); // you cannot assign a char type to string type
to this:
String s3 = Character.toString(s.charAt(i)); // convert the char to string
another solution to accomplishing your task in a simpler manner is by using the Stream#filter method. Then convert each String within the Stream to lowercase prior to comparison, if any Strings match "a" we keep it, if not we ignore it and at the end, we simply return the count.
public static int countA(String input)
{
return (int)Arrays.stream(input.split("")).filter(s -> s.toLowerCase().equals("a")).count();
}
For counting the number of time 'a' or 'A' appears in a String:
public int numberOfA(String s) {
s = s.toLowerCase();
int sum = 0;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == 'a')
sum++;
}
return sum;
}
Or just replace everything else and see how long your string is:
int numberOfA = string.replaceAll("[^aA]", "").length();
To find the number of times character a and A appear in string.
int numA = string.replaceAll("[^aA]","").length();

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 insert a space in a charArray in an exact position [Java]

My problem is that I'm getting a String and I need to check if there is a space in the 4th position but starting from the end. If in this position there is not a space, I should insert it.
For example:
I get this String: TW12EF, need to get it like this: TW1 2EF
First of all I get the 4 last characters in a char array because I also need to check if they are numbers or letters.
With this method I check if there is a space:
public static boolean isSpace(){
return String.valueOf(charArray[0]).matches("[ \\t\\n\\x0B\\f\\r]");
}
charArray contains the last 4 characters of the input String
If charArray[0] wouldn't be a space, I want to insert a space in the 2nd place (charArray[1])
If there is something that I can correct in the question to make it easier to understand, just let me know and I will try to make it better for next questions.
A simple and direct solution (most likely faster than using a regular expression) is to get the 4th to the last character (if it exists), and if it isn't a white-space, insert a space at that position.
public static void main(String[] args) {
String str = "TW12EF";
int insertPos = str.length() - 4;
if (insertPos >= 0) {
char ch = str.charAt(insertPos);
if (!Character.isWhitespace(ch)) {
str = new StringBuilder(str).insert(insertPos + 1, ' ').toString();
}
}
System.out.println(str);
}
A whitespace is determined by invoking isWhitespace, which returns true for space but also tabs or line feeds, like you did in your question. The character is inserted by leveraging the StringBuilder#insert method, which is more direct that taking 2 substrings and concatenating them.
A quick, dirty regex will help :
String p = "TW12EF";
System.out.println(p.replaceAll("(.)\\s*(\\S.{2})$", "$1 $2")); // Select a character followed by 0 or more spaces and followed by 3 non-space characters. And replace multiple spaces if they exist with a single space
O/P :
TW1 2EF
Also works if there are one or more spaces after the 3rd char (from the left)
As char is a primitive data type, the comparison can be done simply with
if (charArray[0] == ' ') {
char[] temp = new char[5];
temp[0] = ' ';
for (int i = 1; i <= 4; i++) {
temp[i] = charArray[i - 1];
}
charArray = temp;
}
You could use something like:
public static void main(String[] args) {
String str = "TW12EF";
processStr(str);
}
public static final int SPACE_POS = 4, OFFSET = 1;
public static String processStr(String str)
{
if(!Character.isWhitespace(str.charAt(str.length() - SPACE_POS)))
{
str = String.format("%s %s", str.substring(0, str.length() - SPACE_POS + OFFSET), str.substring(SPACE_POS - OFFSET));
}
return str;
}
Like this?
` String s="TW12EF";
String result="";
int length=s.length();
for(int i=length-1;i>-1;i--){
if(i==length-4&&s.charAt(i)!=' '){
result+=" ";
}
result+=s.charAt(length-i-1);
}
System.out.println(result);`

Return word specified by the integer

I know I'm missing some things and that's what I really need help with. The code doesn't work in all cases and am looking for help improving/fixing it.
Assignment:
The code I have so far:
public String word(int num, String words)
{
int l = words.indexOf(" ");
int r = words.indexOf(" ", l+1);
for(int i = 3; i <= num; i++){
l = r;
r = words.indexOf(" ", l+1);
//if(i != num)
// l = r;
}
String theword = words.substring(l,r);
return theword;
}
}
As this is clearly homework, I will give you text only.
Your approach may work eventually, but it is laborious and overly complicated, so it's hard to debug and hard to get right.
make use of String's API by using the split() method
after splitting the sentence into an array of word Strings, return the element at num less one (array are indexed starting at zero
check the length of the array first, in case there are less words than num, and take whatever action you think is appropriate in that case
For part 2, a solution in a simple form may be:
create a new blank string for the result
iterate over the characters of the given string adding the character to the front of the result string
make use of String's toUpperCase() method
Since this is homework and you have showed some effort. This is how you can do part 1 of your question. This code is pretty evident.
1) I am returning null if number is greater than the number of words in string as we dont want user to enter 5 when there are only 2 words in a string
2) Splitting the string by space and basically returning the array with the number mentioned by user
There are more conditions which you must figure out such as telling the user to enter a number of the string length since it would not give him any result and taking input from Scanner instead of directy adding input in method.
public static String word(int num, String words)
{
String wordsArr[] = words.split(" ");
if(num <= 0 || num > wordsArr.length) return null;
return (wordsArr[num-1]);
}
the second part of your question must be attempted by you.
Well... not often you see people coming here with homework AND showing effort at the same time so bravo :).
This is example of how you can split the string and return the [x] element from that string
public class SO {
public static void main(String[] args) throws Exception {
int number = 3;
String word = "Hello this is sample code";
SO words = new SO();
words.returnWord(number, word);
}
private void returnWord(int number, String word) throws Exception {
String[] words = word.split("\\s+");
int numberOfWords = words.length;
if(numberOfWords >= number) {
System.out.println(words[number-1]);
} else {
throw new Exception("Not enought words!!!");
}
}
}
Yes it is a working example but do not just copy and paste that for your homework - as simple question from teacher - What is this doing, or how this works and your out :)! So understand the code, and try to modify it in a way that you are familiar what is doing what. Also its worth getting some Java book - and i recommend Head first Java by O'Really <- v.good beginner book!
if you have any questions please do ask!. Note that this answer is not 100% with what the textbook is asking for, so you can modify this code accordingly.
As of part 2. Well what Bohemian said will also do, but there is a lot quicker solution to this.
Look at StringBuilder(); there is a method on it that will be of your interest.
To convert String so all letter are upper case you can use .toUpperCase() method on this reversed string :)
You can try:
public class trial {
public static void main(String[] args)
{
System.out.println(specificword(0, "yours faithfully kyobe"));
System.out.println(reverseString("derrick"));}
public static String specificword(int number, String word){
//split by space
String [] parts = word.split("\\ ");
if(number <= parts.length){
return parts[number];
}
else{
return "null String";
}
}
public static String reverseString(String n){
String c ="";
for(int i = n.length()-1; i>=0; i--){
char m = n.charAt(i);
c = c + m;
}
String m = c.toUpperCase();
return m;
}
}
For the first problem, I'll give you two approaches (1. is recommended):
Use the String.split method to split the words up into an array of words, where each element is a word. Instead of one string containing all of the words, such as "hello my name is Michael", it will create an array of the words, like so [hello, my, name, is, Michael] and that way you can use the array to access the words. Very easy:
public static String word(int num, String words)
{
// split words string into array by the spaces
String[] wordArray = words.split(" "); // or = words.split("\\s+");
// if the number is within the range
if (num > 0 && num <= wordArray.length) {
return wordArray[num - 1]; // return the word from the word array
} else { // the number is not within the range of words
return null;
}
}
Only use this if you cannot use arrays! Loop through the word until you have found enough spaces to match the word you want to find:
public static String word(int num, String words)
{
for (int i = 0; i < words.length(); i++) { // every character in words
if (words.substring(i, i+1).equals(" ")) { // if word is a space
num = num - 1; // you've found the next word, so subtract 1 (number of words left is remaining)
}
if (num == 1) { // found all words
// return this word
int lastIndex = i+1;
while (lastIndex < words.length()) { // until end of words string
if (words.substring(lastIndex, lastIndex+1).equals(" ")) {
break;
}
lastIndex = lastIndex + 1; // not a space so keep moving along the word
}
/*
// or you could use this to find the last index:
int lastIndex = words.indexOf(" ", i + 1); // next space after i+1
if (lastIndex == -1) { // couldn't find another space
lastIndex = words.length(); // so just make it the last letter in words
}*/
if (words.substring(i, i+1).equals(" ")) { // not the first word
return words.substring(i+1, lastIndex);
} else {
return words.substring(i, lastIndex);
}
}
}
return null; // didn't find word
}
As for the second problem, just iterate backwards through the string and add each letter to a new string. You add each letter from the original string to a new string, but just back to front. And you can use String.toUpperCase() to convert the string to upper case. Something like this:
public static String reverse(String str) {
String reversedString = ""; // this will be the reversed string
// for every character started at the END of the string
for (int i = str.length() - 1; i > -1; i--) {
// add it to the reverse string
reversedString += str.substring(i, i+1);
}
return reversedString.toUpperCase(); // return it in upper case
}

Categories

Resources