Kumite (ko͞omiˌtā) is the practice of taking techniques learned from Kata and applying them through the act of freestyle sparring.
You can create a new kumite by providing some initial code and optionally some test cases. From there other warriors can spar with you, by enhancing, refactoring and translating your code. There is no limit to how many warriors you can spar with.
A great use for kumite is to begin an idea for a kata as one. You can collaborate with other code warriors until you have it right, then you can convert it to a kata.
The Codewars built-in runBF
interpreter should correctly interpret a CAT program. According to the specs, the runBF
interpreter treats EOF as byte(-1)
.
,+[-.,+]
Test.describe('The BF CAT program', function () {
Test.it('should return "CAT" when "CAT" is passed in', function () {
Test.assertEquals(runBF(CAT), CAT);
});
Test.it('should return "Codewars" when "Codewars" is passed in', function () {
Test.assertEquals(runBF(CODEWARS), CODEWARS);
});
Test.it('should return "@donaldsebleung" when "@donaldsebleung" is passed in', function () {
Test.assertEquals(runBF(AUTHOR), AUTHOR);
});
Test.it('should return an empty string if nothing is passed in', function () {
Test.assertEquals(runBF(), '');
});
Test.it('should CAT 100 random strings', function () {
for (let i = 0; i < 100; i++) {
var randomString = Test.randomToken();
console.log(`Testing for ${randomString}`);
Test.assertEquals(runBF(randomString), randomString);
}
});
});
Sinus Cardinalis
Summary
This Kumite implements a math function sinc()
that receives up to two arguments, the first (required) argument being $x
and the second (optional) argument being $flag
. It computes and returns the cardinal sine of $x
.
Details
One function sinc()
and two constants (SINC_DEFAULT
and SINC_NORMALIZED
) are defined in this Kumite. The two constants are used internally by the sinc()
function.
Since there are two slightly different definitions for "cardinal sine", the sinc()
function in this Kumite implements both in a clever manner. While the first argument $x
is required, the second argument $flag
is optional and defaults to SINC_DEFAULT
. When the flag is set to SINC_DEFAULT
(or not provided, in which case it defaults to SINC_DEFAULT
anyway), the function computes the historical (unnormalized) cardinal sine of $x
. Otherwise, if the flag is set to SINC_NORMALIZED
, the function computes the normalized cardinal sine of $x
.
The sinc()
function implemented here also does type checking and input validation. $x
is only allowed to be an integer/float and $flag
can only take one of SINC_DEFAULT
and SINC_NORMALIZED
- any other value will throw an InvalidArgumentException
.
Related Kata
/*
function.sinc.php
A simple math function (with input validation)
that computes the cardinal sine of a real
number $x
Author: Donald Leung
NOTE: Comes with two user-defined constants
*/
// Constants (for use by the sinc() function as flags)
define('SINC_DEFAULT', 0);
define('SINC_NORMALIZED', 1);
// Function declaration and definition
function sinc($x, $flag = SINC_DEFAULT) {
// Type check "x" - confirm that it is either of an integer or a float
if (!is_int($x) && !is_float($x)) throw new InvalidArgumentException('In sinc(), the first argument "x" passed in must either be an integer or a float');
// Validate the flag - it can only be one of SINC_DEFAULT and SINC_NORMALIZED
if ($flag !== SINC_DEFAULT && $flag !== SINC_NORMALIZED) throw new InvalidArgumentException('The sinc() function only accepts 2 possible flags: SINC_DEFAULT and SINC_NORMALIZED');
// Special Case: where x = 0, sinc(x) = sinc(0) = 1
if ($x == 0) return 1;
// If the flag is set to SINC_NORMALIZED then multiply the argument "x" by pi and compute its unnormalized cardinal sine at pi * x
if ($flag === SINC_NORMALIZED) return sinc(M_PI * $x);
// Otherwise just return the unnormalized cardinal sine of x
return sin($x) / $x;
}
class SinusCardinalisTest extends TestCase {
protected function assertFuzzyEquals(float $expected, float $actual) {
$this->assertTrue(abs($expected) <= 1 ? abs($expected - $actual) <= 1e-9 : abs(($expected - $actual) / $expected) <= 1e-9, "Actual value $actual not sufficiently close to expected value $expected (accepted relative error: 1e-9)");
}
public function testThatConstantsAreDefined() {
$this->assertTrue(defined('SINC_DEFAULT'));
$this->assertTrue(defined('SINC_NORMALIZED'));
if (defined('SINC_DEFAULT') && defined('SINC_NORMALIZED')) {
echo SINC_DEFAULT . "\r\n";
echo SINC_NORMALIZED . "\r\n";
$this->assertNotEquals(SINC_DEFAULT, SINC_NORMALIZED, 'The two constants/flags used by sinc() should have different values!');
}
}
public function testZero() {
$this->assertFuzzyEquals(1, sinc(0));
$this->assertFuzzyEquals(1, sinc(0.0));
$this->assertFuzzyEquals(1, sinc(0, SINC_DEFAULT));
$this->assertFuzzyEquals(1, sinc(0.0, SINC_DEFAULT));
$this->assertFuzzyEquals(1, sinc(0, SINC_NORMALIZED));
$this->assertFuzzyEquals(1, sinc(0.0, SINC_NORMALIZED));
}
public function testUnnormalized() {
$this->assertFuzzyEquals(0.841470984807897, sinc(1));
$this->assertFuzzyEquals(0.324219657468139, sinc(-2.3));
$this->assertFuzzyEquals(-0.143198957002295, sinc(3.7));
$this->assertFuzzyEquals(-0.191784854932628, sinc(-5));
$this->assertFuzzyEquals(0.119739482820381, sinc(8.1));
$this->assertFuzzyEquals(-0.054402111088937, sinc(-10));
$this->assertFuzzyEquals(0.841470984807897, sinc(1, SINC_DEFAULT));
$this->assertFuzzyEquals(0.324219657468139, sinc(-2.3, SINC_DEFAULT));
$this->assertFuzzyEquals(-0.143198957002295, sinc(3.7, SINC_DEFAULT));
$this->assertFuzzyEquals(-0.191784854932628, sinc(-5, SINC_DEFAULT));
$this->assertFuzzyEquals(0.119739482820381, sinc(8.1, SINC_DEFAULT));
$this->assertFuzzyEquals(-0.054402111088937, sinc(-10, SINC_DEFAULT));
}
public function testNormalized() {
$this->assertFuzzyEquals(0, sinc(1, SINC_NORMALIZED));
$this->assertFuzzyEquals(0.111964394521844, sinc(-2.3, SINC_NORMALIZED));
$this->assertFuzzyEquals(-0.069599488486552, sinc(3.7, SINC_NORMALIZED));
$this->assertFuzzyEquals(0, sinc(-5, SINC_NORMALIZED));
$this->assertFuzzyEquals(0.012143600531895, sinc(8.1, SINC_NORMALIZED));
$this->assertFuzzyEquals(0, sinc(-10, SINC_NORMALIZED));
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidArgument1() {
sinc("11.23");
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidArgument2() {
sinc("Hello World");
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidArgument3() {
sinc(true);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidArgument4() {
sinc(array(5));
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidFlag1() {
sinc(3.2, 0.0);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidFlag2() {
sinc(3.2, 1.0);
}
}
Complex Addition and Subtraction
Related Collection
The Problem
Given two complex numbers z = x + iy
and w = u + iv
, how do I add them together? Furthermore, how do I compute z - w
if required?
The Solution
For addition, adding two complex numbers is as easy as adding their real and imaginary components together. So z + w
becomes (x + iy) + (u + iv) = (x + u) + i(y + v)
and z - w
becomes (x + iy) - (u + iv) = (x - u) + i(y - v)
.
function add(z, w) {
var x = Re(z);
var y = Im(z);
var u = Re(w);
var v = Im(w);
return new ComplexNumber(x + u, y + v); // z + w = (x + u) + i(y + v)
}
function subtract(z, w) {
var x = Re(z);
var y = Im(z);
var u = Re(w);
var v = Im(w);
return new ComplexNumber(x - u, y - v); // z - w = (x - u) + i(y - v)
}
Test.describe('Function "add"', function () {
var z = new ComplexNumber(3, 2); // 3 + 2i
var w = new ComplexNumber(-5, 4); // -5 + 4i
Test.it('should correctly add two complex numbers together', function () {
var sum = add(z, w); // Should equal z + w = (3 + 2i) + (-5 + 4i) = -2 + 6i
Test.assertEquals(Re(sum), -2);
Test.assertEquals(Im(sum), 6);
});
Test.it('should correctly subtract two complex numbers in the given order', function () {
var difference = subtract(z, w); // Should equal z - w = (3 + 2i) - (-5 + 4i) = 8 - 2i
Test.assertEquals(Re(difference), 8);
Test.assertEquals(Im(difference), -2);
});
});
Multiplication of Complex Numbers
Related Collection
Complex Analysis - click the link to try it out now :D
The Problem
Given two complex numbers z = x + iy
and w = u + iv
, how do I multiply them together (i.e. compute z * w
)?
The Solution
First, use the FOIL rule (first, outer, inner, last) to multiply and expand the expression:
z * w = (x + iy) * (u + iv) = xu + xiv + iyu + yvi^2
Then note that i^2 = -1
by definition and collect real and imaginary terms:
xu + xiv + iyu + yvi^2 = xu + i(xv + yu) - yv = (xu - yv) + i(xv + yu)
function multiply(z, w) {
var x = Re(z);
var y = Im(z);
var u = Re(w);
var v = Im(w);
return new ComplexNumber(x * u - y * v, x * v + y * u);
}
Test.describe('The complex "multiply" function', function () {
var z = new ComplexNumber(5, -1); // 5 - i
var w = new ComplexNumber(-2, 4); // -2 + 4i
Test.it('should correctly multiply two complex numbers "z" and "w" together', function () {
var product = multiply(z, w); // should equal -6 + 22i as per WolframAlpha
Test.assertEquals(Re(product), -6);
Test.assertEquals(Im(product), 22);
});
});
Calculate A = B + alpha * C
proc stream(b, c, alpha) {
return b + alpha * c;
}
Test.describe("HPCC STREAM Triad");
const size: int = 5;
const a: real = 3.0;
var B, C: [1..size] real = [i in 1..size] i;
var A: [B.domain] real = stream(B, C, a);
Test.expect(A == [4.0, 8.0, 12.0, 16.0, 20.0]);
Division of Complex Numbers
Related Collection
Complex Analysis <-- click on the link to train on this Collection :D
The Problem
Given two complex numbers z = x + iy
and w = u + iv
, how do I divide one by the other, e.g. compute z / w
(or the reverse)?
The Solution
Just as one may rationalize the denominator of 1 / sqrt(2)
to obtain sqrt(2) / 2
, it is also possible to real-ize the denominator of z / w
by multiplying both the numerator and denominator by the complex conjugate of "w" w* = u - iv
. Then use the identity i^2 = -1
where necessary and collect real and imaginary terms.
z / w
= (z * w*) / (w * w*)
= ((x + iy) * (u - iv)) / ((u + iv) * (u - iv))
= (xu - xiv + iyu - yvi^2) / (u^2 - (iv)^2)
= ((xu + yv) + i(yu - xv)) / (u^2 + v^2)
= ((xu + yv) / (u^2 + v^2)) + i((yu - xv) / (u^2 + v^2))
Also note that u^2 + v^2 = |w|^2
which may help to simplify your code further.
function divide(z, w) {
var x = Re(z);
var y = Im(z);
var u = Re(w);
var v = Im(w);
const abs = z => Math.hypot(Re(z), Im(z));
return new ComplexNumber((x * u + y * v) / Math.pow(abs(w), 2), (y * u - x * v) / Math.pow(abs(w), 2));
}
Test.describe('Your complex "divide" function', function () {
var z = new ComplexNumber(17, 13); // 17 + 13i
var w = new ComplexNumber(-6, 8); // -6 + 8i
Test.it('should divide two complex numbers correctly', function () {
var quotient = divide(z, w); // z / w should equal 1 / 50 - (107 / 50)i as per WolframAlpha
Test.assertApproxEquals(Re(quotient), 1 / 50);
Test.assertApproxEquals(Im(quotient), -107 / 50);
});
});
Computing the real Gamma Function with Stirling's Approximation
Related Kata
Computing the complex Gamma function <-- click on the link to attempt the Kata now :D
Related Collection
Overview
The Gamma Function Γ(x)
is an extension of the factorial function - while the factorial n!
is only defined for non-negative integers, the gamma function is defined for all numbers except the non-positive integers. However, the gamma function has its argument shifted down by 1
such that Γ(n) = (n - 1)!
for all n
where n
is a positive integer. One of its many applications is in fractional calculus.
Definitions
The main definition of the gamma function is based on a definite integral with positive infinity as one of its limits. There are also other exact definitions of the gamma function such as "Euler's definition as an infinite product" and the "Weierstrass definition". However, I will not elaborate on these definitions - more information can be easily found on Wikipedia (or by consulting your math professor).
The Problem
It is technically impossible to implement an exact definition of the Gamma Function in a computer/calculator since "there are, relatively speaking, no such simple solutions for factorials; no finite combination of sums, products, powers, exponential functions, or logarithms will suffice to express x!" (source: Wikipedia) so one must always resort to numerically approximating the Gamma function, ideally to a high degree of accuracy. A common, well-known approximation to the Gamma Function is known as Stirling's Approximation which has a simple formula and is usually sufficiently accurate for large values of x
; however, since it is an asymptotic approximation, it loses its accuracy for small values of x
and doesn't work with negative values of x
due to an attempt at squarerooting a negative number (JavaScript Math.sqrt
returns NaN
for negative inputs).
The Challenge
Stirling's Approximation is implemented in this Kumite as a possible implementation for the Gamma Function; however, you will notice that it fails most, if not all, of the tests. The challenge, should you accept it, is to properly implement the Gamma Function such that it passes all test cases properly.
function gamma(x) {
// Stirling's Approximation is simple and efficient (just a single calculation)
// but will it work?
x -= 1; // Shift argument down by 1
return Math.sqrt(2 * Math.PI * x) * Math.pow(x / Math.E, x); // Compute Stirling's Formula
}
Test.describe('Your real Gamma function "gamma"', function () {
Test.it('should properly compute Γ(n) to a high degree of accuracy where n is a positive integer', function () {
Test.assertApproxEquals(gamma(1), 1, 'Γ(1) = 0! = 1');
Test.assertApproxEquals(gamma(2), 1, 'Γ(2) = 1! = 1');
Test.assertApproxEquals(gamma(3), 2, 'Γ(3) = 2! = 2');
Test.assertApproxEquals(gamma(4), 6, 'Γ(4) = 3! = 6');
Test.assertApproxEquals(gamma(5), 24);
Test.assertApproxEquals(gamma(6), 120);
Test.assertApproxEquals(gamma(7), 720);
Test.assertApproxEquals(gamma(8), 5040);
Test.assertApproxEquals(gamma(9), 40320);
Test.assertApproxEquals(gamma(10), 362880);
Test.assertApproxEquals(gamma(51), 3.041409320e64);
});
Test.it('should properly compute Γ(x) to a high degree of accuracy for common values of positive real x', function () {
Test.assertApproxEquals(gamma(1 / 2), Math.sqrt(Math.PI), 'Γ(1/2) = sqrt(pi)');
Test.assertApproxEquals(gamma(3 / 2), 1 / 2 * Math.sqrt(Math.PI), 'Γ(3/2) = 1/2 * sqrt(pi)');
Test.assertApproxEquals(gamma(5 / 2), 3 / 4 * Math.sqrt(Math.PI), 'Γ(5/2) = 3/4 * sqrt(pi)');
Test.assertApproxEquals(gamma(7 / 2), 15 / 8 * Math.sqrt(Math.PI), 'Γ(7/2) = 15/8 * sqrt(pi)');
});
Test.it('should properly compute Γ(x) to a high degree of accuracy for common values of negative real x as well', function () {
Test.assertApproxEquals(gamma(-1 / 2), -2 * Math.sqrt(Math.PI), 'Γ(-1/2) = -2 * sqrt(pi)');
Test.assertApproxEquals(gamma(-3 / 2), 4 / 3 * Math.sqrt(Math.PI));
Test.assertApproxEquals(gamma(-5 / 2), -8 / 15 * Math.sqrt(Math.PI));
});
});
Game of Life :
The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970.
Your task is to write a program to calculate the next generation of Conway's game of life, given any starting position.
You start with a two dimensional grid of cells, where each cell is either alive or dead.
The grid is finite, and no life can exist off the edges.
When calculating the next generation of the grid, follow these four rules:
- Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
- Any live cell with more than three live neighbours dies, as if by overcrowding.
- Any live cell with two or three live neighbours lives on to the next generation.
- Any dead cell with exactly three live neighbours becomes a live cell.
Examples: * indicates live cell, . indicates dead cell
Example input: (4 x 8 grid)
........
....*...
...**...
........
Example output:
........
...**...
...**...
........
function nextGeneration(grid) {
return grid.map((row, rowIndex) => {
return row.map((cell, colIndex) => {
if (rowIndex !== 0 && colIndex !== 0 && rowIndex < grid.length - 1 && colIndex < row.length - 1) {
let neighboursCount = 0;
if (grid[rowIndex][colIndex + 1] === 1) neighboursCount++;
if (grid[rowIndex][colIndex - 1] === 1) neighboursCount++;
if (grid[rowIndex + 1][colIndex] === 1) neighboursCount++;
if (grid[rowIndex - 1][colIndex] === 1) neighboursCount++;
if (grid[rowIndex + 1][colIndex + 1] === 1) neighboursCount++;
if (grid[rowIndex + 1][colIndex - 1] === 1) neighboursCount++;
if (grid[rowIndex - 1][colIndex + 1] === 1) neighboursCount++;
if (grid[rowIndex - 1][colIndex - 1] === 1) neighboursCount++;
if (cell === 1) {
if (neighboursCount === 2 || neighboursCount === 3 ) {
return 1;
}
} else {
if (neighboursCount === 3 ) {
return 1;
}
}
return 0;
}
return 0;
});
});
}
describe("Given empty grid", () => {
it("when next generation, should return empty", () => {
Test.assertDeepEquals(nextGeneration([]), []);
});
});
describe("Given a single cell", () => {
it("when next generation, should die", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0],
[0,1,0],
[0,0,0],
]), [
[0,0,0],
[0,0,0],
[0,0,0],
]);
});
});
describe("Given a cell with 1 neighbour at rows", () => {
it("when next generation, should die", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0],
[0,1,1,0],
[0,0,0,0],
]), [
[0,0,0,0],
[0,0,0,0],
[0,0,0,0],
]);
});
});
describe("Given a cell with 2 neighbours at rows", () => {
it("when next generation, should live", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,1,1,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,0,1,0,0],
[0,0,0,0,0],
]);
});
});
describe("Given a cell with 2 neighbours at cols", () => {
it("when next generation, should live", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0],
[0,1,0],
[0,1,0],
[0,1,0],
[0,0,0],
]), [
[0,0,0],
[0,0,0],
[0,1,0],
[0,0,0],
[0,0,0],
]);
});
});
describe("Given a cell with 2 neighbours at \ (diagonal)", () => {
it("when next generation, should live", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,0,0,0],
[0,0,1,0,0],
[0,0,0,1,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,1,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
]);
});
});
describe("Given a cell with 2 neighbours at / (diagonal)", () => {
it("when next generation, should live", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,0,0,1,0],
[0,0,1,0,0],
[0,1,0,0,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,1,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
]);
});
});
describe("Given a cell with 4 neighbours", () => {
it("when next generation, should die", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,0,1,0],
[0,0,1,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,0,1,0,0],
[0,1,0,1,0],
[0,0,1,0,0],
[0,0,0,0,0],
]);
});
});
describe("Given a cell with 5 neighbours", () => {
it("when next generation, should die", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,1,1,0],
[0,0,1,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,1,1,1,0],
[0,0,0,0,0],
[0,0,1,0,0],
[0,0,0,0,0],
]);
});
});
describe("Given a cell with 6 neighbours", () => {
it("when next generation, should die", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,1,1,0],
[0,1,1,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
[0,1,0,0,0],
[0,0,0,0,0],
]);
});
});
describe("Given a cell with 7 neighbours", () => {
it("when next generation, should die", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,1,1,0],
[0,1,1,1,0],
[0,1,0,1,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
]);
});
});
describe("Given a cell with 8 neighbours", () => {
it("when next generation, should die", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,1,1,0],
[0,1,1,1,0],
[0,1,1,1,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
]);
});
});
describe("Given a die cell with 2 neighbours", () => {
it("when next generation, should die", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,0,0,0],
[0,0,0,0,0],
[0,1,0,0,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
]);
});
});
describe("Given a die cell with 3 neighbours", () => {
it("when next generation, should live", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
[0,1,0,0,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,1,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
]);
});
});
describe("Given a die cell with 4 neighbours", () => {
it("when next generation, should die", () => {
Test.assertDeepEquals(nextGeneration([
[0,0,0,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
[0,1,0,1,0],
[0,0,0,0,0],
]), [
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
]);
});
});
Description
The Kolakoski Sequence is a infinite string of integers that describes it own construction. Each digit, in order, encodes the size of the run that some digit in the sequence appears.
The inital terms of the sequence seeded by [1,2] are:
1, 2, 2, 1, 1, 2, 1, 2, 2...
Notice that there is one 1, followed by two 2s, then two 1s. In general the repitition of digits can be described as:
1, 2, 2, 1, 1, 2, 1, 2, 2...
Or the sequence itself. That is the idea you will be exploring in this excercise.
Instructions
Task 1:
Generate_Kolakoski_Seq(seed, n)
Write a function that takes an array of symbols as a seed, and an integer n, and produces the Kolakoski Sequence for that seed up to the nth digit as a common separted string.
Generate_Kolakoski_Seq( [2,3], 11 )
returns "2,2,3,3,2,2,2,3,3,3,2"
Generate_Kolakoski_Seq( [2], 5 )
returns "2,2,2,2,2"
Task 2:
Find_Kolaskoski_Number(seed, n)
Write a function that takes an array of symbols and a large integer n, and returns the nth digit of the sequence as an integer.
Find_Kolaskoski_Number( [1,2], 10000 )
returns: 1
(There is a way to compute this without computing the whole sequence)
// takes int[] and int, returns string (comma seperated integers)
function Generate_Kolakoski_Seq(seed, n){
}
// takes int[] and int, returns int
function Find_Kolaskoski_Number(seed, n){
}
Function will recive N for length of array and point as index to pint at in that array.
For example, function should generate arrays like this for
N = 10, point = 7
[7,6,5,4,3,2,1,0,1,2]
N = 10, point = 4
[4,3,2,1,0,1,2,3,4,5]
function func(N, point) {
let start = 0; // starting position of array
let clonePoint = point; // clone for point to start counting from that number at begining of array
let arr = [...Array(N).keys()] // generate array and fill with 0 to 10
if(!(point > N)) {
arr.forEach((o, index) => {
index < point ? arr[index] = clonePoint-- : arr[index] = start++;
});
return arr;
}
return [];
}
// TODO: Replace examples and use TDD development by writing your own tests
// These are some CW specific test methods available:
// Test.expect(boolean, [optional] message)
// Test.assertEquals(actual, expected, [optional] message)
// Test.assertSimilar(actual, expected, [optional] message)
// Test.assertNotEquals(actual, expected, [optional] message)
// NodeJS assert is also automatically required for you.
// assert(true)
// assert.strictEqual({a: 1}, {a: 1})
// assert.deepEqual({a: [{b: 1}]}, {a: [{b: 1}]})
// You can also use Chai (http://chaijs.com/) by requiring it yourself
// var expect = require("chai").expect;
// var assert = require("chai").assert;
// require("chai").should();
describe("Solution", function(){
it("should return specified array format", function(){
let arr = new Array(7,6,5,4,3,2,1,0,1,2)
Test.assertSimilar(func(10, 7), arr);
});
it("should return specified array format", function(){
let arr = new Array(3,2,1,0,1,2,3,4,5,6)
Test.assertSimilar(func(10, 3), arr);
});
});