I am trying to find the common characters in two strings just by using the for loop. The below code is working fine, if I provide two completely different strings ex.one and two but if I provide two strings with same input ex.teen and teen it doesn't work as expected.
import java.util.Scanner;
public class CommonAlphabets {
public static void main(String[] args) {
try(Scanner input = new Scanner(System.in)){
System.out.println("Enter String one ");
String stringOne = input.nextLine();
System.out.println("Enter String two ");
String StringTwo = input.nextLine();
StringBuffer sb = new StringBuffer();
for(int i=0;i<stringOne.length();i++){
for(int j=0;j<StringTwo.length();j++){
if(stringOne.charAt(i)== StringTwo.charAt(j)){
sb.append(stringOne.charAt(i));
}
}
}
System.out.println("Common characters are " +sb.toString());
}
}
}
Should I create another nested for loop to find duplicates in the StringBuffer or is there a better way to handle this scenario.
You do not need an inner for loop but use contains instead
String stringOne = "one";
String stringTwo = "one";
StringBuilder sb = new StringBuilder();
for(int i=0;i<stringOne.length() && i < stringTwo.length ();i++){
if(stringOne.contains(String.valueOf(stringTwo.charAt(i))) &&
!sb.toString().contains(String.valueOf(stringTwo.charAt(i)))){
// check already added
sb.append(stringTwo.charAt(i));
}
}
System.out.println (sb.toString());
edit
check to make sure char to be added does not already exist in StringBuilder -
Could use a Set instead
If using a Set
Set<Character> set = new HashSet<> ();
your logic could be simplified to
if(stringOne.contains(String.valueOf(stringTwo.charAt(i)))){
set.add(stringTwo.charAt(i));
}
You can use Set for it.
Set<Character> set = new HashSet<>();
for(int i = 0; i<stringOne.length(); i++) {
for(int j = 0; j < StringTwo.length(); j++) {
if(stringOne.charAt(i) == StringTwo.charAt(j)){
set.add(stringOne.charAt(i));
}
}
}
StringBuilder sb = new StringBuilder();
for (Character c : set) {
sb.append(c);
}
System.out.println("Common characters are " + sb);
well your approach is fine as the result is showing what you are expecting there fore that code is fine, but you need to stop the duplication , therefore you have to write the code for 'sb' variable so that it will remove duplicates or write code in loop so that it wont provide duplicate.
as your code is becoming complicated to read so i would prefer that you make a method to write code to remove duplicate it will go like
static void removeDuplicate(StringBuilder s){
for(int i=0,i<s.length-1,i++){
for(int j=i+1,j<s.length,j++){
if(s.charAt(i)==s.charAt(j)){
s.deleteCharAt(j);
}
}
}
call this method before printing
Another approach you could try is - combine the two input strings, iterate over the concatenated string and return the characters which exist in both the strings.
Using a Set will ensure you do not add characters which get repeated due to the concatenation of the strings.
Here's what I wrote -
import java.util.HashSet;
public class HelloWorld {
private static Character[] findCommonLetters(String combined, String w1, String w2) {
HashSet<Character> hash = new HashSet<>();
for(char c: combined.toCharArray()) {
if(w1.indexOf(c) != -1 && w2.indexOf(c) != -1) {
hash.add(c);
}
}
return hash.toArray(new Character[hash.size()]);
}
public static void main(String []args){
// System.out.println("Hello World");
String first = "flour";
String second = "four";
String combined = first.concat(second);
Character[] result = findCommonLetters(combined, first, second);
for(char c: result) {
System.out.print(c);
}
System.out.println();
}
}
Demo here.
This is the best way to do this because it's time complexity is n so that why this is the best you could do.
import java.util.Scanner;
public class CommonAlphabets
{
public static void main(String[] args)
{
try (Scanner input = new Scanner(System.in))
{
System.out.println("Enter String one ");
String stringOne = input.nextLine();
System.out.println("Enter String two ");
String StringTwo = input.nextLine();
StringBuffer sb = new StringBuffer();
/**
* Assuming char as index of array where A-Z is from index 0 to 25 and a-z is index 26-51
*/
int[] alphabetArray1 = new int[52];
for(int i = 0, len = stringOne.length(); i < len; i++)
alphabetArray1[stringOne.charAt(i) > 94 ? stringOne.charAt(i) - 71 : stringOne.charAt(i) - 65] = 1;
int[] alphabetArray2 = new int[52];
for(int i = 0, len = StringTwo.length(); i < len; i++)
alphabetArray2[StringTwo.charAt(i) > 94 ? StringTwo.charAt(i) - 71 : StringTwo.charAt(i) - 65] = 1;
// System.out.println(Arrays.toString(alphabetArray1));
// System.out.println(Arrays.toString(alphabetArray2));
for (int i = 0; i < 52; i++)
if (alphabetArray1[i] == 1 && alphabetArray2[i] == 1)
sb.append((char) (i < 26 ? i + 65 : i + 71));
System.out.println("Common characters are " + sb.toString());
}
}
}
Related
I am currently implementing Run Length Encoding for text compression and my algorithm does return Strings of the following form:
Let's say we have a string as input
"AAAAABBBBCCCCCCCC"
then my algorithm returns
"1A2A3A4A5A1B2B3B4B1C2C3C4C5C6C7C8C"
Now I want to apply Java String split to solve this, because I want to get the highest number corresponding to character. For our example it would be
"5A4B8C"
My function can be seen below
public String getStrfinal(){
String result = "";
int counter = 1;
StringBuilder sb = new StringBuilder();
sb.append("");
for (int i=0;i<str.length()-1;i++) {
char c = str.charAt(i);
if (str.charAt(i)==str.charAt(i+1)) {
counter++;
sb.append(counter);
sb.append(c);
}
else {
counter = 1;
continue;
}
}
result = sb.toString();
return result;
}
public static String getStrfinal(){
StringBuilder sb = new StringBuilder();
char last = 0;
int count = 0;
for(int i = 0; i < str.length(); i++) {
if(i > 0 && last != str.charAt(i)) {
sb.append(count + "" + last);
last = 0;
count = 1;
}
else {
count++;
}
last = str.charAt(i);
}
sb.append(count + "" + last);
return sb.toString();
}
Here is one possible solution. It starts with the raw string and simply iterates thru the string.
public static void main(String[] args) {
String input = "AAAABBBCCCCCCCDDDEAAFBBCD";
int index = 0;
StringBuilder sb = new StringBuilder();
while (index < input.length()) {
int count = 0;
char c = input.charAt(index);
for (; index < input.length(); index++) {
if (c != input.charAt(index)) {
count++;
}
else {
break;
}
}
sb.append(Integer.toString(count));
sb.append(c);
count = 0;
}
System.out.println(sb.toString());
}
But one problem with this method and others is what happens if there are digits in the text? For example. What if the string is AAABB999222AAA which would compress to 3A2B39323A. That could also mean AAABB followed by 39 3's and 23 A's
Instead of string Buffer you can use a map it will be much easier and clean to do so.
public static void main(String[] args) {
String input = "AAAAABBBBCCCCCCCCAAABBBDDCCCC";
int counter=1;
for(int i=1; i<input.length(); i++) {
if(input.charAt(i-1)==input.charAt(i)) {
counter=counter+1;
}else if(input.charAt(i-1)!=input.charAt(i)){
System.out.print(counter+Character.toString(input.charAt(i-1)));
counter=1;
}if(i==input.length()-1){
System.out.print(counter+Character.toString(input.charAt(i)));
}
}
}
This will gives
5A4B8C3A3B2D4C
UPDATES
I Agree with #WJS if the string contains number the out put becomes messy
hence if the System.out in above code will be exchange with below i.e.
System.out.print(Character.toString(input.charAt(i-1))+"="+counter+" ");
then for input like
AAAAABBBBCCCCCCCCAAABBBDD556677CCCCz
we get out put as below
A=5 B=4 C=8 A=3 B=3 D=2 5=2 6=2 7=2 C=4 z=1
This is one of the possible solutions to your question. We can use a LinkedHashMap data structure which is similar to HashMap but it also maintains the order. So, we can traverse the string and store the occurrence of each character as Key-value pair into the map and retrieve easily with its maximum occurrence.
public String getStrFinal(String str){
if(str==null || str.length()==0) return str;
LinkedHashMap<Character,Integer> map = new LinkedHashMap<>();
StringBuilder sb=new StringBuilder(); // to store the final string
for(char ch:str.toCharArray()){
map.put(ch,map.getOrDefault(ch,0)+1); // put the count for each character
}
for(Map.Entry<Character,Integer> entry:map.entrySet()){ // iterate the map again and append each character's occurence into stringbuilder
sb.append(entry.getValue());
sb.append(entry.getKey());
}
System.out.println("String = " + sb.toString()); // here you go, we got the final string
return sb.toString();
}
I'm doing a hackerrank medium challenge for a password cracker. I want to be able to check if a given string, attempt, contains all the words in pass. pass is an array of passwords and attempt is a concatenation of random entries in pass. If attempt contains ONLY words that are found as entries in pass, then it is deemed a good password and the words from the input of attempt, limited with spaces, is printed.
Sample Input
3 //3 attempts
6 //6 words for attempt 1
because can do must we what //pass[]
wedowhatwemustbecausewecan //attempt
2 //...
hello planet
helloworld
3
ab abcd cd
abcd
Expected Output
we do what we must because we can
WRONG PASSWORD //Because planet is not in pass[]
ab cd
Code
public class Solution {
static String passwordCracker(String[] pass, String attempt) {
int arrayLength=pass.length;
int accuracy=0;
String trips_array[] = new String[pass.length];
String [] newWord = new String[20];
for (int i=0; i<pass.length;i++)
{
// int j=0;
String[] arr = pass[i].split(" ");
//-------------------------------
if (attempt.contains(pass[i]))
{
accuracy++;
newWord[i] = pass[i];
trips_array[i] = attempt.split(" ");
}
//------------------------------
}
StringBuilder sb = new StringBuilder();
for (String words : trips_array) {
sb.append(words);
}
for (int i=0; i<pass.length;i++)
{
if (accuracy==pass.length)
return sb.toString() + " ";
else
return "WRONG PASSWORD";
}
return "test";
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
int n = in.nextInt();
String[] pass = new String[n];
for(int pass_i = 0; pass_i < n; pass_i++){
pass[pass_i] = in.next();
}
String attempt = in.next();
String result = passwordCracker(pass, attempt);
System.out.println(result);
}
in.close();
}
}
The part in focus is the part in the //----------------- comment section. Basically, my goal is to see if the attempt contains the correct entries in pass, and if so, save that substring of the attempt (or similarly, the entry in pass) to a new array which can be printed in the correct order. If you check the expected output above, you'll see that the output is the same as attempt except with spaces.
Essentially, I would need to find the breaks in the words of attempt and print that if it fulfills the above requirements (first paragraph).
See this for more details
https://www.hackerrank.com/challenges/password-cracker/problem
If it helps you
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int testNumb = Integer.parseInt(reader.readLine());
List<String> passList = new ArrayList<>();
List<String> attList = new ArrayList<>();
for (int i = 0; i < testNumb; i++) {
reader.readLine();
passList.add(reader.readLine());
attList.add(reader.readLine());
}
reader.close();
for (int i = 0; i < testNumb; i++) {
String s1 = passList.get(i);
String s2 = attList.get(i);
StringBuilder sb = new StringBuilder();
String[] s1Arr = s1.split(" ");
while (s2.length() > 0) {
int s2Lenght = s2.length();
for (String s : s1Arr) {
if (s2.startsWith(s)) {
sb.append(s + " ");
s2 = s2.substring(s.length());
}
}
if (s2.length() == s2Lenght) {
sb = new StringBuilder("wrong pass");
break;
}
}
System.out.println(sb.toString());
}
Your for loop looks too complicated, here is how I would approach that part.
boolean isAllWords = true;
int checksum = 0;
for (int j = 0; j < pass.length; j++) {
if (!attempt.contains(pass[j]) {
isAllWords = true;
break;
}
checksum += pass[j].length;
}
if (isAllWords && checksum == attempt.length) {
//This means attempt contains all words in pass array and nothing more
//... handle successful attempt
} else {
//... handle bad attempt
}
Im currently trying to create a function where my input is a string such as "AABBCCDDEE" and the function outputs a String array "AA""BB""CC" and so on.
public static char[] stringSplitter(final String input) {
String[] strarray = new String[input.length()];
if (input == null) {
return null;
}
char[] chrarray = input.toCharArray();
char[] outputarray = new char[input.length()];
int j = 0;
for (int i = 0; i < chrarray.length; i++) {
char chr = chrarray[i];
System.out.print(chr);
outputarray[j] = chrarray[i]; //here i need to find a way to add the characters to the index at j if the preceding characters are equal
if (i + 1 < input.length() && chrarray[i + 1] != chr) {
j++;
outputarray[j] = chrarray[i + 1];
System.out.println(" ");
}
}
}
Arrays are fixed-length, so you can't do this with an array unless you allocate one with sufficient extra room up-front (which would require a pass through the string to find out how much extra room you needed).
Instead, consider using a StringBuilder for the output, which you can convert into a char array when you're done.
If I understood correctly, you want to split the characters in a string so that similar-consecutive characters stay together. If that's the case, here is how I would do it:
public static ArrayList<String> splitString(String str) {
ArrayList<String> output = new ArrayList<>();
String combo = "";
//iterates through all the characters in the input
for(char c: str.toCharArray()) {
//check if the current char is equal to the last added char
if(combo.length() > 0 && c != combo.charAt(combo.length() - 1)) {
output.add(combo);
combo = "";
}
combo += c;
}
output.add(combo); //adds the last character
return output;
}
Note that instead of using an array (has a fixed size) to store the output, I used an ArrayList, which has a variable size. Also, note that it's a list of strings (stores strings), not characters. The reason for this is that if it was a list of characters I wouldn't be able to store more than one character in the same index.
In each iteration of the loop, I check for equality between the current character and it's consecutive. The variable combo is used to temporarily store the characters (in a string) before they go to output.
Now, to print the results in a clear way:
public static void main(String[] args)
{
String input = "EEEE BCD DdA";
ArrayList<String> output = splitString(input);
System.out.print("[");
for(int i = 0; i < output.size(); i++) {
System.out.print("\"" + output.get(i) + "\"");
if(i != output.size()-1)
System.out.print(", ");
}
System.out.println("]");
}
The output when running the above code will be:
["EEEE", " ", "B", "C", "D", " ", "D", "d", "A"]
You can use an ArrayList of type String to store the consecutive letter Strings after splitting them. This code should work for you.
import java.util.*;
public class StringSplitter{
static ArrayList<String> splitString(String str)
{
ArrayList<String> result_list= new ArrayList<String>();
int last_index;
if(str == null)
{
return null;
}
else
{
while(str.length() != 0)
{
last_index = str.lastIndexOf(str.charAt(0));
result_list.add(str.substring(0, last_index+1));
str = str.substring(last_index+1);
}
}
return result_list;
}
public static void main(String[] args)
{
ArrayList<String> result = splitString("AABBCCDDEEE");
System.out.println(result);
}
}
I have used an ArrayList because it does not require you to fix a size while declaration.
I have another challenge, it is when the user inputs 2 words, java prints to the console a list of letters that occur in both words. My thought was to create a char array out of the two inputs. But when I did that, I realized that some words are longer than others (Obviously), so I used an if statement to account for both possibilities (word one is bigger than word 2 and vice versa). When I did that, I got an ArrayIndexOutOfBoundsException. I do not know how else to do this. I have looked on StackOverflow for other solutions. Please help! My method for the challenge is below. PS: This is a challenge "within a challenge", I have to have the user choose 1 of five programs. When the user chooses 3, it runs the program below.
System.out.println("Enter a String");
Scanner scan = new Scanner(System.in);
String word1 = scan.nextLine();
System.out.println("Enter another String");
String word2 = scan.nextLine();
String list = "";
System.out.println("");
System.out.println("");
char[] word1Chars = word1.toCharArray();
char[] word2Chars = word2.toCharArray();
if(word1Chars.length > word2Chars.length) {
for(int s = 1; s < word1Chars.length;) {
if(word1Chars[s] == word2Chars[s]) {
list = "" + word1Chars[s];
}
}
} else if(word2Chars.length > word2Chars.length) {
for(int s = 1; s < word2Chars.length;) {
if(word1Chars[s] == word2Chars[s]) {
list = "" + word2Chars[s];
}
}
}
System.out.println(list);
return list;
If this isn't supposed to be very fast, I recommend writing as little code as possible, e.g. given String word1, word2:
Set<String> s1 = new HashSet<>( Arrays.asList( word1.split( "" ) ) );
Set<String> s2 = new HashSet<>( Arrays.asList( word2.split( "" ) ) );
s1.retainAll( s2 );
for( String c: s1 ) System.out.print(c);
System.out.println();
Replace the code after the initialisation of word1 and word2.
A simple regex could do the trick :
public static void main(String[] args) {
String s1 = "abcd";
String s2 = "saxydp";
System.out.println(s1.replaceAll("[^+" + s2 + "]", "").replaceAll("(\\w).*?\\1+","$1"));
}
O/P :
ad
Explanation : first of all in s1 replace everything that doesn't occur in s2. Next, replace every duplicate element :). Purely experimental code ..
This:
if(word1Chars.length > word2Chars.length) {
for(int s = 1; s < word1Chars.length;) {
is incrementing until s is the length of the LONGER of the two strings, but calling this:
if(word1Chars[s] == word2Chars[s])
So if word1 has 10 letters, eventually s will equal 9, and you'll check word2Chars[9], which could be out of bounds.
You can do something like this :
Scanner input = new Scanner(System.in);
System.out.println("Enter 2 strings : ");
String word1 = input.next();
String word2 = input.next();
String commonChar="";
for(char ch: word1.toCharArray()) {
if(word2.contains(ch+"") && !commonChar.contains(ch+"")) {
commonChar+=ch;
}
}
System.out.println(commonChar);
o/p
Enter 2 strings :
12345678
111222
12
In this we check if the letters contains in the other word then we add it but we add it only once.
I think the easiest way is to use nested for loops to iterate through the char arrays and compare each individual char. Then add to your list as needed.
Something like:
for (int i=0; i < word1chars.length; i++)
for(int x=0; x < word2chars.length; x++)
if (word1chars[i] == word2chars[x])
{
//add your letter to your list here
}
Using a set you can maybe achieve better performance. It follows an example:
import java.util.List;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
class C {
public static void main(String[] args) {
String w1 = "samefoo";
String w2 = "barsame";
Set set = new HashSet();
char[] a1 = w1.toCharArray();
char[] a2 = w2.toCharArray();
List list = new ArrayList();
for(int i = 0; i < a1.length; i++)
set.add(a1[i]);
for(int i = 0; i < a2.length; i++)
if(set.contains(a2[i]))
list.add(a2[i]);
System.out.println(list);
}
}
This is probably not as good as some of the others, but since I've written it, may as well add it to the list.
char[] word1Chars = word1.toCharArray();
char[] word2Chars = word2.toCharArray();
Arrays.sort(word1Chars);
Arrays.sort(word2Chars);
int i = 0, j = 0;
String duplicates = "";
while (i < word1Chars.length && j < word2Chars.length)
{
if (word1Chars[i] == word2Chars[j]) {
duplicates += word1Chars[i];
i++;
j++;
}
else if (word1Chars[i] > word2Chars[j]) j++;
else i++;
}
System.out.println(duplicates);
I have no idea how to start my assignment.
We got to make a Run-length encoding program,
for example, the users enters this string:
aaaaPPPrrrrr
is replaced with
4a3P5r
Can someone help me get started with it?
Hopefully this will get you started on your assignment:
The fundamental idea behind run-length encoding is that consecutively occurring tokens like aaaa can be replaced by a shorter form 4a (meaning "the following four characters are an 'a'"). This type of encoding was used in the early days of computer graphics to save space when storing an image. Back then, video cards supported a small number of colors and images commonly had the same color all in a row for significant portions of the image)
You can read up on it in detail on Wikipedia
http://en.wikipedia.org/wiki/Run-length_encoding
In order to run-length encode a string, you can loop through the characters in the input string. Have a counter that counts how many times you have seen the same character in a row. When you then see a different character, output the value of the counter and then the character you have been counting. If the value of the counter is 1 (meaning you only saw one of those characters in a row) skip outputting the counter.
public String runLengthEncoding(String text) {
String encodedString = "";
for (int i = 0, count = 1; i < text.length(); i++) {
if (i + 1 < text.length() && text.charAt(i) == text.charAt(i + 1))
count++;
else {
encodedString = encodedString.concat(Integer.toString(count))
.concat(Character.toString(text.charAt(i)));
count = 1;
}
}
return encodedString;
}
Try this one out.
This can easily and simply be done using a StringBuilder and a few helper variables to keep track of how many of each letter you've seen. Then just build as you go.
For example:
static String encode(String s) {
StringBuilder sb = new StringBuilder();
char[] word = s.toCharArray();
char current = word[0]; // We initialize to compare vs. first letter
// our helper variables
int index = 0; // tracks how far along we are
int count = 0; // how many of the same letter we've seen
for (char c : word) {
if (c == current) {
count++;
index++;
if (index == word.length)
sb.append(current + Integer.toString(count));
}
else {
sb.append(current + Integer.toString(count));
count = 1;
current = c;
index++;
}
}
return sb.toString();
}
Since this is clearly a homework assignment, I challenge you to learn the approach and not just simply use the answer as the solution to your homework. StringBuilders are very useful for building things as you go, thus keeping your runtime O(n) in many cases. Here using a couple of helper variables to track where we are in the iteration "index" and another to keep count of how many of a particular letter we've seen "count", we keep all necessary info for building our encoded string as we go.
Try this out:
private static String encode(String sampleInput) {
String encodedString = null;
//get the input to a character array.
// String sampleInput = "aabbcccd";
char[] charArr = sampleInput.toCharArray();
char prev=(char)0;
int counter =1;
//compare each element with its next element and
//if same increment the counter
StringBuilder sb = new StringBuilder();
for (int i = 0; i < charArr.length; i++) {
if(i+1 < charArr.length && charArr[i] == charArr[i+1]){
counter ++;
}else {
//System.out.print(counter + Character.toString(charArr[i]));
sb.append(counter + Character.toString(charArr[i]));
counter = 1;
}
}
return sb.toString();
}
Here is my solution in java
public String encodingString(String s){
StringBuilder encodedString = new StringBuilder();
List<Character> listOfChars = new ArrayList<Character>();
Set<String> removeRepeated = new HashSet<String>();
//Adding characters of string to list
for(int i=0;i<s.length();i++){
listOfChars.add(s.charAt(i));
}
//Getting the occurance of each character and adding it to set to avoid repeated strings
for(char j:listOfChars){
String temp = Integer.toString(Collections.frequency(listOfChars,j))+Character.toString(j);
removeRepeated.add(temp);
}
//Constructing the encodingString.
for(String k:removeRepeated){
encodedString.append(k);
}
return encodedString.toString();
}
import java.util.Scanner;
/**
* #author jyotiv
*
*/
public class RunLengthEncoding {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Enter line to encode:");
Scanner s=new Scanner(System.in);
String input=s.nextLine();
int len = input.length();
int i = 0;
int noOfOccurencesForEachChar = 0;
char storeChar = input.charAt(0);
String outputString = "";
for(;i<len;i++)
{
if(i+1<len)
{
if(input.charAt(i) == input.charAt(i+1))
{
noOfOccurencesForEachChar++;
}
else
{
outputString = outputString +
Integer.toHexString(noOfOccurencesForEachChar+1) + storeChar;
noOfOccurencesForEachChar = 0;
storeChar = input.charAt(i+1);
}
}
else
{
outputString = outputString +
Integer.toHexString(noOfOccurencesForEachChar+1) + storeChar;
}
}
System.out.println("Encoded line is: " + outputString);
}
}
I have tried this one. It will work for sure.