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.
Currently, the hiding
test that tests for hidden modules is only available in Haskell 7. Unfortunately, the original source is not compatible with Haskell 8 runner, so we have to write it from scratch.
Here is a small attempt to analyze the import statements from the source code.
module Example where
import Prelude hiding (Bool(..), head, (/))
import Data.Maybe
import qualified Data.Map as Map
import Data.Map (Map(..), fromList)
import Data.Set (Set)
import Data.Monoid (Dual(getDual))
{-# LANGUAGE RecordWildCards #-}
module ExampleSpec where
import Data.List (intercalate)
import Test.Hspec
import Test.HUnit (assertBool)
import Example
import qualified Language.Haskell.Exts as Q
ripParseOk :: Q.ParseResult a -> IO a
ripParseOk (Q.ParseOk x) = return x
ripParseOk _ = fail "Could not parse solution correctly"
getImports :: Q.Module a -> IO [Q.ImportDecl a]
getImports (Q.Module _ _ _ x _) = return x
getImports _ = fail "Unknown source type"
getModuleName :: Q.ModuleName a -> String
getModuleName (Q.ModuleName _ x) = x
nameToStr :: Q.Name a -> String
nameToStr (Q.Ident _ x) = x
nameToStr (Q.Symbol _ x) = x
cnameToStr :: Q.CName a -> String
cnameToStr (Q.VarName _ x) = nameToStr x
cnameToStr (Q.ConName _ x) = nameToStr x
specToStr :: Q.ImportSpec a -> [String]
specToStr (Q.IVar _ x) = [nameToStr x]
specToStr (Q.IAbs _ _ x) = [nameToStr x]
specToStr (Q.IThingAll _ x) = [nameToStr x]
specToStr (Q.IThingWith _ x cn) = nameToStr x : map cnameToStr cn
data ImportDesc =
ImportAll {mName :: String}
| ImportSome {mName :: String, mSymbols :: [String]}
| HideSome {mName :: String, mSymbols :: [String]}
deriving (Eq, Show)
declToDesc :: Q.ImportDecl a -> ImportDesc
declToDesc decl = case Q.importSpecs decl of
Nothing -> ImportAll moduleName
Just (Q.ImportSpecList _ True xs) -> HideSome moduleName (concatMap specToStr xs)
Just (Q.ImportSpecList _ False xs) -> ImportSome moduleName (concatMap specToStr xs)
where
moduleName = getModuleName $ Q.importModule decl
treatPrelude :: [ImportDesc] -> [ImportDesc]
treatPrelude xs = if any (\x -> mName x == "Prelude") xs then xs else ImportAll "Prelude" : xs
data Hidden = Module {moduleName :: String} | FromModule {moduleName :: String, symbolName :: String} deriving (Eq)
instance Show Hidden where
show (Module{..}) = moduleName
show (FromModule{..}) = moduleName ++ "." ++ symbolName
showList hiddens xs = intercalate ", " (map show hiddens) ++ xs
exposed :: ImportDesc -> Hidden -> Bool
exposed (ImportAll{..}) (Module{..}) = mName == moduleName
exposed (ImportAll{..}) (FromModule{..}) = mName == moduleName
exposed (ImportSome{..}) (Module{..}) = mName == moduleName
exposed (ImportSome{..}) (FromModule{..}) = mName == moduleName && symbolName `elem` mSymbols
exposed (HideSome{..}) (Module{..}) = mName == moduleName
exposed (HideSome{..}) (FromModule{..}) = mName == moduleName && symbolName `notElem` mSymbols
hidden :: [Hidden] -> Expectation
hidden hiddens = do
sol <- Q.parseFile "solution.txt" >>= ripParseOk >>= getImports
let imports = treatPrelude $ map declToDesc sol
let failures = [(desc, hide) | desc <- imports, hide <- hiddens, exposed desc hide]
let message = "Import declarations must hide " ++ show hiddens
assertBool message $ null failures
spec :: Spec
spec = do
describe "add" $ do
it "adds Nums" $ do
((+) 1 1) `shouldBe` (2 :: Integer)
describe "hidden module" $ do
it "hidden Prelude.head" $ do
hidden [FromModule "Prelude" "head"]
describe "hidden module" $ do
it "hidden Prelude.head and Data.Set" $ do
hidden [FromModule "Prelude" "head", Module "Data.Set"]
main = hspec spec
A simple test on whether Data.Leibniz
is available as a PureScript module on Codewars.
module LeibnizExample where
import Data.Leibniz
reflexivity :: forall a. a ~ a
reflexivity = id
module DummySpec where
import Prelude
import Test.Spec (Spec, describe, it)
import Test.Spec.Assertions (shouldEqual)
import LeibnizExample
spec :: Spec Unit
spec =
describe "Data.Leibniz" do
describe "Availability on Codewars" do
it "This should compile if it is indeed available on Codewars" do
true `shouldEqual` true
Faça um arrays
function ronalado(){
// 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");
});
});
Crie o retorno da função soma.
function soma() {
}
function soma(a, b) {
}
// 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(soma(2, 2), 4, "O retorno deve ser 4");
});
});
Just testing whether the State
monad in PureScript is available on Codewars.
module StateTest (factorialWithState) where
import Prelude
import Control.Monad.State (State, evalState, get, put)
import Data.Tuple (Tuple(..))
factorialWithState :: Int -> Int
factorialWithState n = evalState executionLoop (Tuple n 1)
where
executionLoop :: State (Tuple Int Int) Int
executionLoop = do
Tuple counter result <- get
if counter == 0
then pure result
else do
put (Tuple (counter - 1) (result * counter))
executionLoop
module StateTestSpec where
import Prelude
import Test.Spec (Spec, describe, it)
import Test.Spec.Assertions (shouldEqual)
import StateTest (factorialWithState)
spec :: Spec Unit
spec =
describe "StateTest.factorialWithState" do
describe "Fixed tests" do
it "should work for some fixed tests" do
factorialWithState 0 `shouldEqual` 1
factorialWithState 1 `shouldEqual` 1
factorialWithState 2 `shouldEqual` 2
factorialWithState 3 `shouldEqual` 6
factorialWithState 4 `shouldEqual` 24
factorialWithState 5 `shouldEqual` 120
factorialWithState 6 `shouldEqual` 720
factorialWithState 7 `shouldEqual` 5040
factorialWithState 8 `shouldEqual` 40320
factorialWithState 9 `shouldEqual` 362880
factorialWithState 10 `shouldEqual` 3628800
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
Bob answers 'Sure.' if you ask him a question.
He answers 'Whoa, chill out!' if you yell at him.
He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
He says 'Fine. Be that way!' if you address him without actually saying anything.
He answers 'Whatever.' to anything else.
Notes:
- Message with ALL UPPERCASES is consider yelling .
function hey(message) {
var isAllUppercase = message === message.toUpperCase();
var isYelling = message.includes("!") || isAllUppercase;
var isQuestioning = message.includes("?");
if (message.length === 0) {
return "Fine. Be that way!";
} else if (isQuestioning && isYelling) {
return "Calm down, I know what I'm doing!";
} else if (isQuestioning) {
return "Sure.";
} else if (isYelling) {
return "Whoa, chill out!";
} else {
return "Whatever.";
}
}
describe('Bob', () => {
it('stating something', () => {
const result = hey('Tom-ay-to, tom-aaaah-to.');
Test.assertEquals(result, 'Whatever.');
});
it('shouting', () => {
const result = hey('WATCH OUT!');
Test.assertEquals(result, 'Whoa, chill out!');
});
it('shouting gibberish', () => {
const result = hey('FCECDFCAAB');
Test.assertEquals(result, 'Whoa, chill out!');
});
it('asking a question', () => {
const result = hey('Does this cryogenic chamber make me look fat?');
Test.assertEquals(result, 'Sure.');
});
it('asking a numeric question', () => {
const result = hey('You are, what, like 15?');
Test.assertEquals(result, 'Sure.');
});
it('asking gibberish', () => {
const result = hey('fffbbcbeab?');
Test.assertEquals(result, 'Sure.');
});
it('using acronyms in regular speech', () => {
const result = hey("It's OK if you don't want to go to the DMV.");
Test.assertEquals(result, 'Whatever.');
});
it('forceful question', () => {
const result = hey('WHAT THE HELL WERE YOU THINKING?');
Test.assertEquals(result, 'Calm down, I know what I\'m doing!');
});
it('shouting numbers', () => {
const result = hey('1, 2, 3 GO!');
Test.assertEquals(result, 'Whoa, chill out!');
});
it('shouting with special characters', () => {
const result = hey('ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!');
Test.assertEquals(result, 'Whoa, chill out!');
});
it('shouting with no exclamation mark', () => {
const result = hey('I HATE YOU');
Test.assertEquals(result, 'Whoa, chill out!');
});
it('silence', () => {
const result = hey('');
Test.assertEquals(result, 'Fine. Be that way!');
});
it('starting with whitespace', () => {
const result = hey(' hmmmmmmm...');
Test.assertEquals(result, 'Whatever.');
});
it('ending with whitespace', () => {
const result = hey('Okay if like my spacebar quite a bit? ');
Test.assertEquals(result, 'Sure.');
});
it('non-question ending with whitespace', () => {
const result = hey('This is a statement ending with whitespace ');
Test.assertEquals(result, 'Whatever.');
});
});
Concatene as listas A, B e C em uma nova lista D.
Importante:
- As listas A, B e C devem continuar intactas.
- Primeiro os valores de A, depois B e por último C, respeitando a ordem
const main = () => {
let a = [1, 2, 3];
let b = [4, 5, 6];
let c = [7, 8, 9];
// converter para ES6
var d = a.concat(b).concat(c);
return d.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();
describe("Solution", function(){
it("should test for something", function(){
Test.assertEquals(main(), "1,2,3,4,5,6,7,8,9", "Victory!");
});
});
Spread operator funciona com push, shift, unshift, slice, splice, concat.
Exercício:
Substitua os valores de A por B sem criar uma nova referência para A.
const main = () => {
const a = [1, 2, 3, 4];
let b = [5, 6, 7, 8];
// converta para ES6
while (a.length) {
a.pop();
}
while (b.length) {
a.push(b.shift());
}
return a.join(',');
};
describe("Solution", function(){
it("should test for something", function(){
Test.assertEquals(main(), "5,6,7,8", "Victory");
});
});
Com destructuring conseguimos ser precisos quanto aos valores que queremos acessar e com spread acumulamos o que sobrou. Usando esses dois recursos em conjunto conseguimos o efeito contrário, remover o desnecessário e guardar o restante.
Exercício:
- Converta rem para arrow function
- Use destructuring e spread operator para remover keywords do objeto principal
- Retorne o novo objeto e armazene na variável obj2
const main = () => {
let obj = {
title: 'UOL - O melhor conteúdo',
url: 'https://www.uol',
keywords: ['Notícias', 'Entretenimento']
};
// converta para ES6
function rem(obj) {
delete obj.keywords;
return obj;
}
var obj2 = rem(obj);
return obj.hasOwnProperty('keywords') && !obj2.hasOwnProperty('keywords');
};
describe("Solution", function(){
it("should test for something", function(){
Test.assertEquals(main(), true, "Victory");
});
});
Não há limite para a quantidade de parâmetros que você pode enviar para uma função JS. A assinatura é um meio mais fácil de acessar alguns desses parâmetros. Em alguns casos pode ser muito útil definir assumir um valor padrão quando o parâmetro é opcional. Uma forma de verificar se o parâmetro foi ou não definido é validar com undefined. Só que com ES6 existe uma forma mais simples e elegante de tornar parâmetros opcionais.
Exercício:
Reescreva o código em ES6.
// reescreva em ES6
function main(a, b, c) {
if (typeof b == 'undefined')
b = 2;
if (typeof c == 'undefined')
c = 3
return a * b * c;
}
describe("Solution", function(){
it("validating", function(){
Test.assertEquals(main(1), 6, "b e c opcionais");
Test.assertEquals(main(2, 3), 18, "c opcional");
Test.assertEquals(main(2, 2, 2), 8, "todos parâmetros");
});
});