How to Optimize Code and Code Optimization Theory - java

I have written a coding challenge. The requirement of the challenge is reversing the particular words in a sentence => still keep the oder the of the words in the sentence but reverse the characters of the word.
The input sample is something like this: RemoteIo is awesome-Candiates pass interview-best candiates are selected.
The sample output of the input above:
oIetomeR si emosewa
setaidnaC ssap weivretni
tseb setaidnac era detceles
As you can see the input sentences are separated by the - character so that mean we have 3 sentences in the example above and the sentence just able to contain anphabet characters and blank space only (one blank space between two words)
So my question is how can I optimize the below code and there is any theory/principle about Code Optimization. My code implementation in Java:
public class Test1 {
public static void main (String[] args) throws java.lang.Exception
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine();
// Put sentences to a String array.
String[] data = input.split("-");
// Loop throw sentence array
for(int i = 0; i < data.length; i++) {
// Put the words from the sentence to a String array.
String[] words = data[i].split(" ");
// Loop throw the word array
for(int w = 0; w < words.length; w++) {
// Revert the characters of each word
for (int j = words[w].length() - 1; j >=0; j--) {
if (j != 0) {
System.out.print(words[w].charAt(j));
} else {
System.out.print(words[w].charAt(j) + " ");
}
}
if ( w == words.length -1) {
System.out.println();
}
}
}
}
}

The following code is bad: having ifs that refer to the loop variable is confusing and technically, maybe very slightly slower than the right way (though the compiler might just fix that for you.)
// Loop throw the word array
for(int w = 0; w < words.length; w++) {
// Revert the characters of each word
for (int j = words[w].length() - 1; j >=0; j--) {
if (j != 0) {
System.out.print(words[w].charAt(j));
} else {
System.out.print(words[w].charAt(j) + " ");
}
}
if ( w == words.length -1) {
System.out.println();
}
}
Instead do:
// Loop throw the word array
for(int w = 0; w < words.length; w++) {
// Revert the characters of each word
for (int j = words[w].length() - 1; j >0; j--) {
System.out.print(words[w].charAt(j) + " ");
}
System.out.print(words[w].charAt(j));
}
System.out.println();
Notice how I changed the j>=0 to j>0. The else block would only have triggered on the last repetition, so this is semantically equivalent.

Related

My reverse a string code includes a space at the end of the string

I am a beginner of Java, and would like to reverse the character order of a sentence when I input some words as command line arguments.
Here is my code. When I input "This is a pen.", the output should be ".nep a si sihT". However, the output of this code is ".nep a si sihT ". It includes an extra space at the end of the reversed sentence.
Does anyone know how can I delete the space?
public class Reverse {
public static void main(String[] args){
for(int i = args.length - 1; i >= 0; i--){
for(int j = args[i].length() - 1; j >= 0; j--){
System.out.print(args[i].charAt(j));
}
System.out.print(" ");
}
}
}
If you're sure that leading and trailing spaces are inconsequential to your subsequent logic, you can just apply the function trim() to your result.
trim() doesn't affect middle spaces, so the rest of your logic should still pan out fine.
You can also save your string in a variable and print it out just once - at the end of your logic. All in all, your logic would look like this:
public class Reverse {
public static void main(String[] args){
String res = "";
for(int i = args.length - 1; i >= 0; i--){
for(int j = args[i].length() - 1; j >= 0; j--){
res += args[i].charAt(j);
}
res += " ";
}
System.out.print(res.trim());
}
}
Avoid space at end by adding a if statement which skips last iteration
public class Reverse {
public static void main(String[] args){
for(int i = args.length - 1; i >= 0; i--){
for(int j = args[i].length() - 1; j >= 0; j--){
System.out.print(args[i].charAt(j));
}
if(i != 0){
System.out.print(" ");
}
}
}
}

Why does java not print inside nested for loops inside a if else statement and appears as terminated?

So, I'm writing a program that returns pyramids when you give a word as an input
for instance:
"Enter a word: "
Hello
Justification (L=left, R=Right)?
L
would print
H
ee
lll
llll
oooo
import java.util.Scanner;
public class Justification{
public static void main(String[] args) {
Scanner in= new Scanner(System.in);
System.out.println("Enter a word: ");
String word=in.nextLine();
System.out.println("Justification (L=left, R=Right)?");
String Justification=in.nextLine();
if(Justification.equalsIgnoreCase("l")){
for (int i = 0; i < word.length(); i++) {
for (int j = 1; j <= i; j++) {
System.out.print(word.substring(i,i));
}
System.out.println();
}
}else if(Justification.equalsIgnoreCase("r")){
for (int i = word.length()-1; i >= 0; i--) {
for (int s = 0; s < i; s++) {
System.out.print(" ");
}
for (int j = word.length()-1; j >= i; j--) {
System.out.println(word.substring(i,i));
}
System.out.println("");
}
}else System.out.println("Bad input");
}}
You are using substring(begin,end) incorrectly. The character at the begin index is included while the character at the end index is not.
If the word is hello, and you call substring(2,4), it would be ll
String str = "hello".substring(2,4); //str is "ll"
One way to check if substring is used correctly is that endIndex-beginIndex=length of substring. In this case, 4-2=2, so the substring should contain 2 characters, which it does.
An easier way to print out the ith character is to use charAt(i) instead of substring(i,i+1);
System.out.println("hello".substring(0,1)); //prints h
System.out.println("hello".charAt(0)); //also prints h

Java program to find the letter that appears in the most words?

I have a sentence, and I want to find the char that appears in the most words, and how many words it appears in.
For example: "I like visiting my friend Will, who lives in Orlando, Florida."
Which should output I 8.
This is my code:
char maxChar2 = '\0';
int maxCount2 = 1;
for (int j=0; j<strs2.length; j++) {
int charCount = 1;
char localChar = '\0';
for (int k=0; k<strs2[j].length(); k++) {
if (strs2[j].charAt(k) != ' ' && strs2[j].charAt(k) != maxChar2) {
for (int l=k+1; l<strs2[j].length(); l++) {
if (strs2[j].charAt(k)==strs2[j].charAt(l)) {
localChar = strs2[j].charAt(k);
charCount++;
}
}
}
}
if (charCount > maxCount2) {
maxCount2 = charCount;
maxChar2 = localChar;
}
}
, where strs2 is a String array.
My program is giving me O 79. Also, uppercase and lowercase do not matter and avoid all punctuation.
As a tip, try using more meaningful variable names and proper indentation. This will help a lot especially when your program is not doing what you thought it should do. Also starting smaller and writing some tests for it will help a bunch. Instead of a full sentence, get it working for 2 words, then 3 words, then a more elaborate sentence.
Rewriting your code to be a bit more readable:
// Where sentence is: "I like".split(" ");
private static void getMostFrequentLetter(String[] sentence) {
char mostFrequentLetter = '\0';
int mostFrequentLetterCount = 1;
for (String word : sentence) {
int charCount = 1;
char localChar = '\0';
for (int wordIndex = 0; wordIndex < word.length(); wordIndex++) {
char currentLetter = word.charAt(wordIndex);
if (currentLetter != ' ' && currentLetter != mostFrequentLetter) {
for (int l = wordIndex + 1; l < word.length(); l++) {
char nextLetter = word.charAt(l);
if (currentLetter == nextLetter) {
localChar = currentLetter;
charCount++;
}
}
}
}
if (charCount > mostFrequentLetterCount) {
mostFrequentLetterCount = charCount;
mostFrequentLetter = localChar;
}
}
}
Now all I did was rename your variables and change your for loop to a for-each loop. By doing this you can see more clearly your algorithm and what you're trying to do. Basically you're going through each word and comparing the current letter with the next letter to check for duplicates. If I run this with "I like" i should get i 2 but instead I get null char 1. You aren't properly comparing and saving common letters. This isn't giving you the answer, but I hope this makes it more clear what your code is doing so you can fix it.
Here is a somewhat more elegant solution
public static void FindMostPopularCharacter(String input)
{
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
input = input.toUpperCase();
HashMap<Character, Integer> charData = new HashMap<>();
char occursTheMost = 'A'; //start with default most popular char
int maxCount = 0;
//create the map to store counts of all the chars seen
for(int i = 0; i < alphabet.length(); i++)
charData.put(alphabet.charAt(i), 0);
//first find the character to look for
for(int i = 0; i < input.length(); i++)
{
char c = input.charAt(i);
//if contained in our map increment its count
if(charData.containsKey(c))
charData.put(c, charData.get(c) + 1);
//check for a max count and set the values accordingly
if(charData.containsKey(c) && charData.get(c) > maxCount)
{
occursTheMost = c;
maxCount = charData.get(c);
}
}
//final step
//now split it up into words and search which contain our most popular character
String[] words = input.split(" ");
int wordCount = 0;
CharSequence charSequence;
for(Character character : charData.keySet())
{
int tempCount = 0;
charSequence = "" + character;
for(int i = 0; i < words.length; i++)
{
if(words[i].contains(charSequence))
tempCount++;
}
if(tempCount > wordCount)
{
occursTheMost = character;
wordCount = tempCount;
}
}
System.out.println(occursTheMost + " " + wordCount);
}
Output of
String input = "I like visiting my friend Will, who lives in Orlando, Florida.";
FindMostPopularCharacter(input);
is
I 8
Note: If there are ties this will only output the character that first reaches the maximum number of occurrences.
FindMostPopularCharacter("aabb aabb aabb bbaa");
Outputs
B 4
because B reaches the max first before A due to the last word in the input.
FindMostPopularCharacter("aab aab b")
B 3

Stopping a for loop without using break

I'm trying to write a program that prints all substrings of entered string. For example if user enter "rum" the output will be this:
r
u
m
ru
um
rum
import java.util.Scanner;
public class AllSubStrings
{
public static void main(String[]args)
{
Scanner in = new Scanner(System.in);
System.out.print("Enter a string: ");
String str = in.next();
String sub = "";
for(int i=0; i<str.length(); i++)
{
for(int a=0; a<str.length() ; a++)
{
if(i+a+1>str.length())break;
sub = str.substring(a,i+a+1);
System.out.println(sub);
}
}
}
}
This program works perfectly but since we didn't learn how to use "break" in classes, i'm looking for something different. Any idea apart from "break" are welcome.
Thanks in advance.
You can use this while loop cycle instead of for:
int a = 0;
while (a < str.length && i + a < str.length()) {
sub = str.substring(a, i + a + 1);
System.out.println(sub);
a++;
}
Also it is possible to replace break with return statement
Calculate how many possible substrings there can be for a certain length. For example, length 1 = 1 substring, length 2 = 3, length 3 = 6, and so on.
Then loop for that many times. There should be a generic formula you can use for no matter how long of an input string.
You don't need a break to do this task.
int len = str.length();
for (int i = 0; i < len; i++) {
for (int j = i; j < len; j++) {
System.out.println( str.substring( i, j + 1 ) );
}
}
You can have two conditions in the for loop
for(int a = 0; a < str.length() && i + a < str.length(); a++)
{
sub = str.substring(a,i+a+1);
System.out.println(sub);
}
Note that i + a + 1 <= str.length() is the same as i + a < str.length()

Word count java

So my code is supposed to return the amount of words (words being lengths of letters) and it works except for when i enter anything 0 or less can some pplease help spot the error??
Edited Code:
public class WordCount {
public static int countWords(String original, int minLength){
String[] s1 = original.split("\\s+");
for(int i = 0; i < s1.length; i++){
s1[i] = s1[i].replaceAll("^\\W]", "");
}
int count = 0;
for(int i = 0; i < s1.length; i++){
String str = s1[i];
int len = 0;
for(int x = 0; x < str.length(); x++){
char c = str.charAt(x);
if(Character.isLetter(c) == true){
len ++;
}
}
if(len >= minLength){
count ++;
}
}
return count;
}
public static void main(String[] args){
System.out.println("enter string: ");
String s = IO.readString();
System.out.println("min length: ");
int m = IO.readInt();
System.out.println(countWords(s, m));
}
}
I would apply a solution that uses a regular expression to process the text.
I prepared a sketch of code, which can be summarized as follows:
String[] words = myString.replaceAll("[^a-zA-Z ]", " ").split("\\s+");
What this code does is to:
replace whatever is not a letter (since you said just letters) with a space
split the results on the spaces
The resulting array words contains all the words (i.e., sequences of letters) which were contained in the original string.
A full example can be found here. In this example I just print the words as a list. In case you want just the count of words, you just have to return the count of elements in the array.
Try this :
String s = original.replaceAll("[\\W]", " ").replaceAll("[\\s]+", " ");
because you have to replace spaces more than 1 here as well.

Categories