Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

1.) DNA Strands For this assignment you will implement a class that roughly mode

ID: 3630005 • Letter: 1

Question

1.) DNA Strands
For this assignment you will implement a class that roughly models a DNA Strand. For our purposes, a DNA strand is a sequence of characters and each character in the sequence is either A, G, C or T. The character A bonds with T and the character G bonds with C. (In little more technical terms, we say that A forms a base pair with T and G forms a base pair with C.)
Given two DNA strands, they align with each other so that the number of bonds formed
is maximized. Let us understand this with an example. Say we start with the the DNA
strand

TCAT

and we want to examine possible alignments with it of another DNA strand
AGAGCAT

If we align them as

A G A G C A T
T C A T

then the number of bonds formed is two (A with T and G with C).
If we shift the second strand one character to the right,

   A G A G C A T
T C A T

then the number of bonds formed is 1 (A with T).
If we shift two characters to the right,

      A G A G C A T
T C A T
then the number of bonds formed is zero.

If we shift three characters to the right,

         A G A G C A T
T C A T

then the number of bonds formed is 1 (A with T).

We can also shift to the left, which we can describe using a negative number as a shift
of -1.

A G A G C A T
   T C A T
Then the number of bonds formed is zero.

If we shift by -2,

A G A G C A T
      T C A T

then the number of bonds formed is three (A with T, G with C, and A with T).

If we shift by -3,

A G A G C A T
         T C A T

then the number of bonds formed is zero.

If we shift by -4,

A G A G C A T
            T C A T

then the number of bonds formed is 1.

If we shift by -5

A G A G C A T
                T C A T
then the number of bonds formed is 1.

If we shift by -6,

A G A G C A T
                  T C A T

then the number of bonds formed is zero.

These are all possible alignments. The maximum number of bonds is 3, seen in the sixth alignment (shifting by -2)


2.) DNAStrand

The class DNAStrand encapsulates the sequence of characters in a DNA strand and has operations for determining the number of bonds formed with another DNAStrand. You will probably just need one instance variable of type String. Your class DNAStrand must have following public methods and constructors.

DNAStrand(String givenData) :- A specific constructor that constructs the DNAStrand
with given String parameter. The given data does not have to be a valid sequence of A, G, C or T, and your constructor does not need to check it.

int letterCount(char ch) :- Returns the number of occurrences of the given character
within this strand.

boolean isValid() :- Returns true if the sequence of characters for this strand includes only the capital letters A, G, C or T, otherwise returns false.

boolean matches(char c1, char c2) :- Returns true if character c1 bonds with character
c2, otherwise returns false. Characters other than A, G, C or T are assumed to never bond with any other character.

int maxBonds(DNAStrand other) :-Returns the maximum number of bonds formed among all possible alignments between this strand and the given strand.

int countBondsInAlignment(DNAStrand other, int shift). Returns the number of
bonds when other is aligned with this strand by shifting it shift characters. The parameter shift can be positive or negative, where a positive value indicates that other is shifted to the right relative to this strand, and a negative value indicates that it is shifted to the left.
For example, if this is the strand TCAT and other represents the strand AGAGCAT,
then countBondsInAlignment(other, 2) returns the number of bonds formed in the alignment

      A G A G C A T
T C A T

which is zero. Likewise, countBondsInAlignment(other, -2) returns the number of bonds formed in the alignment

A G A G C A T
      T C A T

which is 3. If shift is positive and is greater or equal to the length of this strand, or if
shift is negative and -shift is greater than or equal to the length of other the method
returns zero (since the strands don't overlap at all).

3.) Suggestions

First write the constructor and the methods letterCount, and isValid, and matches. Then write the method countBondsInAlignment. For this method, first write the code assuming that shift is nonnegative. Then extend it to the case when shift is negative. Write the method maxStrength at the end. Think about calling the method countBondsInAlignment from maxStrength.

4.) Notes
Notice that the first parameter of maxBonds is another instance of the class DNAStrand itself. In an invocation of this method such as

int bonds = myStrand.maxBonds(otherStrand);

there are two instances of DNAStrand in the picture, namely, the target object myStrand (on which you've invoked the method), and the other one otherStrand that is the argument to the method. As usual, within the implementation of the method, you have access to the instance variables of the target myStrand, and you can refer to it as this. You'll need to use the fact that within the implementation of the method, you also have access to the private instance variables of any other object of the same type, including the other object otherStrand. For example, suppose we wanted to implement a hypothetical method
boolean isSubsequence(DNAStrand other) for our DNAStrand class that returns true if other is a subsequence of this. Suppose also that the sequence data is stored in a private instance variable called data of type String. Then a possible implementation might look like

{
public boolean isSubsequence(DNAStrand other)
{
// is other a subsequence of this strand?
int index = this.data.indexOf(other.data);
return index >= 0;
}
}

The explicit use of the keyword this is optional here.
You'll also want to remember the di_erence between literal values such as 'A', which has
the primitive type char, and "A", a String of length one.

Explanation / Answer

public class DNAStrand
{
    private String data;
   
    //---------------------------------------------------------
    public DNAStrand()
    {
        this.data = "";
    }
   
    //---------------------------------------------------------
    public DNAStrand(String strand)
    {
        this.data = strand;
    }
   
    //---------------------------------------------------------
    // For display debugging
    //---------------------------------------------------------
    public void PrintString(int shift)
    {
        if (shift > 0)
        {
            for (int i = 0; i < shift; ++i)
            {
                System.out.print(" ");
            }
        }
        else
        {
            for (int i = 0; i < -shift; ++i)
            {
                System.out.print(" ");
            }
        }
        for (int i = 0; i < this.Length(); ++i)
        {
            System.out.print(this.data.charAt(i) + " ");
        }
        System.out.println();
    }
   
    //---------------------------------------------------------
    public int Length()
    {
        return this.data.length();
    }
   
    //---------------------------------------------------------
    public boolean IsValid()
    {
        for (int i = 0; i < this.Length(); ++i)
        {
            if (this.data.charAt(i) != 'A' && this.data.charAt(i) != 'T' &&
                this.data.charAt(i) != 'G' && this.data.charAt(i) != 'C')
            {
                return false;
            }
        }
        return true;
    }

    //---------------------------------------------------------
    public char IndexOf(int index)
    {
        return this.data.charAt(index);
    }
   
    //---------------------------------------------------------
    public boolean Matches(char base1, char base2)
    {
        if (base1 == 'A' && base2 == 'T')
        {
            return true;
        }
        if (base1 == 'T' && base2 == 'A')
        {
           return true;
        }
        if (base1 == 'G' && base2 == 'C')
        {
           return true;
        }
        if (base1 == 'C' && base2 == 'G')
        {
           return true;
        }
        return false;
    }
   
    //---------------------------------------------------------
    public int CountBondsInAlignment(DNAStrand rhs, int shift)
    {
        if (this.IsValid() && rhs.IsValid())
        {
            int accumulator = 0;
            if (shift >= 0)
            {
                if (this.Length() > shift)
                {
                    for (int i = 0; i + shift < this.Length() && i < rhs.Length(); ++i)
                    {
                        if (this.Matches(this.data.charAt(i + shift), rhs.IndexOf(i)))
                        {
                            accumulator++;
                        }
                    }
                    return accumulator;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                if (rhs.Length() > -shift)
                {
                    for (int i = 0; i - shift < rhs.Length() && i < this.Length(); ++i)
                    {
                        if (this.Matches(this.data.charAt(i), rhs.IndexOf(i - shift)))
                        {
                            accumulator++;
                        }
                    }
                    return accumulator;
                }
                else
                {
                    return 0;
                }
            }
        }
        return -1;
    }
   
    //---------------------------------------------------------
    public int MaxBonds(DNAStrand rhs)
    {
        int max = 0;
       
        for (int i = 0; i < this.Length(); ++i)
        {
            int countBonds = this.CountBondsInAlignment(rhs, i);
            if (countBonds > max)
            {
                max = countBonds;
            }
        }
        for (int i = 1; i < rhs.Length(); ++i)
        {
            int countBonds = this.CountBondsInAlignment(rhs, -i);
            if (countBonds > max)
            {
                max = countBonds;
            }
        }
        return max;
    }
   
    //---------------------------------------------------------
    // Main
    //---------------------------------------------------------
    public static void main(String[] args)
    {
        DNAStrand s1 = new DNAStrand("TCAT");
        DNAStrand s2 = new DNAStrand("AGAGCAT");
       
        for (int i = 0; i < s2.Length() + 2; ++i)
        {
            s2.PrintString(0);
            s1.PrintString(s2.Length() + 1 - i);
            System.out.print("Bond(s): " + s1.CountBondsInAlignment(s2, i - s2.Length() - 1) + " ");
        }
       
        for (int i = 1; i < s1.Length() + 2; ++i)
        {
            s2.PrintString(i);
            s1.PrintString(0);
            System.out.print("Bond(s): " + s1.CountBondsInAlignment(s2, i) + " ");
        }
       
        System.out.println(s1.MaxBonds(s2));
        System.out.println(s2.MaxBonds(s1));
    }
}