How to count the number of letters that exist without repeated - java

I want a way to count the letters in an string for example:
My string : "Hello my friends "
The characters in the string : {H,e,l,o, ,m,y,f,r,i,n,d,s}
These letters exist without repeating them (with a blank space)
So the result I want is: 13
The goal of all of this is, I want to convert a string to a table of character without repeating the letters
EX: MY String = "Hello"
The table I want to get {H,e,l,o}
My attempt
public static int numberRep(String txt) {
int count = 0;
boolean v = false;
for (int i = 0; i != txt.length(); i++) {
char c = txt.charAt(i);
for (int j = i + 1; j != txt.length(); j++) {
if (txt.charAt(j) == c) {
count++;
}
}
if(count == txt.length()-1){
v = true;
}
}
if(v){
return 1 ;
}
else{
return count;
}
}

Split the string into characters and store them into a Set. A Set keeps only unique elements. The elements of the Set will be the required characters and the size of the Set will give you the count of these characters.
Do it as follows:
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
public class Testing {
public static void main(String[] args) {
String myString = "Hello my friends ";
Set<String> set = Arrays.stream(myString.split("")).collect(Collectors.toCollection(LinkedHashSet::new));
System.out.println("Unique characters including space: " + set);
System.out.println("No. of unique characters including space: " + set.size());
}
}
Output:
Unique characters including space: [H, e, l, o, , m, y, f, r, i, n, d, s]
No. of unique characters including space: 13

What you could do is:
Create an empty list a
for character in list:
If the character is not your list a: add it to your list
This way you won't get any duplicate characters.
You can also use a set like recommended in Arvind's answer, but I think it is better for you to write a function as a task.
Set is the cleaner way to do it once you grasped the concepts of Java.

Well, this could be one of the approach to do so:
String str = "Hello my friends "
String noRepeatStr = "";
for(int i = 0; i < str.length; i++) {
if(noRepeatStr.indexOf(str[i]) == -1) // check if a char already exist, if not exist then return -1
noRepeatStr = noRepeatStr+str[i]; // add new char
}
System.out.println("Letters: " + noRepeatStr.toCharArray())
System.out.println("No of letters: " + noRepeatStr.length)

public static void main(String[] args) {
final String test = "Hello my friends";
final int size = IntStream.range(0, test.length())
.mapToObj(test::charAt)
.collect(Collectors.toSet()).size();
System.out.println(size);
}
What I've done here is iterated over all of the characters in the input string, mapped them to a char object and then collected them into a Set - instead of keeping the raw Set I've used .size() in order to get the output that you were expecting.

Related

Print number of possible non-empty sequences of letters

I want to print number of possible non-empty sequences of letters .
Eg.
String str="ABC";
Expected output is
A,B,C
AB,AC,BC,BA,CA,CB
ABC,ACB,BAC,BCA,CAB,CBA`
But i get the below output which is incorrect. How to fix my code
BB CC A AB ACC BC ABC AC B BBC CCC BCC C CBC CB
I have written the below code using Recurion
String tiles = "ABC";
Set<String> ans = new HashSet<>();
solve(tiles, 0, "", ans);
public static void solve(String tiles, int idx, String output, Set<String> ans) {
ans.add(output);
if (idx >= tiles.length()) {
return;
}
for (int i = idx; i < tiles.length(); i++) {
solve(tiles, idx + 1, output + tiles.charAt(i), ans);
}
}
This is how recursion tree would look like for str="AAB"
You need to ignore the first passing of the "" from output and then you need to ignore each letter you already passed through
public static void main(String[] args) {
String tiles = "ABC";
List<String> ans = new ArrayList<>();
solve(tiles, "", ans);
System.out.println(ans);
}
public static void solve(String tiles, String output, List<String> ans) {
if (!output.equals("")) ans.add(output);
for (int i = 0; i < tiles.length(); i++) {
String str = tiles.substring(0, i) + tiles.substring(i + 1);
solve(str, output + tiles.charAt(i), ans);
}
}
Output
[A, AB, ABC, AC, ACB, B, BA, BAC, BC, BCA, C, CA, CAB, CB, CBA]
you can try this
public class Permutation {
public static List<String> getPermutations(String str) {
Set<String> permutations = new HashSet<>();
permute(str, "", permutations);
return new ArrayList<>(permutations);
}
private static void permute(String string, String prefix, Set<String> permutations) {
if (string.length() == 0) {
permutations.add(prefix);
} else {
for (int i = 0; i < string.length(); i++) {
char charAt = string.charAt(i);
String remainingString = string.substring(0, i) + string.substring(i + 1);
permute(remainingString, prefix + charAt, permutations);
}
}
}
}
The "permute" method takes in 3 parameters: a string, a prefix string and a set of permutations.
The "permute" method takes in 3 parameters: a string, a prefix string and a set of permutations.
If the input string is not empty, it uses a for loop to iterate through the characters of the input string.
For each iteration, it gets the character at the current index, creates a new string by removing that character from the input string.
it then calls the permute method 3 times:
it then calls the permute method 3 times:
One with the original string and prefix
One with the remaining string and prefix
This way, the function explores all the possible permutations of the characters in the input string, including the option of not having one of the characters in the permutation and the permutation of positions, without including an empty string as an option.
Then you use like:
Permutation p = new Permutation();
List<String> permutations = p.getPermutations("abc");
Make 1 change:
Set<String> ans = new TreeSet<>(Comparators.comparing(String::length).thenComparing(s -> s));
It's a quite popular backtracking problem. You can find almost same problem here:
https://leetcode.com/problems/subsets/
The input are numbers instead of characters but the idea is the same.
You can switch to the solution tab and explore different answers:
https://leetcode.com/problems/subsets/solutions/

Find words in String consisting of all distinct characters without using Java Collection Framework

I need your help. I am stuck on one problem, solving it for several hours.
*1. Find word containing only of various characters. Return first word if there are a few of such words.
2. #param words Input array of words
3. #return First word that containing only of various characters*
**public String findWordConsistingOfVariousCharacters(String[] words) {
throw new UnsupportedOperationException("You need to implement this method");
}**
#Test
public void testFindWordConsistingOfVariousCharacters() {
String[] input = new String[] {"aaaaaaawe", "qwer", "128883", "4321"};
String expectedResult = "qwer";
StringProcessor stringProcessor = new StringProcessor();
String result = stringProcessor.findWordConsistingOfVariousCharacters(input);
assertThat(String.format("Wrong result of method findWordConsistingOfVariousCharacters (input is %s)", Arrays.toString(input)), result, is(expectedResult));
}
Thank you in advance
Just go through the data and check whether each string is made up of only distinct characters:
public static boolean repeat(String str) {
char[] chars = str.toCharArray();
Arrays.sort(chars);//The same character will only appear in groups
for(int i = 1;i<chars.length;i++) {
if(chars[i] == chars[i - 1]) {
return false;//Same character appeared twice
}
}
return true;//There is no repeating character
}
The method above is used to check whether a string is made up of distinct characters, now loops through the data:
for(int i = 0;i<input.length;i++){
if(repeat(input[i])){
System.out.println("The answer is " + input[i] + " at index " + i);
break;//you find it! Now break the loop
}
}
Assuming the strings are all ASCII characters, use a boolean[] to mark if you have encountered that character in the word already:
boolean [] encountered = new boolean[256];
for (char c : word.toCharArray()) {
if (encountered[(int)c]) {
// not unique
} else {
encountered[(int)c] = true;
}
}

Accessing index values before and after symbol from input

I am trying to take the input and if there is an # symbol in the input then it finds the maximum of the integers before and after the # symbol. The maximum part I have no problem with but I do not know how to access and find the values before and after the # symbol.
import java.util.Scanner;
public class Max_Min {
public static void main(String[] args) {
//gets keyboard
Scanner keyboard = new Scanner(System.in);
//puts input into string
String inputString = keyboard.nextLine();
//splits string between characters
String[] splitInput = inputString.split("");
for (String s : splitInput) {
if(s.equals("#")){
//computes the maximum of the two integers before and after the #
}
}
//close keyboard
keyboard.close();
I did do a search to find something simliar (and im sure there is something) but could not find anything. If someone could help that would be great!
Try with this:
for (int i = 0; i < splitInput.length; i++){
if (splitInput[i].equals("#") && i != 0 && i != splitInput.length -1){
int max = Math.max(Integer.parseInt(splitInput[i - 1]), Integer.parseInt(splitInput[i + 1]));
}
//...
}
You could try:
String[] splitInput = inputString.split("#");
which would split your string at the #s.
Then you can do a iteration over your splitInput array and do a .length on each index.
You have written the simple for loop, with which you can only access the string, but not its index in the array. If you had the index, you could write:
int possibleMax = Integer.parseInt(splitInput[i - 1]) + Integer.parseInt(splitInput[i + 1]);
To get the index, there are two ways:
for (int i = 0; i < splitInput.length; i++) {
String s = splitInput[i];
...
}
Or:
int i = 0;
for (String s : splitInput) {
…
i++;
}
I don't like either version because both are more complicated than absolutely necessary, in terms of written code. If you would use Kotlin instead of Java, it would be:
splitInput.forEachIndexed { i, s ->
…
}
In Java this could be written:
forEachIndexed(
splitInput,
(i, s) -> …
);
The problem in Java is that the code inside the … cannot update the variables of the enclosing method. I'm not sure whether this will ever change. It would be possible but needs a lot of work by the language committee.
A simple way to do this would be
String input = "12#23";
String [] arr = input.split("#");
if (arr.length == 2) {
System.out.println("Max is "+Math.max(Integer.valueOf(arr[0]),Integer.valueOf(arr[1])));
}

Binary search to find longest common prefix

For an school assignment, we are implementing suffixarray, with the methods of building it and finding the longest common prefix. I manage to build and sort the suffix array quite easily but struggle with the LCP.
I am trying to find the longest common prefix of a pattern string P in another string T, using one singular binary search. The algorithm should return the index of where the longest common prefix begins.
Examples:
If the pattern string P is "racad" and the string T is "abracadabra", the longest common prefix should be "racad", beginning at index 2.
Likewise, if the the pattern string is P "rax" then the longest common prefix should be "ra", beginning at index 2 or 9.
I´ve come quite far but the algorithm is not returning the right value. Here´s my code:
public int compareWithSuffix(int i, String pattern) {
int c = 0;
int j = 0;
while (j < pattern.length() && c == 0) {
if (i + j <= text.length()) {
c = pattern.charAt(0 + j) - text.charAt(i + j);
} else {
c = 1;
}
j++;
}
return c;
}
public int binarySearch(String pattern) {
int left = 0;
int right = text.length() - 1;
int mid, c = 0;
while (c != 0 && left <= right) {
mid = left + (right - left) / 2;
c = compareWithSuffix(mid, pattern);
if (c < 0) {
right = mid - 1;
} else if (c > 0) {
left = mid + 1;
} else if (c == 0) {
return mid;
}
}
return left;
}
I run it with this main-method:
public static void main(String[] args) {
String word = "abracadabra";
String prefix1 = "rax";
String prefix2 = "racad";
SuffixArray s = new SuffixArray(word);
System.out.println("Longest common prefix of: " + "'" + prefix1 + "'" + " in " + "'" + word + "'" + " begins at index: " + s.binarySearch(prefix1));
System.out.println("Longest common prefix of: " + "'" + prefix2 + "'" + " in " + "'" + word + "'" + " begins at index: " + s.binarySearch(prefix2));
}
The output is always whatever value I initialize the local variable left with.
The search algorithm must do a singular binary search. I´ve tried searching other stackoverflow-questions and other web-sources but have not found anything helpfull.
Anyone who can see any errors in my code?
I haven't looked deeply enough to know if this is the only problem in your code, but this immediately jumps out as an explanation for "The output is always whatever value I initialize the local variable left with":
int mid, c = 0;
while (c != 0 && left <= right) {
You set c to zero, and then immediately check if it's not equal to zero. Of course, it's not not equal to zero, so the loop condition is immediately false, thus the loop body is never run. Hence, you will return the initial value of left.
It's not obvious why you are checking c at all. In the only situation where c becomes zero inside the loop, you immediately return. So just change your loop guard to:
while (left <= right) {
(and move the declaration of c inside the loop).
You could easily have found this by stepping through the code with a debugger. I heartily recommend learning how to use one.
first point: analyzing the examples you gave, it appears that you are not interested in the longest common prefix, but in the longest common substring. A prefix always starts with the first letter of the word - https://en.wikipedia.org/wiki/Prefix
second point: perhaps are you interested in finding the longest common substring of a set of words, or just two words?
public class Main3 {
/*
same functionallity as compareWithSuffix, but i think this name
is more suggestive; also, no need to pass i (the starting index) as a
parameter; i will later apply substring(i) to text
*/
public String longestCommonPrefix(String text, String pattern)
{
String commonPrefix="";
for(int j=0; j<text.length() & j<pattern.length(); j++)
{
if(text.charAt(j)==pattern.charAt(j))
{
commonPrefix=commonPrefix+text.charAt(j);
}
else
{
break;
}
}
return commonPrefix;
//for params "abc", "abd", output will be "ab"
}
public String longestCommonSequence(String s1, String s2)
{
/*
take for example "xab" and "yab";in order to find the common
sequence 'ab", we need to chop both x and y; for this reason
i apply substring to both strings, cutting progressivelly their first letters
*/
String longestCommonSequence="";
for(int i=0;i<=s1.length()-1;i++)
{
for(int j=0;j<=s2.length()-1;j++)
{
String s1_temp=s1.substring(i);
String s2_temp=s2.substring(j);
String commonSequence_temp=longestCommonPrefix(s1_temp, s2_temp);
if(commonSequence_temp.length()>longestCommonSequence.length())
longestCommonSequence=commonSequence_temp;
}
}
return longestCommonSequence;
}
public static void main(String args[])
{
Main3 m = new Main3();
String common = m.longestCommonSequence("111abcd2222", "33abcd444");
System.out.println(common);//"abcd"
}
}
I am providing here a different answer, because the approach is totally different, and leads to a generalized solution. (find the common substring of an entire list of strings)
For each word, i build all its possible substrings. A substring is determined by its start and end index. If the length of a word is L, the start index can be: 0, 1, 2,... L-1; if the starting index is 0, the end index can take values from 1 to L-1, thus L-1 values; if the starting index is 1, there are L-2 possible values for the end index. Thus, a word of length L has (L-1) +(L-2) + ... +1 = L*(L-1)/2 substrings. This gives square complexity in regard to L, but that's not an issue, because words rarely exceed 15 letters in length. If the string is not a word, but a text paragraph, then we have a problem with the square complexity.
Next, after i have build the set of substrings for every word, i build the intersection of these sets. The main idea is that a common substring of more words is, in the first place, a substring inside every such word, and, moreover, a substring that is encountered in all of these words. This lead to the idea of building the set of substrings for every word, and then do the intersection.
After we have found all the common substrings, just iterate and keep the longest one
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Main4 {
HashSet<String> allSubstrings(String input)
{
HashSet<String> result = new HashSet<String>();
for(int i=0;i<=input.length()-1;i++)
for(int j=i+1;j<=input.length();j++)
result.add(input.substring(i,j));
return result;
}
public HashSet<String> allCommonSubstrings(ArrayList<String> listOfStrings)
{
ArrayList<HashSet<String>> listOfSetsOfSubstrings =new ArrayList<HashSet<String>>();
//for each string in the list, build the set of all its possible substrings
for(int i=0;i<listOfStrings.size();i++)
{
String currentString = listOfStrings.get(i);
HashSet<String> allSubstrings = allSubstrings(currentString);
listOfSetsOfSubstrings.add(allSubstrings);
}
//find the intersection of all the sets of substrings
HashSet<String> intersection = new HashSet<String>(listOfSetsOfSubstrings.get(0));
for(int i=0;i<listOfSetsOfSubstrings.size();i++)
{
HashSet<String> currentSet=listOfSetsOfSubstrings.get(i);
intersection.retainAll(currentSet);
//retainAll does the set intersection. see: https://stackoverflow.com/questions/8882097/how-to-calculate-the-intersection-of-two-sets
}
return intersection;
}
public String longestCommonSubstring(HashSet<String> setOfSubstrings)
{
if(setOfSubstrings.size()==0)
return null;//if there are no common substrings, then there is no longest common substrings
String result="";
Iterator<String> it = setOfSubstrings.iterator();
while(it.hasNext())
{
String current = it.next();
if(current.length()>result.length())
result=current;
}
return result;
}
public static void main(String[] args)
{
Main4 m = new Main4();
ArrayList<String> list=new ArrayList<String>();
list.add("bbbaaddd1");
list.add("bbbaaccc1");
list.add("dddaaccc1");
HashSet<String> hset = m.allCommonSubstrings(list);
Iterator<String> it = hset.iterator();
System.out.println("all coommon substrings:");
while(it.hasNext())
{
System.out.println(it.next());
}
System.out.println("longest common substring:");
String lcs=m.longestCommonSubstring(hset);
System.out.println(lcs);
}
}
output:
all coommon substrings:
aa
a
1
longest common substring:
aa

Finding Anagrams with vowels always at the end

I was trying out this question :
Write a function using Recursion to display all anagrams of a string entered by the user, in such a way that all its vowels are located at the end of every anagram. (E.g.: Recursion => Rcrsneuio, cRsnroieu, etc.) Optimize it.
From this site :
http://erwnerve.tripod.com/prog/recursion/magic.htm
This is what i have done :
public static void permute(char[] pre,char[] suff) {
if (isEmpty(suff)) {
//result is a set of string. toString() method will return String representation of the array.
result.add(toString(moveVowelstoEnd(pre)));
return;
}
int sufflen = getLength(suff); //gets the length of the array
for(int i =0;i<sufflen;i++) {
char[] tempPre = pre.clone();
char[] tempSuf = suff.clone();
int nextindex = getNextIndex(pre); //find the next empty spot in the prefix array
tempPre[nextindex] = tempSuf[i];
tempSuf = removeElement(i,tempSuf); //removes the element at i and shifts array to the left
permute(tempPre,tempSuf);
}
}
public static char[] moveVowelstoEnd(char[] input) {
int c = 0;
for(int i =0;i<input.length;i++) {
if(c>=input.length)
break;
char ch = input[i];
if (vowels.contains(ch+"")) {
c++;
int j = i;
for(;j<input.length-1;j++)
input[j] = input[j+1];
input[j]=ch;
i--;
}
}
return input;
}
Last part of the question is 'Optimize it'. I am not sure how to optimize this. can any one help?
Group all the vowels into v
Group all consonants into w
For every pair of anagrams, concat the results

Categories