0

I'm trying to practice for a techniqual test where I have to count the number of characters in a DNA sequence, but no matter what I do the counter won't update, this is really frustrating as I learnt code with ruby and it would update, but Java seems to have an issue. I know there's something wrong with my syntaxt but for the life of me I can't figure it out.

public class DNA {

  public static void main(String[] args) {
    String dna1 = "ATGCGATACGCTTGA";
    String dna2 = "ATGCGATACGTGA";
    String dna3 = "ATTAATATGTACTGA";
    String dna = dna1;
    int aCount = 0;
    int cCount = 0;
    int tCount = 0; 

    for (int i = 0; i <= dna.length(); i++) {

      if (dna.substring(i) == "A") {
        aCount+= 1;
      }
      else if (dna.substring(i) == "C") {
        cCount++;
      } 
      else if (dna.substring(i) == "T") {
        tCount++;
      }
      System.out.println(aCount);
    } 
  }
}

It just keeps returning zero instead of adding one to it if the conditions are meet and reassigning the value.

Holloway
  • 6,412
  • 1
  • 26
  • 33
  • 2
    Does this answer your question? [How do I compare strings in Java?](https://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) – OH GOD SPIDERS Nov 23 '22 at 15:52
  • You also might want to read up what the `substring(int beginindex)` actually does: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#substring(int) - You seem to think it will return you a single letter as a String. This is not the case. Never guess what methods do, always check what they actually do in the documentation. – OH GOD SPIDERS Nov 23 '22 at 15:55

4 Answers4

2

Good time to learn some basic debugging!

Let's look at what's actually in that substring you're looking at. Add System.out.println(dna.substring(i)); to your loop. You'll see:

ATGCGATACGCTTGA
TGCGATACGCTTGA
GCGATACGCTTGA
CGATACGCTTGA
GATACGCTTGA
ATACGCTTGA
TACGCTTGA
ACGCTTGA
CGCTTGA
GCTTGA
CTTGA
TTGA
TGA
GA
A

So, substring doesn't mean what you thought it did - it's taking the substring starting at that index and going to the end of the string. Only the last character has a chance of matching your conditions.

Though, that last one still won't match your condition, which is understandably surprising if you're new to the language. In Java, == is "referential equality" - when applied to non-primitives, it's asserting the two things occupy the same location in memory. For strings in particular, this can give surprising and inconsistent results. Java keeps a special section of memory for strings, and tries to avoid duplicates (but doesn't try that hard.) The important takeaway is that string1.equals(string2) is the correct way to check.

It's a good idea to do some visibility and sanity checks like that, when your program isn't doing what you think it is. With a little practice you'll get a feel for what values to inspect.

Edward Peters
  • 3,623
  • 2
  • 16
  • 39
  • Thank you, I figure it out now. By using charAt(i). It what I tried first but the whole string/char comparison through my off, – Katie-Kat Nov 25 '22 at 12:33
  • `chatAt` is a good approach, `"someString.equals()` is fine too. The whole mess of primitives vs. objects vs. strings is really a java problem - the language is old enough to be saddled with some design choices I don't think anyone would make today, and they trip a lot of people up. – Edward Peters Nov 25 '22 at 13:45
  • I agree I learnt ruby, but am going for a role that requires Java, so trying to learn it. Another aspect that confuse me is telling what data type a variable is when assigning that data type. It seems silly to say hey this variable I'm assigning an integer to is an integer variable – Katie-Kat Nov 25 '22 at 19:37
  • @Katie-Kat So there are two things going on there - `dynamic` vs `static` typing, and whether or not a language has type inference. I'll go to the trenches defending static typing, because it can save you from an incredible number of bugs, and can be a tool for enforcing safe design. Dynamic languages like python feel like trying to build a house out of cooked spaghetti, to me. Type inference is another matter - generally I think it's worth it for saving verbosity. Java has some, but it was a late addition and not as strong as in many other languages. – Edward Peters Nov 25 '22 at 20:39
0

Edward Peters is right about misuse of substring that returns a String. In Java, string must be places between double quotes. A String is an object and you must use method equals to compare 2 objects:

String a = "first string";
String b = "second string";
boolean result = a.equals(b));

In your case, you should consider using charAt(int) instead. Chars must be places between simple quotes. A char is a primitive type (not an object) and you must use a double equals sign to compare two of them:

char a = '6';
char b = 't';
boolean result = (a==b);

So, your code should look like this:

public class DNA {
    
        public static void main(String[] args) {
            String dna1 = "ATGCGATACGCTTGA";
            String dna2 = "ATGCGATACGTGA";
            String dna3 = "ATTAATATGTACTGA";
            String dna = dna1;
            int aCount = 0;
            int cCount = 0;
            int tCount = 0;
    
            for (int i = 0; i < dna.length(); i++) {
                if (dna.charAt(i) == 'A') {
                    aCount += 1;
                } else if (dna.charAt(i) == 'C') {
                    cCount++;
                } else if (dna.charAt(i) == 'T') {
                    tCount++;
                }
                System.out.println(aCount);
            }
        }
    }
0

substring(i) doesn't select one character but all the characters from i to the string length, then you also made a wrong comparison: == checks 'object identity', while you want to check that they are equals.

You could substitute

if (dna.substring(i) == "A")

with:

if (dna.charAt(i) == 'A')

this works because charAt(i) returns a primitive type, thus you can correctly compare it to 'A' using ==

mttt
  • 71
  • 4
0

One of the problems, as stated, was the way you are comparing Strings. Here is a way that uses a switch statement and a iterated array of characters. I put all the strings in an array. If you only have one string, the outer loop can be eliminated.

public class DNA {

    public static void main(String[] args) {
        String dna1 = "ATGCGATACGCTTGA";
        String dna2 = "ATGCGATACGTGA";
        String dna3 = "ATTAATATGTACTGA";

        String[] dnaStrings =
            {dna1,dna2,dna3};
        int aCount = 0;
        int cCount = 0;
        int tCount = 0;
        int gCount = 0;
        for (String dnaString : dnaStrings) {
            for (char c : dnaString.toCharArray()) {
                switch (c)  {
                    case 'A' -> aCount++;
                    case 'T' -> tCount++;
                    case 'C' -> cCount++;
                    case 'G' -> gCount++;
                }
            }
        }
        System.out.println("A's = " + aCount);
        System.out.println("T's = " + tCount);
        System.out.println("C's = " + cCount);
        System.out.println("G's = " + gCount);
}

prints

A's = 14
T's = 13
C's = 6
G's = 10
WJS
  • 36,363
  • 4
  • 24
  • 39