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.
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");
});
});
Além de trazer novidades na escrita da linguagem, ES6 também trouxe novas classes.
Exercício:
Remover os itens duplicados do array sem percorrer o array
const main = () => {
let links = [
'https://www.uol',
'https://www.bol.com.br',
'https://www.uol',
'https://noticias.uol.com.br',
'https://www.bol.com.br',
];
// converter para ES6
var uniqueLinks = links.reduce(function (carry, item) {
if (carry.indexOf(item) === -1) {
carry.push(item);
}
return carry;
}, []);
return uniqueLinks.length;
};
Async / await vieram para facilitar a execução de código assíncrono, muitas vezes encapsulado em Promises e dar maior controle sobre o fluxo de execução, dando a possibilidade de transformar trechos assíncronos em síncronos evitando callbacks excessivos (callback from hell).
Exercício:
Converta a execução da Promise para async/await.
function monteCarlo() {
return new Promise(function (resolve, reject) {
resolve([{
titulo: 'UOL - O Melhor conteúdo'
}]);
});
}
async function main() {
// converter para ES6
monteCarlo().then(function(response) {
console.log(response)
});
return true;
}
describe("Solution", function(){
it("should test for something", async function(){
Test.assertEquals(await main(), true, "This is just an example of how you can write your own TDD tests");
});
});
"Você precisa disso para agora?"
Ou então apenas repasse.
Generator é uma instrução que fica na espera, somente é executada quando necessário.
Exercício:
Percorrer o generator na função main e para cada item imprimir no console seu valor.
function* lazyRange(start, stop) {
while (start <= stop) {
console.log(`Interando ${start}`);
yield start;
++start;
}
}
function createRange() {
console.log("Criando um range");
return lazyRange(1, 10);
}
function getData() {
let theRange = createRange();
console.log("Repassando o range");
return {theRange};
}
function main() {
let resp = getData();
// percorra o generator executando o trecho comentado abaixo
// console.log(`Valor ${item}`);
return 1;
}
describe("Solution", function(){
it("should test for something", function(){
Test.assertEquals(main(), 1, "This is just an example of how you can write your own TDD tests");
});
});
LazyRange cria um range de um número até outro com generators. O benefício do generator é que o range só será criado quando necessário.
E se pudermos alinhar generators de forma que várias instruções sejam executadas porém somente quando necessário, evitando percorrer o mesmo array diversas vezes?
Estamos falando de pura performance.
Exercício:
Implementar a função plusOne que some 1 em cada item de doubleRangeValue e retorne os valores sob demanda (generator).
function* lazyRange(start, stop) {
while (start <= stop) {
console.log(`Interando ${start}`);
yield start;
++start;
}
}
function* doubleRangeValue(...args) {
for (let value of lazyRange(...args)) {
value *= 2;
console.log(`Dobro ${value}`);
yield value;
}
}
function* plusOne() {
// implemente
}
async function main() {
let resp = [...plusOne(1, 5)];
return resp.join(',');
}
describe("Solution", function(){
it("should test for something", async function(){
Test.assertEquals(await main(), "3,5,7,9,11", "Victory");
});
});
Quando usar for, forEach, map ou reduce?
Todos percorrem uma lista. Então se o problema exige percorrer uma lista qualquer um deles resolvem.
Mas cada um foi projetado para resolver um tipo de problema e quando aplicado tende a deixar o código mais legível e com menos linhas.
Exercício:
Resposta cada função com "for", "forEach", "map" ou "reduce" no return.
function a() {
"Atualizar o array com o dobro de seus valores"
let a = [1, 2, 3, 4];
a.forEach((item, index) => {
a[index] = item * 2;
});
// responda: for, forEach, map ou reduce
return '';
}
function b() {
"Em uma nova variável atribuir a soma dos valores do array"
let a = [4, 10, 23, 99];
let r = 0;
a.map(item => {
r += item;
});
// responda: for, forEach, map ou reduce
return '';
}
function c() {
"Em um novo array o quadrado dos itens de A"
let a = [4, 8, 16];
let r = a.map(item => Math.pow(item, 2));
// responda: for, forEach, map ou reduce
return '';
}
function d() {
"Encontrar no array um item que seja maior ou igual a 2"
let a = [1, 2, 3, 4];
let resp = null;
a.forEach((item, index) => {
if (item >= 2) {
resp = item;
break;
}
});
// responda: for, forEach, map ou reduce
return '';
}
function e() {
"Um novo array com valores únicos de A"
let a = [1, 2, 2, 3, 4];
let b = [];
for (const item of a) {
if (!b.includes(item))
b.push(b);
}
// responda: for, forEach, map ou reduce
return '';
}
function f() {
"Novo array com itens de índice par"
let a = ['a', 'b', 'c', 'd'];
let b = [];
a.map((item, index) => {
if (index % 2 == 0) {
b.push(item);
}
});
// responda: for, forEach, map ou reduce
return '';
}
function g() {
"Executar chamadas http de forma assíncrona"
let a = ['/p=1', '/p=2', '/p=3'];
for (let path of a) {
let xhr = new function() {};
// ...
}
// responda: for, forEach, map ou reduce
return '';
}
function h() {
"Novo array com apenas titulo e descrição de uma resposta no Monte Carlo"
let results = [{titulo: '..', descricao: '', tags: [], photo: '...'}];
let resp = results.map(({titulo, descricao}) => ({titulo, descricao}));
// responda: for, forEach, map ou reduce
return '';
}
function i() {
"Descompactar a matriz em uma lista"
let a = [[1, 2], [4, 5], [4, 5]];
let resp = a.reduce((carry, row) => ([...carry, ...row]), []);
// responda: for, forEach, map ou reduce
return '';
}
function j() {
"Multiplicar matrizes"
let a = [1, 2, 3];
let b = [4, 5, 6];
let resp = a.reduce((carry, v, i) => carry + v * b[i], 0);
// responda: for, forEach, map ou reduce
return '';
}
function k() {
"Transformar as letras em maiúsculas"
let a = ['Fred', 'John', 'Paul'];
for (const [index, value] of a.entries()) {
a[index] = value.toUpperCase();
}
// responda: for, forEach, map ou reduce
return '';
}
function l() {
"Exibir no console as chaves e os valores"
let config = {portal: 'UOL', channel: 'Notícias', slug: 'uol'};
for (const prop in config) {
console.log(prop, config[prop]);
}
// responda: for, forEach, map ou reduce
return '';
}
function m() {
"Exibir no console os itens do array"
let tags = ['São Paulo', 'Sudeste', 'Brasil'];
for (const k in tags) {
console.log(tags[k]);
}
// responda: for, forEach, map ou reduce
return '';
}
/*
*/
describe("Solution", function(){
it("should test for something", function(){
Test.assertEquals(a(), "forEach", "Um novo array com a mesma quantidade de itens, mas com valor modificados: map");
Test.assertEquals(b(), "reduce", "Reduzir o array a um número cuja representa a soma de todos os itens: reduce");
Test.assertEquals(c(), "map", "Mesma quantidade de itens, valores modificados: map");
Test.assertEquals(d(), "forEach", "Altera o array principal e ainda mais dados sem referência: forEach");
Test.assertEquals(e(), "reduce", "O array é reduzido, removendo duplicados: reduce");
Test.assertEquals(f(), "reduce", "forEach seria a melhor escolha se reduce não tivesse o índice do item: reduce");
Test.assertEquals(g(), "for", "Percorrer os itens do array executando alguma operação: for. Caso tivesse que garantir a ordem das chamadas http seria necessário outra solução.");
Test.assertEquals(h(), "map", "Um novo array com a mesma quantidade de itens, mas com alguns valores modificados: map");
Test.assertEquals(i(), "reduce", "Um novo array modificado: reduce");
Test.assertEquals(j(), "reduce", "Somatória de um cálculo envolvendo matrizes: reduce");
Test.assertEquals(k(), "forEach", "Naturalmente forEach traz o índice do array: forEach");
Test.assertEquals(l(), "for", "For in acessa as chaves do objeto");
Test.assertEquals(m(), "for", "For com resalva de ser for-of");
});
});