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.
let detectType v =
match box v with
| :? int -> printfn "int"
| :? string -> printfn "string"
| _ -> printfn "?"
detectType 1
detectType "1"
detectType 1.0
let areEqualsIgnoreCase (s : string * string) =
match s with
| (s1, s2) when s1.ToUpper() = s2.ToUpper() -> true
| _ -> false
printfn "%b" (areEqualsIgnoreCase ("Hello", "hello"))
printfn "%b" (areEqualsIgnoreCase ("hello", "HELLO"))
printfn "%b" (areEqualsIgnoreCase ("hello", "ello"))
let getSign x = if x > 0 then "+" elif x < 0 then "-" else "0"
let foo = [-3..3] |> List.map getSign |> String.concat(" ")
printfn "%s" foo
let evens = [2 .. 2 .. 10]
let odds = [for i in evens -> i - 1]
let fizzBuzzNumbers = [for i in 1 .. 100 do if i % 3 = 0 && i % 5 = 0 then yield i]
printfn "%A" evens
printfn "%A" odds
printfn "%A" fizzBuzzNumbers
This is a test kumite
var getAge = function(today, dob) {
if(!today || !dob) {
return null;
}
var now = new Date(today);
return now.getYear() - new Date(dob).getYear();
};
// You can also use Chai (http://chaijs.com/) by requiring it yourself
var expect = require("chai").expect;
describe("getAge", function(){
it("should return 10 for 2016/10/20 and 2006/10/20", function(){
expect( getAge('2016/10/20', '2006/10/20') ).to.equal( 10 );
});
it("should return null for blank today", function(){
expect( getAge('', '2006/10/20') ).to.be.null;
});
it("should return null for blank dob", function(){
expect( getAge('2016/10/20', '') ).to.be.null;
});
it("should return null for blank dates", function(){
expect( getAge('', '') ).to.be.null;
});
it("should return null for unparseable today date", function(){
expect( getAge('what', '') ).to.be.null;
});
it("should return null for unparseable dob", function(){
expect( getAge('', 'what') ).to.be.null;
});
});
Reflection in PHP
The Reflection API is a core API in PHP (meaning no installation is required) which is comprised of multiple classes and interfaces and is primarily used to extract information regarding functions and classes etc. by reverse-engineering them.
Why Use Reflection?
At this time you may have wondered: why even bother with reflection? If a certain PHP script, function or class is to be tested, wouldn't it be better (and perhaps easier) to directly test its behaviour with the usual test cases?
While that may be true in most cases where the behaviour of a certain function or class is key (I mean, who cares how you implement a Caesar Cipher as long as it's done properly and it doesn't take too long to execute?), it may sometimes be important to know exactly how the code was implemented, especially when it comes to checking other people's code when teaching them certain syntax and features. Take Codecademy for example (NOTE: By taking Codecademy as an example I do NOT claim to know how they actually test user code). Somewhere in their PHP course, they probably required the user to define a function that receives a fixed number of required arguments (or none), does something to the input and returns the result. Now, there are 2 main ways of testing the user-defined function. The most obvious (and commonly used) way of testing the function is of course by testing its behaviour using test cases which pass certain arguments into the user-defined function and expects certain results depending on the argument(s) passed in; usually, that is all that is needed to ensure that the user has defined and implemented the function correctly. However, in some cases, we may also want to ensure that all of the arguments in the user-defined function are required and do not have a default value, for example (because if the novice programmer added a default value for an argument and passed the exercise, the novice programmer may then think that it is always required to provide a default value for every argument in a function, for example). This cannot be verified for certain using only behavioural tests and this is where reflection comes into play. By using the class ReflectionFunction
(a part of rhe Reflection API in PHP), we can then extract crucial information about the arguments in the user-defined function and confirm that the function indeed has no default values as arguments. Alternatively, we could also verify that the user-defined function indeed receives only a fixed number of arguments instead of receiving the argument list as an array and then accessing arguments by index, which then could again be achieved through Reflection.
Reflection Examples used in this Kumite
In this Kumite, I will be demonstrating how and when Reflection can be used in your test cases to confirm that the user has declared and implemented certain functions or classes properly. For the sake of simplicity, only the ReflectionFunction
class from the Reflection API, used to test the declaration and implementation of both named and anonymous functions, will be demonstrated in this Kumite.
The "Code" section of this Kumite will contain the code for a user-defined function called multiply()
which is expected to require two integer arguments and return an integer as the result via return type declaration. The Test Cases for this Kumite will then assess the user-defined function in two ways:
- By assessing its behaviour (using a number of fixed and random tests to ensure that the function always returns the correct result)
- By using Reflection (
ReflectionFunction
specifically) to ensure that the user has used the correct type declarations for both the arguments and the return type - this aspect of the user-defined function is almost impossible to test and confirm simply by using behavioural testing.
To learn more about Reflection and its uses in PHP, you can refer to the official documentation on Reflection in php.net.
function multiply(int $a, int $b): int {
return $a * $b;
}
class ReflectionExamplesTest extends TestCase {
public function testMultiplyBehaviour() {
// Testing the behaviour of the user-defined "multiply" function as usual using a combination of fixed and random tests
$this->assertEquals(1, multiply(1, 1));
$this->assertEquals(2, multiply(1, 2));
$this->assertEquals(4, multiply(2, 2));
$this->assertEquals(15, multiply(3, 5));
for ($i = 0; $i < 1e3; $i++) {
$this->assertEquals(($a = rand(0, 100)) * ($b = rand(0, 100)), multiply($a, $b));
}
}
public function testMultiplyDeclarationAndImplementation() {
// Testing the actual implementation details of the user-defined "multiply" function (e.g. ensuring that type declarations are used, ensuring that the function receives a fixed number of arguments, ensuring that all arguments in the function are required and do not have a default value)
// This is when Reflection comes into play
// Creating instance of ReflectionFunction (this will allow us to extract all the necessary implementation details from the user-defined function)
$multiply = new ReflectionFunction('multiply');
// Converting our instance of ReflectionFunction into a string (to provide a visual representation of the implementation of our function) and echoing it to the screen
// Somehow converting an instance of ReflectionFunction into a string doesn't work properly on Codewars so I've commented it out but feel free to try it in your local server
// echo htmlspecialchars($multiply . "\n");
// Verifying that the user-defined function "multiply" accepts exactly 2 arguments, no more, no less
$this->assertEquals(2, $multiply->getNumberOfParameters());
// Verifying that both arguments in the user-defined function "multiply" are required and do not have a default value
$this->assertEquals(2, $multiply->getNumberOfRequiredParameters());
// Obtaining the argument list of the user-defined "multiply" function as an array of instances of ReflectionParameter
$params = $multiply->getParameters();
// Check if both parameters of the user-defined "multiply" function have an explicitly declared argument type
$this->assertTrue($params[0]->hasType());
$this->assertTrue($params[1]->hasType());
// Check if both parameters of the user-defined "multiply" function have an explicitly declared type of "int" (Integer)
$this->assertEquals("int", strval($params[0]->getType()));
$this->assertEquals("int", strval($params[1]->getType()));
// Verifying that the user-defined function "multiply" has an **explicitly** declared return type
$this->assertTrue($multiply->hasReturnType());
// Verifying that the user-defined function "multiply" has an explicitly declared return type of "int" (Integer)
$this->assertEquals("int", strval($multiply->getReturnType()));
}
}
An anagram is the result of rearranging the letters of a word to produce a new one.
Write a function that takes a word and returns and array with all anagrams (all possible combinations of letter in a word).
###Example:
allAnagrams("bu") == ["bu", "ub"]
function allAnagrams(word) {
if (word.length < 2) {
return [word];
} else {
var allAnswers = [];
for(var i = 0; i < word.length; i++) {
var letter = word[i];
var shorterWord = word.substr(0, i) + word.substr(i+1, word.length - 1);
var shortWordArray = allAnagrams(shorterWord);
for (var j = 0; j < shortWordArray.length; j++) {
allAnswers.push(letter + shortWordArray[j]);
}
}
return allAnswers;
}
}
// 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();
Test.expect(allAnagrams("bu"), ["bu", "ub"] );
Test.expect(allAnagrams("lol"), ["lol", "llo", "oll", "oll", "llo", "lol"] );
Test.expect(allAnagrams("dog"), ["dog", "dgo", "odg", "ogd", "gdo", "god"] );
Test.expect(allAnagrams("four"), ["four", "foru", "fuor", "furo", "frou", "fruo", "ofur", "ofru", "oufr", "ourf", "orfu", "oruf", "ufor", "ufro", "uofr", "uorf", "urfo", "urof", "rfou", "rfuo", "rofu", "rouf", "rufo", "ruof"] );
Test.expect(allAnagrams("lazy"), ["lazy", "layz", "lzay", "lzya", "lyaz", "lyza", "alzy", "alyz", "azly", "azyl", "aylz", "ayzl", "zlay", "zlya", "zaly", "zayl", "zyla", "zyal", "ylaz", "ylza", "yalz", "yazl", "yzla", "yzal"] )
Write a function that takes a string and returns it with spaces between every letter.
Example:
"october" => "o c t o b e r"
function spaceMaker(str){
return str.split("").join(" ");
}
// 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();
Test.expect(spaceMaker("october"), "o c t o b e r" );
Test.expect(spaceMaker("space"), "s p a c e" );
Test.expect(spaceMaker("random"), "r a n d o m" );
Test.expect(spaceMaker("javascript"), "j a v a s c r i p t" );
Test.expect(spaceMaker("codewars"), "c o d e w a r s" );
Test.expect(spaceMaker("string"), "s t r i n g" );
Write Memoize function.
Memoize is function that take as argument function and return another function.
This returned function should call original function with the same arguments, but it should never call this function with exact the same arguments.
It should just return cahed result instead.
function memoize(func) {
return (...args) => {
// your function
};
}
// 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 test for something", function(){
Test.assertEquals("actual", "expected", "This is just an example of how you can write your own TDD tests");
});
});
You must calculate the virtual cost of an item based on the real cost of the item to the rounded $token.
price = 19.99, token = 5 the token cost should output 20, Tokens can never cost 0 unless token cost and price is 0.
calcTokenCost(19.99, 5) = 20
calcTokenCost(17.30, 5) = 15
calcTokenCost(0.01, 5) = 5
calcTokenCost(0, 5) = 5
calcTokenCost(0, 0) = 0
function calcTokenCost($price, $token) {
}