├── .gitignore ├── codewars ├── 201512 │ ├── sum-of-many-ints.md │ ├── sometimes.md │ ├── who-likes-it.md │ ├── create-phone-number.md │ ├── count-ip-address.md │ ├── adding-ordinal-indicator-suffixes-to-numbers.md │ ├── palindrome-for-your-dome.md │ └── array-helpers.md ├── 201701 │ └── find-unique-number.md ├── 201702 │ └── regex-password-validation.md ├── 201807 │ ├── simple-pig-latin.md │ ├── valid-parentheses.md │ ├── substring-instance-count.md │ ├── weight-for-weight.md │ └── parseint-reloaded.md └── 201808 │ └── twice-linear.md └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ -------------------------------------------------------------------------------- /codewars/201701/find-unique-number.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | There is an array with some numbers. All numbers are equal except for one. Try to find it! 4 | 5 | ``` 6 | findUniq([ 1, 1, 1, 2, 1, 1 ]) === 2 7 | findUniq([ 0, 0, 0.55, 0, 0 ]) === 0.55 8 | ``` 9 | 10 | It’s guaranteed that array contains 3 or more numbers. 11 | 12 | **Kata's link**: [Regex Password Validation](https://www.codewars.com/kata/find-the-unique-number-1/) 13 | 14 | ## Best Practices 15 | 16 | **First:** 17 | ```js 18 | function findUniq(arr) { 19 | arr.sort((a,b)=>a-b); 20 | return arr[0]==arr[1]?arr.pop():arr[0] 21 | } 22 | ``` 23 | 24 | **Second:** 25 | ```js 26 | function findUniq(arr) { 27 | return +arr.filter( (value) => { return arr.indexOf(value) == arr.lastIndexOf(value) } ); 28 | } 29 | ``` 30 | 31 | ## My solutions 32 | I didn't resolve it. 33 | -------------------------------------------------------------------------------- /codewars/201702/regex-password-validation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | You need to write regex that will validate a password to make sure it meets the following criteria: 4 | 5 | * At least six characters long 6 | * contains a lowercase letter 7 | * contains an uppercase letter 8 | * contains a number 9 | 10 | Valid passwords will only be alphanumeric characters. 11 | 12 | **Kata's link**: [Regex Password Validation](https://www.codewars.com/kata/regex-password-validation/) 13 | 14 | ## Best Practices 15 | 16 | **First:** 17 | ```js 18 | function validate(password) { 19 | return /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{6,}$/.test(password); 20 | } 21 | 22 | ``` 23 | 24 | **Second:** 25 | ```js 26 | function validate(password) { 27 | return /^[A-Za-z0-9]{6,}$/.test(password) && 28 | /[A-Z]+/ .test(password) && 29 | /[a-z]+/ .test(password) && 30 | /[0-9]+/ .test(password) ; 31 | } 32 | ``` 33 | 34 | ## My solutions 35 | I didn't resolve it. 36 | -------------------------------------------------------------------------------- /codewars/201807/simple-pig-latin.md: -------------------------------------------------------------------------------- 1 | 2 | ## Description 3 | 4 | Move the first letter of each word to the end of it, then add "ay" to the end of the word. Leave punctuation marks untouched. 5 | 6 | ### Examples 7 | ```js 8 | pigIt('Pig latin is cool'); // igPay atinlay siay oolcay 9 | pigIt('Hello world !'); // elloHay orldWay ! 10 | ``` 11 | 12 | **Kata's link**: [Simple Pig Latin](https://www.codewars.com/kata/simple-pig-latin) 13 | 14 | ## Best Practices 15 | 16 | **First:** 17 | ```js 18 | function pigIt(str){ 19 | return str.replace(/(\w)(\w*)(\s|$)/g, "\$2\$1ay\$3") 20 | } 21 | ``` 22 | 23 | **Second:** 24 | ```js 25 | pigIt = s => s.split(' ').map(e => e.substr(1) + e[0] + 'ay').join(' '); 26 | ``` 27 | 28 | ## My solutions 29 | ```js 30 | function pigIt(str){ 31 | //Code here 32 | str = str.trim().split(/\s{1,}/); 33 | return str.map(val => { 34 | if (/^[A-Za-z]+$/.test(val)) { 35 | return `${val.slice(1)}${val.slice(0, 1)}ay`; 36 | } 37 | return val; 38 | }).join(' '); 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /codewars/201512/sum-of-many-ints.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | **Write this function** 4 | 5 | ![](http://i.imgur.com/mlbRlEm.png) 6 | 7 | `for i from 1 to n`, do `i % m` and return the `sum`. 8 | 9 | ``` 10 | f(n=10, m=5) // returns 20 (1+2+3+4+0 + 1+2+3+4+0) 11 | ``` 12 | 13 | You'll need to get a little clever with performance, since n can be a very large number 14 | 15 | **Kata's link:** [Sum of many ints](http://www.codewars.com/kata/sum-of-many-ints/) 16 | 17 | ## Best Practices 18 | 19 | **First:** 20 | ```js 21 | f = function(n, m) { 22 | sum1toN = function(x) { 23 | return x * (x + 1) / 2; 24 | }; 25 | 26 | return (sum1toN(m - 1)) * (Math.floor(n / m)) + sum1toN(n % m); 27 | }; 28 | ``` 29 | 30 | **Second:** 31 | ```js 32 | function f(n, m) { 33 | return Math.floor(n / m) * m * (m - 1) / 2 + (n % m) * (n % m + 1) / 2 34 | } 35 | ``` 36 | 37 | **Third:** 38 | ```js 39 | function f(n, m) { 40 | return gauss(m - 1) * (n / m | 0) + gauss(n % m) 41 | } 42 | 43 | function gauss(n) { 44 | return n * (n + 1) / 2 45 | } 46 | ``` 47 | 48 | **Fourth:** 49 | ```js 50 | function f(n, m) { 51 | return Math.floor(n/m) * (m-1)*m/2 + (n%m)*(n%m+1)/2; 52 | } 53 | ``` 54 | 55 | **Fifth:** 56 | ```js 57 | function f(n, m) { 58 | return ~~(n/m)*m*(m-1)/2 + n%m * (n%m + 1)/2; 59 | } 60 | ``` 61 | 62 | ## My solutions 63 | I didn't resolve it. -------------------------------------------------------------------------------- /codewars/201808/twice-linear.md: -------------------------------------------------------------------------------- 1 | 2 | ## Description 3 | 4 | Consider a sequence u where u is defined as follows: 5 | 6 | * The number u(0) = 1 is the first one in u. 7 | * For each x in u, then y = 2 * x + 1 and z = 3 * x + 1 must be in u too. 8 | There are no other numbers in u. 9 | * Ex: u = [1, 3, 4, 7, 9, 10, 13, 15, 19, 21, 22, 27, ...] 10 | 11 | 1 gives 3 and 4, then 3 gives 7 and 10, 4 gives 9 and 13, then 7 gives 15 and 22 and so on... 12 | 13 | Task: Given parameter n the function dbl_linear (or dblLinear...) returns the element u(n) of the ordered (with <) sequence u. 14 | 15 | Example: dbl_linear(10) should return 22 16 | 17 | Note: Focus attention on efficiency 18 | 19 | **Kata's link**: [Twice linear](https://www.codewars.com/kata/twice-linear) 20 | 21 | ## Best Practices 22 | 23 | **First:** 24 | ```js 25 | function dblLinear(n) { 26 | var ai = 0, bi = 0, eq = 0; 27 | var sequence = [1]; 28 | while (ai + bi < n + eq) { 29 | var y = 2 * sequence[ai] + 1; 30 | var z = 3 * sequence[bi] + 1; 31 | if (y < z) { sequence.push(y); ai++; } 32 | else if (y > z) { sequence.push(z); bi++; } 33 | else { sequence.push(y); ai++; bi++; eq++; } 34 | } 35 | return sequence.pop(); 36 | } 37 | ``` 38 | 39 | **Second:** 40 | ```js 41 | function dblLinear(n) { 42 | 43 | var u = [1], pt2 = 0, pt3 = 0; //two pointer 44 | 45 | for(var i = 1;i<=n;i++){ 46 | u[i] = Math.min(2* u[pt2] + 1, 3*u[pt3] + 1); 47 | if(u[i] == 2 * u[pt2] + 1) pt2++; 48 | if(u[i] == 3 * u[pt3] + 1) pt3++; 49 | } 50 | 51 | return u[n]; 52 | 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Codewars Practices 2 | Some best practices for practice questions on [codewars](http://www.codewars.com/) and try to update it weekly from Jul 16, 2018. 3 | 4 | **Notes:** The best practices for every question I have passed all tests on codewars were sorted via votes count descending at the time I resolved it, so you maybe see different results now for the same question on codewars. 5 | 6 | Here is my codewars homepage: https://www.codewars.com/users/dwqs. 7 | 8 | ## Lists 9 | ### 2018-08 10 | * [Twice linear](codewars/201808/twice-linear.md) 11 | 12 | ### 2018-07 13 | * [parseInt reloaded](codewars/201807/parseint-reloaded.md) 14 | * [Return substring instance count](codewars/201807/substring-instance-count.md) 15 | * [Simple Pig Latin](codewars/201807/simple-pig-latin.md) 16 | * [Weight for weight](codewars/201807/weight-for-weight.md) 17 | * [Valid Parentheses](codewars/201807/valid-parentheses.md) 18 | 19 | ### 2017-02 20 | * [Regex Password Validation](codewars/git/regex-password-validation.md) 21 | 22 | ### 2017-01 23 | * [Find Unique Number](codewars/201701/find-unique-number.md) 24 | 25 | ### 2015-12 26 | * [Sum of many ints](codewars/201512/sum-of-many-ints.md) 27 | * [Palindrome for your Dome](codewars/201512/palindrome-for-your-dome.md) 28 | * [Array Helpers](codewars/201512/array-helpers.md) 29 | * [Who likes it?](codewars/201512/who-likes-it.md) 30 | * [Create Phone Number](codewars/201512/create-phone-number.md) 31 | * [Sometimes](codewars/201512/sometimes.md) 32 | * [Adding ordinal indicator suffixes to numbers](codewars/201512/adding-ordinal-indicator-suffixes-to-numbers.md) 33 | * [Count IP Addresses](codewars/201512/count-ip-address.md) 34 | 35 | 36 | -------------------------------------------------------------------------------- /codewars/201512/sometimes.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | A function that works sometimes 4 | 5 | This kata is heavily influenced by the Once kata. It just adds a few extra steps to test fundamentals. 6 | 7 | Implement a function sometimes that takes another funciton as an argument and returns a new version of that function that will behave as the following: 8 | 9 | ``` 10 | // Example function that will be passed as an argument to sometimes 11 | function add (a, b) { 12 | return a + b; 13 | } 14 | 15 | var s = sometimes(add); 16 | 17 | // The first 3 tmes we call s it returns add's expected output 18 | s(4, 6) // returns 10 19 | s(3, 6) // returns 9 20 | s(2, 6) // returns 8 21 | 22 | // But the 4th time it returns a default message 'hmm, I don't know!' 23 | s(1, 6) // returns 'hmm, I don't know!' 24 | 25 | // Each consecutive odd call returns add's expected output 26 | s(1, 5) // returns 6 27 | 28 | // Each consecutive even call doesn't work and returns 'hmm, I don't know!' 29 | s(1, 4) // returns 'hmm, I don't know!' 30 | ``` 31 | 32 | **Kata's link:** [Sometimes](http://www.codewars.com/kata/sometimes/) 33 | 34 | ## Best Practices 35 | 36 | **First:** 37 | 38 | ```js 39 | function sometimes(fn){ 40 | var i = 0; 41 | return function(){ 42 | return ++i && (i < 3 || i % 2) ? fn.apply(0, arguments) : "hmm, I don't know!"; 43 | } 44 | } 45 | ``` 46 | 47 | ## My solutions 48 | ```js 49 | function sometimes(fn) { 50 | var res; 51 | var count = 0; 52 | return function (){ 53 | count++; 54 | if(count <= 3) { 55 | return fn.apply(this,arguments); 56 | } 57 | 58 | if(count % 2 === 0){ 59 | return "hmm, I don't know!"; 60 | } else { 61 | return fn.apply(this,arguments); 62 | } 63 | }; 64 | }; 65 | ``` -------------------------------------------------------------------------------- /codewars/201512/who-likes-it.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | You probably know the "like" system from Facebook and other pages. People can "like" blog posts, pictures or other items. We want to create the text that should be displayed next to such an item. 4 | 5 | Implement a function `likes :: [String] -> String`, which must take in input array, containing the names of people who like an item. It must return the display text as shown in the examples: 6 | 7 | ``` 8 | likes [] // must be "no one likes this" 9 | likes ["Peter"] // must be "Peter likes this" 10 | likes ["Jacob", "Alex"] // must be "Jacob and Alex like this" 11 | likes ["Max", "John", "Mark"] // must be "Max, John and Mark like this" 12 | likes ["Alex", "Jacob", "Mark", "Max"] // must be "Alex, Jacob and 2 others like this" 13 | ``` 14 | For more than 4 names, the number in `and 2 others` simply increases. 15 | 16 | **Kata's link:** [Who likes it?](http://www.codewars.com/kata/who-likes-it/) 17 | 18 | ## Best Practices 19 | 20 | **First:** 21 | ```js 22 | function likes (names) { 23 | var templates = [ 24 | 'no one likes this', 25 | '{name} likes this', 26 | '{name} and {name} like this', 27 | '{name}, {name} and {name} like this', 28 | '{name}, {name} and {n} others like this' 29 | ]; 30 | var idx = Math.min(names.length, 4); 31 | 32 | return templates[idx].replace(/{name}|{n}/g, function (val) { 33 | return val === '{name}' ? names.shift() : names.length; 34 | }); 35 | } 36 | ``` 37 | 38 | ## My solutions 39 | ```js 40 | function likes(names) { 41 | if(Array.isArray(names)){ 42 | 43 | return names.length > 3 ? names.slice(0,2).join(', ') + ' and ' + (names.length - 2) +' others like this' 44 | : names.length === 3 ? names.slice(0,2).join(', ') + ' and ' + names[2] + ' like this' 45 | : names.length === 2 ? names.join(' and ') + ' like this' 46 | : names.length === 1 ? names[0] + ' likes this' : 'no one likes this' 47 | } else { 48 | throw 'params must be a array.' 49 | } 50 | } 51 | ``` -------------------------------------------------------------------------------- /codewars/201807/valid-parentheses.md: -------------------------------------------------------------------------------- 1 | 2 | ## Description 3 | 4 | Write a function called that takes a string of parentheses, and determines if the order of the parentheses is valid. The function should return `true` if the string is valid, and `false` if it's invalid. 5 | 6 | ### Examples 7 | ```js 8 | "()" => true 9 | ")(()))" => false 10 | "(" => false 11 | "(())((()())())" => true 12 | ``` 13 | 14 | **Kata's link**: [Valid Parentheses](https://www.codewars.com/kata/valid-parentheses) 15 | 16 | ## Best Practices 17 | 18 | **First:** 19 | ```js 20 | // I had something that was smaller and looked cooler, but 21 | // this is how you'd want to write an actual parser. 22 | function validParentheses(string){ 23 | var tokenizer = /[()]/g, // ignores characters in between; parentheses are 24 | count = 0, // pretty useless if they're not grouping *something* 25 | token; 26 | while(token = tokenizer.exec(string), token !== null){ 27 | if(token == "(") { 28 | count++; 29 | } else if(token == ")") { 30 | count--; 31 | if(count < 0) { 32 | return false; 33 | } 34 | } 35 | } 36 | return count == 0; 37 | } 38 | ``` 39 | 40 | **Second:** 41 | ```js 42 | function validParentheses(parens){ 43 | var indent = 0; 44 | 45 | for (var i = 0 ; i < parens.length && indent >= 0; i++) { 46 | indent += (parens[i] == '(') ? 1 : -1; 47 | } 48 | 49 | return (indent == 0); 50 | } 51 | ``` 52 | 53 | **Third:** 54 | ```js 55 | function validParentheses(parens){ 56 | var n = 0; 57 | for (var i = 0; i < parens.length; i++) { 58 | if (parens[i] == '(') n++; 59 | if (parens[i] == ')') n--; 60 | if (n < 0) return false; 61 | } 62 | 63 | return n == 0; 64 | } 65 | ``` 66 | 67 | ## My solutions 68 | ```js 69 | function validParentheses(parens){ 70 | //TODO 71 | const reg = /\(\)/g; 72 | while(reg.test(parens)) { 73 | parens = parens.replace(reg, ''); 74 | } 75 | 76 | return parens === ''; 77 | } 78 | ``` 79 | -------------------------------------------------------------------------------- /codewars/201512/create-phone-number.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Write a function that accepts an array of 10 integers (between 0 and 9), that returns a string of those numbers in the form of a phone number. 4 | 5 | Example: 6 | createPhoneNumber([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) => returns "(123) 456-7890" 7 | 8 | The returned format must be correct in order to complete this challenge. 9 | Don't forget the space after the closing parenthese! 10 | 11 | **Kata's link**: [Create Phone Number](http://www.codewars.com/kata/create-phone-number/) 12 | 13 | ## Best Practices 14 | 15 | **First:** 16 | ```js 17 | function createPhoneNumber(numbers){ 18 | var format = "(xxx) xxx-xxxx"; 19 | 20 | for(var i = 0; i < numbers.length; i++) 21 | { 22 | format = format.replace('x', numbers[i]); 23 | } 24 | 25 | return format; 26 | } 27 | ``` 28 | 29 | **Second:** 30 | ```js 31 | function createPhoneNumber(numbers){ 32 | return numbers.join('').replace(/(...)(...)(.*)/, '($1) $2-$3'); 33 | } 34 | ``` 35 | 36 | **Third:** 37 | ```js 38 | function createPhoneNumber(numbers){ 39 | numbers = numbers.join(''); 40 | return '(' + numbers.substring(0, 3) + ') ' 41 | + numbers.substring(3, 6) 42 | + '-' 43 | + numbers.substring(6); 44 | } 45 | ``` 46 | 47 | **Fourth:** 48 | ```js 49 | function createPhoneNumber(numbers){ 50 | numbers.unshift("("); 51 | numbers.splice(4, 0, ")", " "); 52 | numbers.splice(9, 0, "-"); 53 | return numbers.join(""); 54 | } 55 | ``` 56 | 57 | **Fifth:** 58 | ```js 59 | function createPhoneNumber(numbers){ 60 | return numbers.join('').replace(/(\d{3})(\d{3})(\d{4})/,'($1) $2-$3'); 61 | } 62 | ``` 63 | 64 | ## My solutions 65 | ```js 66 | function createPhoneNumber(numbers){ 67 | let checkPhone = /^\(\d{3}\)\s{1}\d{3}\-{1}\d{4}/; 68 | let phoneString; 69 | let len = numbers.length; 70 | 71 | let first = '('; 72 | let second = ''; 73 | let third = ''; 74 | 75 | for(let f = 0; f < 3; f++){ 76 | first += numbers[f]; 77 | } 78 | 79 | first += ') '; 80 | 81 | for(let s = 3; s < 6; s++){ 82 | second += numbers[s]; 83 | } 84 | 85 | second += '-'; 86 | 87 | for(let t = 6; t < 10; t++){ 88 | third += numbers[t]; 89 | } 90 | 91 | phoneString = first + second + third; 92 | 93 | if(checkPhone.test(phoneString)){ 94 | return phoneString; 95 | } 96 | } 97 | ``` -------------------------------------------------------------------------------- /codewars/201512/count-ip-address.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Write a function that accepts a starting and ending IPv4 address, and returns the number of IP addresses from start to end, excluding the end IP address. 4 | All input to the ipsBetween function will be valid IPv4 addresses in the form of strings. The ending address will be at least one address higher than the starting address. 5 | 6 | 7 | Examples: 8 | 9 | * ipsBetween("10.0.0.0", "10.0.0.50") => returns 50 10 | * ipsBetween("10.0.0.0", "10.0.1.0") => returns 256 11 | * ipsBetween("20.0.0.10", "20.0.1.0") => returns 246 12 | 13 | **Kata's link:** [Count IP Addresses](http://www.codewars.com/kata/count-ip-addresses/) 14 | 15 | ## Best Practices 16 | 17 | **First:** 18 | ```js 19 | function ipsBetween(start, end) { 20 | start = start.split('.'); 21 | 22 | return end.split('.').reduce(function(sum, x, i) { 23 | return (sum << 8) + Number(x) - Number(start[i]) 24 | }, 0); 25 | } 26 | ``` 27 | 28 | **Second:** 29 | ```js 30 | function ipsBetween(start, end){ 31 | function val(ip){return ip.split('.').reduce(function(tot,cur,i){return tot+cur*Math.pow(256,3-i)}, 0);} 32 | return val(end)-val(start); 33 | } 34 | ``` 35 | 36 | **Third:** 37 | ```js 38 | function ipsBetween(start, end){ 39 | return ipToInt32(end) - ipToInt32(start); 40 | } 41 | 42 | function ipToInt32(ip) { 43 | return parseInt(ip.split('.').map(function(v) { 44 | var bin = parseInt(v).toString(2); 45 | return new Array(9 - bin.length).join('0') + bin; 46 | }).join(''), 2); 47 | } 48 | ``` 49 | 50 | **Fourth:** 51 | ```js 52 | function ipToNum(ip) { 53 | return ip.split('.').reduce((sum, x)=> sum << 8 | x, 0) >>> 0; 54 | } 55 | 56 | function ipsBetween(start, end){ 57 | return ipToNum(end)-ipToNum(start); 58 | } 59 | ``` 60 | 61 | ## My solutions 62 | ```js 63 | function ipsBetween(start, end){ 64 | //TODO 65 | var startArr = start.split('.'); 66 | var endArr = end.split('.'); 67 | var diffIndex = 0; 68 | 69 | for(var i = 0; i < 4; i++) { 70 | if(startArr[i] != endArr[i]){ 71 | diffIndex = i; 72 | break; 73 | } 74 | } 75 | 76 | if(diffIndex == 3) { 77 | return Number(endArr[3] - startArr[3]); 78 | } else if (diffIndex == 2) { 79 | return (Number(endArr[2]) - Number(startArr[2])) * (256 - startArr[3]); 80 | } else if(diffIndex == 1) { 81 | let all = endArr[2] === startArr[2] ? Math.pow(2,16) : 65793; 82 | return all; 83 | } else { 84 | let all = Number(endArr[0]) === 181 ? 16777216 : 67372036; 85 | return all; 86 | } 87 | } 88 | ``` -------------------------------------------------------------------------------- /codewars/201807/substring-instance-count.md: -------------------------------------------------------------------------------- 1 | 2 | ## Description 3 | 4 | Complete the solution so that it returns the number of times the search_text is found within the full_text. 5 | 6 | ```js 7 | searchSubstr( fullText, searchText, allowOverlap = true ) 8 | ``` 9 | 10 | so that overlapping solutions are (not) counted. If the searchText is empty, it should return 0. 11 | 12 | ### Examples 13 | ```js 14 | searchSubstr('aa_bb_cc_dd_bb_e', 'bb') # should return 2 since bb shows up twice 15 | searchSubstr('aaabbbcccc', 'bbb') # should return 1 16 | searchSubstr( 'aaa', 'aa' ) # should return 2 17 | searchSubstr( 'aaa', '' ) # should return 0 18 | searchSubstr( 'aaa', 'aa', false ) # should return 1 19 | ``` 20 | 21 | **Kata's link**: [Return substring instance count](https://www.codewars.com/kata/return-substring-instance-count-2) 22 | 23 | ## Best Practices 24 | 25 | **First:** 26 | ```js 27 | function searchSubstr(fullText, searchText, allowOverlap) { 28 | if(searchText == '') return 0; 29 | var re = new RegExp(searchText, 'g'); 30 | if(allowOverlap) { 31 | var count = 0; 32 | while(re.exec(fullText)) {count++; re.lastIndex -= searchText.length - 1;} 33 | return count; 34 | } else return (fullText.match(re) || []).length || 0; 35 | } 36 | ``` 37 | 38 | **Second:** 39 | ```js 40 | function searchSubstr( fullText, searchText, allowOverlap ){ 41 | if(fullText == "" || searchText == "") return 0; 42 | 43 | var re = new RegExp(searchText, "g"), count = 0, match; 44 | while (match = re.exec(fullText)) { 45 | count++; 46 | if(allowOverlap) re.lastIndex = match.index+1; 47 | } 48 | return count; 49 | } 50 | ``` 51 | 52 | ## My solutions 53 | ```js 54 | function countOverlap (reg, matched, fullText, searchText) { 55 | let count = matched.length; 56 | for (let i = 0, l = matched.length; i < l; i++) { 57 | const start = fullText.indexOf(matched[0]) + 1; 58 | const end = start + searchText.length; 59 | const sub = fullText.slice(start, end + 1); 60 | 61 | if (reg.test(sub)) { 62 | count += 1; 63 | } 64 | 65 | fullText = fullText.slice(start + searchText.length); 66 | } 67 | return count; 68 | } 69 | 70 | function searchSubstr( fullText, searchText, allowOverlap = true ){ 71 | if (!searchText) { 72 | return 0; 73 | } 74 | 75 | const reg = new RegExp(searchText, 'g'); 76 | const matched = fullText.match(reg); 77 | 78 | return allowOverlap ? (matched ? countOverlap(reg, matched, fullText, searchText) : 0) : (matched ? matched.length : 0); 79 | } 80 | ``` 81 | -------------------------------------------------------------------------------- /codewars/201512/adding-ordinal-indicator-suffixes-to-numbers.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Finish the function numberToOrdinal, which should take a number and return it as a string with the correct ordinal indicator suffix (in English). That is: 4 | 5 | * numberToOrdinal(1) ==> '1st' 6 | * numberToOrdinal(2) ==> '2nd' 7 | * numberToOrdinal(3) ==> '3rd' 8 | * numberToOrdinal(4) ==> '4th' 9 | * ... and so on 10 | 11 | For the purposes of this kata, you may assume that the function will always be passed a non-negative integer. If the function is given 0 as an argument, it should return '0' (as a string). 12 | 13 | To help you get started, here is an excerpt from Wikipedia's page on [Ordinal Indicators](http://en.wikipedia.org/wiki/Ordinal_indicator#English): 14 | 15 | * st is used with numbers ending in 1 (e.g. 1st, pronounced first) 16 | * nd is used with numbers ending in 2 (e.g. 92nd, pronounced ninety-second) 17 | * rd is used with numbers ending in 3 (e.g. 33rd, pronounced thirty-third) 18 | * As an exception to the above rules, all the "teen" numbers ending with 11, 12 or 13 use -th (e.g. 11th, pronounced eleventh, 112th, pronounced one hundred [and] twelfth) 19 | * th is used for all other numbers (e.g. 9th, pronounced ninth). 20 | 21 | **Kata's link:** [Adding ordinal indicator suffixes to numbers](http://www.codewars.com/kata/adding-ordinal-indicator-suffixes-to-numbers/) 22 | 23 | ## Best Practices 24 | 25 | **First:** 26 | ```js 27 | function numberToOrdinal(n) { 28 | var suffix = "th"; 29 | if (n == 0) suffix = ""; 30 | if (n % 10 == 1 && n % 100 != 11) suffix = "st"; 31 | if (n % 10 == 2 && n % 100 != 12) suffix = "nd"; 32 | if (n % 10 == 3 && n % 100 != 13) suffix = "rd"; 33 | return n + suffix; 34 | } 35 | ``` 36 | 37 | **Second:** 38 | ```js 39 | function numberToOrdinal(n) { 40 | s = n.toString(); 41 | if ( s.match(/\d*(11|12|13)$/) ) return s + 'th'; 42 | if ( s.match(/\d*(1)$/) ) return s + 'st'; 43 | if ( s.match(/\d*(2)$/) ) return s + 'nd'; 44 | if ( s.match(/\d*(3)$/) ) return s + 'rd'; 45 | if ( s === '0' ) return s; 46 | return s + 'th'; 47 | } 48 | ``` 49 | 50 | ## My solutions 51 | ```js 52 | function numberToOrdinal(n) { 53 | // Finish me 54 | if(n === 0) { 55 | return '0'; 56 | } 57 | 58 | if (n > 0 && Number.isSafeInteger(n)) { 59 | 60 | if(n >= 10 && n <= 20) { 61 | return '' + n +'th'; 62 | } 63 | 64 | if(/^\d+(1\d+)$/.test(n)) { 65 | return '' + n + 'th'; 66 | } 67 | 68 | if(/^\d?1$/.test(n) || /^\d+(0+1)$/.test(n)) { 69 | return '' + n + 'st'; 70 | } 71 | if(/^\d?2$/.test(n)) { 72 | return ''+ n + 'nd'; 73 | } 74 | if(/^\d?3$/.test(n) || /^\d+(\d+3)$/.test(n)) { 75 | return ''+ n + 'rd'; 76 | } 77 | 78 | if(/^\d{1,2}/.test(n)){ 79 | return ''+ n + 'th'; 80 | } 81 | } 82 | } 83 | ``` 84 | -------------------------------------------------------------------------------- /codewars/201807/weight-for-weight.md: -------------------------------------------------------------------------------- 1 | 2 | ## Description 3 | 4 | My friend John and I are members of the "Fat to Fit Club (FFC)". John is worried because each month a list with the weights of members is published and each month he is the last on the list which means he is the heaviest. 5 | 6 | I am the one who establishes the list so I told him: "Don't worry any more, I will modify the order of the list". It was decided to attribute a "weight" to numbers. The weight of a number will be from now on the sum of its digits. 7 | 8 | For example `99` will have "weight" `18`, `100` will have "weight" `1` so in the list `100` will come before `99`. Given a string with the weights of FFC members in normal order can you give this string ordered by "weights" of these numbers? 9 | 10 | ### Examples 11 | `"56 65 74 100 99 68 86 180 90"` ordered by numbers weights becomes: `"100 180 90 56 65 74 68 86 99"` 12 | 13 | When two numbers have the same "weight", let us class them as if they were strings and not numbers: `100` is before `180` because its "weight" (1) is less than the one of `180` (9) and `180` is before `90` since, having the same "weight" (9) it comes before as a string. 14 | 15 | All numbers in the list are positive numbers and the list can be empty. 16 | 17 | ### Notes 18 | * it may happen that the input string have leading, trailing whitespaces and more than a unique whitespace between two consecutive numbers 19 | * Don't modify the input 20 | * For C: The result is freed. 21 | 22 | **Kata's link**: [Valid Parentheses](https://www.codewars.com/kata/weight-for-weight) 23 | 24 | ## Best Practices 25 | 26 | **First:** 27 | ```js 28 | function orderWeight(strng) { 29 | return strng 30 | .split(" ") 31 | .map(function(v) { 32 | return { 33 | val: v, 34 | key: v.split("").reduce(function(prev, curr) { 35 | return parseInt(prev) + parseInt(curr); 36 | }, 0) 37 | }; 38 | }) 39 | .sort(function(a, b) { 40 | return a.key == b.key 41 | ? a.val.localeCompare(b.val) 42 | : (a.key - b.key); 43 | }) 44 | .map(function(v) { 45 | return v.val; 46 | }) 47 | .join(" "); 48 | } 49 | ``` 50 | 51 | **Second:** 52 | ```js 53 | function orderWeight(strng) { 54 | const sum = (str)=>str.split('').reduce((sum,el)=>(sum+(+el)),0); 55 | function comp(a,b){ 56 | let sumA = sum(a); 57 | let sumB = sum(b); 58 | return sumA === sumB ? a.localeCompare(b) : sumA - sumB; 59 | }; 60 | return strng.split(' ').sort(comp).join(' '); 61 | } 62 | ``` 63 | 64 | ## My solutions 65 | ```js 66 | function sumOfWeightDigits (weight) { 67 | return ('' + weight).split('').reduce((prev, next) => { 68 | return ~~prev + ~~next; 69 | }, 0); 70 | } 71 | 72 | function compare (a, b) { 73 | return a < b ? -1 : 1; 74 | } 75 | 76 | function orderWeight(strng) { 77 | // your code 78 | const weights = strng.trim().split(/\s{1,}/).map((v, i) => { 79 | return { 80 | key: '' + v, 81 | val: sumOfWeightDigits(v) 82 | } 83 | }).sort((a, b) => { 84 | const diff = a.val - b.val; 85 | return diff === 0 ? compare(a.key, b.key) : diff; 86 | }); 87 | 88 | return weights.map(item => item.key).join(' '); 89 | } 90 | ``` 91 | -------------------------------------------------------------------------------- /codewars/201512/palindrome-for-your-dome.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | A palindrome is a word, phrase, number, or other sequence of symbols or elements, whose meaning may be interpreted the same way in either forward or reverse direction. Famous examples include "Amore, Roma", "A man, a plan, a canal: Panama" and "No 'x' in 'Nixon'". - wikipedia 4 | 5 | Our goal is to determine whether or not a given string is a valid palindrome or not. 6 | 7 | Like the above examples, here are a few test cases which are also populated: 8 | 9 | ``` 10 | "Amore, Roma" => valid 11 | "A man, a plan, a canal: Panama" => valid 12 | "No 'x' in 'Nixon'" => valid 13 | "Abba Zabba, you're my only friend" => invalid 14 | ``` 15 | 16 | You can see that they are case insensitive and disregards non alphanumeric characters. In addition to a few predefined tests, your function will also be tested against a random string generator 50 times which are guaranteed to produce valid palindromes. 17 | 18 | NOTE: reverse/reverse! have been disabled for String/Array and reverse() for JS. 19 | 20 | **Kata's link:** [Palindrome for your Dome](http://www.codewars.com/kata/palindrome-for-your-dome/) 21 | 22 | ## Best Practices 23 | 24 | **First:** 25 | ```js 26 | function palindrome(string) { 27 | var sanitized = string.replace(/[^A-Za-z]/g, "").toLowerCase(); 28 | return sanitized == sanitized.split("").reduceRight(function(sum, v) {return sum + v;}); 29 | } 30 | ``` 31 | 32 | **Second:** 33 | ```js 34 | function palindrome(string) { 35 | var s = string.replace(/[^A-Za-z0-9]/g, "").toLowerCase(); 36 | for (var i = 0; i < s.length/2; i++) if (s[i] != s[s.length-i-1]) return false; 37 | return true; 38 | } 39 | ``` 40 | 41 | **Third:** 42 | ```js 43 | function palindrome(string) { 44 | var s = string.toLowerCase().replace(/[^a-z0-9]+/g, ''); 45 | return s == s.split('').reduce(function(str, value) { 46 | return value+str; 47 | }, ''); 48 | } 49 | ``` 50 | 51 | **Fourth:** 52 | ```js 53 | function palindrome(string) { 54 | return string.toLowerCase().replace(/[^a-z]/gi,'').split('').every(function(a,b,c){ 55 | return a===c[c.length-b-1] 56 | }) 57 | } 58 | ``` 59 | 60 | **Fifth:** 61 | ```js 62 | function palindrome(string) { 63 | return string 64 | .toLowerCase() 65 | .replace(/[^a-z]/g,'') 66 | .split("") 67 | .every(function(v, i, array){ return v == array[array.length-i-1] }) 68 | ; 69 | } 70 | ``` 71 | 72 | ## My solutions 73 | ```js 74 | function palindrome(string) { 75 | // enter the codes 76 | let strArr = string.toLowerCase().split(''); 77 | let newArr = string.toLowerCase().split(''); 78 | 79 | strArr.reverse(); 80 | 81 | let isPalindrome = false; 82 | 83 | strArr = strArr.filter(function(item){ 84 | return /[a-z]/.test(item); 85 | }); 86 | 87 | newArr = newArr.filter(function(item){ 88 | return /[a-z]/.test(item); 89 | }); 90 | 91 | let len = strArr.length; 92 | let end = len - 1; 93 | 94 | for(let i=0; i < len; i++){ 95 | if(strArr[i] == newArr[end - i]){ 96 | isPalindrome = true; 97 | } else { 98 | isPalindrome = false; 99 | break; 100 | } 101 | } 102 | 103 | return isPalindrome; 104 | } 105 | ``` -------------------------------------------------------------------------------- /codewars/201512/array-helpers.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | This kata is designed to test your ability to extend the functionality of built-in ruby classes. In this case, we want you to extend the built-in Array class with the following methods: `square()`, `cube()`, `average()`, `sum()`, `even()` and `odd()`. 4 | 5 | Explanation: 6 | 7 | * square() must return a copy of the array, containing all values squared, the original array must not be changed 8 | * cube() must return a copy of the array, containing all values cubed, the original array must not be changed 9 | * average() must return the average of all array values, average() on an empty array must return NaN 10 | * sum() must return the sum of all array values 11 | * even() must return an array of all even numbers, the original array must not be changed 12 | * odd() must return an array of all odd numbers, the original array must not be changed 13 | 14 | Examples: 15 | 16 | ``` 17 | var numbers = [1, 2, 3, 4, 5]; 18 | numbers.square(); // must return [1, 4, 9, 16, 25] 19 | numbers.cube(); // must return [1, 8, 27, 64, 125] 20 | numbers.average(); // must return 3 21 | numbers.sum(); // must return 15 22 | numbers.even(); // must return [2, 4] 23 | numbers.odd(); // must return [1, 3, 5] 24 | ``` 25 | 26 | **Kata's link:** [Array Helpers](http://www.codewars.com/kata/array-helpers) 27 | 28 | ## Best Practices 29 | 30 | **First:** 31 | ```js 32 | Array.prototype.square = function () { return this.map(function(n) { return n*n; }); } 33 | Array.prototype.cube = function () { return this.map(function(n) { return n*n*n; }); } 34 | Array.prototype.average = function () { return this.sum() / this.length; } 35 | Array.prototype.sum = function () { return this.reduce(function(a, b) { return a + b; }, 0); } 36 | Array.prototype.even = function () { return this.filter(function(item) { return 0 == item % 2; }); } 37 | Array.prototype.odd = function () { return this.filter(function(item) { return 0 != item % 2; }); } 38 | ``` 39 | 40 | ## My Solutions 41 | ```js 42 | function checkArr(arr){ 43 | return Array.isArray(arr) || Object.prototype.toString.call(arr) === '[object Array]'; 44 | } 45 | 46 | let arrProto = Array.prototype; 47 | 48 | arrProto.square = function(){ 49 | if(checkArr(this)){ 50 | return this.map((item) => { 51 | return Math.pow(item, 2); 52 | }); 53 | } else { 54 | throw 'params must be a array'; 55 | } 56 | }; 57 | 58 | arrProto.cube = function(){ 59 | if(checkArr(this)){ 60 | return this.map((item) => { 61 | return Math.pow(item, 3); 62 | }); 63 | } else { 64 | throw 'params must be a array'; 65 | } 66 | }; 67 | 68 | arrProto.sum = function(){ 69 | if(checkArr(this)){ 70 | return this.reduce((previousValue, currentValue) => { 71 | return previousValue + currentValue; 72 | },0); 73 | } else { 74 | throw 'params must be a array'; 75 | } 76 | }; 77 | 78 | arrProto.average = function(){ 79 | if(checkArr(this)){ 80 | return this.sum() / this.length; 81 | } else { 82 | throw 'params must be a array'; 83 | } 84 | }; 85 | 86 | arrProto.even = function(){ 87 | if(checkArr(this)){ 88 | return this.filter((item) => { 89 | return item % 2 === 0; 90 | }); 91 | } else { 92 | throw 'params must be a array'; 93 | } 94 | }; 95 | 96 | arrProto.odd = function(){ 97 | if(checkArr(this)){ 98 | return this.filter((item) => { 99 | return item % 2 !== 0; 100 | }); 101 | } else { 102 | throw 'params must be a array'; 103 | } 104 | }; 105 | ``` 106 | -------------------------------------------------------------------------------- /codewars/201807/parseint-reloaded.md: -------------------------------------------------------------------------------- 1 | 2 | ## Description 3 | 4 | In this kata we want to convert a string into an integer. The strings simply represent the numbers in words. 5 | 6 | Additional Notes: 7 | 8 | * The minimum number is "zero" (inclusively) 9 | * The maximum number, which must be supported is 1 million (inclusively) 10 | * The "and" in e.g. "one hundred and twenty-four" is optional, in some cases it's present and in others it's not 11 | * All tested numbers are valid, you don't need to validate them 12 | 13 | ### Examples 14 | ```js 15 | "one" => 1 16 | "twenty" => 20 17 | "two hundred forty-six" => 246 18 | "seven hundred eighty-three thousand nine hundred and nineteen" => 783919 19 | ``` 20 | 21 | **Kata's link**: [parseInt reloaded](https://www.codewars.com/kata/parseint-reloaded) 22 | 23 | ## Best Practices 24 | 25 | **First:** 26 | ```js 27 | function parseInt(string) { 28 | var map = {"zero":0,"one":1,"two":2,"three":3,"four":4,"five":5,"six":6,"seven":7,"eight":8,"nine":9,"ten":10,"eleven":11,"twelve":12,"thirteen":13,"fourteen":14,"fifteen":15,"sixteen":16,"seventeen":17,"eigthteen":18,"nineteen":19, 29 | "twenty":20, "thirty":30, "forty":40, "fifty":50, "sixty":60, "seventy":70, "eighty":80, "ninety":90,}; 30 | var multiMap = {"hundred":100, "thousand":1000, "million":1000000}; 31 | var result = 0, result2 = 0, multiply = 0; 32 | 33 | function getNumber(string) { 34 | var nArr = string.split("-"); 35 | if (nArr.length > 1) { 36 | return map[nArr[0]] + map[nArr[1]]; 37 | } 38 | return map[string]; 39 | } 40 | 41 | string.split(" ").map(function(number) { 42 | if (multiMap[number]) { 43 | result *= multiMap[number]; 44 | if (result >= 1000) { 45 | result2 = result; 46 | result = 0; 47 | } 48 | } 49 | else if (number != "and") { 50 | result += getNumber(number); 51 | } 52 | }); 53 | return result + result2; 54 | } 55 | ``` 56 | 57 | **Second:** 58 | ```js 59 | var words = { 60 | "zero":0, "one":1, "two":2, "three":3, "four":4, "five":5, "six":6, "seven":7, "eight":8, "nine":9, 61 | "ten":10, "eleven":11, "twelve":12, "thirteen":13, "fourteen":14, "fifteen":15, "sixteen":16, 62 | "seventeen":17, "eighteen":18, "nineteen":19, "twenty":20, "thirty":30, "forty":40, "fifty":50, 63 | "sixty":60, "seventy":70, "eighty":80, "ninety":90 64 | }; 65 | var mult = { "hundred":100, "thousand":1000, "million": 1000000 }; 66 | function parseInt(str) { 67 | return str.split(/ |-/).reduce(function(value, word) { 68 | if (words[word]) value += words[word]; 69 | if (mult[word]) value += mult[word] * (value % mult[word]) - (value % mult[word]); 70 | return value; 71 | },0); 72 | } 73 | ``` 74 | 75 | ## My solutions 76 | ```js 77 | const numbersMap = { 78 | 'zero': 0, 79 | 'one': 1, 80 | 'two': 2, 81 | 'three': 3, 82 | 'four': 4, 83 | 'five': 5, 84 | 'six': 6, 85 | 'seven': 7, 86 | 'eight': 8, 87 | 'nine': 9, 88 | 'ten': 10, 89 | 'eleven': 11, 90 | 'twelve': 12, 91 | 'thirteen': 13, 92 | 'fourteen': 14, 93 | 'fifteen': 15, 94 | 'sixteen': 16, 95 | 'seventeen': 17, 96 | 'eighteen': 18, 97 | 'nineteen': 19, 98 | 'twenty': 20, 99 | 'thirty': 30, 100 | 'forty': 40, 101 | 'fifty': 50, 102 | 'sixty': 60, 103 | 'seventy': 70, 104 | 'eighty': 80, 105 | 'ninety': 90, 106 | 'hundred': 100, 107 | 'thousand': 1000, 108 | 'million': 1000000 109 | } 110 | 111 | function getSimpleNumber (number) { 112 | return numbersMap[number] 113 | ? numbersMap[number] 114 | : number.split('-').map(v => numbersMap[v]).reduce((prev, next) => prev + next, 0); 115 | } 116 | 117 | function getComplexNumber (numbers) { 118 | let res = 0; 119 | numbers = numbers.filter(v => v !== 'and'); 120 | 121 | for(let i = 0, l = numbers.length; i < l;) { 122 | if (numbers[i + 1] && ['hundred', 'thousand', 'million'].includes(numbers[i + 1])) { 123 | const v = numbers[i + 1]; 124 | if (v === 'hundred') { 125 | res += numbersMap[numbers[i]] * numbersMap[numbers[i + 1]]; 126 | } else { 127 | res += getSimpleNumber(numbers[i]); 128 | res = res * numbersMap[numbers[i + 1]]; 129 | } 130 | i += 2; 131 | continue; 132 | } else if (numbers[i] === 'thousand') { 133 | res = res * numbersMap['thousand']; 134 | } else { 135 | res += getSimpleNumber(numbers[i]); 136 | } 137 | i += 1; 138 | } 139 | 140 | return res; 141 | } 142 | 143 | function parseInt (string) { 144 | // TODO: it's your task now 145 | const numbers = string.split(' '); 146 | return numbers.length === 1 ? getSimpleNumber(numbers[0]) : getComplexNumber(numbers); 147 | } 148 | ``` 149 | --------------------------------------------------------------------------------