Why are two strings or two arrays necessary to accomplish this? - java

This method is essentially taking an array that contains percentages, and based on whether or not the percentages are above or below 50%, a letter is appended onto a returned String to result in a final type.
I was told that I should "should create either two Strings or two arrays
that hold the characters, then loop through the dimensions and
test percentageB[i] with the 3 tests"
I don't understand why doing this is necessarily more valid or effective than the method I have already used. Could someone explain this to me?
public static String getPersonality(int[] percentageB) {
char [] types = {'E','I','S','N','T','F','J','P'};
String MBTItype = "";
for (int j = 0; j < types.length; j += 2) {
int i = j/2;
if (percentageB[i] < 50){
MBTItype += types[j];
} else if (percentageB[i] > 50) {
MBTItype += types[j + 1];
} else if (percentageB[i] == 50) {
MBTItype += 'X';
}
}
return MBTItype;
}

The reason you would have been told to use two arrays is that it makes the relationship between the letters clearer, at each position you are assigned the letter from one of the two lists. By combining them into a single array you are not making the mutually exclusive nature of the letters obvious to a reader of your code. Compare this implementation with your own
public static String getPersonality(int[] percentageB) {
char [] lowPercentTypes = {'E','S','T','J'};
char [] highPercentTypes = {'I','N','F','P'};
String MBTItype = "";
for (int i = 0; i < lowPercentTypes.length; i++) {
if (percentageB[i] < 50){
MBTItype += lowPercentTypes[i];
} else if (percentageB[i] > 50) {
MBTItype += highPercentTypes[i];
} else if (percentageB[i] == 50) {
MBTItype += 'X';
}
}
return MBTItype;
}
Reading this you do not need to go through the mental effort of knowing that each type has its compliment in the next item of the array, instead you are explicitly told that it is a high/low percentage type.
We are trying to reduce the cognitive load on the future reader of your code so you want to make things as straightforward as possible

Related

word length in Java

I am having trouble with understanding some of the codes in my assignment of finding the word lengths in a file. NB: the Environment I am using is Blue J with a library from dukelearntoprogram.com, this is the link for downloading Blue J, http://www.dukelearntoprogram.com/course3/index.php. I have created a void method called countWordLength, with parameter FileResource called resource, and an integer array called counts. this method should return the number words at a specific length in a file. For instance: 2 words of length 2: My as.
They have given me the code for this assignment but I am not understanding the following code, in my countWordLength method.
for (String word : resource.words()) {
int finalLength = 0;
int totalLength = word.length();
if (Character.isLetter(word.charAt(0)) == false) {
finalLength = totalLength-1;
}
else {
finalLength = totalLength;
}
if (Character.isLetter(word.charAt(totalLength-1)) == false && totalLength > 1) {
finalLength = finalLength-1;
}
if (finalLength >= counts.length) {
counts[counts.length-1] += 1;
}
else {
counts[finalLength] += 1;
}
The specific part that I don't understand is the meaning or usefulness of
if (finalLength >= counts.length) {
counts[counts.length-1] += 1;
}
else {
counts[finalLength] += 1;
}
if my question is not clear, and you may want more parts of my code please let know. Any help
will be highly appreciated.
Explanation:
int finalLength = 0;
int totalLength = word.length();
if (Character.isLetter(word.charAt(0)) == false) {
finalLength = totalLength-1;
}
else {
finalLength = totalLength;
}
Above lines are initiating lengths. If 1st character is not alphabet, then reducing length.
if (Character.isLetter(word.charAt(totalLength-1)) == false && totalLength > 1) {
finalLength = finalLength-1;
}
If last character is not alphabet, removing one more character but a special condition added here that it is we reduce word length only if it's length > 1
if (finalLength >= counts.length) {
counts[counts.length-1] += 1;
}
This might be bit tricky for you. If calculated length is greater than array we assigned, we are adding count to last one. Ex: Let's say they assigned array with 20 and if got word length as 30, then we will assign this word count to last index (19).
else {
counts[finalLength] += 1;
}
If length is less than size allowed than we will add to that respective index.

String out of Index :java.lang.ArrayIndexOutOfBoundsException. String overflows maybe

class Solution {
public String longestCommonPrefix(String[] strs) {
String result = new String("");
char compareElement;
int i;//index of strs
int j;//index of the first one of string
for(j = 0; j < strs[0].length(); j++){
compareElement = strs[0].charAt(j);
for(i = 1; i < strs.length; i++){
if(compareElement == strs[i].charAt(j)){
if(i == strs.length - 1)
result += compareElement;
else
continue;
}
else{
break;
}
}
}
return result;
}
}
Test sample is
Input: ["flower","flow","flight"]
Output: "fl"
hi there I have got a problem with string in Java in my 4th small program in Leetcode. The aim of this function is to find the longest common prefix string amongst an array of strings. But the exception
Exception in thread "main"
java.lang.StringIndexOutOfBoundsException: String index out of
range: 4
at java.lang.String.charAt(String.java:614)
at Solution.longestCommonPrefix(Solution.java:11)
at __DriverSolution__.__helper__(__Driver__.java:4)
appears over again.
Has someone any idea? Thanks!
I think this is where you go wrong:
if(compareElement == strs[i].charAt(j))
j can become too large as it goes from 0 to strs[0].lenght() (see your outer loop).
If strs[i].lengt() is smaller than strs[0].length() you get an StringIndexOutOfBoundsException.
When you iterate through the comparison strings, you're never checking the length of the string you're comparing. In your example the test case flow. The char at index 4 doesn't exist since only indices 0-3 are defined. if(compareElement == strs[i].charAt(j)){ when j is 4 it'll mess up. In order to fix it you have to make sure you're not going past the length of the string. In addition to that look up what a StringBuilder is, for this small of a test case it won't matter however as you go up larger it will.
Your code fails if you have an element in the array which is shorter than the first element. You need to check that j is still smaller than the length of the string you're comparing:
public String longestCommonPrefix(String[] strs) {
String result = new String("");
char compareElement;
int i;// index of strs
int j;// index of the first one of string
for (j = 0; j < strs[0].length(); j++) {
compareElement = strs[0].charAt(j);
for (i = 1; i < strs.length; i++) {
if (j < strs[i].length() && compareElement == strs[i].charAt(j)) {
if (i == strs.length - 1)
result += compareElement;
else
continue;
} else {
break;
}
}
}
return result;
}

Calculate pi to the nth term with leibiniz sequence

Hey I have to create a method where I have to calculate pi to a passed term (a) using the leibiniz sequence. This is what I have so far
public static double calculatePi(int a){
double oddNum=1;
double pi=0;
for(int x=0; x<a; x++){
if(x%2==0)
pi=pi+(4/oddNum);
else
pi=pi-(4/oddNum);
oddNum=oddNum+2;
}
return pi;
}
I also need help writing a method that accepts a passed string and a (x)term. In the method it will add a "#" every x letters. So if its passed (sundae, 2) it will return su#nd#ae#. I have most of it down but theres a logical error that doesnt allow something like (cats, 3) to compile.
public static String addPounds(String s, int x){
String a="";
for(int i=0; i<s.length(); i=i+x){
a=(a+s.substring(i,i+x)+"#");
}
return a;
}
Thanks so much!
Your pi method is working fine.
You should change the other one to this. I have written it a little bit different so you get the logic easily.
public static String addPounds(String s, int x){
String a = "";
//starting from 1 so i can do mod division easily
for(int i = 1; i <= s.length(); i++){
//check if next # has to be placed at the end
if(i + 1 > s.length() && (i + 1) % x == 0){
a += "#";
//check if next # has to be placed somewhere inside the string
}else if(i % x == 0){
a += s.charAt(i - 1);
a += "#";
//oherwise just add the char at i-1
}else {
a += s.charAt(i - 1 );
}
}
return a;
}
Your addPounds method throws a StringIndexOutOfBoundsException with your given example (cats,3).
for(int i=0; i<s.length(); i=i+x){
a=(a+s.substring(i,i+x)+"#");
}
In the first execution of this for-loop, your variable 'a' will correctly be "Cat#". But now it goes wrong.
The variable 'i' gets increased to 3. And now you want to get a substring starting from the index 3 and ending with the index 6. The String "Cats" is only 4 letters, therefore the IndexOutOfBoundsException.
I guess the easiest way to solve your problem would be inserting a if else statement like this:
for(int i=0; i<s.length(); i=i+x){
if(s.length()>=i+x){
a=(a+s.substring(i,i+x)+"#");
}
else{
a= a+s.substring(i);
}
}

Using for loop to get the Hamming distance between 2 strings

In this task i need to get the Hamming distance (the Hamming distance between two strings of equal length is the number of positions at which the corresponding symbols are different - from Wikipedia) between the two strings sequence1 and sequence2.
First i made 2 new strings which is the 2 original strings but both with lowered case to make comparing easier. Then i resorted to using the for loop and if to compare the 2 strings. For any differences in characters in these 2 pair of string, the loop would add 1 to an int x = 0. The returns of the method will be the value of this x.
public static int getHammingDistance(String sequence1, String sequence2) {
int a = 0;
String sequenceX = sequence1.toLowerCase();
String sequenceY = sequence2.toLowerCase();
for (int x = 0; x < sequenceX.length(); x++) {
for (int y = 0; y < sequenceY.length(); y++) {
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else if (sequenceX.charAt(x) != sequenceY.charAt(y)) {
a += 1;
}
}
}
return a;
}
So does the code looks good and functional enough? Anything i could to fix or to optimize the code? Thanks in advance. I'm a huge noob so pardon me if i asked anything silly
From my point the following implementation would be ok:
public static int getHammingDistance(String sequence1, String sequence2) {
char[] s1 = sequence1.toCharArray();
char[] s2 = sequence2.toCharArray();
int shorter = Math.min(s1.length, s2.length);
int longest = Math.max(s1.length, s2.length);
int result = 0;
for (int i=0; i<shorter; i++) {
if (s1[i] != s2[i]) result++;
}
result += longest - shorter;
return result;
}
uses array, what avoids the invocation of two method (charAt) for each single char that needs to be compared;
avoid exception when one string is longer than the other.
your code is completely off.
as you said yourself, the distance is the number of places where the strings differ - so you should only have 1 loop, going over both strings at once. instead you have 2 nested loops that compare every index in string a to every index in string b.
also, writing an if condition that results in a+=0 is a waste of time.
try this instead:
for (int x = 0; x < sequenceX.length(); x++) { //both are of the same length
if (sequenceX.charAt(x) != sequenceY.charAt(x)) {
a += 1;
}
}
also, this is still a naive approach which will probbaly not work with complex unicode characters (where 2 characters can be logically equal yet not have the same character code)
public static int getHammingDistance(String sequenceX, String sequenceY) {
int a = 0;
// String sequenceX = sequence1.toLowerCase();
//String sequenceY = sequence2.toLowerCase();
if (sequenceX.length() != sequenceY.length()) {
return -1; //input strings should be of equal length
}
for (int i = 0; i < sequenceX.length(); i++) {
if (sequenceX.charAt(i) != sequenceY.charAt(i)) {
a++;
}
}
return a;
}
Your code is OK, however I'd suggest you the following improvements.
do not use charAt() of string. Get char array from string using toCharArray() before loop and then work with this array. This is more readable and more effective.
The structure
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else if (sequenceX.charAt(x) != sequenceY.charAt(y)) {
a += 1;
}
looks redundant. Fix it to:
if (sequenceX.charAt(x) == sequenceY.charAt(y)) {
a += 0;
} else {
a += 1;
}
Moreover taking into account that I recommended you to work with array change it to something like:
a += seqx[x] == seqY[x] ? 0 : 1
less code less bugs...
EDIT: as mentionded by #radai you do not need if/else structure at all: adding 0 to a is redundant.

Finding pairs out of five

I am having trouble finding pairs in a string of size five. So therefore, there can only be two pairs. For every pair that I have found, I should increase the score by 2 points.
Here is what I have so far, but it is incorrect.
String temp = "4 5 4 3 3";
String tempLine = temp.replaceAll(" ", "");
String[] hand = temp.split(" ");
for(int i = 0; i < hand.length; i++)
{
if(hand[i].equals(tempLine.substring(0, 1)) && i !=0 )
score += 1;
if(hand[i].equals(tempLine.substring(1, 2)) && i != 1 )
score += 1;
if(hand[i].equals(tempLine.substring(2, 3)) && i!= 2 )
score += 1;
if(hand[i].equals(tempLine.substring(3, 4)) && i!= 3)
score += 1;
if(hand[i].equals(tempLine.substring(4)) && i != 4)
score += 1;
}
EDIT: I am trying to find pairs in the hand that have similar value, for example 4 would be one pair found in this hand
Sort the hand first and then loop though looking for hand[i] == hand[i-1]. Note that you might have to be slightly clever as to not count sets of 3s or 4s twice but this should get you started.
Create an actual Hand class and don't use Strings to represent your cards. A Card's rank and suit are suitable candidates for an enum:
class Card {
enum Suite { ... };
enum Rank { ... };
private final Suite s;
private final Rank r;
// ...
}
class Hand {
private Card[] cards;
// ...
}
And sort the Card[] in your Hand class which makes it easier to evaluate .
Checkout Oracle's enum tutorial which has an example with cards: http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html
I think this fits what you're trying to do.
char[] hand = {'a','b','c','b','c'};
/* sort the hand to ensure pairs are next to each other */
for(int x=0;x<hand.length - 1;x++){
for(int y=(x+1);y<hand.length;y++){
if((int)hand[x] > (int)hand[y]){
char temp = hand[y];
hand[y] = hand[x];
hand[x] = temp;
}
}
}
int score = 0;
for(int x=0;x<hand.length - 1;x++){
if(hand[x] == hand[x + 1]){
score++;
/*if you want to make sure you only get pairs
add an "x++;" that way it'll skip over the
letter you just tested*/
}
}
1) Why aren't you comparing elements of the hand array to other elements? You already did the work to interpret the string and create the array data; use it.
2) There are more possible pairs of elements than that. Put down five similar objects in a row in front of you at the computer and try it out for yourself. You should be able to identify ten pairs. You should also be able to identify a pattern to how to find/label the pairs.
This example below is one possibility of how to count pairs. The question is how it should behave (increase the score) in case there are three equal values in the string or array or whatever. Shall this be counted as three pairs or not at all...?
123 is in fact three combinations 12 && 13 && 23
111 is in fact three combinations 11 && 11 && 11
package edu.harris.pairs;
public class FindPairs {
public static void main(String[] args) {
String s = "hello";
int score = 0;
for (int i = 0; i < s.length() - 1; i++) {
for (int j = i + 1; j < s.length(); j++) {
if (s.charAt(i) == s.charAt(j)) {
score++;
}
}
}
System.out.println(score);
}
}
Hope this helps a bit.

Categories