Daily Challenge: Prime Numbers

As mentioned before, the tech team at Kosong Satu Network has been running a daily challenge, small problems to exercise our programming logic.
One of the recent ones was a prime number utility that should:
- Test if a number is prime, and return why if it isn’t.
- Get the first
nprime numbers. - Get the list of primes between
xandy.
Here’s what I came up with, Go first, then a near-equivalent JavaScript version with Mocha tests.
Golang
File: prime.go
package main
import (
"fmt"
"math"
)
const Min = 2
type Prime struct{}
func (p Prime) Is(n int) error {
if n < Min {
return fmt.Errorf("prime must be integer greater than %d", Min)
}
divider := int(math.Floor(math.Sqrt(float64(n))))
for i := Min; i <= divider; i++ {
if n%i == 0 {
return fmt.Errorf("%d is divisor of %d", i, n)
}
}
return nil
}
func (p Prime) First(n int) []int {
var (
r []int = []int{}
count int = 0
iteration int = Min
)
for count < n {
if err := p.Is(iteration); err == nil {
r = append(r, iteration)
count++
}
iteration++
}
return r
}
func (p Prime) Between(x, y int) []int {
var r []int = []int{}
if x < Min {
x = Min
}
for i := x; i <= y; i++ {
if err := p.Is(i); err == nil {
r = append(r, i)
}
}
return r
}
File: prime_test.go
package main
import (
"reflect"
"strconv"
"strings"
"testing"
)
func int_to_string_arrays(a []int) []string {
r := []string{}
for _, v := range a {
r = append(r, strconv.Itoa(v))
}
return r
}
func TestIsPrime(t *testing.T) {
type PrimeData struct {
number int
reason string
}
primes := []PrimeData{
{number: 1, reason: "prime must be integer greater than 2"},
{number: 2},
{number: 3},
{number: 9, reason: "3 is divisor of 9"},
{number: 11},
{number: 12, reason: "2 is divisor of 12"},
{number: 13},
}
prime := Prime{}
for _, v := range primes {
expected := (len(v.reason) == 0)
err := prime.Is(v.number)
if err != nil && expected {
t.Errorf("%d expected true got false", v.number)
}
if !expected && err.Error() != v.reason {
t.Errorf("%d expected %s got %s", v.number, v.reason, err.Error())
}
}
}
func TestFirstPrimes(t *testing.T) {
prime := Prime{}
first_count := 5
expected := []int{2, 3, 5, 7, 11}
primes := prime.First(first_count)
if !reflect.DeepEqual(expected, primes) {
t.Errorf("first %d primes expected %s got %s",
first_count,
strings.Join(int_to_string_arrays(expected), ","),
strings.Join(int_to_string_arrays(primes), ","))
}
}
func TestBetweenPrimes(t *testing.T) {
prime := Prime{}
x, y := 1, 15
expected := []int{2, 3, 5, 7, 11, 13}
primes := prime.Between(x, y)
if !reflect.DeepEqual(expected, primes) {
t.Errorf("between %d - %d primes expected %s got %s",
x, y,
strings.Join(int_to_string_arrays(expected), ","),
strings.Join(int_to_string_arrays(primes), ","))
}
}
➜ primes git:(master) go test
PASS
ok _/chazuka/challenges/primes 0.006s
JavaScript
File: prime.js
'use strict';
var min = 2;
var reason = (function () {
var m = '';
return {
set: function (r) { m = r; },
get: function () { return m; },
reset: function () { m = ''; },
};
})();
var is = function (n) {
if (n < min) {
reason.set('prime must be integer greater than 2');
return false;
}
var sqrt = Math.floor(Math.sqrt(n));
for (var i = min; i <= sqrt; i++) {
if (n % i === 0) {
reason.set(i + ' is divisor of ' + n);
return false;
}
}
reason.reset();
return true;
};
var first = function (n) {
var x = min, y = 0, r = [];
while (y < n) {
if (is(x)) { r.push(x); y++; }
x++;
}
return r;
};
var between = function (x, y) {
var r = [];
for (var i = x; i <= y; i++) if (is(i)) r.push(i);
return r;
};
var why = function () { return reason.get(); };
exports.is = is;
exports.first = first;
exports.between = between;
exports.why = why;
File: test.js
const prime = require('./prime');
const assert = require('assert');
describe('prime', function () {
describe('#is', function () {
it('should detect if a number is prime or not and giving a reason when it is not', function () {
var primes = [
{ number: 1, expected: false, reason: 'prime must be integer greater than 2' },
{ number: 2, expected: true },
{ number: 3, expected: true },
{ number: 9, expected: false, reason: '3 is divisor of 9' },
{ number: 11, expected: true },
{ number: 12, expected: false, reason: '2 is divisor of 12' },
{ number: 13, expected: true },
];
for (var i = 0; i < primes.length; i++) {
var o = primes[i];
assert.equal(prime.is(o.number), o.expected);
if (!o.expected) assert.equal(prime.why(), o.reason);
}
});
});
describe('#first', function () {
it('should giving the first n of prime numbers', function () {
var primes = prime.first(5);
assert.equal(primes.length, 5);
assert.deepEqual(primes, [2, 3, 5, 7, 11]);
});
});
describe('#between', function () {
it('should giving the array of prime numbers between x,y', function () {
var primes = prime.between(1, 15);
assert.equal(primes.length, 6);
assert.deepEqual(primes, [2, 3, 5, 7, 11, 13]);
});
});
});
➜ primes git:(master) mocha
prime
#is
✓ should detect if a number is prime or not and giving a reason when it is not
#first
✓ should giving the first n of prime numbers
#between
✓ should giving the array of prime numbers between x,y
3 passing (12ms)
The interesting bit isn’t the algorithm, it’s how similar the two implementations end up looking once you ignore type declarations and idioms. That’s usually the value of doing the same problem in two languages.
