Error to find the first no repeated char in Java - java

I have a strange issue to print the first non repeated character from String.
If I put for example "sasso" as String it gives me back correctly: 'a'
but if I try with "sassa" I wonder why it gives me back: "s"
public class FirstChar {
public char findFirst(String s) {
boolean[] letters = new boolean[26];
char[] firstLetter = new char[26];
for (int i = 0; i < s.length(); i++) {
if (letters[s.charAt(i) - 97] &&
(firstLetter[0] != (s.charAt(i)))) {
System.out.println( firstLetter[0]);
return firstLetter[0];
}
letters[s.charAt(i) - 97] = true;
char c = (char) (s.charAt(i));
firstLetter[i] = c;
}
System.out.println(firstLetter[1]);
return firstLetter[1];
}
public static void main(String args[]) {
FirstChar obj = new FirstChar();
obj.findFirst("sassa");
}
}

You need to ensure that firstLetter acts as a queue of non repeating characters and remove from it, the moment repeated character is encountered. You are always returning character at 0th or 1st position without overwriting firstLetter array elements.
In case is sassa, when last character a is encountered, conditions in first if evaluate to true and thus return s which is the first character stored in the firstLetter array.
You need HashMap and Queue to achieve this

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"

First non-repeating character in a stream of characters

The question asks us to find new string B.
B is formed such that we have to find first non-repeating character each time a character is inserted to the stream and append it at the end to B. If no non-repeating character is found then append '#' at the end of B.
Example:
"a" - first non repeating character 'a'
"ab" - first non repeating character 'a'
"aba" - first non repeating character 'b'
"abad" - first non repeating character 'b'
"abadb" - first non repeating character 'd'
"abadbc" - first non repeating character 'd'
Can someone help me out where my code went wrong. my logic is to use substring function of string and find the unique character and add it to arraylist and print the entire arraylist.
public class Solution
{
public String solve(String A)
{
ArrayList<Character>a=new ArrayList<Character>();
String res="";
for(int i=0;i<A.length();i++)
{
String ss=A.substring(0,i+1);
String ue=uniqueCharacters(ss);
// System.out.println(ue);
if(ue!="") a.add(ue.charAt(0));
else a.add('#');
}
for(Character j:a) res+=j;
return res;
}
public static String uniqueCharacters(String test)
{
String temp = "";
for (int i = 0; i < test.length(); i++)
{
char current = test.charAt(i);
if (temp.indexOf(current) < 0) temp = temp + current;
else temp = temp.replace(String.valueOf(current), "");
}
return temp;
}
}
It may be better to use a Set to detect unique characters in the input string using the result of Set::add which returns false if no element has been actually added to the set, and a Queue to maintain the non-repeated characters.
When a repeated (non-unique) character is detected, it gets removed from the queue and if necessary, "#" is applied as a placeholder. And if a unique character is detected, it is just added to the queue.
Example implementation:
public static String solve(String str) {
// verify the input
if (null == str || str.isEmpty()) {
return str;
}
Set<Character> previous = new LinkedHashSet<>();
Queue<Character> nonRepeated = new LinkedList<>();
StringBuilder sb = new StringBuilder();
// use the first character
char curr = str.charAt(0);
previous.add(curr);
nonRepeated.add(curr);
sb.append(curr);
for (int i = 1, n = str.length(); i < n; i++) {
char c = str.charAt(i);
if (!previous.add(c)) { // duplicate character found
nonRepeated.remove(c);
if (nonRepeated.isEmpty()) {
curr = '#';
} else { // get the next non-repeated character
curr = nonRepeated.peek();
}
} else { // unique element is detected
if (curr == '#') {
curr = c;
}
nonRepeated.add(c);
}
sb.append(curr);
}
return sb.toString();
}
Tests:
for (String t : Arrays.asList("abadbc", "abcdba", "aaabbbacab")) {
System.out.printf("input: %s --> %s%n----%n", t, solve(t));
}
Output:
input: abadbc --> aabbdd
----
input: abcdba --> aaaaac
----
input: aaabbbacab --> a##b###ccc
----
When you encounter a char a 2nd time you remove it from the unique characters (1), but if there was a 3rd of that character it would be added again (2).
public static String uniqueCharacters(String test)
{
String temp = "";
for (int i = 0; i < test.length(); i++)
{
char current = test.charAt(i);
if (temp.indexOf(current) < 0) temp = temp + current; <---- (2)
else temp = temp.replace(String.valueOf(current), ""); <----- (1)
}
return temp;
}
Solution count the number of chars and then return only those whose count is 1 (one).

Comparing characters in 2 char Array using Java

I am a beginner in Java and I will like to know if there's a way to compare characters in a char Array with other characters in another char Array in order to see if they have characters that match. Not to see if they contain exactly the same characters in the same sequence as most examples explain.
For instance:
char [] word1= {'a','c','f','b','e'};
char[] word2= {'a','b','c','d','e','h','j','f','i','m'};
and using maybe if statements to say that word1 contains the characters in word2 so it is correct. Else it is incorrect if word2 is missing at least one character that word1 has.
Try this. It will report if either array contains all the characters of the other. I used strings and converted them to arrays to facilitate the coding.
String[][] testData =
{ {"axyzx","xxyzaa"},
{"aaxyz","aaax"},
{"axa","a"},
{"arrs","asrrrs"},
{"acfbe","abcdehjfim"}};
for (String[] words : testData) {
boolean result = contains(words[0].toCharArray(), words[1].toCharArray());
String output = String.format("%s contains all %s","'"+words[0]+"'","'"+words[1]+"'");
System.out.printf("%34s - %b%n", output, result);
output = String.format("%s contains all %s","'"+words[1]+"'","'"+words[0]+"'");
result = contains(words[1].toCharArray(), words[0].toCharArray());
System.out.printf("%34s - %b%n%n", output, result);
}
Prints
'axyzx' contains all 'xxyzaa' - false
'xxyzaa' contains all 'axyzx' - true
'aaxyz' contains all 'aaax' - false
'aaax' contains all 'aaxyz' - false
'axa' contains all 'a' - true
'a' contains all 'axa' - false
'arrs' contains all 'asrrrs' - false
'asrrrs' contains all 'arrs' - true
'acfbe' contains all 'abcdehjfim' - false
'abcdehjfim' contains all 'acfbe' - true
Using a map, do a frequency count of the characters in the second array.
Now iterate thru the map using the first array, decrementing the character count when the character is found. When the count reaches 0, assign null to the value.
if map is now "empty", the first array contains all characters of second array.
// see if first array contains all of second array,
// regardless of order of the characters
public static boolean contains(char[] ch1, char[] ch2) {
// a smaller array cannot possible contain the same
// characters as a larger array
if (ch1.length < ch2.length) {
return false;
}
Map<Character,Integer> map = new HashMap<>();
// Do a frequency count
for(char c : ch2) {
map.compute(c, (k,v)->v == null ? 1 : v+1);
}
// now decrement count for each occurrence
// of character in first array, setting value to
// null when count reaches 0.
for(char c : ch1) {
map.computeIfPresent(c, (k,v)-> v <= 1 ? null : v-1);
}
return map.isEmpty();
}
I created a little snippet and think it is what you are looking for:
public class Main {
public static void main(String[] args) {
char[] word1= {'a','c','f','b','e'};
char[] word2= {'a','b','c','d','e','h','j','f','i','m'};
System.out.println(Contains(word1, word2));
}
private static boolean Contains(char[] arr1, char[] arr2) {
for (int i = 0; i < arr1.length; i++) {
boolean containsChar = false;
for (int j = 0; j < arr2.length; j++) {
if (arr1[i] == arr2[j]) containsChar = true;
}
if (!containsChar) return false; // arr2 does not contain arr1[i]
}
return true;
}
}

Counting unique characters in a string

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();
}

Need to use Scanner to read a file but don't know how to compare

I am trying to write a method that reads a text file using Scanner then compare them to see if they are characters ('a' - 'z') however binary operators can't be used (compilation error). Any ideas how to work around it?
I need to convert uppercase letters to lowercase, and I have a counter that keep track of how many times each letter appeared in the text file.
I also need to ignore any symbols and numbers in the text file.
After reading your comments, I changed my code into:
import java.util.Scanner;
public class LetterInventory {
int counter = 0;
private int[] inventory;
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
public LetterInventory () {
inventory = new int[26];
}
public void countOccurrences(Scanner file) {
while (file.hasNextLine()) {
// Read line by line and make it lowercase
String line = file.nextLine().toLowerCase();
// get all the character of the line
for (char c :line.toCharArray()) {
if (c >= 'a' && c <= 'z'){ // Check for character only
counter++;
}
}
}
}
public void displayTable () {
for (int i = 0; i < alphabet.length; i++) {
System.out.println(alphabet[i] + ": " + inventory[i]);
}
}
public void resetInventory () {
counter = 0;
}
I am still not really sure how to make this thing work.
This program is supposed to be able to read a text file, make a count each alphabet was read, ignore any symbol/number, and output a table with each letter followed by how many times they are in the text file.
As pointed out in the comments there are some problems with your code.
First: Every time you call file.next() it will try to read the next character. So what you do in your loop is: read all characters, convert to lower case but ignore this new value and carry on.
The compilation problem is due to the fact that you try to compare a string with a character.
What you want to do is something like this:
while(file.hasNext())
{
String currentTokes = file.next().toLowerCase(); //save the current token as lower text in the variable
//check each character of the string
for(char c : currentToken.toCharArray())
{
if(c <= ....) //check etc.
}
}
Another way would be to use regular expressions.
Instead of comparing file.next() to a char why not just use a regular expression?
For example:
if(file.next().matches("[a-z]")){
//do something
}
will return true if the next value picked up by the next method is a lower case character between a and z. This way you don't have to deal with unnecessary logic or worry about whether you are comparing a String to a char.
note:
I am not sure what your input is however and the above regex will only match if it is a single lower case letter not if it is a word. That said if you are reading in words you will need to split them into a character array before using the above solution.
For an example, you could try something like this:
while (file.hasNext()) {
// grabs next word/string from file
String str = file.next().toLowerCase();
// converts that string to a character array
char[] charArray = str.toCharArray();
for (char chars : charArray) {
// converts current character into a string and checks whether
// it
// is a lower case letter
if (String.valueOf(chars).matches("[a-z]")) {
// do something
}
}
}
this will work
public void countOccurrences(Scanner file) {
int[] alpha = new int[25];
while (file.hasNext()) {
char[] stringTokens = file.next().toLowerCase().toCharArray();
for (char c : stringTokens) {
if (c - 'a' > -1 || c - 'a' < 26) {
alpha[c - 'a']++;
}
}
}
}
Read inline comments for more info.
while (file.hasNextLine()) {
// Read line by line and make it lowercase
String line = file.nextLine().toLowerCase();
// get all the character of the line
for (char c : line.toCharArray()) {
if (c >= 'a' && c <= 'z'){ // check for character only
inventory[c - 'a']++; // Increment the occurrence of the Character
}
}
}

Categories

Resources