Perl Weekly Challenge 145: Dot Product
These are some answers to the Week 145 of the Perl Weekly Challenge organized by Mohammad S. Anwar.
Spoiler Alert: This weekly challenge deadline is due in a few days from now (on January 2, 2022 at 24:00). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.
Task 1: Dot Product
You are given 2 arrays of same size, @a
and @b
.
Write a script to implement Dot Product.
Example:
@a = (1, 2, 3);
@b = (4, 5, 6);
$dot_product = (1 * 4) + (2 * 5) + (3 * 6) => 4 + 10 + 18 => 32
An important point is that we are told that the arrays have the same size. Thus, we don’t need to check that. We’ll also assume that they contain only numbers.
Dot Product in Raku
Raku is particularly well-suited to solve this task.
Assuming we have the two arrays presented in the task description (@a = (1, 2, 3);
and @b = (4, 5, 6);
), the infix Z
zip operator will interleave the values from the two arrays like a zipper, taking index-corresponding elements from each operand:
say @a Z @b; # prints: ((1 4) (2 5) (3 6))
That’s already quite good, but Z
is also a metaoperator) that can be combined with another infix operator that will be applied to each pair of the above result. Thus, using Z*
, we obtain directly the individual products:
say @a Z* @b; # prints: (4 10 18)
Finally, we only need to add these partial results (with the built-in sum
function or method, or with another metaoperator combination, [+]
) to fulfill the task in just one very short code-line:
use v6;
my @a = 1, 2, 3;
my @b = 4, 5, 6;
say sum @a Z* @b; # Could also be: say [+] @a Z* @b;
This script displays the following output:
$ raku ./dot-product.raku
32
Dot Product in Perl
Since Perl doesn’t have the Zip operator and metaoperator, we cannot port the Raku solution to Perl. But, using a map
, we can nevertheless implement a fairly concise solution:
use strict;
use warnings;
use feature "say";
my @a = (1, 2, 3);
my @b = (4, 5, 6);
my $result = 0;
$result += $_ for map { $a[$_] * $b[$_] } 0..$#a;
say $result;
This script displays the following output:
$ perl ./dot-product.pl
32
Update (Jan 2, 2022): Added the new section below with 16 languages.
Dot Product in 16 Other Programming Languages
All these implementations basically implement the same idea, with some minor differences due to syntactic differences.
In Julia
#!/usr/bin/julia
function dot_product(a1, a2)
res = 0
for i in eachindex(a1)
res = res + a1[i] * a2[i]
end
return res
end
print( "Dot product: ", dot_product([1, 2, 3], [4, 5, 6]))
Output:
$ julia ./dot-product.jl
Dot product: 32
In Python
def dot_product (a1, a2):
res = 0
for i in range(0, len(a1)):
res += a1[i] * a2[i]
return res
product = dot_product([1, 2, 3], [4, 5, 6])
print(product)
Output:
$ python3 ./dot-product.py
32
In Scala
object dot_product extends App {
val a1 = Array(1, 2, 3)
val a2 = Array(4, 5, 6)
var res = 0
for (i <- a1.indices) {
res = res + a1(i) * a2(i)
}
println("Dot product: " + res)
}
Output:
Dot product: 32
In Lua
#!/usr/bin/lua
local function dot_product(a1, a2)
res = 0
for i, v in next, a1 do
res = res + v * a2[i]
end
return res
end
print(dot_product({1, 2, 3}, {4, 5, 6}))
Output:
$ lua ./dot-product.lua
32
In Kotlin
fun dot_product(a1: List<Int>, a2: List<Int>): Int {
var res = 0
for (i in a1.indices) {
res += a1[i] * a2[i]
}
return res
}
fun main() {
println (dot_product(listOf<Int>(1, 2, 3), listOf<Int>(4, 5, 6)))
}
Output:
32
In Ruby
def dot_product(a1, a2)
res = 0
a1.each_with_index do |v, i|
res += v * a2[i]
end
return res
end
print dot_product([1, 2, 3], [4, 5, 6]), "\n"
Output:
bundle exec ruby dot-product.rb
32
In Rust
fn dot_product(a1: Vec<i32>, a2: Vec<i32>) -> i32 {
let mut res = 0;
a1.iter().enumerate().for_each(|(i, v)| {
res += v * a2[i];
});
return res
}
fn main() {
println!("{} ", dot_product(vec![1, 2, 3],vec![4, 5, 6]));
}
Output:
32
In Awk
$ echo '1 2 3
4 5 6 ' | awk -e '{
for (i = 1; i <= NF; i ++) {
if (NR == 1) {
col[i] = $i
}
else {
result += col[i] * $i
}
}
}
END {
print result
}
'
32
In C
#include <stdio.h>
int main() {
int a1[] = {1, 2, 3};
int a2[] = {4, 5, 6};
int res = 0;
int size = sizeof(a1)/sizeof(a1[0]);
for (int i = 0; i < size; i++) {
res += a1[i] * a2[i];
}
printf("%d\n", res);
}
Output:
$ ./a.out
32
In Pascal
program dot_product;
const
SIZE = 2;
var
a1: array[0..SIZE] of integer = (1, 2, 3);
a2: array[0..SIZE] of integer = (4, 5, 6);
result, i : integer;
begin
result := 0;
for i := 0 to SIZE do
result += a1[i] * a2[i];
writeln(result);
end.
Output:
32
In D
import std.stdio;
int a1[] = [1, 2, 3];
int a2[] = [4, 5, 6];
int main() {
int result = 0;
for (int i = 0; i < 3; i++) {
result += a1[i] * a2[i];
}
writeln(result);
return 0;
}
Output:
32
In Bash
$ echo '1 2 3
4 5 6 ' | bash -c '
read -a a1
read -a a2
for ((i = 0; i < ${#a1[@]}; i ++))
do ((result += a1[i] * a2[i]))
done
echo $result
'
32
In Dart
var a1 = [1, 2, 3];
var a2 = [4, 5, 6];
void main() {
int result = 0;
for (int i = 0; i < 3; i++ ) {
result += a1[i] * a2[i];
}
print(result);
}
Output:
32
In Go
package main
import "fmt"
func main() {
a1 := [3]int{1, 2, 3}
a2 := [3]int{4, 5, 6}
var result int = 0
for i := 0; i < 3; i++ {
result += a1[i] * a2[i]
}
fmt.Printf("Dot product: %d\n", result)
}
Output:
Dot product: 32
In Nim
Remember that Nim uses Python-like code indentation.
proc dot_product (a1, a2: array[0..2, int]) : int =
result = 0
for i in 0..2:
result += a1[i] * a2[i]
return result
let a1 = [1, 2, 3]
let a2 = [4, 5, 6]
let res = dot_product(a1, a2)
echo "dot product: ", res
Output:
dot product: 32
In Ring
Ring is a new programming language. Well, it is at least completely new to me (I had never heard about it until this morning of Jan 2, 2022), but it was released for the first time in January 2016. Its documentation states:
The Ring is an Innovative and practical general-purpose multi-paradigm scripting language that can be embedded in C/C++ projects, extended using C/C++ code and/or used as standalone language. The supported programming paradigms are Imperative, Procedural, Object-Oriented, Functional, Meta programming, Declarative programming using nested structures, and Natural programming.
I thought it would be interesting to use is as a guest language in the Perl Weekly Challenge to get a gist of it. Here we go.
see "Dot product: " + dot_product([1, 2, 3], [4, 5, 6]) + nl
func dot_product a1, a2
res = 0
for i = 1 to len(a1)
res = res + a1[i] * a2[i]
next
return res
Using the Ring online compiler, I obtain the following output:
Dot product = 32
Task 2: Palindromic Tree
This task requests us to implement a fairly complicated algorithm. I’ll try to come back to that later, if I have time and if I succeed to understand the requirement.
Update (Dec. 29): Finally, I have completed this second task here.
Wrapping up
The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on January 9, 2022. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment