how to compare two strings to find common substring - java

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";
}

Related

HackerRank Anagram program in JAVA is running fine on my Eclipse but not on HackerRank platform

I am trying out a HackerRank problem in JAVA. It is running fine on my Eclipse but it is not giving the expected output on HackerRank platform. The problem is to check whether two strings are anagrams of each other or not (ignoring their case). Link to the problem: https://www.hackerrank.com/challenges/java-anagrams/problem?isFullScreen=true
Below is the code:
import java.util.Scanner;
public class Solution {
static boolean isAnagram(String a, String b) {
if(a.length()!=b.length())
return false;
char c1[]=a.toCharArray();
char c2[]=b.toCharArray();
java.util.Arrays.sort(c1);
java.util.Arrays.sort(c2);
a=String.valueOf(c1);
b=String.valueOf(c2);
if(a.equalsIgnoreCase(b))
return true;
else
return false;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String a = scan.next();
String b = scan.next();
scan.close();
boolean ret = isAnagram(a, b);
System.out.println( (ret) ? "Anagrams" : "Not Anagrams" );
}
}
It is passing two test cases but not the third one in which String a="Hello" and String b="hello".
But it is passing this test case on eclipse.
Please advise.
At the end of the sorting your arrays contains,
char c1[]=a.toCharArray();
char c2[]=b.toCharArray();
java.util.Arrays.sort(c1); // c1 = ['H','e','l','l','o']
java.util.Arrays.sort(c2); // c2 = ['e','h','l','l','o']
After this step when you convert this back to String,
a=String.valueOf(c1); //a = "Hello"
b=String.valueOf(c2); //b = "ehllo"
Hence it return false when you compare the a and b.
Solution: you might want to convert the strings to lowercase/uppercase before you sort them by using (toLowerCase() or toUpperCase()).
To solve this problem we have to create an int array for character frequency of size 26 ( 26 size is for every alphabet) which is initialized to zero so that we have 26 zeros in the array.
int[] frequency = new int[26];
then we will loop through first string creating an int index which will count the frequency of each alphabet in the string and increment the index of the frequency array representing that particular alphabet for example if the string is CAT the frequency[0], frequency[2]and frequency[19] will be incremented as 'C', 'A', and 'T' are represented by 2,0 and 19 indexes respectively.
for(int i=0;i<a.length();i++){
int index = a.charAt(i)-'a';
frequency[index]++;
}
now we will loop through second string the same way we did with first-string but in this case, rather then incrementing the frequency array we will decrement the frequency.
for(int i=0;i<b.length();i++){
int index = b.charAt(i)-'a';
frequency[index]--;
}
finally, we will check the frequency array if after performing the above operation all the indexes of frequency array come to zero it means that strings are anagram as the alphabets found in the first string which increment the frequency when found in the second string will decrease the frequency.
for(int i=0;i<26;i++){
if(frequency[i] != 0)
return false;
}
don't forget to convert string to lowercase before starting this otherwise, it shows runtime error.
a = a.toLowerCase();
b = b.toLowerCase();
for complete solution visit https://github.com/Gursimir/Java-Practice/blob/master/anagram.java

Checking if a word is a sub-Anagram of another (Java)

The words "unsold" & "silo" are sub-anagrams of the word "insidiously". That is, they can be spelt using only letters from "insidiously". There are obviously many more, and this concept is the basis of a word game found in 'The Australian' newspaper.
I'm trying to write a program that takes two arguments - a word, and another that might be a sub-anagram of this word and returns true if it is. So far this is what I've got:
public boolean isAnswer(String word, String base)
ArrayList<Character> characters = new ArrayList<>();
for(char x : base.toCharArray)
{
characters.add(x)
}
for(char y : word.toCharArray)
{
if(characters.contains(x))
{
characters.remove(x)
}
else
{
return false;
}
return true;
}
It does work, but if I'm looping through every word in the English dictionary this will be extremely taxing on memory. How can I do this without creating an ArrayList local variable?
If you want to make your existing program better consider using a SET instead of a LIST as it will
Eliminate the duplicate additions in your characters collection, saving space.
Save you some iterations in the next loop, saving time.
EDIT
However this optimization may not work in conditions pointed out by one of the comments.
EX - when an base has only "ab" & the word has "aab"
I would suggest you to go for a java.util.Set to avoid unnecessary iterations. Please find the code below:
private static boolean isSubAnagram() {
String str = "insidiously";
String anagram = "siloy";
Set<Character> set = new HashSet<Character>();
for(int i = 0 ; i < str.length() ; ++i){
set.add(new Character(str.charAt(i)));
}
int count = 0;
for(int i = 0 ; i < anagram.length() ; ++i){
if(set.contains(anagram.charAt(i))){
++count;
}
}
return count == anagram.length();
}
If the letter count in the base string and the so called sub anagram needs to be same then go for:
private static boolean isSubAnagram() {
String str = "insidiously";
String anagram = "siloyl";
List<Character> list = new ArrayList<Character>();
for(int i = 0 ; i < str.length() ; ++i){
list.add(new Character(str.charAt(i)));
}
for(int i = 0 ; i < anagram.length() ; ++i){
char curChar = anagram.charAt(i);
if(list.contains(curChar)){
list.remove(new Character(curChar));
continue;
}else{
return false;
}
}
return true;
}
One optimisation might be to first ensure that the word is not longer than the base.
public boolean isAnswer(String word, String base)
{
if (word.length() > base.length()) return false;
//...
}
I suspect if the words are exactly the same length, there may be a faster way than comparing all of the characters:
public boolean isAnswer(String word, String base)
{
if (word.length() > base.length()) {
return false;
}
else if (word.length() == base.length()) {
return isFullAnagram(); // I'll leave the implementation of this up to you
}
//...
}
The next step in optimising this would be to ensure you're not naively trying every word in the dictionary:
// Don't do this
public static void main(String... args)
{
String base = "something";
for (final String word : dictionary)
{
if (isAnswer(word, base)) // do something
}
}
// Don't do this
You have a big advantage in that any dictionary text file worth its salt will be pre-sorted. A basic optimisation would be to chunk your dictionary into 26 files - one for words starting with each letter - and skip any files which can't possibly match.
public static void main(String... args)
{
String base = "something";
Set<Characters> characters = // populate with chars from base
for (final Section section : dictionary)
{
if (characters.contains(section.getChar())
{
for (final String word : section)
{
if (isAnswer(word, base)) // do something
}
}
}
}
The next thing I would do is to look at parallelising this process. A basic approach would be to run each section on its own thread (so you're looking at up to about 12 threads for most common English words).
public static void main(String... args)
{
String base = "something";
Set<Characters> characters = // populate with chars from base
for (final Section section : dictionary)
{
if (characters.contains(section.getChar())
{
startMyThread(section, base);
}
}
}
You could get the threads to return a Future that you can check at the end. I'll leave that detail up to you.
A library like CUDA allows you to use very high concurrency by pushing computation to the GPU. You could have hundreds of threads running simultaneously. I'm not sure what a good strategy would look like in this case.
I'm working on the assumption that you'll only have to deal with the 26 letters of the Roman alphabet. Every such game I've seen in newspapers avoids words with diacritics: café, fiancée, naïve etc.
I believe this would be the solution that should run fast and consume the smallest amount of memory:
public class Snippet {
public static void main(String[] args) {
System.out.println(isAnswer("unsold", "insidiously"));
System.out.println(isAnswer("silo", "insidiously"));
System.out.println(isAnswer("silk", "insidiously"));
}
public static boolean isAnswer(String word, String base) {
char[] baseCharArr = base.toCharArray();
for (int wi = 0; wi < word.length(); wi++) {
boolean contains = false;
char wchar = word.charAt(wi);
for (int bi = 0; bi < baseCharArr.length; bi++) {
if (baseCharArr[bi]==wchar) {
baseCharArr[bi]='_'; // to not use this letter anymore we delete it using some sign that is non valid to from a word.
contains=true;
break;
}
}
if (!contains) {
return false;
}
}
return true;
}
}
Your code miss many {},;, () , It can't clearly compilet and work ^^, and i changed the order of the "if" and how to add all the base
public boolean isAnswer(String word, String base) {
ArrayList<Character> characters = new ArrayList<>();
characters.addAll(Arrays.asList(base.toCharArray()));
for (char y : word.toCharArray()) {
if (!characters.contains(y)) {
return false;
}
characters.remove(y);
}
return true;
}
You could directly replace in base. this is not very efficient and creates a lot of String objects but it is very easy to read:
public boolean isAnswer(String word, String base)
{
for (char ch : word.toCharArray())
{
base = base.replaceFirst("" + ch, "");
}
return base.trim().length() == 0;
}
Problems With the Current Approach / Other Answers
There are a lot of answers, but none of them is very efficient.
For every letter in a sub-anagram candidate, we search through a list and remove letters. One search takes linear time. Since we have to do a search for each letter, we end up with a quadratic time complexity.
Some people suggested to use a set instead of a list. Searching in a set takes constant time, so we would end up with linear time. However, the set approach fails when the same letter occurs multiple times.
The presented solutions are also slow because of constant speed factors. When we use List<Character> or Set<Character>, the chars of the String have to be boxed inside Character objects. Creating and handling these objects is much slower than using the primitive char type.
Solution
Multisets
We can us a multiset (also know as bag) to represent the letters in a word. For each word, we create a multiset of its letters and check whether that multiset is a subset of the base word's letter multiset.
Example
Base word "Food" has the multi set {f, o, o, d}.
Word "do" has the multi set {d, o}.
Word "dod" has the multi set {d, d, o}.
{d, o} is a subset of {f, o, o, d} ==> do is a sub-anagram of food.
{d, o, d} is not a subset of {f, o, o, d} ==> dod is not a sub-anagram of food.
Storing Multisets
Since we know, that only the characters 'a' to 'z' occur, we use an int array to represent a multiset. The value of array[0] is the number of 'a's; the value of array[1] is the number of 'b's, and so on.
array[1] can also be written as array['b' - 'a']
Example
The word "Food" with the multiset {f, o, o, d} is represented by the array
// Entry for: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
int[] multiSet = {0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0};
Subset Check
a is subset of b if and only if a[i] <= b[i] for all i.
When we do the subset test while computing the multiset a, we don't have to check all 26 array entries, but only the entries which were set to a value greater than zero.
Re-use Work
We want to check a lot of words for one base word. We can re-use the multiset for the base word and don't have to compute it over and over again.
Instead of writing a method that returns true or false, we write a method that returns the list of all sub-anagrams for a given base word and a given dictionary (list of words to be checked).
Minor optimizations
If a word is longer than the base word, it cannot be a sub-anagram. In such cases, we don't have to compute the multiset for that word.
Implementation
public static List<String> subAnagrams(String base, List<String> dictionary) {
char[] usableChars = new char['z' - 'a'];
base = base.toLowerCase();
for (int i = 0; i < base.length(); ++i) {
++usableChars[base.charAt(i) - 'a'];
}
List<String> subAnagrams = new ArrayList<>();
for (String candidate : dictionary) {
boolean isSubAnagram = candidate.length() <= base.length();
candidate = candidate.toLowerCase();
char[] usedChars = new char['z' - 'a'];
for (int i = 0; isSubAnagram && i < candidate.length(); ++i) {
int charIndex = candidate.charAt(i) - 'a';
isSubAnagram = ++usedChars[charIndex] <= usableChars[charIndex];
}
if (isSubAnagram) {
subAnagrams.add(candidate);
}
}
return subAnagrams;
}
Example usage
public static void main(String[] args) {
List<String> dict = new ArrayList<>();
dict.add("Do");
dict.add("Odd");
dict.add("Good");
dict.add("World");
dict.add("Foo");
System.out.println(subAnagrams("Food", dict));
}
prints [do, foo]

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.

Number of words in a string that are not in an array of strings

I want to create a method that returns the number of words in a string that have no occurrences of words in the array of strings. I want to implement this logic only using anything in the java.lang package.
public int count(String a, String[] b) {
}
E.g.
count(" hey are you there ", new String[]{ "are", "i", "am"})
would return 3 as there is the word "are" in the string.
First off, I think I have to use the string.split function to convert the string to an array of strings. Any ideas?
You could simply do something like:
public int count(String a, String[] b) {
int count = b.length;
for(String s : b) if(a.contains(s)) count--;
return count;
}
EDIT: I might have been confused, I thought you wanted the # of strings in b not in a (in your example it would still be 3). In that case, from your example, split seems inconvenient unless you use regex, so you could create a String[] using Scanner:
public int count(String a, String[] b) {
ArrayList<String> words = new ArrayList<String>();
Scanner scan = new Scanner(a);
while(scan.hasNext()) words.add(scan.next());
int count = words.size();
for(String s : words) if(/*b contains s*/) count--;
return count;
}
Follow the steps to complete the task.
Use StringTokenizer to tokenize the String a.
Convert String Array b to Collection, so that you can check if it contains the given token.
Use loop to get next token from StringTokenizer and check if it contains in List.
-
Try below code, it'll work.
EDIT : Using java.util package.
public int count(String a, String[] b) {
java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(a);
java.util.List bList = java.util.Arrays.asList(b);
int tokens = tokenizer.countTokens();
int counter = tokens;
for(int i=0;i<tokens;i++) {
String token = tokenizer.nextToken().trim();
if(bList.contains(token)) {
counter--;
}
}
return counter;
}
By using this, you can get the counter in just one for loop.
EDIT :: Using java.lang package only.
public int count(String a, String[] b) {
String[] words = a.split(" ");
int tokens = words.length;
int wordCount = 0;
int counter = 0;
for(int i=0;i<tokens;i++) {
String token = words[i].trim();
if(token.length() <= 0) {
continue;
}
wordCount++;
for(String bItem : b) {
if(bItem.equals(token)) {
counter++;
break;
}
}
}
return wordCount - counter;
}
You logic should go somewhat like this:
Split a, right. Now you have a list of words. In a real life, you should probably also try to clarify the requirement—what exactly is a “word”? A reasonable assumption is that it's a sequence of non-whitespace characters, but could be something different (for example, a sequence of letters).
Iterate over a and check whether each word is in b. If it isn't, increment your counter. But every check is a linear search in b, leading to the total complexity of O(nm), so...
Before iterating, convert b into a HashSet. This is a linear operation, but then your main loop will also become a linear operation, therefore the total complexity will be O(m + n).
If you have to do this thing repeatedly for different strings, but the same word list, consider creating a WordCounter class so you only have to create the HashSet once in the constructor.

The text within a String is rearranged after being submitted and returned back

I'm creating a program that takes single any characters between the ASCII codes of 32 - 126 and returns the result as Binary. It's a bunch of if statements with .contains("")'s. The code works when returning single characters, but when entering words, the Strings come back in binary re-alphabetized. So if I enter in the name Lauren it comes out in Binary like this: 010011000110000101100101011011100111001001110101-Laenru (capitals come first still).
Here's all my code:
Main.java
import java.util.Scanner;
public class Main {
public static Scanner input = new Scanner(System.in);
public static void main (String[] args) {
Letters l = new Letters();
l.Letters();
}
}
Letters.java
public class Letters extends Main {
#SuppressWarnings("null")
public static void Letters () {
System.out.println("Enter your letter(s)");
String givenLetters = input.next();
if (givenLetters.contains("A"))
System.out.println("01000001");
if (givenLetters.contains("B"))
System.out.println("01000010");
if (givenLetters.contains("C"))
System.out.println("01000011");
if (givenLetters.contains("D"))
System.out.println("01000100");
if (givenLetters.contains("E"))
System.out.println("01000101");
if (givenLetters.contains("F"))
System.out.println("01000110");
if (givenLetters.contains("G"))
System.out.println("01000111");
if (givenLetters.contains("H"))
System.out.println("01001000");
if (givenLetters.contains("I"))
System.out.println("01001001");
if (givenLetters.contains("J"))
System.out.println("01001010");
if (givenLetters.contains("K"))
System.out.println("01001011");
if (givenLetters.contains("L"))
System.out.println("01001100");
if (givenLetters.contains("M"))
System.out.println("01001101");
if (givenLetters.contains("N"))
System.out.println("01001110");
if (givenLetters.contains("O"))
System.out.println("01001111");
if (givenLetters.contains("P"))
System.out.println("01010000");
if (givenLetters.contains("Q"))
System.out.println("01010001");
if (givenLetters.contains("R"))
System.out.println("01010010");
if (givenLetters.contains("S"))
System.out.println("01010011");
if (givenLetters.contains("T"))
System.out.println("01010100");
if (givenLetters.contains("U"))
System.out.println("01010101");
if (givenLetters.contains("V"))
System.out.println("01010110");
if (givenLetters.contains("W"))
System.out.println("01010111");
if (givenLetters.contains("X"))
System.out.println("01011000");
if (givenLetters.contains("Y"))
System.out.println("01011001");
if (givenLetters.contains("Z"))
System.out.println("01011010");
if (givenLetters.contains(" "))
System.out.println("00100000");
if (givenLetters.contains("a"))
System.out.println("01100001");
if (givenLetters.contains("b"))
System.out.println("01100010");
if (givenLetters.contains("c"))
System.out.println("01100011");
if (givenLetters.contains("d"))
System.out.println("01100100");
if (givenLetters.contains("e"))
System.out.println("01100101");
if (givenLetters.contains("f"))
System.out.println("01100110");
if (givenLetters.contains("g"))
System.out.println("01100111");
if (givenLetters.contains("h"))
System.out.println("01101000");
if (givenLetters.contains("i"))
System.out.println("01101001");
if (givenLetters.contains("j"))
System.out.println("01101010");
if (givenLetters.contains("k"))
System.out.println("01101011");
if (givenLetters.contains("l"))
System.out.println("01101100");
if (givenLetters.contains("m"))
System.out.println("01101101");
if (givenLetters.contains("n"))
System.out.println("01101110");
if (givenLetters.contains("o"))
System.out.println("01101111");
if (givenLetters.contains("p"))
System.out.println("01110000");
if (givenLetters.contains("q"))
System.out.println("01110001");
if (givenLetters.contains("r"))
System.out.println("01110010");
if (givenLetters.contains("s"))
System.out.println("01110011");
if (givenLetters.contains("t"))
System.out.println("01110100");
if (givenLetters.contains("u"))
System.out.println("01110101");
if (givenLetters.contains("v"))
System.out.println("01110110");
if (givenLetters.contains("w"))
System.out.println("01110111");
if (givenLetters.contains("x"))
System.out.println("01111000");
if (givenLetters.contains("y"))
System.out.println("01111001");
if (givenLetters.contains("z"))
System.out.println("01111010");
}
}
I want the String to come out the same way the user will have entered it if that means I have to add code to re-rearrange the letters or that I need to fix something in my buggy code.
Thanks in advanced! :)
try
String givenLetters = input.next();
for(char c : givenLetters.toCharArray()) {
if (c == 'A')
System.out.println("01000001");
....
or better create a map
static Map<Character, String> map = new HashMap<>();
static {
map.put('A', "01000001");
...
}
then the code will be
for(char c : givenLetters.toCharArray()) {
String s = map.get(c);
if (s != null) {
System.out.print(s);
}
...
You problem is that givenLetters.contains("X") returns true if the substring "X" is found anywhere in the string givenLetters. As Evgeniy Dorofeev suggests, what you should do instead is to loop over the characters in the string one by one.
Of course, using a huge list of if statements (or even a huge array) is a silly way to convert a character to binary. Instead, you can do it bit by bit (demo on ideone.com):
char[] bits = new char[8];
for (char c : givenLetters.toCharArray()) {
for (int i = 0; i < 8; i++) {
int bitmask = 1 << (7-i);
bits[i] = ((c & bitmask) == 0 ? '0' : '1');
}
System.out.println(bits);
}
(Note that Java chars are actually 16 bits long; this code will only print the lowest 8 bits of each.)
Two comments:
1) To loop through the characters in the string...
for(int i=0; i<givenLetters.length(); i++) {
char c = givenLetters.charAt(i);
System.out.println(code[c]);
}
2) Make an array with your code to avoid that nasty if statement
private static String code[255];
static {
code['A'] = "01000001";
code['B'] = "01000010";
(and so on)
That allows you to use System.out.println(code[c]) in place of that huge if chain.
If you want to literally put the binary on the same line, replace println with print

Categories