Solving Perl Weekly Challenge 090 -- DNA Sequence and Ethiopian Multiplication

作者:   發佈於:   #raku

TASK #1 › DNA Sequence

Submitted by: Mohammad S Anwar

DNA is a long, chainlike molecule which has two strands twisted into a double helix. The two strands are made up of simpler molecules called nucleotides. Each nucleotide is composed of one of the four nitrogen-containing nucleobases cytosine (C), guanine (G), adenine (A) and thymine (T).

You are given DNA sequence, GTAAACCCCTTTTCATTTAGACAGATCGACTCCTTATCCATTCTCAGAGATGTGTTGCTGGTCGCCG.

Write a script to print nucleiobase count in the given DNA sequence. Also print the complementary sequence where Thymine (T) on one strand is always facing an adenine (A) and vice versa; guanine (G) is always facing a cytosine (C) and vice versa.

To get the complementary sequence use the following mapping:

T => A
A => T
G => C
C => G

I had no idea what should the end-result looks like for this task until I learn a gist about what "nucleiobase" means. It turns out we need to count the number of occurances of each character for part 1, and do character translation for part 2. Both are relatively easy to do using Raku.

my $dnaseq = 'GTAAACCCCTTTTCATTTAGACAGATCGACTCCTTATCCATTCTCAGAGATGTGTTGCTGGTCGCCG';

# Count of each nucleiobase
my %histogram = ( "A" => 0, "T" => 0, "C" => 0, "G" => 0 );
$dnaseq.comb.map(-> $c { %histogram{$c}++ });

# Complementary sequence
my $complemnet = $dnaseq.trans('TAGC' => 'ATCG');

# Print everything
say "nucleiobase count";
for 'A', 'T', 'C', 'G' -> $c {
    say "  $c: " ~ %histogram{$c};
}
say "Complement: " ~ $complement;

TASK #2 › Ethiopian Multiplication

Submitted by: Mohammad S Anwar

You are given two positive numbers $A and $B.

Write a script to demonstrate Ethiopian Multiplication using the given numbers.


The Ethiopian Multiplication is a process to calculate the product of two numbers with an algorithm that is pretty easy to memorize. Probabbly easier than the doing it "directly." The gist of this method is:

  1. In line 1, make 2 coulmns and put down two number A and B in each.
  2. In line 2, put the result of A\2 under column A, and the result of B×2k under column B.
  3. Repeatly put the result of \2 and ×2 of the numebrs from previous line in column A and B respectly, until the last number in column A reaches 1
  4. The product of A×B is the sum of all the numbers in column B with correspoding number from column A being odd numbers.

The notation of '\' here means integer division, which is just doing normal division than discard all the decimal parts. For examlpe, 15\2 = 7, 42\2 = 21. Although it seems weird to implement multiplication with division, only 'divided by two' is used, not the general version. As long as we couldd do all three of addition, multiplied by two, divided by two, we could do all multiplications in general. That seems like a bargain.

Refer to Wolfram Mathworld for a proof.

# multiply.raku

sub MAIN (Int $num1, Int $num2) {
    my $n1 = $num1;
    my $n2 = $num2;
    my @logs;
    push @logs, [ $n1, $n2 ];
    while $n1 != 1 {
        $n1 = $n1 div 2;
        $n2 = $n2 * 2;
        push @logs, [ $n1, $n2 ];
    }

    say "\#\t$num1 × $num2\n";
    for @logs -> $log {
        my $star = $log[0] %% 2 ?? " " !! "+";
        say "\t$log[0]\t$star $log[1]";
    }
    say "-------------------------";
    say "\t\t  " ~ @logs.grep({ .[0] % 2 == 1 }).map({ .[1] }).sum ~ "\n";
}

Demo:

# raku multiply.raku 42 84
#       42 × 84

        42        84
        21      + 168
        10        336
        5       + 672
        2         1344
        1       + 2688
-------------------------
                  3528

END.


本文為《解 Perl Weekly Challenge 090 -- DNA 序列與衣索比亞乘法》之英文版。