Java String spilter - java

I have a string of annotation of country abbreviation , I want to split them out so I can identify the country of each abbreviation. Such that I will have String c = USA; I will output the country name...
currently it doesnt have c = USA but only A
public class Example {
public static void main(String[] args) {
String x = "USAIND";
String c = "";
System.out.print("Country: ");
for (int i = 0; i < 3; i++) {
c = Character.toString(x.charAt(i));
System.out.print(c);
if (c.equals("USA")) {
System.out.println("United State of America");
}
}
System.out.println("");
System.out.print("Country: ");
for (int i = 3; i < 6; i++) {
c = Character.toString(x.charAt(i));
System.out.print(c);
if (c.equals("IND")) {
System.out.println("India");
}
}
System.out.println("");
}
}

You need to append each character to your String and then compare it, otherwise, it'll just keep replacing your String with the last character always.
for (int i = 0; i < 3; i++) {
c += Character.toString(x.charAt(i)); // Appending all the characters one by one
}
System.out.print(c); // Printing the String c after all the characters are appending
if (c.equals("USA")) { // checking if its equal to USA
System.out.println("United State of America");
}
And the same goes with the other half of the process.
c = ""; // re-initialize it to blank
for (int i = 3; i < 6; i++) {
c += Character.toString(x.charAt(i));
}
System.out.print(c);
if (c.equals("IND")) {
System.out.println("India");
}
But the easiest way would be to use String.substring(startIndex, endIndex) for this.
String c = x.substring(0,3); // For USA
String c1 = x.substring(3,6); // For IND

because when you do this
c = Character.toString(x.charAt(i));
the character at the ith position is getting stored in c and as it is in a for loop the only thing that would be stored there would be 'A'
use a substring instead of the for loop and charAt
c = x.substring(0,3); \\which would give you "USA"

You should probably use String.substring(...) for this.

You are iterating through the string, but you only retain the last character because of this snippet:
c = Character.toString(x.charAt(i));
This should be:
c += Character.toString(x.charAt(i));
As this will append the current character iteration to the overall string. Replace the snippets with this fix, for the two loops. The c variable will build up the country code and will pass this condition this time:
if (c.equals("USA")) {
After the first loop and before the second loop, you will need to re-initialize the c variable:
c = "";
Once done, you can put that logic in a method of its own, so you avoid duplicate code within the loops.
This logic could be simplified by using String.substring instead, as others pointed out, as you work in details with the String.charAt which is more tedious. I thought though that pointing out your logic error was worth it, before giving you other pointers.
So talking about other approaches, you could try another one to your country code and name console output. Try to use a HashMap where the keys are the country code and the value is the country's name. You can iterate through the HashMap after that and print out both keys and values. That would be more high-level to your current solution and way shorter in code.
EDIT1: I offered the code to the last suggestion but I removed it, as I realized that giving code to assignment related questions is not encouraged.

I would go another way, either try to add a terminal symbol like ";". If this is not possible you could check with String.contains("USA") if a certain country is set. But beaware it could happen that you will find a country not listed in because the combination of two others.

With your logic, I thing it will be better to use
public String substring(int beginIndex, int endIndex)
Get the substring for a start index and the end index and compare. Currently you are just getting the character .With your current implementation you have to convert each character to String and append.

For the part of splitting, I would use Guava's Splitter, like so:
Splitter.fixedLength(3).split(x)
And for the part of matching abbreviation with full name, I would use an enum instead of equals comparing, it seems a little cleaner. So, a possible full result would be:
public class Example {
public static enum Country {
USA("United States of America"), IND("India");
String fullName;
Country(String fullName) {
this.fullName = fullName;
}
String getFullName() {
return fullName;
}
};
public static void main(String[] args) {
String x = "USAINDUSAIND";
for (String s : Splitter.fixedLength(3).split(x)) {
System.out.println(Country.valueOf(s).getFullName());
}
}
}
EDIT: Sorry about using third party, seemed clean to me. I agree with the other answers in using substring, but I like more thinking of everything as just one process and not two, so you can easily have a string of more than 2 abbreviations, like (example assuming the Enum as above)
public static void main(String[] args) {
String x = "USAINDUSAIND";
for (int i = 0;i < x.length();i += 3) {
System.out.println(Country.valueOf(x.substring(i, i + 3).getFullName());
}
}

Related

how to compare two strings to find common substring

i get termination due to timeout error when i compile. Please help me
Given two strings, determine if they share a common substring. A substring may be as small as one character.
For example, the words "a", "and", "art" share the common substring "a" . The words "be" and "cat" do not share a substring.
Input Format
The first line contains a single integer , the number of test cases.
The following pairs of lines are as follows:
The first line contains string s1 .
The second line contains string s2 .
Output Format
For each pair of strings, return YES or NO.
my code in java
public static void main(String args[])
{
String s1,s2;
int n;
Scanner s= new Scanner(System.in);
n=s.nextInt();
while(n>0)
{
int flag = 0;
s1=s.next();
s2=s.next();
for(int i=0;i<s1.length();i++)
{
for(int j=i;j<s2.length();j++)
{
if(s1.charAt(i)==s2.charAt(j))
{
flag=1;
}
}
}
if(flag==1)
{
System.out.println("YES");
}
else
{
System.out.println("NO");
}
n--;
}
}
}
any tips?
Below is my approach to get through the same HackerRank challenge described above
static String twoStrings(String s1, String s2) {
String result="NO";
Set<Character> set1 = new HashSet<Character>();
for (char s : s1.toCharArray()){
set1.add(s);
}
for(int i=0;i<s2.length();i++){
if(set1.contains(s2.charAt(i))){
result = "YES";
break;
}
}
return result;
}
It passed all the Test cases without a time out issue.
The reason for the timeout is probably: to compare two strings that each are 1.000.000 characters long, your code needs 1.000.000 * 1.000.000 comparisons, always.
There is a faster algorithm that only needs 2 * 1.000.000 comparisons. You should use the faster algorithm instead. Its basic idea is:
for each character in s1: add the character to a set (this is the first million)
for each character in s2: test whether the set from step 1 contains the character, and if so, return "yes" immediately (this is the second million)
Java already provides a BitSet data type that does all you need. It is used like this:
BitSet seenInS1 = new BitSet();
seenInS1.set('x');
seenInS1.get('x');
Since you're worried about execution time, if they give you an expected range of characters (for example 'a' to 'z'), you can solve it very efficiently like this:
import java.util.Arrays;
import java.util.Scanner;
public class Whatever {
final static char HIGHEST_CHAR = 'z'; // Use Character.MAX_VALUE if unsure.
public static void main(final String[] args) {
final Scanner scanner = new Scanner(System.in);
final boolean[] characterSeen = new boolean[HIGHEST_CHAR + 1];
mainloop:
for (int word = Integer.parseInt(scanner.nextLine()); word > 0; word--) {
Arrays.fill(characterSeen, false);
final String word1 = scanner.nextLine();
for (int i = 0; i < word1.length(); i++) {
characterSeen[word1.charAt(i)] = true;
}
final String word2 = scanner.nextLine();
for (int i = 0; i < word2.length(); i++) {
if (characterSeen[word2.charAt(i)]) {
System.out.println("YES");
continue mainloop;
}
}
System.out.println("NO");
}
}
}
The code was tested to work with a few inputs.
This uses a fast array rather than slower sets, and it only creates one non-String object (other than the Scanner) for the entire run of the program. It also runs in O(n) time rather than O(n²) time.
The only thing faster than an array might be the BitSet Roland Illig mentioned.
If you wanted to go completely overboard, you could also potentially speed it up by:
skipping the creation of a Scanner and all those String objects by using System.in.read(buffer) directly with a reusable byte[] buffer
skipping the standard process of having to spend time checking for and properly handling negative numbers and invalid inputs on the first line by making your own very fast int parser that just assumes it's getting the digits of a valid nonnegative int followed by a newline
There are different approaches to solve this problem but solving this problem in linear time is a bit tricky.
Still, this problem can be solved in linear time. Just apply KMP algorithm in a trickier way.
Let's say you have 2 strings. Find the length of both strings first. Say length of string 1 is bigger than string 2. Make string 1 as your text and string 2 as your pattern. If the length of the string is n and length of the pattern is m then time complexity of the above problem would be O(m+n) which is way faster than O(n^2).
In this problem, you need to modify the KMP algorithm to get the desired result.
Just need to modify the KMP
public static void KMPsearch(char[] text,char[] pattern)
{
int[] cache = buildPrefix(pattern);
int i=0,j=0;
while(i<text.length && j<pattern.length)
{
if(text[i]==pattern[j])
{System.out.println("Yes");
return;}
else{
if(j>0)
j = cache[j-1];
else
i++;
}
}
System.out.println("No");
return;
}
Understanding Knuth-Morris-Pratt Algorithm
There are two concepts involved in solving this question.
-Understanding that a single character is a valid substring.
-Deducing that we only need to know that the two strings have a common substring — we don’t need to know what that substring is.
Thus, the key to solving this question is determining whether or not the two strings share a common character.
To do this, we create two sets, a and b, where each set contains the unique characters that appear in the string it’s named after.
Because sets 26 don’t store duplicate values, we know that the size of our sets will never exceed the letters of the English alphabet.
In addition, the small size of these sets makes finding the intersection very quick.
If the intersection of the two sets is empty, we print NO on a new line; if the intersection of the two sets is not empty, then we know that strings and share one or more common characters and we print YES on a new line.
In code, it may look something like this
import java.util.*;
public class Solution {
static Set<Character> a;
static Set<Character> b;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
for(int i = 0; i < n; i++) {
a = new HashSet<Character>();
b = new HashSet<Character>();
for(char c : scan.next().toCharArray()) {
a.add(c);
}
for(char c : scan.next().toCharArray()) {
b.add(c);
}
// store the set intersection in set 'a'
a.retainAll(b);
System.out.println( (a.isEmpty()) ? "NO" : "YES" );
}
scan.close();
}
}
public String twoStrings(String sOne, String sTwo) {
if (sOne.equals(sTwo)) {
return "YES";
}
Set<Character> charSetOne = new HashSet<Character>();
for (Character c : sOne.toCharArray())
charSetOne.add(c);
Set<Character> charSetTwo = new HashSet<Character>();
for (Character c : sTwo.toCharArray())
charSetTwo.add(c);
charSetOne.retainAll(charSetTwo);
if (charSetOne.size() > 0) {
return "YES";
}
return "NO";
}
This must work. Tested with some large inputs.
Python3
def twoStrings(s1, s2):
flag = False
for x in s1:
if x in s2:
flag = True
if flag == True:
return "YES"
else:
return "NO"
if __name__ == '__main__':
q = 2
text = [("hello","world"), ("hi","world")]
for q_itr in range(q):
s1 = text[q_itr][0]
s2 = text[q_itr][1]
result = twoStrings(s1, s2)
print(result)
static String twoStrings(String s1, String s2) {
for (Character ch : s1.toCharArray()) {
if (s2.indexOf(ch) > -1)
return "YES";
}
return "NO";
}

Writing method that spells word backwords and identifies number of palindromes

I'm new to java and I wrote this method to input a string word and output the word spelled backwards. The intent is to create a method and not use an already existing method such as the simple reverse. Please help point me in the direction of how to do this to reverse a word. I'm also trying to determine/count if there are palindromes. Please help! I've read other questions and I can't find anything specific enough to my case. I know that my code doesn't run, though I'm unsure how to fix it to get the correct output.
An example would be the word "backwards" to go to "sdrawkcab".
public static int reverseWord(String word) {
int palindromes = 0;
for (int i = word.length(); i >= 0; i--) {
System.out.print(i);
word.equalsIgnoreCase();
if (word.charAt(i)) == index(word.charAt(0 && 1))) {
palindromes++
System.out.println(palindromes)
}
return i;
}
}
There are multiple problems with your code.
1.The prototype of equalsIgnoreCase is
public boolean equalsIgnoreCase(String str);
So this method expect a String to be passed,but your not not passing anything here.To fix this,pass another string with whom you want to match your word like this..
word.equalsIgnoreCase("myAnotherString");
2.word.charAt(i);
Suppose word="qwerty",so indexing of each character will be like this
/* q w e r t y
0 1 2 3 4 5 */
So when you use i = word.length();i will 6 since word is of length 6.So
word.charAt(i) will search for character at index 6,but since there is not index 6,it will return an exception ArrayIndexOutOfBound.To fix this,start i from word.length()-1.
3.if (word.charAt(i));
This extra " ) ".Remove it.
Is Index() your own method?.If Yes,then check that also.
the below code prints the reverse of the input string and checks if it is a palindrome
public static void main(String[] args) {
String input = "dad";
char temp[] = input.toCharArray();//converting it to a array so that each character can be compared to the original string
char output[] = new char[temp.length];//taking another array of the same size as the input string
for (int i = temp.length - 1, j = 0; i >= 0; i--, j++) {//i variable for iterating through the input string and j variable for inserting data into output string.
System.out.print(temp[i]);//printing each variable of the input string in reverse order.
output[j] = temp[i];//inserting data into output string
}
System.out.println(String.valueOf(output));
if (String.valueOf(output).equalsIgnoreCase(input)) {//comparing the output string with the input string for palindrome check
System.out.println("palindrome");
}
}
Because your question about what is wrong with your code was already answered here is another way you could do it by using some concepts which are somewhat less low level than directly working with character arrays
public static boolean printWordAndCheckIfPalindrome(final String word) {
// Create a StringBuilder which helps when building a string
final StringBuilder reversedWordBuilder = new StringBuilder("");
// Get a stream of the character values of the word
word.chars()
// Add each character to the beginning of the reversed word,
// example for "backwards": "b", "ab", "cab", "kcab", ...
.forEach(characterOfString -> reversedWordBuilder.insert(0, (char) characterOfString));
// Generate a String out of the contents of the StringBuilder
final String reversedWord = reversedWordBuilder.toString();
// print the reversed word
System.out.println(reversedWord);
// if the reversed word equals the given word it is a palindrome
return word.equals(reversedWord);
}

Java 8 : How to REDUCE compile time for the following code?

How to improve the performance of this code, reducing the compile time and keeping the functionality of the code same ?
The code is to extract two sub-strings from different strings and concatinating them to provide the largest possible palindromic string.
the Question was :You have two strings, (a) and (b). Find a string, (c), such that: (c)=(d)+(e).
(d),(e) can be expressed as where (d) is a non-empty substring of (a) and (e) is a non-empty substring of (b).
(c) is a palindromic string.
The length of is as long as possible.
For each of the pairs of strings (a) and (b) received as input, find and print string on a new line. If you're able to form more than one valid string , print whichever one comes first alphabetically. If there is no valid answer, print -1 instead.
import java.io.*;
import java.util.*;
public class Solution {
boolean isPalindrome(String s) {
int n = s.length();
for (int i=0;i<(n / 2);++i) {
if (s.charAt(i) != s.charAt(n - i - 1)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
String result="";
Scanner in = new Scanner(System.in);
int n = in.nextInt();
for(int a=0; a<n; a++)
{int length1, length2, i,c,d,j;
int max_length=0;
String string1 = in.next();
String sub1,sub2;
String string2 = in.next();
length2=string2.length();
length1 = string1.length();
for( c = 0 ; c <length1 ; c++ )
{
for( i = length1-c ; i >0 ; i-- )
{
sub1 = string1.substring(c, c+i);
for( d = 0 ; d < length2 ; d++ )
{
for( j = length2-d ; j >0 ; j-- )
{
sub2 = string2.substring(d, d+j);
String temp=sub1+sub2;
Solution obj= new Solution();
if(temp.length()>=max_length && obj.isPalindrome(temp)==true)
{
if (max_length==temp.length())
{ if(temp.compareTo(result)<0)
{
result=temp;
}}
else {
max_length=temp.length();
result=temp;
}
}
}
}
}
}
if(max_length==0)
System.out.println(-1);
else
{
System.out.println(result);
result="";
}
} /* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
}
}
I assume you want to reduce execution time, as opposed to compile time.
It is always best to avoid guessing, and rather determine exactly how the time is spent.
This is a good example.
If you do have a guess, this will prove it, or disprove it by showing you what the real problem is.
I have a guess (and it's only a guess).
You have a three-level nested loop, and inside the innermost loop I see a bunch of things that look suspicious.
The biggest one is new Solution().
That hits the memory manager, which can be very costly, not only to make the objects, but to clean them up.
Maybe you could move that out of the inner loop.
After that comes String temp=sub1+sub2;, which also hits the memory manager to make a new string.
Maybe you could make use the the string builder.
After that comes isPalindrome.
Whether that is efficient or not, I don't know.
Finally, your code needs much more disciplined indentation.
That alone can cause all kinds of bugs due to not being able to follow what you're doing.

String splitting and wrapping

Suppose I am given this string-
String A_Old[]="010.011.100.000.111";
On every occurrence of "000" I am expected to break the string and wrap the end towards the front of the string. The resultant should look like this-
String A_New[]="111.010.011.100";
Any help on how to tackle this problem would be appreciated.
Also, what do I do when there are multiple occurrences of "000"?
String A_Old[]="010.011.100.000.111.001.011.000.101.110";
should convert to :
String A_New[]="101.110.111.001.011.010.011.100";
Code in java or c++ is understood and appreciated.
EDIT
This was what I thought would work-
String b[]=A_Old.split(".000.",2); //should split the string in 2 parts.
A_New=b[1].concat(b[0]); // concatenation with a loss of a period
I was told to avoid the loss of the period as well as not using dummy variables. Both of which fails here. Any idea on how to tackle this?
To rotate the list, you wanna split and then concatenate in the order you want. You probably want to check for blanks/if it's the last element.
public static void main(String[] args)
{
String inString = "010.011.100.000.111";
String outString = "";
String[] arr = inString.split("\\.000\\.");
outString = arr[0];
for(int i = 1; i < arr.length; i++)
{
outString = outString + arr[i];
}
System.out.println(outString);
}
By Using Split method and reverse forloop in java
public static void main(String[] args) {
//insert code here
String A_Old="010.011.100.000.111.001.011.000.101.110";
String A_new ="";
String newe[]=A_Old.split("\\.000");
for(int i=newe.length-1;i>=0;i--){
A_new+=newe[i];
}
System.out.print(A_new.replaceFirst("\\.", ""));
}
I tried it in java:
public static String convert(String in) {
String[] strs = in.split("\\.*000\\.*");
StringBuilder sb = new StringBuilder();
for (int i = strs.length - 1; i >= 0; --i) {
sb.append(strs[i]);
if (i > 0 && strs[i - 1].length() > 0) {
sb.append(".");
}
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(convert("010.011.100.000.111"));
System.out.println(convert("010.011.100.000.111.001.011.000.101.110"));
System.out.println(convert("010.011.100.111"));
System.out.println(convert("000.010.011.100.111"));
System.out.println(convert("010.011.100.111.000"));
System.out.println(convert("000.010.011.100.111.000"));
}
Output:
111.010.011.100
101.110.111.001.011.010.011.100
010.011.100.111
010.011.100.111
010.011.100.111
010.011.100.111
"No dummy variables" sounds like a recursive solution is sought. Is this a Scheme class?
Here's a Perl solution. C++11 is sufficiently high-level to provide most of the facilities demonstrated here:
my #tests = (
'010.011.100.000.111',
'010.011.100.000.111.001.011.000.101.110'
);
foreach ( #tests ) {
print "$_ => ", rotate($_), "\n"; # Call our rotate routine, and show results.
}
sub rotate {
# Split the string into components, reverse their order, join them with '.'
return join('.', reverse split /(?:^|\.)000(?:\.|$)/, shift);
}
No dummy variables. In fact, no explicit variables either.
Here's how the split regex works:
(?:^|\.) # Match either start of string, or a dot.
000 # Match three zeros.
(?:\.|$) # Match either a dot, or the end of string.
This permits the 000 to appear anywhere in the string (including beginning or end). If it appears at the beginning, there will not need to be a leading dot. If it appears at the end, a trailing dot will not be required. Anywhere else, dots must surround the 000.
Update:
Here is a recursive solution using Perl. From what I've read of the Java solutions (I'm not a Java guy), it seems like translation should be straightforward for someone with some Java background.
my #tests = (
'010.011.100.000.111',
'010.011.100.000.111.001.011.000.101.110'
);
foreach ( #tests ) {
print "($_) => (", rotate($_), ")\n";
}
sub rotate {
my( $ok, $rest ) = split /(?:^|\.)000(?:\.|$)/, $_[0], 2;
return $ok unless defined $rest;
return join( '.', rotate($rest), $ok);
}
Update2:
And here's another Perl solution that eliminates any explicit variables, using only subroutine parameters:
my #tests = (
'010.011.100.000.111',
'010.011.100.000.111.001.011.000.101.110'
);
foreach ( #tests ) {
print "($_) => (", rotate($_), ")\n";
}
sub rotate {
return sub {
return $_[0] unless defined $_[1];
return join( '.', rotate($_[1]), $_[0]);
}->( split /(?:^|\.)000(?:\.|$)/, shift, 2 );
}
I have no idea how one would translate that Java. I suspect translation would become a little more difficult, though I'm confident there must exist a semantically equivalent C++11 solution.

How to look for a target in an array using two string array's

So in looking around for an answer to my question, i have only been able to find map structures or just comparing the strings and having to code to stop. I need to be able to essentially translate between languages and print out the translation and have the user to able to ask again to translate another word. I have 2 strings of 10 matching words from English to Russian. I need to able to use a target (or key) to find the translation. Also I need to use a sequential search.
import java.util.*;
public class CISCLabTwo
{
public static void main (String [] args)
{
Scanner keyBoard = new Scanner (System.in);
String [] english = {"House", "Fat", "Monkey", "Trip", "Jumbo", "Chicken", "Unicorn", "Radio", "Shack", "Xylophone"};
String [] russian = {"Dom", "Zhir", "Obeziana", "Poezdka", "Ogromniy", "Kuricha", "Edinorog", "Raadiioo", "Hizhina", "Ksilofon"};
System.out.println ("House, Fat, Monkey, Trip, Jumbo, Chicken, Unicorn, Radio, Shack, Xylophone");
System.out.println("Enter a Word From Above to Translate to Russian: ");
int i = 0;
for (i = 0; i < english.length; i++)
if (english[i]=target){
return i;
}
else{
return - 1;
}
}//end class
public static int translate (String [] english, String target)
}//end main
http://en.wikipedia.org/wiki/Sequential_search
Basically you create a for-loop checking for a match in the english array.
When you have a match the function will return the position of the string in the given array. Use this position to get the corresponding Russian translation.
public static int translate(String [] english, String target)
{
for(int i = 0; i < english.length; i++){
if(english[i].equals(target)){
// Found on position i
return i;
}
}
return -1;
}
You might want to rename the function because it doesn't really translate and only returns an integer and not a string.
Firstly, it's confusing to individually handle two arrays in this way. You probably want to create an extra class in the same file:
class Word {
String english;
String russian;
}
Then you can create the following array:
Word[] words = new Word[10];
That way, you can translate using a separate method, as follows:
String translate(String eng) {
for (Word w : words) if (eng.equals(w.english)) return w.russian;
return null;
}
All you need to do is get the index, print the Russian word then break the loop.
If just printing within main then you can do this.
for (i = 0; i < english.length; i++)
{
if (english[i].equals(target))
{
System.out.println(russian[i]; //Print the russian word
break; //stop looping
}
}
Otherwise if you want to have your translate method that returns the index of the word you could do it like so
public static int translate (String [] english, String target)
{
for (i = 0; i < english.length; i++)
{
if (english[i].equals(target))
return i; // No need for the else statement as it would
// fail on first iteration if it wasnt the word
}
return -1; // After loop exits return -1 as was not found
}
Then in main you would call
String russianWord = russian[translate(english, target)];
As for your code, the proper check is in your for-next loop is
if (english[i].equals(target))
return i;
Also, consider whether the case of the words matters. In your example, is "House" the same as "house"? If case doesn't matter, you should use equalsIgnoreCase() instead of equals, i.e.
if (english[i].equalsIgnoreCase(target))
return i;
(moved later cause it seems like this was homework)
You could save yourself a little work by using two ArrayList to hold the words, since ArrayList has an indexOf() method to do the linear search. (I have no idea why the Arrays utility class does not have an indexOf method).
That said, a map based structure seems like a much better fit (and will be more efficient).

Categories