How to search String array through char array? - java

I want to build a simple dictionary search program without using dictionary library. I want to search the string array if the string in array is equal to the char array. It should print the string and its index number. If there are 2 strings that are matching the char then it should print the first string and leave the after string
.e.g String array["fine","rest","door","shine"] char character ['t','r','e','s']. the answer should be "rest" at index 1. and if the String rest is repeat then it should only print first one.
I tried to compare the string array and char array but its returning all the words of string array that matches char array.
String strArray[]=new String[4];
char chrArray[]=new char[4];
String value="";
char compare;
System.out.println("Enter the words :");
for(int i=0;i<strArray.length;i++){
strArray[i]=input.next();
}
System.out.println("Enter the Characters :");
for (int i = 0; i < chrArray.length; i++) {
chrArray[i]=input.next().charAt(0);
}
for (int i = 0; i < strArray.length; i++) {
if(strArray[i].length()==chrArray.length){
if(""+strArray[i]!=value){
value="";
}
for (int j = 0; j < strArray[i].length(); j++) {
for (int k = 0; k < chrArray.length; k++) {
if(strArray[i].charAt(j)==chrArray[k]){
value=value+strArray[i].charAt(j);
}
}
}
}
}
System.out.println(value);
The output should be the string from array that is equal to char array.

You can sort char array and then compare it using Arrays.equal. By sorting char array, there will be no need to use 2 for loops.
import java.util.Arrays;
import java.util.Scanner;
public class Bug {
public static void main(String[] args) {
String strArray[]=new String[4];
char chrArray[]=new char[4];
Scanner input = new Scanner(System.in);
System.out.println("Enter the words :");
for(int i=0;i<strArray.length;i++){
strArray[i]=input.next();
}
System.out.println("Enter the Characters :");
for (int i = 0; i < chrArray.length; i++) {
chrArray[i]=input.next().charAt(0);
}
Arrays.sort(chrArray);
for (int i = 0; i < strArray.length; i++) {
char[] x = strArray[i].toCharArray();
Arrays.sort(x);
if(Arrays.equals(chrArray, x))
{
System.out.println(strArray[i]);
break;
}
}
}
}

You could also create a Map<Character, Integer> to store counts for both the words and the characters, and compare each word character counts with the character counts. If both are equal, print it out.
Demo:
import java.util.Map;
import java.util.HashMap;
public class Example {
private static final String[] words = {"fine", "rest", "door", "shine"};
private static final char[] chars = {'t', 'r', 'e', 's'};
/**
* Initialise String character counts in a hashmap datastructure.
* #param word The string word to iterate.
* #return Hashmap of character -> counts.
*/
private static Map<Character, Integer> getCharCounts(String word) {
Map<Character, Integer> wordCounts = new HashMap<>();
for (int i = 0; i < word.length(); i++) {
Character character = word.charAt(i);
// If key doesn't exist, initialise it
if (!wordCounts.containsKey(character)) {
wordCounts.put(character, 0);
}
// Increment count by 1
wordCounts.put(character, wordCounts.get(character) + 1);
}
return wordCounts;
}
public static void main(String[] args) {
// Initialise character counts first
Map<Character, Integer> charCounts = getCharCounts(String.valueOf(chars));
for (int i = 0; i < words.length; i++) {
Map<Character, Integer> wordCounts = getCharCounts(words[i]);
// If Hashmaps are equal, then we have found a match
if (wordCounts.equals(charCounts)) {
System.out.println(words[i] + ", at index = " + i);
break;
}
}
}
}
Output:
rest, at index = 1

Related

Common characters in n strings

I m trying to make a function that prints the number of characters common in given n strings. (note that characters may be used multiple times)
I am struggling to perform this operation on n strings However I did it for 2 strings without any characters repeated more than once.
I have posted my code.
public class CommonChars {
public static void main(String[] args) {
String str1 = "abcd";
String str2 = "bcde";
StringBuffer sb = new StringBuffer();
// get unique chars from both the strings
str1 = uniqueChar(str1);
str2 = uniqueChar(str2);
int count = 0;
int str1Len = str1.length();
int str2Len = str2.length();
for (int i = 0; i < str1Len; i++) {
for (int j = 0; j < str2Len; j++) {
// found match stop the loop
if (str1.charAt(i) == str2.charAt(j)) {
count++;
sb.append(str1.charAt(i));
break;
}
}
}
System.out.println("Common Chars Count : " + count + "\nCommon Chars :" +
sb.toString());
}
public static String uniqueChar(String inputString) {
String outputstr="",temp="";
for(int i=0;i<inputstr.length();i++) {
if(temp.indexOf(inputstr.charAt(i))<0) {
temp+=inputstr.charAt(i);
}
}
System.out.println("completed");
return temp;
}
}
3
abcaa
bcbd
bgc
3
their may be chances that a same character can be present multiple times in
a string and you are not supposed to eliminate those characters instead
check the no. of times they are repeated in other strings. for eg
3
abacd
aaxyz
aatre
output should be 2
it will be better if i get solution in java
You have to convert all Strings to Set of Characters and retain all from the first one. Below solution has many places which could be optimised but you should understand general idea.
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static void main(String[] args) {
List<String> input = Arrays.asList("jonas", "ton", "bonny");
System.out.println(findCommonCharsFor(input));
}
public static Collection<Character> findCommonCharsFor(List<String> strings) {
if (strings == null || strings.isEmpty()) {
return Collections.emptyList();
}
Set<Character> commonChars = convertStringToSetOfChars(strings.get(0));
strings.stream().skip(1).forEach(s -> commonChars.retainAll(convertStringToSetOfChars(s)));
return commonChars;
}
private static Set<Character> convertStringToSetOfChars(String string) {
if (string == null || string.isEmpty()) {
return Collections.emptySet();
}
Set<Character> set = new HashSet<>(string.length() + 10);
for (char c : string.toCharArray()) {
set.add(c);
}
return set;
}
}
Above code prints:
[n, o]
A better strategy for your problem is to use this method:
public int[] countChars(String s){
int[] count = new int[26];
for(char c: s.toCharArray()){
count[c-'a']++;
}
return count;
}
Now if you have n Strings (String[] strings) just find the min of common chars for each letter:
int[][] result = new int[n][26]
for(int i = 0; i<strings.length;i++){
result[i] = countChars(s);
}
// now if you sum the min common chars for each counter you are ready
int commonChars = 0;
for(int i = 0; i< 26;i++){
int min = result[0][i];
for(int i = 1; i< n;i++){
if(min>result[j][i]){
min = result[j][i];
}
}
commonChars+=min;
}
Get list of characters for each string:
List<Character> chars1 = s1.chars() // list of chars for first string
.mapToObj(c -> (char) c)
.collect(Collectors.toList());
List<Character> chars2 = s2.chars() // list of chars for second string
.mapToObj(c -> (char) c)
.collect(Collectors.toList());
Then use retainAll method:
chars1.retainAll(chars2); // retain in chars1 only the chars that are contained in the chars2 also
System.out.println(chars1.size());
If you want to get number of unique chars just use Collectors.toSet() instead of toList()
Well if one goes for hashing:
public static int uniqueChars(String first, String second) {
boolean[] hash = new boolean[26];
int count = 0;
//reduce first string to unique letters
for (char c : first.toLowerCase().toCharArray()) {
hash[c - 'a'] = true;
}
//reduce to unique letters in both strings
for(char c : second.toLowerCase().toCharArray()){
if(hash[c - 'a']){
count++;
hash[c - 'a'] = false;
}
}
return count;
}
This is using bucketsort which gives a n+m complexity but needs the 26 buckets(the "hash" array).
Imo one can't do better in regards of complexity as you need to look at every letter at least once which sums up to n+m.
Insitu the best you can get is imho somewhere in the range of O(n log(n) ) .
Your aproach is somewhere in the league of O(n²)
Addon: if you need the characters as a String(in essence the same as above with count is the length of the String returned):
public static String uniqueChars(String first, String second) {
boolean[] hash = new boolean[26];
StringBuilder sb = new StringBuilder();
for (char c : first.toLowerCase().toCharArray()) {
hash[c - 'a'] = true;
}
for(char c : second.toLowerCase().toCharArray()){
if(hash[c - 'a']){
sb.append(c);
hash[c - 'a'] = false;
}
}
return sb.toString();
}
public static String getCommonCharacters(String... words) {
if (words == null || words.length == 0)
return "";
Set<Character> unique = words[0].chars().mapToObj(ch -> (char)ch).collect(Collectors.toCollection(TreeSet::new));
for (String word : words)
unique.retainAll(word.chars().mapToObj(ch -> (char)ch).collect(Collectors.toSet()));
return unique.stream().map(String::valueOf).collect(Collectors.joining());
}
Another variant without creating temporary Set and using Character.
public static String getCommonCharacters(String... words) {
if (words == null || words.length == 0)
return "";
int[] arr = new int[26];
boolean[] tmp = new boolean[26];
for (String word : words) {
Arrays.fill(tmp, false);
for (int i = 0; i < word.length(); i++) {
int pos = Character.toLowerCase(word.charAt(i)) - 'a';
if (tmp[pos])
continue;
tmp[pos] = true;
arr[pos]++;
}
}
StringBuilder buf = new StringBuilder(26);
for (int i = 0; i < arr.length; i++)
if (arr[i] == words.length)
buf.append((char)('a' + i));
return buf.toString();
}
Demo
System.out.println(getCommonCharacters("abcd", "bcde")); // bcd

How to refacor a code use only loops and simple arrays?

I wrote that code and it's working. But I need to refactor it. I can use only simple methods for solving the problem, for example: "for" loops and simple array.
public class Anagram {
public static void main(String[] args) throws IOException {
Anagram anagrama = new Anagram();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));) {
System.out.println("Enter word or phrase: ");
String userText = reader.readLine();
String resultAnagrama = anagrama.makeAnagram(userText);
System.out.println("Result of Anagrama : " + resultAnagrama);
}
}
This method take user's text and make anagram, but all non-letters should stay on the same places
/**
* #param text
* #return reversed text and all non-letter symbols stay on the same places
*/
public String makeAnagram(String text) {
HashMap<Integer, Character> mapNonLetters;
String[] textFragments = text.split(" ");
StringBuilder stringBuilder = new StringBuilder();
//Check each elements of array for availability symbols and make reverse of elements
for (int i = 0; i < textFragments.length; i++) {
char[] arrayCharacters = textFragments[i].toCharArray();
mapNonLetters = saerchNonLetters(arrayCharacters); // search symbols
StringBuilder builderAnagramString = new StringBuilder(textFragments[i]);
//Delete all non-letters from element of array
int reindexing = 0;
for (HashMap.Entry<Integer, Character> entry : mapNonLetters.entrySet()) {
int key = entry.getKey();
builderAnagramString.deleteCharAt(key - reindexing);
reindexing ++;
}
builderAnagramString.reverse();
//Insert all non-letters in the same places where ones stood
for (HashMap.Entry<Integer, Character> entry : mapNonLetters.entrySet()) {
int key = entry.getKey();
char value = entry.getValue();
builderAnagramString.insert(key, value);
}
textFragments[i] = builderAnagramString.toString();
stringBuilder.append(textFragments[i]);
if (i != (textFragments.length - 1)) {
stringBuilder.append(" ");
}
mapNonLetters.clear();
}
return stringBuilder.toString();
}
This method search all non-letters from each worв of user's text
/**
* Method search symbols
* #param arrayCharacters
* #return HashMap with symbols found from elements of array
*/
public HashMap<Integer, Character> saerchNonLetters(char[] arrayCharacters) {
HashMap<Integer, Character> mapFoundNonLetters = new HashMap<Integer, Character>();
for (int j = 0; j < arrayCharacters.length; j++) {
//Letters lay in scope 65-90 (A-Z) and 97-122 (a-z) therefore other value is non-letter
if (arrayCharacters[j] < 65 || (arrayCharacters[j] > 90 && arrayCharacters[j] < 97) ||
arrayCharacters[j] > 122) {
mapFoundNonLetters.put(j, arrayCharacters[j]);
}
}
return mapFoundNonLetters;
}
}
public class Anagram {
public static void main(String[] args) {
String text = "!Hello123 ";
char[] chars = text.toCharArray();
int left = 0;
int right = text.length() - 1;
while (left < right) {
boolean isLeftLetter = Character.isLetter(chars[left]);
boolean isRightLetter = Character.isLetter(chars[right]);
if (isLeftLetter && isRightLetter) {
swap(chars, left, right);
left++;
right--;
} else {
if (!isLeftLetter) {
left++;
}
if (!isRightLetter) {
right--;
}
}
}
String anagram = new String(chars);
System.out.println(anagram);
}
private static void swap(char[] chars, int index1, int index2) {
char c = chars[index1];
chars[index1] = chars[index2];
chars[index2] = c;
}
}
If I understand correctly and you need only 1 anagram, this should work:
String originalString = "This is 1 sentence with 2 numbers!";
System.out.println("original: "+originalString);
// make a mask to keep track of where the non letters are
char[] mask = originalString.toCharArray();
for(int i=0; i<mask.length; i++)
mask[i] = Character.isLetter(mask[i]) ? '.' : mask[i];
System.out.println("mask: "+ new String(mask));
// remove non letters from the string
StringBuilder sb = new StringBuilder();
for(int i=0; i< originalString.length(); i++) {
if(mask[i] == '.')
sb.append(originalString.charAt(i));
}
// find an anagram
String lettersOnlyAnagram = sb.reverse().toString();
// reinsert the non letters at their place
int letterIndex = 0;
for(int i=0; i<mask.length; i++) {
if(mask[i] == '.') {
mask[i] = lettersOnlyAnagram.charAt(letterIndex);
letterIndex++;
}
}
String anagram = new String(mask);
System.out.println("anagram: "+ anagram);
It prints out:
original: This is 1 sentence with 2 numbers!
mask: .... .. 1 ........ .... 2 .......!
anagram: sreb mu 1 nhtiwecn etne 2 ssisihT!

Used an arraylist in Java to find four consecutive letters in a dictionary, error while building the code

This is the initial challenge I'm trying to address
1) takes two arguments—a “source" English word in a string, and an English dictionary supplied in an array
2) returns a list of English words as an array
The words returned are those from the dictionary that have four consecutive letters (or more) in common with the “source” word. For example, the word MATTER has the four letters in a row “ATTE" in common ATTEND.
The code however gives me errors with the substring
Below is the code for your reference.
public class FourLetterInCommon {
static String wrd = "split";
static String[] d = new String[]{"SPLITS", "SPLITTED", "SPLITTER", "SPLITTERS", "SPLITTING", "SPLITTINGS", "SPLITTISM", "SPLITTISMS", "SPLITTIST", "SPLITTISTS"};
public static void main(String[] args){
System.out.println(fourletters (wrd, d));
}
public static List<String> fourletters (String word, String[] dict){
int dictsize = dict.length;
int wordlength = word.length();
List<String> Commonletters = new ArrayList<String>();
for(int i = 0; i<=dictsize; i++) {
for (int j=0; j<=wordlength;) {
if(dict[i].contains(word.substring(i, 5)))
{
Commonletters.add(dict[i]);
}
break;
}
}
return Commonletters;
}
}
This is the error message I get:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1 at java.lang.String.substring(Unknown Source) at FourLetterInCommon.fourletters(FourLetterInCommon.java:22) at FourLetterInCommon.main(FourLetterInCommon.java:10)
What does the errors mean? Apologies, but a bit clueless at this stage.
Quite a few issues here.
1)
for(int i = 0; i<=dictsize; i++) {
should be
for(int i = 0; i<dictsize; i++) {
2)
for (int j=0; j<=wordlength;) {
should be
for (int j=0; j<=wordlength-4; j++) {
3)
if(dict[i].contains(word.substring(i, 5)))
should be
if(dict[i].contains(word.substring(j, j+4)))
4)
I don't believe you really want to break; there. I'm guessing you want to break when you find a match, so it should be inside the if statement.
Corrected code:
public class FourLetterInCommon
{
static String wrd = "SPLIT";
static String[] d = new String[] { "SPLITS", "SPLITTED", "SPLITTER", "SPLITTERS", "SPLITTING", "SPLITTINGS",
"SPLITTISM", "SPLITTISMS", "SPLITTIST", "SPLITTISTS" };
public static void main(String[] args)
{
System.out.println(fourletters(wrd, d));
}
public static List<String> fourletters(String word, String[] dict)
{
int dictsize = dict.length;
int wordlength = word.length();
List<String> Commonletters = new ArrayList<String>();
for (int i = 0; i < dictsize; i++)
{
for (int j = 0; j <= wordlength - 4; j++)
{
if (dict[i].contains(word.substring(j, j + 4)))
{
Commonletters.add(dict[i]);
break;
}
}
}
return Commonletters;
}
}
Output:
[SPLITS, SPLITTED, SPLITTER, SPLITTERS, SPLITTING, SPLITTINGS, SPLITTISM, SPLITTISMS, SPLITTIST, SPLITTISTS]
The following line would throw an Exception:
if(dict[i].contains(word.substring(i, 5)))
Here, i ranges from 0 to dict.length which is 10 in this case. word contains 5 characters only. So, accessing any character from index 5 onwards would throw an Exception.
If you want to check for certain number of characters then you should use this:
for (int j=0; j < wordlength;) {
if(dict[i].contains(word.substring(j, wordlength - j)))

How to shift array of char elements to left

I have an array of characters. I should remove any duplicate characters. I did comparison between the string elements with an array of alphabets. There is another array that acts as counter for any duplictae alphabet. If any character has been found for more than once, I should remove the duplicated character and shif the elements to left. Below is the code. I get error at the line with the comment. Java needs the left hand side of the assignment to be variable. Can you help?
import java.util.ArrayList;
import java.util.Scanner;
public class removeduplicate {
public static void main (String args[])
{
Scanner s=new Scanner(System.in);
String str="abbsded";
String myChars="abcdefghijklmnopqrstuvwxyz";
int[] myCounter=new int[26];
for (int i=0; i<str.length(); i++)
{
for(int j=0; j<myChars.length(); j++)
{
if(str.charAt(i)==myChars.charAt(j))
{
myCounter[j]++;
if (myCounter[j]>1)
{
System.out.println("duplication found in "+ str.charAt(i));
for(int h=i; h<str.length();h++)
{
//this line does not work.
str.charAt(h)=str.charAt(h-1);
}
}
}
}
}//end for
}
}
You can use a Hashmap to keep track of the characters you have run into during your implementation. Then just increment every time you see a character in the alphabet. Only adding a letter to the returned string if the character hasn't been seen before.
public static String removeDuplicates(String input)
{
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
input = input.toUpperCase();
HashMap<Character, Integer> charData = new HashMap<>();
//create the map to store counts of all the chars seen
for(int i = 0; i < alphabet.length(); i++)
charData.put(alphabet.charAt(i), 0);
String cleanedInput = "";
for(int index = 0; index < input.length(); index++)
{
char letter = input.charAt(index);
if(charData.containsKey(letter))
{
charData.put(letter, charData.get(letter) + 1);
//if count is 1 then its the first time we have seen it
if(charData.get(letter) == 1)
{
cleanedInput += letter;
}
}
}
return cleanedInput.toLowerCase();
}
Example Call
public static void main(String[] args) {
System.out.println(removeDuplicates("abbsded"));
System.out.println(removeDuplicates("abbsded!!!"));
System.out.println(removeDuplicates("hahahahahahahahahah"));
}//main method
Output
absde
absde
ha
Note: it only returns the characters once and no characters that aren't in the alphabet are considered in the new trimmed String.

How can I change the chars of a String in a method? (same chars, randomly order)

//Please, help me to fix this codes. I wanna return a String that the have same chars with the sending String but is in different order.
public static String mix(String s){
int random;
int n= s.length();
int [] control = new int[n];
String miX="";
for(int i=0 ; i < n ; i++){
random = (int)(1+Math.random()*(n));
if( control[i] != random ){
control[i]= random;
miX += s.charAt(random);
}
}
return miX;
}
You can make use of Collections.shuffle.
String word= "word";
ArrayList<Character> chars =newArrayList<Character>(word.length());
for(char c : word.toCharArray()){
chars.add(c); }
Collections.shuffle(chars);
char[] shuffled =newchar[chars.size()];
for(int i =0; i < shuffled.length; i++){
shuffled[i]= chars.get(i);
}
String shuffledWord =newString(shuffled);
Another way similar to your code without using functions is:
public static void main(String[] args) {
// Create a random object
Random r = new Random();
String word = "Animals";
System.out.println("Before: " + word );
word = scramble( r, word );
System.out.println("After : " + word );
}
public static String scramble( Random random, String inputString )
{
// Convert your string into a simple char array:
char a[] = inputString.toCharArray();
// Scramble the letters
for( int i=0 ; i<a.length-1 ; i++ )
{
int j = random.nextInt(a.length-1);
// Swap letters
char temp = a[i]; a[i] = a[j]; a[j] = temp;
}
return new String( a );
}
You should select two positions within the length of the String RANDOMLY and then exchange them .
Run this within a loop for any number of times depending on the amount of randomness you want in your String.
Based on your code you might miss some of the characters in your new string if random selects the same index twice
Mix string chars with this code
import java.util.*;
class MixStringChars
{
public static String mix(String s)
{
StringBuilder sb = new StringBuilder(s);
Random r = new Random();
for (int i = 0; i < s.length(); i++)
{
char curr = sb.charAt(i); //current char
int rix = r.nextInt(s.length()); //random index
char temp = sb.charAt(rix); //memorize char at index rix
sb.setCharAt(rix, curr); //put current char to rix index
sb.setCharAt(i , temp); //put memorized char to i index
}
return sb.toString();
}
public static void main (String[] args)
{
System.out.println(mix("Hello"));
}
}

Categories