Here is my code to an array method:
private int _a;
public static void main(String[] args) {}
public int[] countAll(String s) {
int[] xArray = new int[27];
int[] yArray = new int[27];
_a = (int)'a';
for (int i = 0; i < xArray.length; i++) {
xArray[i] = _a;
_a = _a++;
}
for (int j = 0; j < s.length(); j++) {
s = s.toLowerCase();
char c = s.charAt(j);
int g = (int) c;
int letterindex = g - yArray[0];
if (letterindex >= 0 && letterindex <= 25) {
xArray[letterindex]++;
} else if (letterindex < 0 || letterindex > 25) {
xArray[26]++;
}
}
return xArray;
}
This code works in java but I was told that there is a simpler way. I am having a lot of trouble figuring out a simplified version of my code. Please help me.
If all you want to do is count the upper and lower case, that's a very roundabout way of doing it, what's wrong with something like:
public static int countUpper(String str)
{
int upper = 0;
for(char c : str.toCharArray())
{
if(Character.isUpperCase(c))
{
upper++;
}
}
return upper;
}
Then just the same thing with Character.isLowerCase(c) for the opposite.
public static int[] countAll(String s) {
int[] xArray = new int[27];
for (char c : s.toLowerCase().toCharArray()){
if (Character.isLetter(c))
xArray[c -'a']++;
else
xArray[26]++;
}
return xArray;
}
It looks like your program is trying to find frequencies of different alphabets in a string, and you are counting the non letters in special index 26. In that case your code to initialize the count is wrong. It is getting pre-initialized with some values in following for loop:
for (int i = 0; i < xArray.length; i++) {
xArray[i] = _a;
_a = _a++;
}
I think the method can be simply something like:
s = s.toLowerCase();
int histogram[] = new int[27];
for (char c: s.toCharArray()) {
int index = c - 'a';
if (index < 0 || index > 25) {
index = 26;
}
histogram[index]++;
}
Here are two important improvements that should be made to your code:
Add a method javadoc for countAll, so that readers don't have to trawl through 20+ lines of turgid code to reverse engineer what the method is supposed to be.
Get rid of the _a abomination. According to the most widely accepted Java coding standard, the underscore character has no place in a variable name. Besides, a is about the most useless field name I've ever come across. If it is intended to convey some meaning to the reader ... you have totally lost me.
(Oh I get it. It shouldn't be a field at all. Bzzzt!!!)
Then there is the yArray array. As far as I can tell the only place it is used is here:
int letterindex = g - yArray[0];
which is actually the same as:
int letterindex = g;
since yArray[0] is never assigned to. In short yArray is completely redundant.
And this:
if (letterindex >= 0 && letterindex <= 25) {
xArray[letterindex]++;
} else if (letterindex < 0 || letterindex > 25) {
xArray[26]++;
}
The condition in the else part is redundant. Your code will be easier to read if you just write this:
if (letterindex >= 0 && letterindex <= 25) {
xArray[letterindex]++;
} else {
xArray[26]++;
}
The two are equivalent. Do you see why?
Finally the initialization of the xArray elements looks plain wrong to me. If xArray contains counts, the elements need to start at zero. (Didn't you wonder why your code was telling you that every string contained lots of "zees"?)
"This code works in java ..."
I don't think so. Maybe it compiles. Maybe it runs without crashing. But it doesn't give correct answers!
public static int[] countAll(String s) {
int[] count = new int[26];
for (char c : s.toLowerCase().toCharArray()) {
if ('a' <= c && c <= 'z') {
count[c - 'a']++;
}
}
return count;
}
First.. your arrays where to big.
Second.. why do you need two arrays at all?
Third.. your code didn't seemt to work.. the word "hello" returned an array with the number 97 (26 times) and the number 102.
Edit: Made it shorter.
Related
I am still new to Java, and I am currently working on a program that will take two strings as arguments and return the number of mismatched pairs. For my program I am working with ATGC because in science, A's always match up with T's and G's always match up with C's. I cant quite figure out how to iterate over the strings and see that the first character in string one (T for example) matches up with its intended pair (A), and if it doesn't it is a mismatched pair and it should be added to a counter to be totaled at the end. I believe I can use something called charAt(), but I am unsure of how that works.
I also need to figure out how to be able to take the absolute value of counter before it is added to the finalCounter. The main reason for this is because I just want to worry about getting the length difference between the two rather than making sure that the longer string is subracted from the smaller string.
Any help would be greatly appreciated!
''''
public class CountMismatches {
public static void main(String[] args) {
{
String seq1 = "TTCGATGGAGCTGTA";
String seq2 = "TAGCTAGCTCGGCATGA";
System.out.println(count_mismatches(seq1, seq2))
//*expected to print out 5 because there are 3 mismatched pairs and 2 that do not have a pair*
}
}
public static int count_mismatches(String seq1, String seq2) {
int mismatchCount = 0;
int counter = seq1.length() - seq2.length();
int finalCounter = mismatchCount + counter;
for(int i = 0; i < seq1.length(); i++) if (seq1.charAt(i) == seq2.charAt(i)) {
break; //checks to see if the length of seq1 and seq2 are the same
}
for(int i = 0; i < seq1.length(); i++) if (seq1.charAt(i) != seq2.charAt(i)) {
return counter; //figure out how to do absolute value for negative numbers
}
return finalCounter;
}
}
'''
Since you want to count only the places where there are differences, you can iterate through the minimum length present in both the strings and find out the places where they are different.
In the end, you can add absolute difference of length between seq1 and seq2 and return that value to the main function.
For the logic, all you have to do is apply 4 if conditions to check if character is A,G,C,T and if suitable pair is present in the other string.
public class CountMismatches {
public static void main(String[] args) {
{
String seq1 = "TTCGATGGAGCTGTA";
String seq2 = "TAGCTAGCTCGGCATGA";
System.out.println(count_mismatches(seq1, seq2));
}
}
public static int count_mismatches(String seq1, String seq2) {
int finalCounter = 0;
for (int i = 0; i < Math.min(seq1.length(), seq2.length()); i++) {
char c1 = seq1.charAt(i);
char c2 = seq2.charAt(i);
if (c1 == 'A') {
if (c2 == 'T')
continue;
else
finalCounter++;
} else if (c1 == 'T') {
if (c2 == 'A')
continue;
else
finalCounter++;
} else if (c1 == 'G') {
if (c2 == 'C')
continue;
else
finalCounter++;
} else if (c1 == 'C') {
if (c2 == 'G')
continue;
else
finalCounter++;
}
}
return finalCounter + (Math.abs(seq1.length() - seq2.length()));
}
}
and the output is as follows :
5
Make these refactorings:
To make the comparisons easy to code and understand, create a Map whose entires are each pair (both directions)
Iterate over the Strings up to the length of the shortest one, adding up the number of matching pairs as you go
The result is the length of the longest String minus the number of pairs
Like this:
public static int count_mismatches(String seq1, String seq2) {
Map<Character, Character> pairs = Map.of('A', 'T', 'T', 'A', 'G', 'C', 'C', 'G');
int count = 0;
for (int i = 0; i < Math.min(seq1.length(), seq2.length()); i++) {
if (pairs.get(seq1.charAt(i)) == seq2.charAt(i)) {
count++;
}
}
return Math.max(seq1.length(), seq2.length()) - count;
}
See live demo, which returns 5 for your sample input.
Good Evening,
Something seems off here, this snippet of code:
for(int i = 0; i < seq1.length(); i++)
if (seq1.charAt(i) == seq2.charAt(i)) {
break; //checks to see if the length of seq1 and seq2 are the same
}
Does not do what you think it does. This cycle will loop through all characters in sequence1 using i < seq1.length() and for each character that exists in seq1, it will check if said character is equal to the character with the same index in seq2.
This means that a correction is in order:
int countMismatches = 0;
for(int i = 0; i < seq1.length();i++){
switch(seq1.charAt(i)){
case 'A':
if(seq2.charAt(i) != 'T') countMismatches++;
break;
}
}
Repeat this process for the other letters, and voilá, you should be able to count your mismatches this way.
Do be careful with sequences having different lengths, as if that happens, as soon as you step out of a bound, you will receive an IndexOutOfBoundsException, indicating you've tried to check a character that does not exist.
First you must find out which string is the shortest in length. Also you need to get the length difference when calculating the shortest string. After that, use that length as a terminating condition in your for loop. You can use booleans to check whether the values are present before incrementing the counter with an if statement.
The absolute value of any number can be obtained by calling the static method abs() from the Math class. Last, just add the mismatchCounts to the absolute value of the length difference in order to obtain the result.
Here is my solution.
public class App {
public static void main(String[] args) throws Exception {
String seq1 = "TTCGATGGAGCTGTA";
String seq2 = "TAGCTAGCTCGGCATGA";
System.out.println(compareStrings(seq1, seq2));
}
public static int compareStrings(String stringOne, String stringTwo) {
Character A = 'A', T = 'T', G = 'G', C = 'C';
int mismatchCount = 0;
int lowestStringLenght = 0;
int length_one = stringOne.length();
int length_two = stringTwo.length();
int lenght_difference = 0;
if (length_one < length_two) {// string one lenght is greater
lowestStringLenght = length_one;
lenght_difference = length_one - length_two;
} else if (length_one > length_two) {// string two lenght is greater
lowestStringLenght = length_two;
lenght_difference = length_two - length_one;
} else { // lenghts must be equal, use either
lowestStringLenght = length_one;
lenght_difference = 0; // there is no difference because they are equal
}
for (int i = 0; i < lowestStringLenght; i++) {
// A matches with T
// G matches with C
// evaluate if the values A, T, G, C are present
boolean A_T_PRESENT = stringOne.charAt(i) == A && stringTwo.charAt(i) == T;
boolean G_C_PRESENT = stringOne.charAt(i) == G && stringTwo.charAt(i) == C;
boolean T_A_PRESENT = stringOne.charAt(i) == T && stringTwo.charAt(i) == A;
boolean C_G_PRESENT = stringOne.charAt(i) == C && stringTwo.charAt(i) == G;
boolean TWO_EQUAL = stringOne.charAt(i) == stringTwo.charAt(i);
// characters are equal, increase mismatch counter
if (TWO_EQUAL) {
mismatchCount++;
continue;
}
// all booleans evaluated to false, it means that the characters are not proper
// matches. Increment mismatchCount
else if (!A_T_PRESENT && !G_C_PRESENT && !T_A_PRESENT && !C_G_PRESENT) {
mismatchCount++;
continue;
} else {
continue;
}
}
// calculate the sum of the mismatches plus the abs of the lenght difference
lenght_difference = Math.abs(lenght_difference);
return mismatchCount + lenght_difference;
}
}
Avoid char
The char type is legacy, essentially broken. As a 16-bit value, char is physically incapable of representing most characters. The char type in your particular case would work. But using char is a bad habit generally, as such code may break when encountering any of about 75,000 characters defined in Unicode.
Code point
Use code point integer numbers instead. A code point is the number assigned to each of the over 140,000 characters defined by the Unicode Consortium.
Here we get an IntStream, a series of int values, one for each character in the input string. Then we collect these integer numbers into an array of int values.
int[] codePoints1 = seq1.codePoints().toArray() ;
int[] codePoints2 = seq2.codePoints().toArray() ;
You said the input strings may be of unequal length. So our two arrays may be jagged, of different lengths. Figure out the size of the shorter array.
int smallerSize = Math.min( codePoints1.length , codePoints2.length ) ;
Keep track of the index number of mismatched rows.
List<Integer> mismatchIndices = new ArrayList <>();
Loop the arrays based on that smaller size.
for( int i = 0 ; i < smallerSize ; i ++ )
{
if ( isBasePairValid( codePoint first , codePoint second ) )
{
…
} else
{
mismatchIndices.add( i ) ;
}
}
Write an isBasePairValid method
Write the isBasePairValid method, taking two arguments, the code points of the two nucleobase letters.
static int A = "A".codePointAt( 0 ) ; // Annoying zero-based index counting. So first character is number zero.
static int C = "C".codePointAt( 0 ) ;
static int G = "G".codePointAt( 0 ) ;
static int T = "T".codePointAt( 0 ) ;
if( first == A ) return ( second == T )
else if( first == T ) return ( second == A )
else if( first == C ) return ( second == G )
else if( first == G ) return ( second == C )
else { throw new IllegalStateException( … ) ; }
Count the mismatches.
int countMismatches = mismatchIndices.size() ;
The numerical sum of chars T & A and G & C is fixed and unique for legal nucleobase pairs. So you just need to ensure that the corresponding bases have one of those sums.
String seq1 = "TTCGATGGAGCTGTA";
String seq2 = "TAGCTAGCTCGGCATGA";
System.out.println(count_mismatches(seq1, seq2));
prints
5
find max length to iterate
establish fixed sums for comparison
iterate and compare to expected pairing and update count appropriately
public static int count_mismatches(String seq1, String seq2) {
int len1 = seq1.length();
int len2 = seq2.length();
int len = len1;
if (len1 > len2) {
len = len2;
}
int sumTA = 'T'+'A';
int sumGC = 'G'+'C';
int misMatchCount = Math.abs(len1-len2);
for (int i = 0; i < len; i++) {
int pair = seq1.charAt(i) + seq2.charAt(i);
if (pair != sumTA && pair != sumGC) {
misMatchCount++;
}
}
return misMatchCount;
}
I'm not really sure how to word the question for the title but this post explains what I'm after. I apologize if my question is worded incorrectly.
In Java, how would I go about creating a method that returns the number of 'hippos' found in two different integer arrays:
int[] hippo1 = new int[100];
int[] hippo2 = new int[10000];
given that a 'hippo' is considered an integer that is 75 or above?
Would it be?
public static int calcNumberOfHippos(int[] hippos)
{
for (int i = 0; i < hippos.length; i++)
{
if (hippos[i] >= 75)
{
return hippos[i];
}
}
int numHippos = (int)hippos.length;
return numHippos;
}
I'm not sure if I should return hippos.length at the end. That's the only way I can get it to return something. I would really like to return hippos[i] but every time I try to return that out of the for loop it says that it doesn't recognize the variable i. It says Cannot find symbol variable i.
public static int calcNumberOfHippos(int[] hippos)
{
for (int i = 0; i < hippos.length; i++)
{
if (hippos[i] >= 75)
{
return hippos[i];
}
}
return hippos[i];
}
Can anyone please point me in the right direction?
If you want to calculate the number of hippos (how many members of the array are larger than 75), then this code could help:
public static int calcNumberOfHippos(int[] hippos) {
int numOfHippos = 0;
for (int i = 0; i < hippos.length; i++) {
if (hippos[i] >= 75)
{
numOfHippos++;
}
}
return numOfHippos;
}
The idea is to go over the array and count up every time a hippo is spotted. You don't need to return the first hippo that you see - which is what your original code would've done.
int hippoCount = Arrays.stream(hippos).reduce(0, (acc, n) -> acc + (n >= 75 ? 1 : 0));
should do the trick.
I'm trying to understanding the following Java + Dynamic Programming implementation (https://pingzhblog.wordpress.com/2015/09/17/word-break/):
public class Solution {
public boolean wordBreak(String s, Set<String> wordDict) {
if(s == null) {
return false;
}
boolean[] wordBreakDp = new boolean[s.length() + 1];
wordBreakDp[0] = true;
for(int i = 1; i <= s.length(); i++) {
for(int j = 0; j < i; j++) {
String word = s.substring(j, i);
if(wordBreakDp[j] && wordDict.contains(word)) {
wordBreakDp[i] = true;
break;
}
}
}//end for i
return wordBreakDp[s.length()];
}
}
But need some clarification with String s = "abcxyz" and Set <String> wordDict = ["z", "xy", "ab", "c"].
I'm still unclear as to what wordBreakDp[] represents, and setting one to true means.
So I made the attempt and got wordBreakDP[2,3,5,6]=true, but what do those indexes tell? Couldn't I have just checked for i=6 since all we are checking is if last index of wordBreakDp[] is true, wordBreakDp[s.length()];?
And say for example I got ab for s.substring(0, 2);, but then how can we just assume that next loop, s.substring(1, 2);, is not useful and just break; out of the loop?
Thank you
This isn't really an answer, but it might be helpful in understanding the loops. It prints the value of substring(i,j) and also wordBreakDp[j] at each iteration. It also prints the final solution (segmentation) at the end of the method.
public boolean wordBreak(String s, Set<String> wordDict) {
if(s == null) {
return false;
}
boolean[] wordBreakDp = new boolean[s.length() + 1];
wordBreakDp[0] = true;
for(int i = 1; i <= s.length(); i++) {
for(int j = 0; j < i; j++) {
String word = s.substring(j, i);
System.out.println("["+j+","+i+"]="+s.substring(j,i)+", wordBreakDP["+j+"]="+wordBreakDp[j]);
if(wordBreakDp[j] && wordDict.contains(word)) {
wordBreakDp[i] = true;
break;
}
}
}//end for i
for (int i = 1, start=0; i <= s.length(); i++) {
if (wordBreakDp[i]) {
System.out.println(s.substring(start,i));
start = i;
}
}
return wordBreakDp[s.length()];
}
I think I have the answer to your last question, which was:
And say for example I got ab for s.substring(0, 2);, but then how can
we just assume that next loop, s.substring(1, 2);, is not useful and
just break; out of the loop?
You are right that if you got "ab" for s.substring(0,2) and you break out of the loop, this doesn't necessarily mean that s.substring(1,2) is not useful. Let's say that s.substring(1,2) is useful. This means that "a" is also a valid word, and so is "b". The solution found by this algorithm would start with "ab" whereas the solution found by not breaking would be "a" followed by "b". Both these solutions are correct (assuming that the rest of the string can be broken into valid words as well). The algorithm doesn't find all valid solutions. It just returns true if the string can be broken into valid words, i.e., if there is one solution that satisfies the condition. There may be more than one solution, of course, but that is not the purpose of this algorithm.
Note, f[i] means whether the first i characters of s is valid. An example,
String = catsand
Dict = [cat, cats, sand, and]
s = c a t s a n d
dp = T F F T T F F ?
i = 0 1 2 3 4 5 6 7
*
Note dp[0] is True, because empty string is valid. Say we have dp[0] through dp[6].
Let's calculate dp[7], which denotes whether catsand is valid.
For catsand to be valid, there must be a non-empty suffix that is in dict, AND the remaining prefix is valid.
"catsand" is a valid, if:
If "" is valid, and "catsand" is inDict, or
If "c" is valid, and "atsand" is inDict, or
If "ca" is valid, and "tsand" is inDict, or
If "cat" is valid, and "sand" is inDict, or
If "cats" is valid, and "and" is inDict, or
If "catsa" is valid, and "nd" is inDict, or
If "catsan" is valid, and "d" is inDict
Translated to pesudo code:
dp[7] is True, if:
j j i
If dp[0] && inDict( s[0..7) ) or
If dp[1] && inDict( s[1..7) ) or
If dp[2] && inDict( s[2..7) ) or
If dp[3] && inDict( s[3..7) ) or
If dp[4] && inDict( s[4..7) ) or
If dp[5] && inDict( s[5..7) ) or
If dp[6] && inDict( s[6..7) )
public class Solution {
public int wordBreak(String a, ArrayList<String> b) {
int n = a.length();
boolean dp[] = new boolean[n+1];
dp[0] = true;
for(int i = 0;i<n;i++){
if(!dp[i])continue;
for(String s : b){
int len = s.length();
int end = len + i;
if(end > n || dp[end])continue;
if(a.substring(i,end).equals(s)){
dp[end] = true;
}
}
}
if(dp[n])return 1;
else return 0;
}
}
I have a String/character sequence that is being repeated infinitesimally... Naturally ,characters will go out of range of Integer and start falling into range of Long, since methods used for accessing characters for both String as well as StringBuilder class all require an int "index" how do I access these characters at say ,Long long>Intger.MAX_VALUE . is there a way to override these methods such as charAt(int index) so that they start "accepting " long arguments ,if not so , how can I access the characters at this index, considered conversion to character array using String.toCharArray() method but then again, array length can only be upto Integer.MAX_VALUE. Is there a method/constructor type that I'm not aware of which accepts long arguments?
You should definitely not construct a string and do measurements on it.
This is a test on how well you are able to abstract things. I will give you some code you may study. You should not copy+paste it for several reasons - including the possibility that I did some mistake.
The idea is, to simply compute the information, which is possible because we have a simple repetition pattern.
class RepeatedString {
private String s;
public RepeatedString(String s) {this.s = s;}
public char charAt(long i) {
return s.charAt((int)(i % s.length()));
}
public long count(char c, long i) {
long n = 0;
// how many complete repetitions?
{
long r = i / s.length();
if (r > 0) {
// count c in s
for (int j = 0 ; j < s.length() ; j++) n += s.charAt(j) == c ? 1 : 0;
n *= r;
}
}
// how many c in last repitition
{
long l = i % s.length();
for (int j = 0 ; j < l ; j++) n += s.charAt(j) == c ? 1 : 0;
}
return n;
}
}
class Kata {
public static void main(String[] args) {
RepeatedString s = new RepeatedString("bla");
System.out.println(s.charAt(1)); // expected 'l'
System.out.println(s.charAt(6)); // expected 'b'
System.out.println(s.count('a', 19)); // expected 6
System.out.println(s.count('a', 21)); // expected 7
}
}
I try to make a program which it can find palindromic number (it has to be pruduct of two 3-digits number and I hope that it contain 6 digit but it is not important). Here is my code:
public class palindromicNumber {
public static void getPalindromicNumber() {
boolean podminka = false;
int test;
String s;
for (int a = 999; podminka == false && a > 100; a--) {
for (int b = 999; podminka == false && b > 100; b--) {
test = a * b;
s = Integer.toString(test);
int c = 0;
int d = s.length();
while (c != d && podminka == false) {
if (s.charAt(c) == s.charAt(d)) { // I think that problem is here but I can't see what
System.out.println(s);
podminka = true;
}
c++;
d--;
}
}
}
}
}
and if I want to compile it :
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 6
at java.lang.String.charAt(String.java:695)
at faktorizace.palindromicNumber.getPalindromicNumber(palindromicNumber.java:24)
at faktorizace.Faktorizace.main(Faktorizace.java:19)
Java Result: 1
There are two problems here:
You're starting off with the wrong upper bound, as other answers have mentioned
If c starts off odd and d starts off even, then c will never equal d. You need to use
while (c < d && !podminka) // Prefer !x to x == false
Additionally, judicious use of break and return would avoid you having to have podminka at all.
As another aside, you've got a separation of concerns issue. Your method currently does three things:
Iterates over numbers in a particular way
Checks whether or not they're palandromic
Prints the first it finds
You should separate those out. For example:
public void printFirstPalindrome() {
long palindrome = findFirstPalindrome();
System.out.println(palindrome);
}
public long findFirstPalindrome() {
// Looping here, calling isPalindrome
}
public boolean isPalindrome(long value) {
// Just checking here
}
I suspect findFirstPalindrome would normally take some parameters, too. At this point, you'd have methods which would be somewhat easier to both write and test.
String indices go from [0..length - 1]
Change int d = s.length(); to int d = s.length() - 1;
Update: As a quick aside, you are setting podminka to true when
s.charAt(c) == s.charAt(d)
If s = 100101 for example, you will terminate all of the loops on the first iteration of the while loop because the first and last characters are the same.
int d = s.length();
An array of the strings chars will only go from 0 - length-1.
s.charAt(d) will always be out of bounds on the first iteration.
Take a look on JDK source code:
public char charAt(int index) {
if ((index < 0) || (index >= count)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index + offset];
}
You can see that this exception is thrown when index is less then zero or exceeds the string length. Now use debugger, debug your code and see why do you pass this wrong parameter value to charAt().
public class palindromicNumber {
public static void getPalindromicNumber(){
boolean podminka = false;
int test;
String s;
for(int a = 999;podminka == false && a>100; a-- ){
for(int b = 999;podminka == false && b>100; b-- ){
test = a*b;
s = Integer.toString(test);
int c = 0;
int d = s.length();
while(c!=d && podminka == false){
if(s.charAt(c)==s.charAt(d - 1)){
System.out.println(s);
podminka = true;
}
c++;
d--;
}
}
}
try this! string count starts from 0!