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.
