how to compare two strings visually in java? - java

As of now I am making a small program that compares two string with the outcome of true and false. However, the program needs to say true if it visually looks the same. for example if it say box and b0x then it would be true. As of now the outcome is looking false as shown below.
Enter First String:
box
Enter Second String:
b0x
false
the string below needs to be considered the same
0, o and Q
1, I and T
2 and Z
5 and S
8 and B
below is my current work
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
{
Scanner sc = new Scanner(System.in);
System.out.println("Enter First String:");
String str1 = sc.nextLine();
System.out.println("Enter Second String:");
String str2 = sc.nextLine();
sc.close();
String string1 = new String("0");
String string2 = new String("o");
String string3 = new String("q");
String string4 = new String("1");
String string5 = new String("l");
String string6 = new String("T");
String string7 = new String("2");
String string8 = new String("z");
String string9 = new String("5");
String string10 = new String("s");
String string11 = new String("8");
String string12 = new String("b");
// Comparing for String 3 = String 4
if (str1.equals(str2))
{
System.out.print(true);
}
else if(string1.equals(str1))
{
System.out.print(true);
}
else if(string2.equals(str2))
{
System.out.print(true);
}
else
{
System.out.print(false);
}
}
}
}
Is there any algorithm that I can use or any way where the program can detect as true even when they are visually the same. I appreciate any help, thank you

The answer to this question (as well as most questions about pattern matching in Strings) is regular expressions. All you need to do is use replaceAll for all your character transformations to normalize your strings.
like:
str1 = str1.replaceAll("[oQ]", 0);
str1 = str1.replaceAll("[IT]", 1);

First of all, when you declare String variables, you don't have to make a constructor call each time.
String string1 = "0" // that is fine. No need to call constructor.
Then, I advise you to create a collection of all the characters that are supposed to look the same.
Iterate over all the characters of the first input, and check if :
each character of the first input is equal to each character of the second input
if it is a "look visually the same character", check if second input contains the associated(s) character(s).
According to the data you provided, I suggest you this solution, though it is not the perfect one :
import javafx.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
private static List<List<Character>> charactersVisuallyLookingTheSame = new ArrayList<>();
public static void main(String[] args) {
initCharactersThatLookTheSame();
Scanner sc = new Scanner(System.in);
System.out.println("Enter First String:");
String str1 = sc.nextLine();
System.out.println("Enter Second String:");
String str2 = sc.nextLine();
sc.close();
boolean equal = equalsVisually(str1, str2);
System.out.println(equal);
}
private static boolean equalsVisually(String first, String second)
{
// some checks just in case...
if(first == null || second == null)
{
return false;
}
// to be equal visually, they must have the same length.
if(first.length() != second.length())
{
return false;
}
char[] firstAsArray = first.toCharArray();
char[] secondAsArray = second.toCharArray();
for(int i = 0; i < firstAsArray.length; i++)
{
// if it is different
if(firstAsArray[i] != secondAsArray[i])
{
if(!isCharVisuallyLookingTheSame(firstAsArray[i], secondAsArray[i]))
{
return false;
}
}
}
return true;
}
private static boolean isCharVisuallyLookingTheSame(char first, char second)
{
// we check if it looks visually the same
for(List<Character> visuallyTheSameList : charactersVisuallyLookingTheSame)
{
boolean doesFirstStringContainVisualChar = false;
for(Character c1 : visuallyTheSameList)
{
if(first == c1)
{
boolean doesSecondStringCharVisuallyEquals = false;
for(Character c2 : visuallyTheSameList)
{
if((second == c2))
{
return true;
}
}
}
}
}
return false;
}
private static void initCharactersThatLookTheSame()
{
// these lists contain all the characters that look visually the same.
// add in here any list of characters that visually look the same.
List<Character> o = new ArrayList<>();
charactersVisuallyLookingTheSame.add(o);
o.add('0');
o.add('o');
o.add('Q');
List<Character> i = new ArrayList<>();
charactersVisuallyLookingTheSame.add(i);
i.add('1');
i.add('I');
i.add('T');
List<Character> z = new ArrayList<>();
charactersVisuallyLookingTheSame.add(z);
z.add('2');
z.add('Z');
List<Character> S = new ArrayList<>();
charactersVisuallyLookingTheSame.add(S);
S.add('5');
S.add('S');
List<Character> B = new ArrayList<>();
charactersVisuallyLookingTheSame.add(B);
B.add('8');
B.add('B');
}
}
Some outputs :
I guess that will do the job. don't hesitate to execute it in debug mode if there are any problems. I fast coded this and I could have made mistakes.
But overall, I suggest you to : use regular expressions. It was suggested by another answer and I think that can only be better than this. Nevertheless, regular expressions can be hard to understand...

The other option would be to build a Map with a common Identifier between similar values. Might be a bit more complicated, but should be more performant than looping a replaceAll multiple times to normalize both values.
import java.util.HashMap;
import java.util.Map;
public class VisuallySimilar
{
public static int id = 0;
public static Map<Character, Integer> map = new HashMap<>();
public static void similarChars(Character... chars) {
for(Character c : chars) {
map.put(c, id);
}
id++;
}
public static boolean areSimilar(String val1, String val2) {
if(val1.length() != val2.length())
return false;
char[] char1 = val1.toCharArray();
char[] char2 = val2.toCharArray();
for(int i = 0; i < char1.length; i++) {
if(char1[i] == char2[i] || map.get(char1[i]) == map.get(char2[i]))
continue;
return false;
}
return true;
}
public static void main(String[] args) {
similarChars('0', 'o', 'O', 'Q');
similarChars('T', 'I', '1');
String val1 = "b0x";
String val2 = "box";
System.out.println("Are Similar: " + areSimilar(val1, val2));
}
}

Related

How to read from input and report whether two strings have exactly the same 'tokens' at the exact same positions?

Im trying to basically report whether or not string1 and string2 contain exactly the same tokens in the same order. I can't find whats wrong with my code. I fixed the infinite loop but now it doesn't check an empty string.
public static boolean sameTokens (String s1, String s2)
{
Scanner scan1 = new Scanner(s1);
Scanner scan2 = new Scanner(s2);
boolean contains = true;
String token1 = scan1.next();
String token2 = scan2.next();
while (token1.length() <= token2.length())
{
if (!(scan1.hasNext() || scan2.hasNext()))
{
contains = false;
}
if (token1.equals(token2))
{
contains = true;
}
}
return contains;
}
These are my test cases.
#Test
public void testSameTokens ()
{
assertTrue(sameTokens("this is a test", " this is a test "));
assertTrue(sameTokens("", ""));
assertFalse(sameTokens("hello there", "hello there Joe"));
assertFalse(sameTokens("abc def", "def abc"));
assertFalse(sameTokens("a", "A"));
assertFalse(sameTokens("a b c", "abc"));
}
And this is the result.
Thanks in advance guys.
I modified your code and it outputs the expected true values.
public static boolean sameTokens(String s1, String s2) {
Scanner scan1 = new Scanner(s1);
Scanner scan2 = new Scanner(s2);
while(scan1.hasNext()||scan2.hasNext()){
if ((!scan1.hasNext() && scan2.hasNext()) || (!scan2.hasNext() && scan1.hasNext())) {
return false;
} else {
String token1 = scan1.next();
String token2 = scan2.next();
if (!token1.equals(token2)) {
return false;
}
}
}
return true;
}
Hope that helps.

Isogram- a word without repeated letters

I want to develop a java code to detect a repeated letter in word and print the desired result but mine keeps iterating and i have no idea on how to get about it. Here is the code:
import java.util.*;
public class Isogram {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("Enter the name: ");
String car = input.nextLine().toLowerCase();
char[] jhd = car.toCharArray();
Arrays.sort(jhd);
for(int ch = 0; ch < jhd.length; ch++){
try {
if (jhd[ch] == jhd[ch + 1]) {// || jhd[ch] == jhd[ch]){
System.out.print("THis is an Isogram");
} else {
System.out.println("Ripu from here");
}
} catch(ArrayIndexOutOfBoundsException ae) {
System.out.println(ae);
}
}
}
}
If u have an adjustment or a better code it will be helpful.
private static String isIsogram(String s){
String[] ary = s.split("");
Set<String> mySet = new HashSet<String>(Arrays.asList(ary));
if(s.length() == mySet.size()){
return "Yes!";
}else{
return "NO";
}
}
Create an array from the string.
Convert array to a List and then create a Set from that List. Set
keeps only unique values.
If set size equals the initial string length then it is an
isogram. If set is smaller than initial string then there were
duplicate characters.
public static boolean isIsogram(String str) {
boolean status = true;
char [] array = str.toCharArray();
Character[] charObjectArray = ArrayUtils.toObject(array);
Map<Character,Integer> map = new HashMap<>();
for (Character i : charObjectArray){
Integer value = 1;
if (map.containsKey(i)){
Integer val = map.get(i);
map.put(i,val+1);
}
else map.put(i,value);
}
for (Integer integer: map.values()){
if (integer>1){
status= false;
break;
}
else status = true;
}
return status;
}
}

Given a Morse String with out any spaces, how to find the no. of words it can represent irrespective of the meaning

Given A morse String eg. aet = ".- . -" if the spaces are removed it will become an ambiguous morse string ".-.-" which can represent "aet","eta","ent","etet" etc.
the problem is to find the no.of words that the morse string without spaces can represent irrespective of the meaning of the words. The constraint is that the new word which is formed should be the same size of the input i.e "aet" = "ent" and other words like "etet" should be discarded.
i implemented a recursive solution for some reason it is not working. below is my code and thinking of converting this to DP approach to increase time efficiency. Can some one help to point out the mistake in the below code and is DP a right approach to follow for this problem? Thanks in advance!!
EDIT 1 :- The program gives me an output but not the correct one. for ex. for the morse String representing aet = ".- . -" if given without any spaces to the program ".-.-" it should give an out put "3" i.e 3 words can be formed that is of the same size as the input including the input "aet","eta","ent" but it gives me an output "1". I think there is some thing wrong with the recursive calls.
The approach used here is to simply cut the morse string in a place where first valid morse code is encountered and the repeat the process with the rest of the string untill 3 such valid morse code are found and check whether whole morse string is consumed. if consumed increment the word count and repeat the process for different values of substring size(end variable in the below code).
I hope this helps!!.Tried my best to explain as clearly as I could.
import java.util.*;
import java.io.*;
import java.math.*;
import java.text.*;
public class MorseCode2 {
static Map<String,String> morseCode;
static Map<String,String> morseCode2;
static int count = 0;
public static void main(String args[]){
String[] alpha = {"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"};
String[] morse = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",
".--","-..-","-.--","--.."};
morseCode = new HashMap<String,String>();
morseCode2 = new HashMap<String,String>();
for(int i = 0;i<26;i++){
morseCode.put(morse[i],alpha[i]);
}
for(int i = 0;i<26;i++){
morseCode2.put(alpha[i],morse[i]);
}
Scanner in = new Scanner(System.in);
String input = in.next();
String morseString = "";
for(int j = 0; j< input.length(); j++){
morseString += morseCode2.get(input.charAt(j)+"");
}
countPossibleWord(morseString,input.length(),0,1,0);
System.out.println(count);
in.close();
}
public static void countPossibleWord(String s,int inputSize,int start,int end,int tempCount){
if(start >= s.length() || end > s.length()){
return;
}
if(tempCount>inputSize){
return;
}
String sub = s.substring(start, end);
if(sub.length()>4){
return;
}
if(morseCode.get(sub)!=null){
tempCount++;
countPossibleWord(s,inputSize,end,end+1,tempCount);
}
else{
countPossibleWord(s,inputSize,start,end+1,tempCount);
}
if(tempCount == inputSize && end == s.length()){
count++;
}
countPossibleWord(s,inputSize,start,end+1,0);
}
}
EDIT 2 :- Thank you all for your Responses and Extremely sorry for the confusing code, will surely try to improve on writing neat and clear code. learnt a lot from your replies!!
And i also some how made the code work, the problem was I passed wrong argument which changed the state of the recursive calls. Instead of passing "tempCount-1" for the last argument in the last function call in the method "countPossibleWord" i passed "0" this altered the state. found this after running through the code manually for larger inputs. below is the corrected method
public static void countPossibleWord(String s,int inputSize,int start,int end,int tempCount){
if(start >= s.length() || end > s.length()){
return;
}
if(tempCount>inputSize){
return;
}
String sub = s.substring(start, end);
if(sub.length()>4){
return;
}
if(morseCode.get(sub)!=null){
tempCount++;
countPossibleWord(s,inputSize,end,end+1,tempCount);
}
else{
countPossibleWord(s,inputSize,start,end+1,tempCount);
}
if(tempCount == inputSize && end == s.length()){
count++;
}
countPossibleWord(s,inputSize,start,end+1,tempCount-1);
}
}
If you like to have a recursive function, you should be clear about your parameters (use as few as possible) as well as when to step down and when to go up again.
My solution would look something like
public static int countPossibleWord(String strMorse, String strAlpha, int inputSize) {
if (strMorse.length() > 0) { // still input to process
if (strAlpha.length() >= inputSize)
return 0; // String already has wrong size
int count = 0;
for (int i = 0; i < morse.length; i++) { // try all morse codes
if (strMorse.startsWith(morse[i])) { // on the beginning of the given string
count += countPossibleWord(strMorse.substring(morse[i].length()), strAlpha+alpha[i], inputSize);
}
}
return count;
} else {
if( strAlpha.length() == inputSize ) {
System.out.println( strAlpha );
return 1; // one solution has been found
} else {
return 0; // String has wrong size
}
}
}
Your morse and alpha arrays need to be static variables for this to work.
Note that there is only one situation where the recursion will step down: when there is some input left and the size limit is not reached. Then it will check for the next possible letter in the loop.
All other cases will lead the recursion to go one step up again - and when going up, it will return the number of solutions found.
Call it like this:
System.out.println(countPossibleWord(morseString, "", input.length() ));
The fact that you use a class variable instead of the returned value of the recursive function makes it extremely unclear. Even for you as #Thomas Weller said. You should clarify the possible cases when a count one more letter. I deleted eclipse, hence I coded it in C, I hope I will still help you to understand the algo :(understand char* as string)
char morse[26][5] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",
".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
int countPossibleWord(char* s, int inputSize, int start, char* buffer, int sizeBuff){
if(start == inputSize){
if(sizeBuff == 0) return 1;
else return 0;
}
char buff[sizeBuff+2]; //
strncpy(buff, buffer, sizeBuff);//
buff[sizeBuff] = s[start]; // buff = buff+s[start]
buff[sizeBuff+1] = '\0'; //
for(int i = 0; i < 26; ++i){
//run the equivalent of your map to find a match
if(strcmp(buff, morse[i]) == 0)
return countPossibleWord(s, inputSize, start+1, "", 0) + countPossibleWord(s, inputSize, start+1, buff, sizeBuff+1);
}
return countPossibleWord(s, inputSize, start+1, buff, sizeBuff+1);
}
The problem with your code is, that you don't understand it any more, because it's not clean as described by Robert C. Martin. Compare your code to the following. This is certainly still not the cleanest, but I think you can understand what it does. Tell me if you don't.
Consider this main program:
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
String morsetext = enterTextOnConsole();
MorseTable morseTable = new MorseTable();
MorseCode code = convertToMorseCodeWithoutSpaces(morsetext, morseTable);
List<String> guesses = getAllPossibleMeanings(code, morseTable);
List<String> guessesOfSameLength = filterForSameLength(morsetext, guesses);
printListOnConsole(guessesOfSameLength);
}
private static void printListOnConsole(List<String> guessesOfSameLength) {
for (String text : guessesOfSameLength) {
System.out.println(text);
}
}
private static List<String> filterForSameLength(String morsetext, List<String> guesses) {
List<String> guessesOfSameLength = new LinkedList<String>();
for (String guess : guesses) {
if (guess.length() == morsetext.length())
{
guessesOfSameLength.add(guess);
}
}
return guessesOfSameLength;
}
private static List<String> getAllPossibleMeanings(MorseCode code, MorseTable morseTable) {
MorseCodeGuesser guesser = new MorseCodeGuesser(morseTable);
List<String> guesses = guesser.guess(code);
return guesses;
}
private static MorseCode convertToMorseCodeWithoutSpaces(String morsetext, MorseTable morseTable) {
MorseCode code = new MorseCode(morseTable);
code.fromText(morsetext);
code.stripSpaces();
return code;
}
private static String enterTextOnConsole() {
Scanner scanner = new Scanner(System.in);
String text = scanner.next();
scanner.close();
return text;
}
}
and the following MorseTable class:
import java.util.HashMap;
import java.util.Map;
public class MorseTable {
private static final Map<String, String> morseTable;
private static int longestCode = -1;
static
{
morseTable = new HashMap<String, String>();
morseTable.put("a", ".-");
morseTable.put("b", "-...");
morseTable.put("c", "-.-.");
morseTable.put("e", ".");
morseTable.put("t", "-");
morseTable.put("n", "-.");
// TODO: add more codes
for (String code : morseTable.values()) {
longestCode = Math.max(longestCode, code.length());
}
}
public String getMorseCodeForCharacter(char c) throws IllegalArgumentException {
String characterString = ""+c;
if (morseTable.containsKey(characterString)) {
return morseTable.get(characterString);
}
else {
throw new IllegalArgumentException("No morse code for '"+characterString+"'.");
}
}
public int lengthOfLongestMorseCode() {
return longestCode;
}
public String getTextForMorseCode(String morseCode) throws IllegalArgumentException {
for (String key : morseTable.keySet()) {
if (morseTable.get(key).equals(morseCode)) {
return key;
}
}
throw new IllegalArgumentException("No character for morse code '"+morseCode+"'.");
}
}
and the MorseCode class
public class MorseCode {
public MorseCode(MorseTable morseTable)
{
_morseTable = morseTable;
}
final MorseTable _morseTable;
String morseCode = "";
public void fromText(String morsetext) {
for(int i=0; i<morsetext.length(); i++) {
char morseCharacter = morsetext.charAt(i);
morseCode += _morseTable.getMorseCodeForCharacter((morseCharacter));
morseCode += " "; // pause between characters
}
}
public void stripSpaces() {
morseCode = morseCode.replaceAll(" ", "");
}
public MorseCode substring(int begin, int end) {
MorseCode subcode = new MorseCode(_morseTable);
try{
subcode.morseCode = morseCode.substring(begin, end);
} catch(StringIndexOutOfBoundsException s) {
subcode.morseCode = "";
}
return subcode;
}
public MorseCode substring(int begin) {
return substring(begin, morseCode.length());
}
public String asPrintableString() {
return morseCode;
}
public boolean isEmpty() {
return morseCode.isEmpty();
}
}
and last not least, the MorseCodeGuesser
import java.util.LinkedList;
import java.util.List;
public class MorseCodeGuesser {
private final MorseTable _morseTable;
public MorseCodeGuesser(MorseTable morseTable) {
_morseTable = morseTable;
}
public List<String> guess(MorseCode code) {
List<String> wordList = new LinkedList<String>();
if (code.isEmpty()) return wordList;
for(int firstCodeLength=1; firstCodeLength<=_morseTable.lengthOfLongestMorseCode(); firstCodeLength++) {
List<String> guesses = guess(code, firstCodeLength);
wordList.addAll(guesses);
}
return wordList;
}
private List<String> guess(MorseCode code, int firstCodeLength) {
MorseCode firstCode = code.substring(0, firstCodeLength);
String firstCharacter;
try{
firstCharacter = _morseTable.getTextForMorseCode(firstCode.asPrintableString());
} catch(IllegalArgumentException i) {
return new LinkedList<String>(); // no results for invalid code
}
MorseCode remainingCode = code.substring(firstCodeLength);
if (remainingCode.isEmpty()) {
List<String> result = new LinkedList<String>();
result.add(firstCharacter); // sole result if nothing is left
return result;
}
List<String> result = new LinkedList<String>();
List<String> remainingPossibilities = guess(remainingCode);
for (String possibility : remainingPossibilities) {
result.add(firstCharacter + possibility); // combined results
}
return result;
}
}
I have pasted my own solution to it. I have followed DFS and it is giving the correct answer for the given problem statement. Please ask if there are any queries.
alpha =["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"]
key = [".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--",
"-..-","-.--","--.."]
dic = dict(list(zip(key,alpha)))
def morse_code(morse,count,res,char,length):
global dic
if count == length - 1:
if morse[char:] in dic:
res = res + 1
return res
word = ''
for i in range(char,len(morse)):
word = word + morse[i]
if word not in dic:
continue
else:
count = count + 1
res = morse_code(morse,count,res,i+1,length)
count = count - 1
return res
if __name__ = 'main'
inp = input()
morse = ''
for i in inp:
morse = morse + key[ord(i)-ord('a')]
result = morse_code(morse,0,0,0,len(inp))
print(result)

how to capitalize first letter after period in each sentence using java?

I'm currently learning on how to manipulate strings and i think it'll take awhile for me to get used to it. I wanted to know how to capitalize a letter after a period in each sentence.
The output is like this:
Enter sentences: i am happy. this is genius.
Capitalized: I am happy. This is genius.
I have tried creating my own code but its not working, feel free to correct and change it. Here is my code:
package Test;
import java.util.Scanner;
public class TestMain {
public static void main(String[]args) {
String sentence = getSentence();
int position = sentence.indexOf(".");
while (position != -1) {
position = sentence.indexOf(".", position + 1);
sentence = Character.toUpperCase(sentence.charAt(position)) + sentence.substring(position + 1);
System.out.println("Capitalized: " + sentence);
}
}
public static String getSentence() {
Scanner hold = new Scanner(System.in);
String sent;
System.out.print("Enter sentences:");
sent = hold.nextLine();
return sent;
}
}
The tricky part is how am i gonna capitalize a letter after the period(".")? I don't have a lot of string manipulation knowledge so I'm really stuck in this area.
Try this:
package Test;
import java.util.Scanner;
public class TestMain {
public static void main(String[]args){
String sentence = getSentence();
StringBuilder result = new StringBuilder(sentence.length());
//First one is capital!
boolean capitalize = true;
//Go through all the characters in the sentence.
for(int i = 0; i < sentence.length(); i++) {
//Get current char
char c = sentence.charAt(i);
//If it's period then set next one to capital
if(c == '.') {
capitalize = true;
}
//If it's alphabetic character...
else if(capitalize && Character.isAlphabetic(c)) {
//...we turn it to uppercase
c = Character.toUpperCase(c);
//Don't capitalize next characters
capitalize = false;
}
//Accumulate in result
result.append(c);
}
System.out.println(result);
}
public static String getSentence(){
Scanner hold = new Scanner(System.in);
String sent;
System.out.print("Enter sentences:");
sent = hold.nextLine();
return sent;
}
}
What this is doing it advancing sequentially through all of the characters in the string and keeping state of when the next character needs to be capitalized.
Follow the comments for a deeper exaplanations.
You could implement a state machine:
It starts in the capitalize state, as each character is read it emits it and then decides what state to go to next.
As there are just two states, the state can be stored in a boolean.
public static String capitalizeSentence(String sentence) {
StringBuilder result = new StringBuilder();
boolean capitalize = true; //state
for(char c : sentence.toCharArray()) {
if (capitalize) {
//this is the capitalize state
result.append(Character.toUpperCase(c));
if (!Character.isWhitespace(c) && c != '.') {
capitalize = false; //change state
}
} else {
//this is the don't capitalize state
result.append(c);
if (c == '.') {
capitalize = true; //change state
}
}
}
return result.toString();
}
Here is solution with regular expressions:
public static void main(String[]args) {
String sentence = getSentence();
Pattern pattern = Pattern.compile("^\\W*([a-zA-Z])|\\.\\W*([a-zA-Z])");
Matcher matcher = pattern.matcher(sentence);
StringBuffer stringBuffer = new StringBuffer("Capitalized: ");
while (matcher.find()) {
matcher.appendReplacement(stringBuffer, matcher.group(0).toUpperCase());
}
matcher.appendTail(stringBuffer);
System.out.println(stringBuffer.toString());
}
Seems like your prof is repeating his assignments. This has already been asked:
Capitalize first word of a sentence in a string with multiple sentences
Use a pre-existing lib:
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/text/WordUtils.html#capitalize(java.lang.String,%20char...)
and guava
public static void main(String[] args) {
String sentences = "i am happy. this is genius.";
Iterable<String> strings = Splitter.on('.').split(sentences);
List<String> capStrings = FluentIterable.from(strings)
.transform(new Function<String, String>()
{
#Override
public String apply(String input){
return WordUtils.capitalize(input);
}
}).toList();
System.out.println(Joiner.on('.').join(capStrings));
}
Just use
org.apache.commons.lang3.text.WordUtils.capitalizeFully(sentence);
You can use below code to capitalize first letter after period in
each sentence.
String input = "i am happy. this is genius.";
String arr[] = input.split("\\.");
for (int i = 0; i < arr.length; i++) {
System.out.print(Character.toUpperCase(arr[i].trim().
charAt(0)) + arr[i].trim().substring(1) + ". ");
}
I'd go for regex as it is fast to use:
Split your string by ".":
String[] split = input.split("\\.");
Then capitalize the first letter of the resulting substrings and reunite to result string. (Be careful for spaces between periods and letters, maybe split by "\. "):
String result = "";
for (int i=0; i < split.length; i++) {
result += Character.toUpperCase(split[i].trim());
}
System.out.println(result);
Should do it.
The correct method to do it with core java using regex will be
String sentence = "i am happy. this is genius.";
Pattern pattern = Pattern.compile("[^\\.]*\\.\\s*");
Matcher matcher = pattern.matcher(sentence);
String capitalized = "", match;
while(matcher.find()){
match = matcher.group();
capitalized += Character.toUpperCase(match.charAt(0)) + match.substring(1);
}
System.out.println(capitalized);
Try this:
1. Capitalize the first letter.
2. If the character is '.' set the flag true so that you can capitalize the next character.
public static String capitalizeSentence(String str)
{
if(str.length()>0)
{
char arr[] = str.toCharArray();
boolean flag = true;
for (int i = 0; i < str.length(); i++)
{
if (flag)
{
if (arr[i] >= 97 && arr[i] <= 122)
{
arr[i] = (char) (arr[i] - 32);
flag = false;
}
} else
{
if (arr[i] == '.')
flag = true;
}
}
return new String(arr);
}
return str;
}

Code verifcation and optimization - Two String common substring

I was solving Two String problem. I have written below code.
It passed 4 test cases but for two test cases it showed timeout. Kindly let me know how can I optimize it to avoid timeouts? Also any links which explains and shows examples of such optimization is welcome.
public class TwoStrings
{
private static final String YES = "YES";
private static final String NO = "NO";
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int testCases = Integer.parseInt(in.nextLine());
String input1[] = new String[testCases];
String input2[] = new String[testCases];
for (int i = 0; i < testCases; i++)
{
input1[i] = in.nextLine();
input2[i] = in.nextLine();
}
in.close();
for (int i = 0; i < testCases; i++)
{
displayResult(input1[i], input2[i]);
}
}
private static void displayResult(String string1, String string2)
{
// choosing smaller String for iterating through it.
String smallerString = string1.length() <= string2.length() ? string1
: string2;
String biggerString = string1 == smallerString ? string2 : string1;
boolean constains = false;
// Concept - Even if single letter is common, substring exists.
// So checking just one string.
for (int i = 0; i < smallerString.length(); i++)
{
if (biggerString.contains(String.valueOf(smallerString.charAt(i))))
{
constains = true;
break;
}
}
if (constains)
System.out.println(YES);
else
System.out.println(NO);
}
}
What you are currently doing is O(n^2) because you loop through the small string and the search for that character in the longer string is a linear search because it is not sorted (all letters in alphabetical order).
Below is a O(n) solution. The concept is to have a size 26 boolean array (one for each letter), and make an index true if a letter is in the small (could actually be small or long string, doesn't matter) string. Creating the array from the small string is O(n), and checking the letters in the long string is O(n), yielding a grand total of O(n + n), which reduces to O(n).
private static void displayResult(String string1, String string2)
{
boolean[] contains = new boolean[26];
boolean noSubstring = true;
// populate the contains array
for (char c : string1.toCharArray())
{
int value = (int)c - (int)'a'; // make the char 0-25
contains[value] = true;
}
for (char c : string2.toCharArray())
{
int value = (int)c - (int)'a'; // make the char 0-25
if (contains[value])
{
noSubstring = false;
break;
}
}
if (noSubstring) System.out.println("NO");
else System.out.println("YES");
}

Categories