├── .gitignore ├── .jshintignore ├── solutions ├── php │ ├── shortest-fizz-buzz.php │ ├── integer-length.php │ ├── reverse-words-in-string.php │ ├── sum-of-array-plus-one.php │ ├── factorial.php │ └── hotel-room.php ├── ruby │ ├── sum_plus_one.rb │ ├── fibonacci.rb │ ├── remove_duplicates.rb │ ├── reverse_words.rb │ ├── int_length.rb │ ├── sum_of_array_plus_one.rb │ ├── fib.rb │ ├── multiples_of_three_and_five.rb │ ├── odd_occuring_element.rb │ ├── shortest_fizz_buzz.rb │ ├── word_position.rb │ ├── selection_sort.rb │ ├── bubble_sort.rb │ ├── balanced_brackets.rb │ ├── prime_number.rb │ ├── longest_words.rb │ ├── array_pair_sum.rb │ ├── merge_sort.rb │ ├── anagram_detection.rb │ ├── flatten_array.rb │ ├── factorial.rb │ └── quick_sort.rb ├── javascript │ ├── shortest-fizz-buzz.js │ ├── string-rotation.js │ ├── reverse-words-in-string.js │ ├── odd-occuring-element.js │ ├── integer-length.js │ ├── queen-threatens-king │ │ ├── queen-threatens-king-solution-vertical.png │ │ ├── queen-threatens-king-solution-diagonal-1.png │ │ ├── queen-threatens-king-solution-diagonal-2.png │ │ ├── queen-threatens-king-solution-horizontal.png │ │ └── readme.md │ ├── string-format.js │ ├── flatten-array │ │ ├── es5.js │ │ ├── in-place.js │ │ ├── copy.js │ │ └── recursive.js │ ├── prime-number.js │ ├── remove-duplicates-from-string.js │ ├── largest-continuous-sum.js │ ├── byte-format.js │ ├── multiples-of-3-and-5.js │ ├── sum-of-array-plus-one.js │ ├── money-format.js │ ├── even-occuring-element.js │ ├── integer-difference.js │ ├── missing-number.js │ ├── balanced-brackets.js │ ├── convert-array.js │ ├── factorial.js │ ├── array-pair-sum.js │ ├── binary-search-tree-check.js │ ├── number-format.js │ ├── largest-palindrome.js │ ├── throttle.js │ ├── debounce.js │ ├── once.js │ ├── first-non-repeated-character.js │ ├── stack.js │ ├── bubble-sort.js │ ├── search-unknown-length-array.js │ ├── string-permutations.js │ ├── tree-level-order-print.js │ ├── selection-sort.js │ ├── queen-threatens-king.js │ ├── sorted-array-search.js │ ├── kth-largest-element-in-array.js │ ├── next-palindrome-number.js │ ├── flatten-array.js │ ├── queue.js │ ├── longest-words.js │ ├── find-missing-element.js │ ├── csv-parsing.js │ ├── quick-sort.js │ ├── merge-sort.js │ ├── combine-two-strings.js │ ├── insertion-sort.js │ ├── async-task-runner.js │ ├── word-positions.js │ ├── next-highest-number.js │ ├── linked-list.js │ ├── matching-nodes.js │ ├── get-elements-by-class-name.js │ ├── hotel-room.js │ ├── spiral.js │ ├── fibonnaci.js │ ├── anagram-detection.js │ ├── median-integer-stream.js │ ├── longest-compound-word.js │ ├── binary-search-tree.js │ └── transform-word.js ├── coffeescript │ ├── integer-length.coffee │ ├── largest-continuous-sum.coffee │ ├── even-occuring-element.coffee │ ├── integer-difference.coffee │ ├── byte-format.coffee │ ├── factorial.coffee │ ├── balanced-brackets.coffee │ ├── debounce.coffee │ ├── bubble-sort.coffee │ ├── first-non-repeated-character.coffee │ ├── combine-two-strings.coffee │ ├── largest-palindrome.coffee │ ├── array-pair-sum.coffee │ ├── kth-largest-element-in-array.coffee │ ├── flatten-array.coffee │ ├── find-missing-element.coffee │ ├── linked-list.coffee │ ├── csv-parsing.coffee │ ├── word-positions.coffee │ ├── hotel-room.coffee │ ├── anagram-detection.coffee │ ├── get-elements-by-class-name.coffee │ └── fibonacci.coffee ├── go │ ├── shortest-fizz-buzz.go │ ├── multiples-of-3-or-5.go │ ├── longest-words.go │ └── merge-sort.go └── java │ ├── FindingMissingElement.java │ ├── StringRotation.java │ ├── ReverseWordsInAString.java │ ├── LargestContinuousSum.java │ ├── LongestCommonPrefix.java │ ├── Fibonacci.java │ ├── IntegerDifference.java │ ├── BalancedBrackets.java │ ├── LargestPalindrome.java │ ├── ConvertArray.java │ ├── NextHighestNumber.java │ ├── EvenOccuringElement.java │ ├── SearchUnknownLengthArray.java │ ├── BubbleSort.java │ ├── RemoveDuplicatesFromString.java │ ├── BinarySearchTree.java │ ├── AnagramDetection.java │ ├── TreeLevelOrderPrint.java │ ├── HotelRoom.java │ ├── LongestCompoundWord.java │ ├── CombineTwoStrings.java │ ├── Spiral.java │ └── MedianIntegerStream.java ├── .gitmodules ├── tests ├── cpp │ ├── common.cpp │ ├── spiral.cpp │ ├── common.hpp │ └── once.cpp └── javascript │ ├── insertion-sort.js │ ├── search-unknown-length-array.js │ ├── array-pair-sum.js │ ├── word-positions.js │ ├── prime-number.js │ ├── largest-continuous-sum.js │ ├── convert-array.js │ ├── flatten-array.js │ ├── anagram-detection.js │ ├── sorted-array-search.js │ ├── next-highest-number.js │ ├── queen-threatens-king.js │ ├── factorial.js │ ├── quick-sort.js │ ├── byte-format.js │ └── binary-search-tree-check.js ├── problems ├── spiral │ ├── input-1.png │ ├── input-2.png │ └── Readme.md ├── linked-list │ └── Readme.md ├── queue │ └── Readme.md ├── quick-sort │ └── Readme.md ├── stack │ └── Readme.md ├── bubble-sort │ └── Readme.md ├── merge-sort │ └── Readme.md ├── insertion-sort │ └── README.md ├── number-format │ └── Readme.md ├── selection-sort │ └── readme.md ├── prime-number │ └── Readme.md ├── integer-length │ └── Readme.md ├── queen-threatens-king │ ├── queen-threatens-king.png │ └── readme.md ├── sorted-array-search │ └── Readme.md ├── missing-number │ └── Readme.md ├── factorial │ └── readme.md ├── money-format │ └── Readme.md ├── sum-of-array-plus-one │ └── Readme.md ├── binary-search-tree │ └── Readme.md ├── flatten-array │ └── Readme.md ├── first-non-repeated-character │ └── Readme.md ├── largest-palindrome │ └── Readme.md ├── once │ └── Readme.md ├── string-rotation │ └── Readme.md ├── get-elements-by-class-name │ └── Readme.md ├── byte-format │ └── README.md ├── longest-common-prefix │ └── Readme.md ├── search-unknown-length-array │ └── Readme.md ├── binary-search-tree-check │ └── Readme.md ├── integer-difference │ └── Readme.md ├── multiples-of-3-and-5 │ └── Readme.md ├── largest-continuous-sum │ └── Readme.md ├── closest-sum │ └── problem.txt ├── string-format │ └── Readme.md ├── string-permutations │ └── Readme.md ├── convert-array │ └── Readme.md ├── fibonacci │ └── Readme.md ├── anagram-detection │ └── Readme.md ├── balanced-brackets │ └── Readme.md ├── odd-occuring-element │ └── Readme.md ├── even-occuring-element │ └── Readme.md ├── next-palindrome-number │ └── Readme.md ├── word-positions │ └── Readme.md ├── hotel-room │ └── Readme.md ├── tree-level-order-print │ └── Readme.md ├── matching-nodes │ └── Readme.md ├── find-missing-element │ └── Readme.md ├── remove-duplicates-from-string │ └── Readme.md ├── next-highest-number │ └── Readme.md ├── longest-words │ └── Readme.md ├── throttle │ └── Readme.md ├── kth-largest-element-in-array │ └── Readme.md ├── debounce │ └── Readme.md ├── shortest-fizz-buzz │ └── Readme.md ├── transform-word │ └── Readme.md ├── reverse-words-in-string │ └── Readme.md ├── combine-two-strings │ └── Readme.md ├── csv-parsing │ └── Readme.md ├── median-integer-stream │ └── Readme.md ├── longest-compound-word │ └── Readme.md ├── spreadsheet │ └── README.md ├── array-pair-sum │ └── Readme.md ├── async-task-runner │ └── Readme.md ├── skiing-in-singapore │ └── README.md ├── word-analytics │ └── Readme.md └── stack-machine │ └── Readme.md ├── .editorconfig ├── package.json ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── .jshintrc └── Readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | node_modules 4 | *.o 5 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | solutions/javascript/shortest-fizz-buzz.js 2 | -------------------------------------------------------------------------------- /solutions/php/shortest-fizz-buzz.php: -------------------------------------------------------------------------------- 1 | > eventLog; 4 | int nextId; 5 | -------------------------------------------------------------------------------- /problems/spiral/input-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muthu-cs/code-problems-solutions/HEAD/problems/spiral/input-1.png -------------------------------------------------------------------------------- /problems/spiral/input-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muthu-cs/code-problems-solutions/HEAD/problems/spiral/input-2.png -------------------------------------------------------------------------------- /solutions/ruby/int_length.rb: -------------------------------------------------------------------------------- 1 | def int_length(num) 2 | return 1 if num.abs < 10 3 | 1 + int_length(num / 10) 4 | end 5 | -------------------------------------------------------------------------------- /solutions/ruby/sum_of_array_plus_one.rb: -------------------------------------------------------------------------------- 1 | def sum_of_array_plus_one array 2 | array.inject(:+) + array.count 3 | end 4 | -------------------------------------------------------------------------------- /problems/linked-list/Readme.md: -------------------------------------------------------------------------------- 1 | # Linked List 2 | 3 | Write a linked list implementation, better yet - make it doubly linked. 4 | -------------------------------------------------------------------------------- /problems/queue/Readme.md: -------------------------------------------------------------------------------- 1 | # Basic Queue 2 | 3 | Implement a basic queue function with the ability to `add` and `remove` values. 4 | -------------------------------------------------------------------------------- /problems/quick-sort/Readme.md: -------------------------------------------------------------------------------- 1 | # Quick Sort 2 | 3 | Implement the [quick sort algorithm](http://en.wikipedia.org/wiki/Quicksort). 4 | -------------------------------------------------------------------------------- /problems/stack/Readme.md: -------------------------------------------------------------------------------- 1 | # Basic Stack 2 | 3 | Implement a basic stack function with the ability to `add` and `remove` values. 4 | -------------------------------------------------------------------------------- /problems/bubble-sort/Readme.md: -------------------------------------------------------------------------------- 1 | # Bubble Sort 2 | 3 | Implement the [bubble sort algorithm](http://en.wikipedia.org/wiki/Bubble_sort). 4 | -------------------------------------------------------------------------------- /problems/merge-sort/Readme.md: -------------------------------------------------------------------------------- 1 | # Merge Sort 2 | 3 | Implement the [merge sort algorithm](http://en.wikipedia.org/wiki/Merge_sort). 4 | -------------------------------------------------------------------------------- /solutions/php/integer-length.php: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /solutions/ruby/fib.rb: -------------------------------------------------------------------------------- 1 | def fib(n) 2 | return 0 if n == 0 3 | return 1 if n == 1 || n == 2 4 | fib(n - 2) + fib(n - 1) 5 | end 6 | -------------------------------------------------------------------------------- /solutions/javascript/string-rotation.js: -------------------------------------------------------------------------------- 1 | module.exports = function (a, b) { 2 | return a.length === b.length && (a + a).indexOf(b) > -1; 3 | }; 4 | -------------------------------------------------------------------------------- /problems/insertion-sort/README.md: -------------------------------------------------------------------------------- 1 | # Insertion Sort 2 | 3 | Implement the [insertion sort algorithm](http://en.wikipedia.org/wiki/Insertion_sort). 4 | -------------------------------------------------------------------------------- /problems/number-format/Readme.md: -------------------------------------------------------------------------------- 1 | # Numeric String 2 | 3 | Format any number into a string with "," (commas) in the correct places. E.g. "1,000,000". 4 | -------------------------------------------------------------------------------- /problems/selection-sort/readme.md: -------------------------------------------------------------------------------- 1 | # Selection Sort 2 | 3 | Implement the [selection sort algorithm](http://en.wikipedia.org/wiki/Selection_sort). 4 | -------------------------------------------------------------------------------- /solutions/javascript/reverse-words-in-string.js: -------------------------------------------------------------------------------- 1 | module.exports = function (string) { 2 | return string.split(/\s+/g).reverse().join(' '); 3 | }; 4 | -------------------------------------------------------------------------------- /problems/prime-number/Readme.md: -------------------------------------------------------------------------------- 1 | # Prime Number 2 | 3 | Write a function that accepts a number and return a boolean based on whether it's a prime number. 4 | -------------------------------------------------------------------------------- /problems/integer-length/Readme.md: -------------------------------------------------------------------------------- 1 | # Integer Length 2 | 3 | Write a function that takes an integer as input and returns the number of digits in that integer. 4 | -------------------------------------------------------------------------------- /solutions/ruby/multiples_of_three_and_five.rb: -------------------------------------------------------------------------------- 1 | def multiples_of_three_and_five 2 | (1...1000).to_a.select { |num| num % 3 == 0 || num % 5 == 0 }.reduce(&:+) 3 | end 4 | -------------------------------------------------------------------------------- /solutions/ruby/odd_occuring_element.rb: -------------------------------------------------------------------------------- 1 | def odd_occuring_element(array) 2 | array.uniq.each do |num| 3 | return num if array.count(num) % 2 != 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /solutions/ruby/shortest_fizz_buzz.rb: -------------------------------------------------------------------------------- 1 | def shortest_fizz_buzz 2 | (1..100).to_a.each{|i|puts i%3==0&&i%5==0 ? "FizzBuzz": i%3==0 ? "Fizz": i%5==0 ? "Buzz": i} 3 | end 4 | -------------------------------------------------------------------------------- /problems/queen-threatens-king/queen-threatens-king.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muthu-cs/code-problems-solutions/HEAD/problems/queen-threatens-king/queen-threatens-king.png -------------------------------------------------------------------------------- /solutions/coffeescript/integer-length.coffee: -------------------------------------------------------------------------------- 1 | integerLength = (num) -> 2 | # There is an extra check here to ensure the number is an integer 3 | ("" + (num | 0)).length 4 | -------------------------------------------------------------------------------- /solutions/go/shortest-fizz-buzz.go: -------------------------------------------------------------------------------- 1 | package main;import f"fmt";func main(){p:=f.Print;for i:=1;i<101;i++{if i%3<1{p("Fizz")};if i%5<1{p("Buzz")};if i%3>0&&i%5>0{p(i)};p("\n")}} -------------------------------------------------------------------------------- /solutions/javascript/odd-occuring-element.js: -------------------------------------------------------------------------------- 1 | module.exports = function (array) { 2 | return array.reduce(function (memo, number) { 3 | return memo ^ number; 4 | }, 0); 5 | }; 6 | -------------------------------------------------------------------------------- /solutions/javascript/integer-length.js: -------------------------------------------------------------------------------- 1 | module.exports = function (num) { 2 | // There is an extra check here to ensure the number is an integer 3 | return ('' + (num|0)).length; 4 | }; 5 | -------------------------------------------------------------------------------- /solutions/php/reverse-words-in-string.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /problems/sorted-array-search/Readme.md: -------------------------------------------------------------------------------- 1 | # Sorted Array Search 2 | 3 | Given an array of numbers sorted in ascending order, write a function that will return the index at which the number is found. 4 | -------------------------------------------------------------------------------- /problems/missing-number/Readme.md: -------------------------------------------------------------------------------- 1 | # Missing Number 2 | 3 | Write a function that accepts an array of integers in random order of unknown length, but with one number missing. Return the missing number. 4 | -------------------------------------------------------------------------------- /problems/factorial/readme.md: -------------------------------------------------------------------------------- 1 | Factorial 2 | ========== 3 | 4 | Factorial of any number n is defined as the multiplication of numbers from one to the given number. 5 | 6 | `` 7 | n! = 1 x 2 x 3 x 4 x ........ x n 8 | `` 9 | -------------------------------------------------------------------------------- /solutions/ruby/word_position.rb: -------------------------------------------------------------------------------- 1 | def word_position(text, word) 2 | text = text.split(" ") 3 | positions = [] 4 | text.each_index do |i| 5 | positions << i if text[i] == word 6 | end 7 | return positions 8 | end 9 | -------------------------------------------------------------------------------- /solutions/javascript/queen-threatens-king/queen-threatens-king-solution-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muthu-cs/code-problems-solutions/HEAD/solutions/javascript/queen-threatens-king/queen-threatens-king-solution-vertical.png -------------------------------------------------------------------------------- /problems/money-format/Readme.md: -------------------------------------------------------------------------------- 1 | # Money Formatting 2 | 3 | Given an amount of money as a float, format it as a string. 4 | 5 | ```javascript 6 | formatMoney(2310000.159897); // '2 310 000.16' 7 | formatMoney(1600); // '1 600.00' 8 | ``` 9 | -------------------------------------------------------------------------------- /problems/sum-of-array-plus-one/Readme.md: -------------------------------------------------------------------------------- 1 | # Sum of Array Plus One 2 | 3 | Write a function that takes an array of integers and returns the sum of the integers after adding 1 to each. 4 | 5 | ``` 6 | plusOneSum([1, 2, 3, 4]); // 14 7 | ``` 8 | -------------------------------------------------------------------------------- /solutions/javascript/queen-threatens-king/queen-threatens-king-solution-diagonal-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muthu-cs/code-problems-solutions/HEAD/solutions/javascript/queen-threatens-king/queen-threatens-king-solution-diagonal-1.png -------------------------------------------------------------------------------- /solutions/javascript/queen-threatens-king/queen-threatens-king-solution-diagonal-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muthu-cs/code-problems-solutions/HEAD/solutions/javascript/queen-threatens-king/queen-threatens-king-solution-diagonal-2.png -------------------------------------------------------------------------------- /solutions/javascript/queen-threatens-king/queen-threatens-king-solution-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muthu-cs/code-problems-solutions/HEAD/solutions/javascript/queen-threatens-king/queen-threatens-king-solution-horizontal.png -------------------------------------------------------------------------------- /problems/binary-search-tree/Readme.md: -------------------------------------------------------------------------------- 1 | # Binary Search Tree 2 | 3 | Gives methods to create a binary search tree. 4 | 5 | ## Source 6 | 7 | [http://en.wikipedia.org/wiki/Binary_search_tree](http://en.wikipedia.org/wiki/Binary_search_tree) 8 | -------------------------------------------------------------------------------- /problems/flatten-array/Readme.md: -------------------------------------------------------------------------------- 1 | # Flatten Array 2 | 3 | Write a function that accepts a multi dimensional array and returns a flattened version. 4 | 5 | ```javascript 6 | flatten([1, 2, [3, [4], 5, 6], 7]) // [1, 2, 3, 4, 5, 6, 7] 7 | ``` 8 | -------------------------------------------------------------------------------- /problems/first-non-repeated-character/Readme.md: -------------------------------------------------------------------------------- 1 | # First Non-repeated character 2 | 3 | Write a function that accepts a single string input and returns the first non-repeated character. 4 | 5 | ```js 6 | "AABBC" // "C" 7 | "AABBCCDEEFF" // "D" 8 | ``` 9 | -------------------------------------------------------------------------------- /solutions/php/sum-of-array-plus-one.php: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /solutions/javascript/string-format.js: -------------------------------------------------------------------------------- 1 | module.exports = function (string /* , args */) { 2 | var args = Array.prototype.slice.call(arguments, 1); 3 | 4 | return string.replace(/\{(\d+)\}/g, function (_, arg) { 5 | return arg in args ? args[arg] : _; 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /solutions/ruby/selection_sort.rb: -------------------------------------------------------------------------------- 1 | def selection_sort(array) 2 | 0.upto(array.size - 1) do |i| 3 | min = i 4 | (i + 1).upto(array.size - 1) { |j| min = j if (array[j] <=> array[min]) == -1 } 5 | array[i], array[min] = array[min], array[i] 6 | end 7 | array 8 | end 9 | -------------------------------------------------------------------------------- /problems/largest-palindrome/Readme.md: -------------------------------------------------------------------------------- 1 | # Largest Palindrome 2 | 3 | Write a function that finds the largest palindrome in a string. All characters can be valid for the palindrome, including whitespace. In the string "I am a red racecar driver" - the largest palindrome would be "d racecar d". 4 | -------------------------------------------------------------------------------- /problems/once/Readme.md: -------------------------------------------------------------------------------- 1 | # Once 2 | 3 | Write a function that accepts a function as it's only argument and returns a new function that can only ever be executed once. 4 | 5 | Once completed, add a second arguments that allows the function to be executed `x` number of times before it stops working. 6 | -------------------------------------------------------------------------------- /solutions/javascript/flatten-array/es5.js: -------------------------------------------------------------------------------- 1 | module.exports = function flatten (array) { 2 | return array.reduce(function (arr, val) { 3 | // Concat is extremely slow which leads to this being the slowest solution. 4 | return arr.concat(Array.isArray(val) ? flatten(val) : val); 5 | }, []); 6 | }; 7 | -------------------------------------------------------------------------------- /solutions/ruby/bubble_sort.rb: -------------------------------------------------------------------------------- 1 | def bubble_sort(array) 2 | i = 0 3 | while i < array.size - 1 4 | j = i + 1 5 | while j < array.size 6 | array[i], array[j] = array[j], array[i] if array[i] > array[j] 7 | j = j + 1 8 | end 9 | i = i + 1 10 | end 11 | array 12 | end 13 | -------------------------------------------------------------------------------- /problems/string-rotation/Readme.md: -------------------------------------------------------------------------------- 1 | # String Rotation 2 | 3 | Find out if a string is a rotation of another string. E.g. `ABCD` is a rotation of `BCDA` but not `ACBD`. 4 | 5 | ## Source 6 | 7 | [Reddit](http://www.reddit.com/r/javascript/comments/1ftyjh/common_code_problems_solved_in_javascript_xpost/cae25ra) 8 | -------------------------------------------------------------------------------- /solutions/ruby/balanced_brackets.rb: -------------------------------------------------------------------------------- 1 | def balanced_brackets(str) 2 | brackets = { '(' => ')', '{' => '}', '[' => ']' } 3 | 4 | arr = [] 5 | str.each_char do |c| 6 | if brackets[c] then arr << c 7 | else return false if arr.size < 1 || (brackets.key(c) != arr.pop) end 8 | end 9 | arr.empty? 10 | end 11 | -------------------------------------------------------------------------------- /problems/get-elements-by-class-name/Readme.md: -------------------------------------------------------------------------------- 1 | # Get Elements by Class Name 2 | 3 | Implement the `getElementsByClassName(element, className)` function in Javascript. 4 | 5 | ## Source 6 | 7 | [GlassDoor](http://www.glassdoor.com/Interview/Implement-the-getElementsByClassName-element-className-function-in-Javascript-QTN_226449.htm) 8 | -------------------------------------------------------------------------------- /solutions/javascript/flatten-array/in-place.js: -------------------------------------------------------------------------------- 1 | module.exports = function (array) { 2 | var i = 0; 3 | 4 | while (i < array.length) { 5 | if (Array.isArray(array[i])) { 6 | array.splice.apply(array, [i, 1].concat(array[i])); 7 | } else { 8 | i += 1; 9 | } 10 | } 11 | 12 | return array; 13 | }; 14 | -------------------------------------------------------------------------------- /solutions/javascript/prime-number.js: -------------------------------------------------------------------------------- 1 | module.exports = function (n) { 2 | if (n === 2) { return true; } 3 | if (n < 2 || !(n&1)) { return false; } 4 | 5 | for (var i = 3, l = Math.floor(Math.pow(n, 0.5)); i <= l; i += 2) { 6 | if (n % i === 0) { 7 | return false; 8 | } 9 | } 10 | 11 | return true; 12 | }; 13 | -------------------------------------------------------------------------------- /problems/byte-format/README.md: -------------------------------------------------------------------------------- 1 | # Byte String 2 | 3 | Convert a number to a string that represents a rounded size in bytes. 4 | 5 | ## Example 6 | 7 | ``` 8 | f(156833213) // => "149.57 MB" 9 | f(8101) // => "7.91 KB" 10 | f(12331, 3) // => "12.042 KB" 11 | ``` 12 | 13 | ## Source 14 | 15 | By [Riga](https://github.com/riga). 16 | -------------------------------------------------------------------------------- /solutions/javascript/remove-duplicates-from-string.js: -------------------------------------------------------------------------------- 1 | module.exports = function (string) { 2 | var output = '', 3 | hash = {}; 4 | 5 | for (var i = 0; i < string.length; i++) { 6 | if (!hash[string[i]]) { 7 | output += string[i]; 8 | } 9 | hash[string[i]] = true; 10 | } 11 | 12 | return output; 13 | }; 14 | -------------------------------------------------------------------------------- /problems/longest-common-prefix/Readme.md: -------------------------------------------------------------------------------- 1 | # Longest Common Prefix 2 | 3 | Given a String array, find the longest common prefix. 4 | 5 | ## Example 6 | 7 | ``` 8 | f([‘rocket’, ‘rockstar’, ‘rockbottom’, ‘rock’, ‘rollingstone’] // ‘ro’ 9 | f([‘shuffle’, ‘shuttle’, ‘shut’] // ‘shu’ 10 | ``` 11 | 12 | ## Source 13 | Personal Phone Interview 14 | -------------------------------------------------------------------------------- /solutions/go/multiples-of-3-or-5.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func findMultiples() int { 8 | sum := 0; 9 | for i := 0; i < 1000; i++ { 10 | if i % 3 == 0 || i % 5 == 0 { 11 | sum += i 12 | } 13 | } 14 | return sum 15 | 16 | } 17 | 18 | func main() { 19 | fmt.Println(findMultiples()) 20 | } -------------------------------------------------------------------------------- /problems/search-unknown-length-array/Readme.md: -------------------------------------------------------------------------------- 1 | # Search Unknown Length Array 2 | 3 | Given a sorted array of unknown length and a number to search for, return the index of the number in the array. Accessing an element out of bounds throws exception. If the number occurs multiple times, return the index of any occurrence. If it isn’t present, return -1. 4 | -------------------------------------------------------------------------------- /solutions/javascript/flatten-array/copy.js: -------------------------------------------------------------------------------- 1 | module.exports = function flatten (array) { 2 | var copy = []; 3 | 4 | for (var i = 0; i < array.length; i++) { 5 | if (Array.isArray(array[i])) { 6 | copy.push.apply(copy, flatten(array[i])); 7 | } else { 8 | copy.push(array[i]); 9 | } 10 | } 11 | 12 | return copy; 13 | }; 14 | -------------------------------------------------------------------------------- /problems/binary-search-tree-check/Readme.md: -------------------------------------------------------------------------------- 1 | # Binary Search Tree Check 2 | 3 | Given a binary tree, check whether it’s a binary search tree or not. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/10/10/programming-interview-questions-7-binary-search-tree-check/](http://www.ardendertat.com/2011/10/10/programming-interview-questions-7-binary-search-tree-check/) 8 | -------------------------------------------------------------------------------- /problems/integer-difference/Readme.md: -------------------------------------------------------------------------------- 1 | # Integer Difference 2 | 3 | Write a function that accepts an array of random integers and an integer *n*. Determine the number of times where two integers in the array have the difference of *n*. 4 | 5 | ```js 6 | f(4, [1, 1, 5, 6, 9, 16, 27]) // 3 (Due to 2x [1, 5], and [5, 9]) 7 | f(2, [1, 1, 3, 3]) // 4 (Due to 4x [1, 3]) 8 | ``` 9 | -------------------------------------------------------------------------------- /problems/multiples-of-3-and-5/Readme.md: -------------------------------------------------------------------------------- 1 | # Multiples of 3 and 5 2 | 3 | If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. 4 | 5 | Find the sum of all the multiples of 3 or 5 below 1000. 6 | 7 | ## Source 8 | 9 | [http://projecteuler.net/problem=1](http://projecteuler.net/problem=1) 10 | -------------------------------------------------------------------------------- /problems/largest-continuous-sum/Readme.md: -------------------------------------------------------------------------------- 1 | # Largest Continuous Sum 2 | 3 | Given an array of integers (positive and negative) find the largest continuous sum. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/09/24/programming-interview-questions-3-largest-continuous-sum/](http://www.ardendertat.com/2011/09/24/programming-interview-questions-3-largest-continuous-sum/) 8 | -------------------------------------------------------------------------------- /problems/closest-sum/problem.txt: -------------------------------------------------------------------------------- 1 | Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. 2 | Return the sum of the three integers. 3 | You may assume that each input would have exactly one solution. 4 | 5 | Example: 6 | given array S = {-1 2 1 -4}, 7 | and target = 1. 8 | 9 | The sum that is closest to the target is 2. (-1 + 2 + 1 = 2) -------------------------------------------------------------------------------- /problems/string-format/Readme.md: -------------------------------------------------------------------------------- 1 | # String Format 2 | 3 | Create a string formatting function that accepts an input string and a number of arguments to replace positions in the input string. 4 | 5 | ## Example 6 | 7 | ``` 8 | f('Hello {0} {1}', 'Mr.', 'X') // => 'Hello Mr. X' 9 | f('{1}_{0}', '{1}', '{0}') // => '{0}_{1}' 10 | ``` 11 | 12 | By [Riga](https://github.com/riga). 13 | -------------------------------------------------------------------------------- /solutions/coffeescript/largest-continuous-sum.coffee: -------------------------------------------------------------------------------- 1 | largestContinuousSum = (array) -> 2 | return if !array or !array.length 3 | 4 | currentSum = maximumSum = array.shift() 5 | 6 | # Checks the array of sums and compares them 7 | array.forEach (num) -> 8 | currentSum = Math.max(currentSum + num, num) 9 | maximumSum = Math.max(currentSum, maximumSum) 10 | maximumSum 11 | -------------------------------------------------------------------------------- /solutions/ruby/prime_number.rb: -------------------------------------------------------------------------------- 1 | # Iterative version 2 | 3 | def is_prime? number 4 | return 0 if (number == 0 or number == 1) 5 | 6 | for d in (2...number) do 7 | return 0 if (number % d == 0) 8 | end 9 | 10 | return 1 11 | end 12 | 13 | #built-in version 14 | 15 | require 'mathn' #mathematical library 16 | 17 | def is_prime2? number 18 | (Prime.prime? number)? 1:0 19 | end 20 | -------------------------------------------------------------------------------- /problems/string-permutations/Readme.md: -------------------------------------------------------------------------------- 1 | # All Permutations of a String 2 | 3 | Generate all permutations of a given string. (Note: also known as the generating anagrams problem). 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/10/28/programming-interview-questions-11-all-permutations-of-string/](http://www.ardendertat.com/2011/10/28/programming-interview-questions-11-all-permutations-of-string/) 8 | -------------------------------------------------------------------------------- /solutions/javascript/flatten-array/recursive.js: -------------------------------------------------------------------------------- 1 | var flatten = function (array, result) { 2 | for (var i = 0; i < array.length; i++) { 3 | if (Array.isArray(array[i])) { 4 | flatten(array[i], result); 5 | } else { 6 | result.push(array[i]); 7 | } 8 | } 9 | 10 | return result; 11 | }; 12 | 13 | module.exports = function (array) { 14 | return flatten(array, []); 15 | }; 16 | -------------------------------------------------------------------------------- /solutions/ruby/longest_words.rb: -------------------------------------------------------------------------------- 1 | def longest_words string 2 | # splitting the string into words and removing duplicates from the array 3 | words = string.downcase.split.uniq 4 | # finding the maximum value in the array based on length 5 | max = words.max_by { |word| word.length } 6 | # selecting all the words with the same length as the max value 7 | words = words.select { |word| word.length == max.length } 8 | end -------------------------------------------------------------------------------- /problems/convert-array/Readme.md: -------------------------------------------------------------------------------- 1 | # Convert Array 2 | 3 | Given an array `[a1, a2, ..., aN, b1, b2, ..., bN, c1, c2, ..., cN]` convert it to `[a1, b1, c1, a2, b2, c2, ..., aN, bN, cN]` in-place using constant extra space. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/10/18/programming-interview-questions-9-convert-array/](http://www.ardendertat.com/2011/10/18/programming-interview-questions-9-convert-array/) 8 | -------------------------------------------------------------------------------- /problems/fibonacci/Readme.md: -------------------------------------------------------------------------------- 1 | # Fibonacci 2 | 3 | By definition, the first two numbers in the Fibonacci sequence are 0 and 1, and each subsequent number is the sum of the previous two. 4 | 5 | For example, the first ten Fibonacci numbers are: 6 | 7 | ``` 8 | 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 9 | ``` 10 | 11 | Write a function that accepts a number and returns the number at that position in the fibonnaci sequence. 12 | -------------------------------------------------------------------------------- /problems/anagram-detection/Readme.md: -------------------------------------------------------------------------------- 1 | # Anagram Detection 2 | 3 | Write a function that accepts two parameters, a parent and a child string. Determine how many times the child string - or an anagram of the child string - appears in the parent string. There is a solution which can be done in near instant time. 4 | 5 | ```js 6 | f('AdnBndAndBdaBn', 'dAn') // 4 ("Adn", "ndA", "dAn", "And") 7 | f('AbrAcadAbRa', 'cAda') // 2 8 | ``` 9 | -------------------------------------------------------------------------------- /tests/cpp/spiral.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | 3 | #include "../../solutions/cpp/spiral.hpp" 4 | 5 | TEST(SpiralTest, BasicTest) { 6 | typedef std::vector v; 7 | EXPECT_EQ(v({ 13, 8, 7, 12, 17, 18, 19, 14, 9, 4, 3, 2, 1, 6, 11, 16, 8 | 21, 22, 23, 24, 25, 20, 15, 10, 5 }), spiral(5, 5, 3, 3)); 9 | EXPECT_EQ(v({ 2, 1, 5, 6, 7, 3, 8, 4 }), spiral(2, 4, 1, 2)); 10 | } 11 | -------------------------------------------------------------------------------- /problems/balanced-brackets/Readme.md: -------------------------------------------------------------------------------- 1 | # Balanced Brackets 2 | 3 | Write a function that accepts a string consisting entirely of brackets (`[](){}`) and returns whether it is balanced. Every "opening" bracket must be followed by a closing bracket of the same type. There can also be nested brackets, which adhere to the same rule. 4 | 5 | ```js 6 | f('()[]{}(([])){[()][]}') // true 7 | f('())[]{}') // false 8 | f('[(])') // false 9 | ``` 10 | -------------------------------------------------------------------------------- /problems/odd-occuring-element/Readme.md: -------------------------------------------------------------------------------- 1 | # Find Odd Occurring Element 2 | 3 | Given an integer array, one element occurs odd number of times and all others have even occurrences. Find the element with odd occurrences. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/12/13/programming-interview-questions-22-find-odd-occurring-element/](http://www.ardendertat.com/2011/12/13/programming-interview-questions-22-find-odd-occurring-element/) 8 | -------------------------------------------------------------------------------- /problems/even-occuring-element/Readme.md: -------------------------------------------------------------------------------- 1 | # Find Even Occurring Element 2 | 3 | Given an integer array, one element occurs even number of times and all others have odd occurrences. Find the element with even occurrences. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/11/29/programming-interview-questions-18-find-even-occurring-element/](http://www.ardendertat.com/2011/11/29/programming-interview-questions-18-find-even-occurring-element/) 8 | -------------------------------------------------------------------------------- /problems/next-palindrome-number/Readme.md: -------------------------------------------------------------------------------- 1 | # Find Next Palindrome Number 2 | 3 | Given a number, find the next smallest palindrome larger than the number. For example if the number is 125, next smallest palindrome is 131. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/12/01/programming-interview-questions-19-find-next-palindrome-number/](http://www.ardendertat.com/2011/12/01/programming-interview-questions-19-find-next-palindrome-number/) 8 | -------------------------------------------------------------------------------- /problems/word-positions/Readme.md: -------------------------------------------------------------------------------- 1 | # Find Word Positions in Text 2 | 3 | Given a text file and a word, find the positions that the word occurs in the file. We’ll be asked to find the positions of many words in the same file. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/12/20/programming-interview-questions-23-find-word-positions-in-text/](http://www.ardendertat.com/2011/12/20/programming-interview-questions-23-find-word-positions-in-text/) 8 | -------------------------------------------------------------------------------- /tests/javascript/insertion-sort.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var insertion = require('../../solutions/javascript/insertion-sort'); 3 | 4 | describe('sort functions ->', function(){ 5 | var sorted = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 6 | var array = [9, 8, 7, 6, 5, 4, 3, 2, 1]; 7 | 8 | it("sort array: " + sorted, function(){ 9 | array = insertion(array); 10 | assert.deepEqual(array, sorted); 11 | }) 12 | }) 13 | 14 | -------------------------------------------------------------------------------- /problems/hotel-room/Readme.md: -------------------------------------------------------------------------------- 1 | # Room Number 2 | 3 | You're in a hotel and you forgot what room number you were in but remember that the sum of it's divisors is greater than the number, yet there is no subset of those divisors that add up to the number itself. There are 100 rooms in the Hotel, what's your room number? 4 | 5 | ## Source 6 | 7 | [Reddit](http://www.reddit.com/r/javascript/comments/1ftyjh/common_code_problems_solved_in_javascript_xpost/cae25ra) 8 | -------------------------------------------------------------------------------- /solutions/coffeescript/even-occuring-element.coffee: -------------------------------------------------------------------------------- 1 | evenOccuringElement = (array) -> 2 | hash = {} 3 | 4 | # Loop though the array adding all the elements together in a hash 5 | array.forEach (num) -> 6 | hash[num] = hash[num] + 1 or 1 7 | 8 | # Loop through all the keys in the hash, returning the number if we have an 9 | # even number of occurances 10 | for i of hash 11 | return Number(i) unless hash[i] & 1 12 | false 13 | -------------------------------------------------------------------------------- /problems/tree-level-order-print/Readme.md: -------------------------------------------------------------------------------- 1 | # Tree Level Order Print 2 | 3 | Given a binary tree of integers, print it in level order. The output will contain space between the numbers in the same level, and new line between different levels. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/12/05/programming-interview-questions-20-tree-level-order-print/](http://www.ardendertat.com/2011/12/05/programming-interview-questions-20-tree-level-order-print/) 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 2 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | 18 | [Makefile] 19 | indent_style = tab 20 | indent_size = 4 21 | -------------------------------------------------------------------------------- /problems/matching-nodes/Readme.md: -------------------------------------------------------------------------------- 1 | # Matching Nodes 2 | 3 | Given two identical tree structures (consider them DOM tree if you want) and a node from the first tree, find and return the same node on the second tree. Assume you have access to a function that can test whether two nodes are the same (E.g. the node in the first tree matches the one in the second tree). Consider ways to optimize your approach. 4 | 5 | ## Source 6 | 7 | In-person interview question using whiteboard 8 | -------------------------------------------------------------------------------- /solutions/javascript/largest-continuous-sum.js: -------------------------------------------------------------------------------- 1 | module.exports = function (array) { 2 | if (!array || !array.length) { return; } 3 | 4 | var currentSum, maximumSum; 5 | 6 | // Set the starting sum as the first number 7 | currentSum = maximumSum = array.shift(); 8 | 9 | array.forEach(function (num) { 10 | currentSum = Math.max(currentSum + num, num); 11 | maximumSum = Math.max(currentSum, maximumSum); 12 | }); 13 | 14 | return maximumSum; 15 | }; 16 | -------------------------------------------------------------------------------- /solutions/javascript/byte-format.js: -------------------------------------------------------------------------------- 1 | var suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; 2 | 3 | module.exports = function (value, precision) { 4 | var factor = Math.pow(10, precision != null ? precision : 2); 5 | 6 | var suffix = Math.min( 7 | ~~(Math.log(value) / Math.log(1024)), suffixes.length - 1 8 | ); 9 | 10 | var num = Math.ceil(value / Math.pow(1024, suffix) * factor) / factor; 11 | 12 | return num + ' ' + suffixes[suffix]; 13 | }; 14 | -------------------------------------------------------------------------------- /solutions/ruby/array_pair_sum.rb: -------------------------------------------------------------------------------- 1 | def array_pair_sum(sum, arr) 2 | result = [] 3 | seen = Hash.new(false) 4 | while elem = arr.shift 5 | target = sum - elem 6 | (seen[elem] || seen[target]) ? next : (seen[elem] = true) 7 | result << [elem, target] if arr.include?(target) 8 | end 9 | result 10 | end 11 | 12 | alias :f :array_pair_sum 13 | 14 | puts f(10, [3, 4, 5, 6, 7]).to_s # => [[3, 7], [4, 6]] 15 | puts f(8, [3, 4, 5, 4, 4]).to_s # => [[3, 5], [4, 4]] -------------------------------------------------------------------------------- /solutions/coffeescript/integer-difference.coffee: -------------------------------------------------------------------------------- 1 | integerDifference = (n, array) -> 2 | hash = {} 3 | total = 0 4 | 5 | # Loop through the array once, storing the results in an object for a 6 | # time complexity of O(n) - the naive solution consists of two for loops 7 | # which results in a complexity of O(n^2) 8 | array.forEach (number) -> 9 | hash[number] = (hash[number] or 0) + 1 10 | total += (hash[number - n] or 0) + (hash[number + n] or 0) 11 | total 12 | -------------------------------------------------------------------------------- /solutions/javascript/multiples-of-3-and-5.js: -------------------------------------------------------------------------------- 1 | // Accepts a number and an array of multiples 2 | module.exports = function sumOfMultiples (number, multiples) { 3 | return Array.apply(null, new Array(number)).map(function (_, index) { 4 | return index; 5 | }).filter(function (number) { 6 | return multiples.some(function (multiple) { 7 | return number % multiple === 0; 8 | }); 9 | }).reduce(function (memo, number) { 10 | return memo + number; 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /solutions/javascript/sum-of-array-plus-one.js: -------------------------------------------------------------------------------- 1 | // ES5 method is nice and clean 2 | exports.es5 = function (array) { 3 | return array.reduce(function (memo, num) { 4 | return memo + num; 5 | }, array.length); 6 | }; 7 | 8 | // Without array.reduce method isn't much different 9 | exports.iterative = function (array) { 10 | var result = array.length; 11 | 12 | for (var i = 0; i < array.length; i++) { 13 | result += array[i]; 14 | } 15 | 16 | return result; 17 | }; 18 | -------------------------------------------------------------------------------- /problems/find-missing-element/Readme.md: -------------------------------------------------------------------------------- 1 | # Find Missing Element 2 | 3 | There is an array of non-negative integers. A second array is formed by shuffling the elements of the first array and deleting a random element. Given these two arrays, find which element is missing in the second array. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/09/27/programming-interview-questions-4-find-missing-element/](http://www.ardendertat.com/2011/09/27/programming-interview-questions-4-find-missing-element/) 8 | -------------------------------------------------------------------------------- /problems/remove-duplicates-from-string/Readme.md: -------------------------------------------------------------------------------- 1 | # Remove Duplicate Characters in String 2 | 3 | Remove duplicate characters in a given string keeping only the first occurrences. For example, if the input is ‘tree traversal’ the output will be "tre avsl". 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2012/01/06/programming-interview-questions-25-remove-duplicate-characters-in-string/](http://www.ardendertat.com/2012/01/06/programming-interview-questions-25-remove-duplicate-characters-in-string/) 8 | -------------------------------------------------------------------------------- /solutions/go/longest-words.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func longest(sentence string) string { 9 | longest := "" 10 | words := make([]string, 0) 11 | words = strings.Split(sentence, " ") 12 | 13 | for _, word := range words { 14 | if len(longest) < len(word) { 15 | longest = word 16 | } 17 | } 18 | 19 | return longest; 20 | } 21 | 22 | func main() { 23 | fmt.Println(longest("You are just an old antidisestablishmentarian")) 24 | } -------------------------------------------------------------------------------- /problems/next-highest-number/Readme.md: -------------------------------------------------------------------------------- 1 | # Find Next Higher Number With Same Digits 2 | 3 | Given a number, find the next higher number using only the digits in the given number. For example if the given number is 1234, next higher number with same digits is 1243. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2012/01/02/programming-interview-questions-24-find-next-higher-number-with-same-digits/](http://www.ardendertat.com/2012/01/02/programming-interview-questions-24-find-next-higher-number-with-same-digits/) 8 | -------------------------------------------------------------------------------- /solutions/javascript/money-format.js: -------------------------------------------------------------------------------- 1 | module.exports = function (value) { 2 | var remaining = value - ~~value, 3 | string = '' + ~~value, 4 | length = string.length, 5 | places = 0; 6 | 7 | while (--length) { 8 | places += 1; 9 | // At every third position we want to insert a comma 10 | if (places % 3 === 0) { 11 | string = string.substr(0, length) + ',' + string.substr(length); 12 | } 13 | } 14 | 15 | return '$' + string + remaining.toFixed(2).slice(1); 16 | }; 17 | -------------------------------------------------------------------------------- /solutions/coffeescript/byte-format.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (bytes, precision) -> 2 | suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] 3 | factor = Math.pow(10, (if precision > 0 then precision else 2)) 4 | 5 | # Using a for loop since it's perfect for this kind of problem 6 | i = bytes 7 | k = 0 8 | 9 | while i >= 1024 and k < suffixes.length 10 | i /= 1024 11 | k++ 12 | 13 | # Return the number rounded to precision 14 | (Math.round(i * factor) / factor) + " " + suffixes[k] 15 | -------------------------------------------------------------------------------- /problems/longest-words/Readme.md: -------------------------------------------------------------------------------- 1 | # Longest Words 2 | 3 | Write a function that returns the longest word(s) from a sentence. The function should not return any duplicate words (case-insensitive). 4 | 5 | ## Example 6 | 7 | ```js 8 | longestWords("You are just an old antidisestablishmentarian") // ["antidisestablishmentarian"] 9 | longestWords("I gave a present to my parents") // ["present", "parents"] 10 | longestWords("Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo") // ["buffalo"] or ["Buffalo"] 11 | ``` 12 | -------------------------------------------------------------------------------- /problems/throttle/Readme.md: -------------------------------------------------------------------------------- 1 | # Throttle 2 | 3 | Write a function that accepts a function and timeout, `x`, in number of milliseconds. It returns a function that can only be executed once per `x` milliseconds. This can be useful for limiting the number of time and computation heavy function that are run. For example, making AJAX requests to an autocompletion API. 4 | 5 | Once written, add a third parameter that will allow the function to be executed immediately if set to true. Otherwise the function will run at the end of the timeout period. 6 | -------------------------------------------------------------------------------- /solutions/javascript/even-occuring-element.js: -------------------------------------------------------------------------------- 1 | module.exports = function (array) { 2 | var hash = {}; 3 | 4 | // Loop though the array adding all the elements together in a hash 5 | array.forEach(function (num) { 6 | hash[num] = hash[num] + 1 || 1; 7 | }); 8 | 9 | // Loop through all the keys in the hash, returning the number if we have an 10 | // even number of occurances 11 | for (var i in hash) { 12 | if (!(hash[i] & 1)) { 13 | return Number(i); 14 | } 15 | } 16 | 17 | return false; 18 | }; 19 | -------------------------------------------------------------------------------- /solutions/javascript/integer-difference.js: -------------------------------------------------------------------------------- 1 | module.exports = function (n, array) { 2 | var hash = {}, 3 | total = 0; 4 | 5 | // Loop through the array once, storing the results in an object for a 6 | // time complexity of O(n) - the naive solution consists of two for loops 7 | // which results in a complexity of O(n^2) 8 | array.forEach(function (number) { 9 | hash[number] = (hash[number] || 0) + 1; 10 | total += (hash[number - n] || 0) + (hash[number + n] || 0); 11 | }); 12 | 13 | return total; 14 | }; 15 | -------------------------------------------------------------------------------- /solutions/coffeescript/factorial.coffee: -------------------------------------------------------------------------------- 1 | # Recursive function example 2 | exports.recursive = factorial = (number) -> 3 | return 1 if number < 2 4 | number * factorial(number - 1) 5 | 6 | # Iterative solution 7 | exports.iterative = (number) -> 8 | result = 1 9 | i = 1 10 | 11 | while i <= number 12 | result *= i 13 | i++ 14 | result 15 | 16 | # Iterative using a reverse loop 17 | exports.iterativeReverse = (number) -> 18 | result = 1 19 | while number 20 | result *= number 21 | number -= 1 22 | result 23 | -------------------------------------------------------------------------------- /solutions/ruby/merge_sort.rb: -------------------------------------------------------------------------------- 1 | def merge_sort(a) 2 | return a if a.size <= 1 3 | l, r = split_array(a) 4 | combine(merge_sort(l), merge_sort(r)) 5 | end 6 | 7 | def split_array(a) 8 | mid = (a.size / 2).round 9 | [a.take(mid), a.drop(mid)] 10 | end 11 | 12 | def combine(a, b) 13 | return b.empty? ? a : b if a.empty? || b.empty? 14 | smallest = a.first <= b.first ? a.shift : b.shift 15 | combine(a, b).unshift(smallest) 16 | end 17 | 18 | # a = [6, 23, 53, 1, 2, 5, 62, 61, 33, 21, 14, 6, 23].shuffle 19 | # p merge_sort(a) 20 | -------------------------------------------------------------------------------- /solutions/coffeescript/balanced-brackets.coffee: -------------------------------------------------------------------------------- 1 | # Use an object to map sets of brackets to their opposites 2 | brackets = 3 | "(": ")" 4 | "{": "}" 5 | "[": "]" 6 | 7 | # On each input string, process it using the balance checker 8 | balancedBrackets = (string) -> 9 | stack = [] 10 | 11 | # Process every character on input 12 | i = 0 13 | 14 | while i < string.length 15 | if brackets[stack[stack.length - 1]] is string[i] 16 | stack.pop() 17 | else 18 | stack.push string[i] 19 | i++ 20 | not stack.length 21 | -------------------------------------------------------------------------------- /problems/kth-largest-element-in-array/Readme.md: -------------------------------------------------------------------------------- 1 | # Kth Largest Element in Array 2 | 3 | Given an array of integers find the kth element in the sorted order (not the kth distinct element). So, if the array is `[3, 1, 2, 1, 4]` and k is 3 then the result is 2, because it’s the 3rd element in sorted order (but the 3rd distinct element is 3). 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/10/27/programming-interview-questions-10-kth-largest-element-in-array/](http://www.ardendertat.com/2011/10/27/programming-interview-questions-10-kth-largest-element-in-array/) 8 | -------------------------------------------------------------------------------- /solutions/javascript/missing-number.js: -------------------------------------------------------------------------------- 1 | var add = function (a, b) { 2 | return a + b; 3 | }; 4 | 5 | module.exports = function (array) { 6 | // http://en.wikipedia.org/wiki/Arithmetic_progression#Sum 7 | // Add one to the array length since we are missing a single number, use 1 8 | // as the starting value and the length of the array + 1 as the ending value. 9 | // Then just minus the result of adding all the values together to get our 10 | // missing number. 11 | return ((array.length + 1) * (2 + array.length) / 2) - array.reduce(add, 0); 12 | }; 13 | -------------------------------------------------------------------------------- /solutions/ruby/anagram_detection.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | # return true if string a and string b are anagrams 4 | def anagram?(a, b) 5 | char_count = proc { |hsh, c| 6 | hsh[c] ||= 0 7 | hsh[c] += 1 8 | hsh 9 | } 10 | if a.each_char.reduce({}, &char_count) == b.each_char.reduce({}, &char_count) 11 | true 12 | else 13 | false 14 | end 15 | end 16 | 17 | 18 | def anagram_detection(parent, child) 19 | x = parent.length - child.length 20 | (0...x).reduce(0) { |c, i| anagram?(parent[i, child.length], child) ? c + 1 : c } 21 | end 22 | 23 | -------------------------------------------------------------------------------- /solutions/javascript/balanced-brackets.js: -------------------------------------------------------------------------------- 1 | // Use an object to map sets of brackets to their opposites 2 | var brackets = { 3 | '(': ')', 4 | '{': '}', 5 | '[': ']' 6 | }; 7 | 8 | // On each input string, process it using the balance checker 9 | module.exports = function (string) { 10 | var stack = []; 11 | // Process every character on input 12 | for (var i = 0; i < string.length; i++) { 13 | if (brackets[stack[stack.length - 1]] === string[i]) { 14 | stack.pop(); 15 | } else { 16 | stack.push(string[i]); 17 | } 18 | } 19 | 20 | return !stack.length; 21 | }; 22 | -------------------------------------------------------------------------------- /solutions/ruby/flatten_array.rb: -------------------------------------------------------------------------------- 1 | # Note that there is already an implementation in the core ruby library 2 | # http://ruby-doc.org/core-2.2.0/Array.html#method-i-flatten 3 | 4 | def flatten_array(arr = []) 5 | return arr unless arr.is_a? Array 6 | 7 | result = [] 8 | arr.each do |elem| 9 | if elem.is_a? Array 10 | result += flatten_array(elem) 11 | else 12 | result << elem 13 | end 14 | end 15 | 16 | result 17 | end 18 | 19 | flatten_array([]) # => [] 20 | flatten_array([[["a"]]]) # => ["a"] 21 | flatten_array([0, ["damn"], [[["a", "b"]]], 0]) # => [0, "damn", "a", "b", 0] 22 | -------------------------------------------------------------------------------- /problems/debounce/Readme.md: -------------------------------------------------------------------------------- 1 | # Debounce 2 | 3 | Write a function that accepts a function and timeout, `x`, in number of milliseconds. It will return a new function that can only be executed on per timeout period - and if the function is invoked during the timeout period, the timeout period restarts. This is useful for functions that can be need to be blocked on subsequent attempts over short period of times. Once such is example, is clicks on a button. 4 | 5 | Once written, add a third parameter that will allow the function to be executed immediately if set to true. Otherwise the function will run at the end of the timeout period. 6 | -------------------------------------------------------------------------------- /solutions/javascript/convert-array.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function getSwapIndex(currentInd, n) { 4 | var swapInd = (currentInd % 3) * n + parseInt(currentInd/3); 5 | while (swapInd < currentInd) { 6 | swapInd = getSwapIndex(swapInd, n); 7 | } 8 | 9 | return swapInd; 10 | } 11 | 12 | function convert(arr) { 13 | var n = parseInt(arr.length / 3); 14 | 15 | for(var i = 0; i < arr.length; i++) { 16 | var swapInd = getSwapIndex(i, n); 17 | 18 | var tmp = arr[i]; 19 | arr[i] = arr[swapInd]; 20 | arr[swapInd] = tmp; 21 | } 22 | 23 | return arr; 24 | } 25 | 26 | module.exports = convert; 27 | -------------------------------------------------------------------------------- /solutions/java/FindingMissingElement.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class FindingMissingElement { 3 | 4 | /** 5 | *The difference in the sum of the two arrays will give us the desired value 6 | */ 7 | static int find_missing(int a[],int b[]) 8 | { 9 | int sum=0; 10 | for(int i:a) 11 | sum+=i; 12 | for(int i:b) 13 | sum-=i; 14 | return sum; 15 | } 16 | public static void main(String[] args) { 17 | int[] arr={1,3,5,6,2,5,6,8,9,23,45,67,87}; 18 | int[] shuffled_ar={1,2,5,6,8,9,3,45,87,6,67,5}; 19 | System.out.println("The missing value is:"+find_missing(arr,shuffled_ar)); 20 | 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /solutions/java/StringRotation.java: -------------------------------------------------------------------------------- 1 | public class StringRotation { 2 | 3 | public static void main(String[] args) { 4 | // TODO Auto-generated method stub 5 | StringRotation sr = new StringRotation(); 6 | System.out.println(sr.isRotation("ABCD", "BCDA")); 7 | } 8 | 9 | public boolean isRotation(String one, String two) { 10 | /** 11 | * This code checks if one is a rotation of two The way it works is - 12 | * concatenate the original string with itself, and check if the rotated 13 | * string is contained in it. For example : ABCD is contained in BCDABCDA 14 | */ 15 | return (two + two).contains(one); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /problems/shortest-fizz-buzz/Readme.md: -------------------------------------------------------------------------------- 1 | # Shortest Fizz Buzz 2 | 3 | Write a program that prints (to STDOUT) the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”. 4 | 5 | The goal is to write the shortest code possible. 6 | 7 | Expected output: [http://cdn.hackerrank.com/fizzbuzz.txt](http://cdn.hackerrank.com/fizzbuzz.txt) 8 | 9 | Your output should exactly match the above. 10 | 11 | ## Source 12 | 13 | [https://www.hackerrank.com/challenges/fizzbuzz](https://www.hackerrank.com/challenges/fizzbuzz) 14 | -------------------------------------------------------------------------------- /solutions/javascript/factorial.js: -------------------------------------------------------------------------------- 1 | // Recursive function example 2 | exports.recursive = function factorial (number) { 3 | if (number < 2) { return 1; } 4 | 5 | return number * factorial(number - 1); 6 | }; 7 | 8 | // Iterative solution 9 | exports.iterative = function (number) { 10 | var result = 1; 11 | 12 | for (var i = 1; i <= number; i++) { 13 | result *= i; 14 | } 15 | 16 | return result; 17 | }; 18 | 19 | // Iterative using a reverse loop 20 | exports.iterativeReverse = function (number) { 21 | var result = 1; 22 | 23 | while (number) { 24 | result *= number; 25 | number -= 1; 26 | } 27 | 28 | return result; 29 | }; 30 | -------------------------------------------------------------------------------- /solutions/coffeescript/debounce.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (fn, delay, execAsap) -> 2 | timeout = undefined # Keep a reference to the timeout outside the function 3 | -> 4 | 5 | # Keep the functions execution context and arguments in tact 6 | that = this 7 | args = arguments_ 8 | 9 | # If we already have a function ready to execute, clear it 10 | # Else if we are allowed to execute immediately, call the function 11 | if timeout 12 | clearTimeout timeout 13 | else fn.apply that, args if execAsap 14 | timeout = setTimeout(-> 15 | execAsap or fn.apply(that, args) 16 | timeout = null 17 | , delay or 100) 18 | -------------------------------------------------------------------------------- /solutions/javascript/array-pair-sum.js: -------------------------------------------------------------------------------- 1 | module.exports = function arraypairsum (k, array) { 2 | var hash = {}; 3 | var pairs = []; 4 | 5 | // Iterate over the array, tracking the times each number appears. For each 6 | // new number, we calculate the difference to `k` and look up the number of 7 | // times that number has been seen and push those occurances in pairs output. 8 | array.forEach(function (number) { 9 | var diff = k - number; 10 | var len = hash[diff]; 11 | 12 | while (len--) { 13 | pairs.push([diff, number]); 14 | } 15 | 16 | hash[number] = (hash[number] + 1) || 1; 17 | }); 18 | 19 | return pairs; 20 | }; 21 | -------------------------------------------------------------------------------- /tests/javascript/search-unknown-length-array.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var searchArray = require( 3 | '../../solutions/javascript/search-unknown-length-array' 4 | ); 5 | 6 | describe('Search Unknown Length Array', function () { 7 | it('should find the number', function () { 8 | expect(searchArray([3, 5, 6, 7, 8], 3)).to.equal(0); 9 | expect(searchArray([-8, -6, -5, -1, 5, 12, 99], 99)).to.equal(6); 10 | expect(searchArray([1, 4, 6, 7, 9, 12, 34, 47, 53, 65], 12)).to.equal(5); 11 | }); 12 | 13 | it('should fail to find the number', function () { 14 | expect(searchArray([1, 2, 3], 4)).to.equal(-1); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /tests/javascript/array-pair-sum.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var arrayPairSum = require('../../solutions/javascript/array-pair-sum'); 3 | 4 | describe('Array Pair Sum', function () { 5 | it('should find pairs that equal the expected sum', function () { 6 | expect(arrayPairSum(10, [3, 4, 5, 6, 7])).to.eql([[4, 6], [3, 7]]); 7 | }); 8 | 9 | it('should not output duplicate results', function () { 10 | expect(arrayPairSum(8, [3, 4, 5, 4, 4])).to.eql([[3, 5], [4, 4], [4, 4], [4, 4]]); 11 | }); 12 | 13 | it('should work not find any matches', function () { 14 | expect(arrayPairSum(10, [3, 5, 6, 8])).to.eql([]); 15 | }) 16 | }); 17 | -------------------------------------------------------------------------------- /tests/javascript/word-positions.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var wordPositions = require('../../solutions/javascript/word-positions'); 3 | 4 | describe('word positions', function () { 5 | it('should return an array of word positions', function () { 6 | assert.deepEqual(wordPositions('test')('test'), [0]); 7 | assert.deepEqual(wordPositions('test test test')('test'), [0, 4, 9]); 8 | assert.deepEqual(wordPositions('find a word in some sentence')('in'), [11]); 9 | }); 10 | 11 | it('should return an empty array when not found', function () { 12 | assert.deepEqual(wordPositions('it does not exist')('test'), []); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /problems/transform-word/Readme.md: -------------------------------------------------------------------------------- 1 | # Transform Word 2 | 3 | Given a source word, target word and an English dictionary, transform the source word to target by changing/adding/removing 1 character at a time, while all intermediate words being valid English words. Return the transformation chain which has the smallest number of intermediate words. 4 | 5 | ## Example 6 | 7 | ```js 8 | transformWord(['cat', 'bat', 'bet', 'bed', 'at', 'ad', 'ed'], 'cat', 'bed'); 9 | ``` 10 | 11 | ## Source 12 | 13 | [http://www.ardendertat.com/2011/10/17/programming-interview-questions-8-transform-word/](http://www.ardendertat.com/2011/10/17/programming-interview-questions-8-transform-word/) 14 | -------------------------------------------------------------------------------- /solutions/java/ReverseWordsInAString.java: -------------------------------------------------------------------------------- 1 | public class ReverseWordsInAString { 2 | public static void main(String[] args) { 3 | String input = "Interviews are awesome!"; 4 | System.out.println("In: " + input); 5 | 6 | String output = reverseWords(input); 7 | System.out.println("Out: " + output); 8 | } 9 | 10 | private static String reverseWords(String input) { 11 | String[] split = input.split("\\s"); 12 | String output = ""; 13 | for (int i = split.length - 1; i >= 0; i--) { 14 | output += split[i]; 15 | output += " "; 16 | } 17 | return output; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /solutions/javascript/binary-search-tree-check.js: -------------------------------------------------------------------------------- 1 | //Method 4 (Using In-Order Traversal) 2 | //Reference: 3 | // http://www.geeksforgeeks.org/a-program-to-check-if-a-binary-tree-is-bst-or-not/ 4 | module.exports = function(bst) { 5 | if (!bst || bst.value == null) { 6 | return false; 7 | } 8 | 9 | var prev; 10 | 11 | return (function isBst(root) { 12 | if (!root) { 13 | return true; 14 | } 15 | 16 | if (!isBst(root.left)) { 17 | return false; 18 | } 19 | 20 | if (prev && prev.value >= root.value) { 21 | return false; 22 | } 23 | 24 | prev = root; 25 | 26 | return isBst(root.right); 27 | 28 | })(bst); 29 | }; -------------------------------------------------------------------------------- /solutions/ruby/factorial.rb: -------------------------------------------------------------------------------- 1 | class Integer 2 | # Iterative 3 | def factorial_simple(number) 4 | fat = 1 5 | (2..number).each { |n| fat = fat * n } 6 | fat 7 | end 8 | 9 | # Iterative Reverse Loop 10 | def factorial_reverse(number) 11 | (number - 1).downto(1).each { |i| n *= i } 12 | n 13 | end 14 | 15 | # Recursive - Ternary Operator 16 | def factorial_recursive(number) 17 | (number == 1) ? 1 : (number * factorial_recursive(number-1)) 18 | end 19 | 20 | # The Ruby-iest version, using reduce function 21 | def factorial_reduce(number) 22 | (1..number).reduce(:*) 23 | end 24 | 25 | alias_method :factorial, factorial_reduce 26 | end 27 | -------------------------------------------------------------------------------- /solutions/javascript/number-format.js: -------------------------------------------------------------------------------- 1 | exports.iterative = function (number) { 2 | var string = ('' + number).split('.'), 3 | length = string[0].length, 4 | places = 0; 5 | 6 | while (--length) { 7 | places += 1; 8 | // At every third position we want to insert a comma 9 | if (places % 3 === 0) { 10 | string[0] = string[0].substr(0, length) + ',' + string[0].substr(length); 11 | } 12 | } 13 | 14 | return string.join('.'); 15 | }; 16 | 17 | exports.regexp = function (number) { 18 | var string = ('' + number).split('.'); 19 | 20 | string[0] = string[0].replace(/(\d)(?=(?:\d{3})+(?:\.|$))/g, '$1,'); 21 | 22 | return string.join('.'); 23 | }; 24 | -------------------------------------------------------------------------------- /solutions/java/LargestContinuousSum.java: -------------------------------------------------------------------------------- 1 | public class LargestContinuousSum { 2 | public static void main(String[] args) { 3 | LargestContinuousSum lcd = new LargestContinuousSum(); 4 | int[] input = { 1, -1, 2, -5, 10, 15, -10, 5 }; 5 | System.out.print(lcd.getSum(input)); 6 | } 7 | 8 | public int getSum(int[] input) { 9 | int currentMax = input[0]; 10 | int finalMax = input[0]; 11 | for (int i = 1; i < input.length; i++) { 12 | if (currentMax + input[i] > input[i]) 13 | currentMax = currentMax + input[i]; 14 | else 15 | currentMax = input[i]; 16 | 17 | if (currentMax > finalMax) 18 | finalMax = currentMax; 19 | 20 | } 21 | return finalMax; 22 | } 23 | } -------------------------------------------------------------------------------- /tests/javascript/prime-number.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var primeNumber = require('../../solutions/javascript/prime-number'); 3 | 4 | describe('prime number', function () { 5 | it('should return true if the number is a prime number', function () { 6 | assert.equal(primeNumber(2), true); 7 | assert.equal(primeNumber(859), true); 8 | assert.equal(primeNumber(983), true); 9 | assert.equal(primeNumber(283), true); 10 | }); 11 | 12 | it('should return false if the number is not prime', function () { 13 | assert.equal(primeNumber(324), false); 14 | assert.equal(primeNumber(-124), false); 15 | assert.equal(primeNumber(89325), false); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /solutions/javascript/largest-palindrome.js: -------------------------------------------------------------------------------- 1 | function isPalindrome (str) { 2 | const mid = Math.floor(str.length / 2) 3 | 4 | for (let i = 0; i < mid; i++) { 5 | if (str[i] !== str[str.length - 1 - i]) { 6 | return false 7 | } 8 | } 9 | 10 | return true 11 | } 12 | 13 | module.exports = function longestPalindrome (str) { 14 | let longest = '' 15 | 16 | for (let i = 0; i < str.length; i++) { 17 | let len = str.length 18 | 19 | while (len > i && len - i > longest.length) { 20 | const substring = str.substring(i, len--) 21 | 22 | if (isPalindrome(substring)) { 23 | longest = substring 24 | } 25 | } 26 | } 27 | 28 | return longest 29 | } 30 | -------------------------------------------------------------------------------- /solutions/coffeescript/bubble-sort.coffee: -------------------------------------------------------------------------------- 1 | bubbleSort = (array, compare) -> 2 | # Not an array, empty or array of 1 is already sorted 3 | return array if not Array.isArray(array) or array.length < 2 4 | swap = (array, first, second) -> 5 | temp = array[first] 6 | array[first] = array[second] 7 | array[second] = temp 8 | array 9 | 10 | # Create a compare func if not passed in 11 | if typeof compare isnt "function" 12 | compare = (a, b) -> 13 | (if a > b then 1 else -1) 14 | i = undefined 15 | l = undefined 16 | i = 0 17 | while i < array.length 18 | l = i 19 | swap array, l, l + 1 while l-- and compare(array[l], array[l + 1]) > 0 20 | i++ 21 | array 22 | -------------------------------------------------------------------------------- /tests/javascript/largest-continuous-sum.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var solution = require('../../solutions/javascript/largest-continuous-sum'); 3 | 4 | describe('largest continuous sum', function () { 5 | it('should be able to get the largest sum', function () { 6 | assert.equal(solution([1, 2, 3]), 6); 7 | assert.equal(solution([2, 4, -1, 4, 5]), 14); 8 | assert.equal(solution([10, -5, 15, -20, 5]), 20); 9 | }); 10 | 11 | it('should work with negative numbers', function () { 12 | assert.equal(solution([-1, -2, -3]), -1); 13 | }); 14 | 15 | it('should return nothing when given nothing', function () { 16 | assert.equal(solution(), undefined); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /solutions/java/LongestCommonPrefix.java: -------------------------------------------------------------------------------- 1 | public class LongestCommonPrefix { 2 | public static void main(String[] args) { 3 | LongestCommonPrefix lcs = new LongestCommonPrefix(); 4 | String[] input = { "rocket", "rockstar", "rockbottom", "rollingstone"}; 5 | System.out.println(lcs.getSubstring(input)); 6 | } 7 | 8 | public String getSubstring(String[] input) { 9 | String base = input[0]; 10 | for (int i = 0; i < base.length(); i++) { 11 | for (int j = 1; j < input.length; j++) { // Run for all words 12 | String comparer = input[j]; 13 | if (i >= comparer.length() 14 | || comparer.charAt(i) != base.charAt(i)) 15 | return base.substring(0, i); 16 | } 17 | } 18 | return ""; 19 | } 20 | } -------------------------------------------------------------------------------- /solutions/coffeescript/first-non-repeated-character.coffee: -------------------------------------------------------------------------------- 1 | firstNonRepeatedCharacter = (string) -> 2 | checkChar = undefined 3 | prevCharacter = undefined 4 | checkChar = (-> 5 | repeated = false 6 | (char) -> 7 | repeated = true if prevCharacter and char is prevCharacter 8 | if prevCharacter and char isnt prevCharacter 9 | return true unless repeated 10 | repeated = false 11 | prevCharacter = char 12 | 13 | # Return false to say it's not been repeated 14 | false 15 | )() 16 | 17 | # Interate one extra time past the last character 18 | i = 0 19 | 20 | while i <= string.length 21 | return prevCharacter if checkChar(string[i]) 22 | i++ 23 | -------------------------------------------------------------------------------- /solutions/php/factorial.php: -------------------------------------------------------------------------------- 1 | 36 | -------------------------------------------------------------------------------- /tests/javascript/convert-array.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var convert = require('../../solutions/javascript/convert-array'); 3 | 4 | describe('Convert Array', function() { 5 | it('should convert an array', function() { 6 | var arr = [ 7 | 'a1', 'a2', 'a3', 'a4', 'a5', 8 | 'b1', 'b2', 'b3', 'b4', 'b5', 9 | 'c1', 'c2', 'c3', 'c4', 'c5' 10 | ]; 11 | 12 | var expectedArr = [ 13 | 'a1', 'b1', 'c1', 14 | 'a2', 'b2', 'c2', 15 | 'a3', 'b3', 'c3', 16 | 'a4', 'b4', 'c4', 17 | 'a5', 'b5', 'c5' 18 | ]; 19 | 20 | convert(arr); 21 | 22 | for(var i = 0; i < arr.length; i++) { 23 | assert.equal(arr[i], expectedArr[i]); 24 | } 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /problems/reverse-words-in-string/Readme.md: -------------------------------------------------------------------------------- 1 | # Reverse Words in a String 2 | 3 | Given an input string, reverse all the words. To clarify, input: "Interviews are awesome!" output: "awesome! are Interviews". Consider all consecutive non-whitespace characters as individual words. If there are multiple spaces between words reduce them to a single white space. Also remove all leading and trailing whitespaces. So, the output for " CS degree", "CS degree", "CS degree ", or " CS degree " are all the same: "degree CS". 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/10/31/programming-interview-questions-12-reverse-words-in-a-string/](http://www.ardendertat.com/2011/10/31/programming-interview-questions-12-reverse-words-in-a-string/) 8 | -------------------------------------------------------------------------------- /solutions/javascript/throttle.js: -------------------------------------------------------------------------------- 1 | module.exports = function (fn, delay, execAsap) { 2 | var timeout; // Keeps a reference to the timeout inside the returned function 3 | 4 | return function () { 5 | // Continue to pass through the function execution context and arguments 6 | var that = this, 7 | args = arguments; 8 | 9 | // If there is no timeout variable set, proceed to create a new timeout 10 | if (!timeout) { 11 | execAsap && fn.apply(that, args); 12 | 13 | timeout = setTimeout(function () { 14 | execAsap || fn.apply(that, args); 15 | // Remove the old timeout variable so the function can run again 16 | timeout = null; 17 | }, delay || 100); 18 | } 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /solutions/coffeescript/combine-two-strings.coffee: -------------------------------------------------------------------------------- 1 | combineTwoStrings = (str1, str2, combined) -> 2 | # Generate all the posible paths between `str1` and `str2` 3 | paths = {} 4 | 5 | # Check the string lengths are the same to begin 6 | return false if (str1 + str2).length isnt combined.length 7 | 8 | # Finding paths is essentially the anagrams solution 9 | (findPath = (str1, str2, path) -> 10 | return paths[path] = true if path.length is combined.length 11 | 12 | # Find the next path from the first character of either strings 13 | str1 and findPath(str1.substr(1), str2, path + str1.substr(0, 1)) 14 | str2 and findPath(str1, str2.substr(1), path + str2.substr(0, 1)) 15 | ) str1, str2, "" 16 | combined of paths 17 | -------------------------------------------------------------------------------- /solutions/coffeescript/largest-palindrome.coffee: -------------------------------------------------------------------------------- 1 | largestPalindrome = (str) -> 2 | palindromes = [] 3 | walkPalindrome = (result, str, leftIndex, rightIndex) -> 4 | result = str[leftIndex -= 1] + result + str[rightIndex += 1] while str[leftIndex - 1] is str[rightIndex + 1] 5 | palindromes.push result 6 | i = 0 7 | 8 | while i < str.length 9 | if str[i] is str[i - 1] 10 | walkPalindrome str[i] + str[i - 1], str, i - 1, i 11 | else if str[i] is str[i + 1] 12 | walkPalindrome str[i] + str[i + 1], str, i, i + 1 13 | else walkPalindrome str[i - 1] + str[i] + str[i + 1], str, i - 1, i + 1 if str[i - 1] is str[i + 1] 14 | i++ 15 | palindromes.reduce ((memo, str) -> (if str.length > memo.length then str else memo)), "" 16 | -------------------------------------------------------------------------------- /solutions/javascript/debounce.js: -------------------------------------------------------------------------------- 1 | module.exports = function (fn, delay, execAsap) { 2 | var timeout; // Keep a reference to the timeout outside the function 3 | 4 | return function () { 5 | // Keep the functions execution context and arguments in tact 6 | var that = this, 7 | args = arguments; 8 | 9 | // If we already have a function ready to execute, clear it 10 | // Else if we are allowed to execute immediately, call the function 11 | if (timeout) { 12 | clearTimeout(timeout); 13 | } else if (execAsap) { 14 | fn.apply(that, args); 15 | } 16 | 17 | timeout = setTimeout(function () { 18 | execAsap || fn.apply(that, args); 19 | timeout = null; 20 | }, delay || 100); 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /problems/combine-two-strings/Readme.md: -------------------------------------------------------------------------------- 1 | # Combine Two Strings 2 | 3 | We are given 3 strings: str1, str2, and str3. Str3 is said to be a shuffle of str1 and str2 if it can be formed by interleaving the characters of str1 and str2 in a way that maintains the left to right ordering of the characters from each string. For example, given str1="abc" and str2="def", str3="dabecf" is a valid shuffle since it preserves the character ordering of the two strings. So, given these 3 strings write a function that detects whether str3 is a valid shuffle of str1 and str2. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/10/10/programming-interview-questions-6-combine-two-strings/](http://www.ardendertat.com/2011/10/10/programming-interview-questions-6-combine-two-strings/) 8 | -------------------------------------------------------------------------------- /solutions/javascript/once.js: -------------------------------------------------------------------------------- 1 | module.exports = function (fn, times) { 2 | // Set times to one if nothing is passed through and keep track of the 3 | // latest return value to return when we run out of execution times. 4 | var memo; 5 | times = times || 1; 6 | 7 | // Return the function that will be executed. 8 | return function () { 9 | if (!times) { return memo; } 10 | 11 | // Set memo to the result of the function and decrement the number of 12 | // executions. 13 | memo = fn.apply(this, arguments); 14 | times -= 1; 15 | 16 | // If there are no more execution times, set the function to `null` so 17 | // it can be garbage collected and return the memo. 18 | times || (fn = null); 19 | return memo; 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /problems/csv-parsing/Readme.md: -------------------------------------------------------------------------------- 1 | # CSV Parsing 2 | 3 | Write a function that accepts a string as it's only argument. The string consists of comma-separated values and all values are either an integer or a string. Return an array of the parsed input string. 4 | 5 | ```js 6 | f('2,6,3,2,5') // [ 2, 6, 3, 2, 5 ] 7 | 8 | f('"pears","apples","walnuts","grapes","cheese,cake"') // [ "pears", "apples", "walnuts", "grapes", "cheese,cake" ] 9 | 10 | f('1,"Que?","Kay?",2,"Si.","Sea? Kay, sea?","No, no, no. Que... ‘what’.",234,"Kay Watt?","Si, que ‘what’.","C.K. Watt?",3,"Yes!","comma,comma, comma , :)"') // [ 1, "Que?", "Kay?", 2, "Si.", "Sea? Kay, sea?", "No, no, no. Que... ‘what’." 234, "Kay Watt?", "Si, que ‘what’.", "C.K. Watt?", 3, "Yes!", "comma,comma, comma , :)" ] 11 | ``` 12 | -------------------------------------------------------------------------------- /solutions/coffeescript/array-pair-sum.coffee: -------------------------------------------------------------------------------- 1 | # This is just a modification of the integer difference problem presented elsewhere 2 | arrayPairSum = (k, array) -> 3 | hash = {} 4 | pairs = [] 5 | 6 | # Loop through the array once, storing the results in an object for a 7 | # time complexity of O(n) - the naive solution consists of two for loops 8 | # which results in a complexity of O(n^2) 9 | array.forEach (number) -> 10 | # Make sure the value in unused and it's a unique pair 11 | if hash[k - number] is false and k - number isnt number 12 | pairs.push [number, k - number] 13 | hash[k - number] = true # Set it to "used" 14 | # If the hash value is not true, set the hash to "unused" 15 | not hash[k - number] and (hash[number] = false) 16 | pairs 17 | -------------------------------------------------------------------------------- /problems/median-integer-stream/Readme.md: -------------------------------------------------------------------------------- 1 | # Median of Integer Stream 2 | 3 | Given a stream of unsorted integers, find the median element in sorted order at any given time. So, we will be receiving a continuous stream of numbers in some random order and we don’t know the stream length in advance. Write a function that finds the median of the already received numbers efficiently at any time. We will be asked to find the median multiple times. Just to recall, median is the middle element in an odd length sorted array, and in the even case it’s the average of the middle elements. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2011/11/03/programming-interview-questions-13-median-of-integer-stream/](http://www.ardendertat.com/2011/11/03/programming-interview-questions-13-median-of-integer-stream/) 8 | -------------------------------------------------------------------------------- /solutions/javascript/first-non-repeated-character.js: -------------------------------------------------------------------------------- 1 | module.exports = function (string) { 2 | var checkChar, 3 | prevCharacter; 4 | 5 | checkChar = (function () { 6 | var repeated = false; 7 | 8 | return function (char) { 9 | if (prevCharacter && char === prevCharacter) { 10 | repeated = true; 11 | } 12 | if (prevCharacter && char !== prevCharacter) { 13 | if (!repeated) { return true; } 14 | repeated = false; 15 | } 16 | prevCharacter = char; 17 | // Return false to say it's not been repeated 18 | return false; 19 | }; 20 | })(); 21 | 22 | // Interate one extra time past the last character 23 | for (var i = 0; i <= string.length; i++) { 24 | if (checkChar(string[i])) { return prevCharacter; } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /problems/queen-threatens-king/readme.md: -------------------------------------------------------------------------------- 1 | # The Queen threatens the King 2 | 3 | ![Chessboard](queen-threatens-king.png) 4 | 5 | Given an imaginary chess board of size _m_ x _n_ including only the Queen and the King write a function that takes the positions (coordinates) of both the Queen and the King as parameters and returns a boolean telling whether or not the King is threatened by the Queen: 6 | 7 | ```js 8 | function threatens(qX, qY, kX, kY) { 9 | // ... 10 | } 11 | ``` 12 | 13 | Extra: how would you modify your solution if the rest of the chessmen were included in the board? 14 | 15 | If you are not familiar with the rules of chess, please refer to the [related Wikipedia page](http://en.wikipedia.org/wiki/Queen_(chess)) to learn how the Queen can move around the chess board and threaten other chessmen. 16 | -------------------------------------------------------------------------------- /problems/spiral/Readme.md: -------------------------------------------------------------------------------- 1 | # Spiral 2 | 3 | Write a function that accepts four arguments. The first two arguments are the size of the grid (*h x w*), filled with ascending integers from left to right, top to bottom, starting from 1. The next two arguments are the starting positions, the row (*r*) and column (*c*). 4 | 5 | Return an array of integers obtained by spiralling outward anti-clockwise from the *r* and *c*, starting upward. 6 | 7 | ``` 8 | f(5, 5, 3, 3) // [ 13, 8, 7, 12, 17, 18, 19, 14, 9, 4, 3, 2, 1, 6, 11, 16, 21, 22, 23, 24, 25, 20, 15, 10, 5 ] 9 | 10 | f(2, 4, 1, 2) // [ 2, 1, 5, 6, 7, 3, 8, 4 ] 11 | ``` 12 | 13 | **Supporting Content** 14 | 15 | The following graphics show the grid in question and the spiral generated, beginning at cell (3, 3). 16 | 17 | ![Grid 1](input-1.png) 18 | 19 | ![Grid 2](input-2.png) 20 | -------------------------------------------------------------------------------- /solutions/javascript/stack.js: -------------------------------------------------------------------------------- 1 | var Stack = module.exports = function () { 2 | this.head = null; 3 | this.length = 0; 4 | }; 5 | 6 | Stack.prototype.push = function (value) { 7 | var node = { 8 | value: value, 9 | next: null 10 | }; 11 | 12 | if (!this.head) { 13 | this.head = node; 14 | } else { 15 | node.next = this.head; 16 | this.head = node; 17 | } 18 | 19 | return this.length += 1; 20 | }; 21 | 22 | Stack.prototype.pop = function () { 23 | // If there is no head node, return `undefined` 24 | if (!this.head) { return; } 25 | 26 | var node = this.head; 27 | 28 | // Update the head reference and remove the next node reference from the 29 | // previous head. 30 | this.head = node.next; 31 | node.next = null; 32 | 33 | this.length -= 1; 34 | 35 | return node.value; 36 | }; 37 | -------------------------------------------------------------------------------- /solutions/java/Fibonacci.java: -------------------------------------------------------------------------------- 1 | // program to print the fibonacci series 2 | import java.util.Scanner; 3 | 4 | public class Fibonacci { 5 | // computes and displays the value at nth position using dynamic programming 6 | static void printSeries(int n) { 7 | long first = 0,second = 1,third = 0; 8 | 9 | for (int i = 2 ; i < n ; i++) { 10 | third = first + second; 11 | first = second; 12 | second = third; 13 | } 14 | System.out.print("The number at position " +n+" of the fibonacci series is: " +third); 15 | } 16 | 17 | public static void main (String[] a) { 18 | Scanner in = new Scanner(System.in); 19 | System.out.print("Enter the position of the element to displayed in the fibonacci series: "); 20 | int n = in.nextInt(); 21 | System.out.println(); 22 | printSeries(n); 23 | in.close(); 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /solutions/javascript/bubble-sort.js: -------------------------------------------------------------------------------- 1 | module.exports = function (array, compare) { 2 | // Not an array, empty or array of 1 is already sorted 3 | if (!Array.isArray(array) || array.length < 2) { 4 | return array; 5 | } 6 | 7 | var swap = function (array, first, second) { 8 | var temp = array[first]; 9 | array[first] = array[second]; 10 | array[second] = temp; 11 | return array; 12 | }; 13 | 14 | // Create a compare func if not passed in 15 | if (typeof compare !== 'function') { 16 | compare = function (a, b) { 17 | return a > b ? 1 : -1; 18 | }; 19 | } 20 | 21 | var i, l; 22 | 23 | for (i = 0; i < array.length; i++) { 24 | l = i; 25 | while (l-- && compare(array[l], array[l + 1]) > 0) { 26 | swap(array, l, l + 1); 27 | } 28 | } 29 | 30 | return array; 31 | }; 32 | -------------------------------------------------------------------------------- /tests/javascript/flatten-array.js: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | 3 | var fs = require('fs'); 4 | var expect = require('chai').expect; 5 | var dirname = __dirname + '/../../solutions/javascript/flatten-array'; 6 | 7 | // Load all the solutions from the test directory. 8 | var solutions = fs.readdirSync(dirname).filter(function (file) { 9 | return /\.js$/.test(file); 10 | }).map(function (file) { 11 | return [file.replace(/\.js$/, ''), require(dirname + '/' + file)]; 12 | }); 13 | 14 | describe('flatten-array', function () { 15 | solutions.forEach(function (solution) { 16 | var flatten = solution[1]; 17 | 18 | describe(solution[0], function () { 19 | it('should flatten an array', function () { 20 | expect(flatten([1, [2, [3], 2], 1])).to.deep.equal([1, 2, 3, 2, 1]); 21 | }); 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "code-problems", 3 | "version": null, 4 | "private": true, 5 | "description": "Repository full of code problems and common solutions.", 6 | "main": null, 7 | "dependencies": {}, 8 | "devDependencies": { 9 | "mocha": "~1.16.2", 10 | "jshint": "~2.4.0", 11 | "chai": "~1.8.1" 12 | }, 13 | "scripts": { 14 | "test": "jshint solutions/javascript && mocha tests/javascript" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/blakeembrey/code-problems.git" 19 | }, 20 | "keywords": [ 21 | "code", 22 | "problems", 23 | "interview", 24 | "programming" 25 | ], 26 | "author": "Blake Embrey", 27 | "license": "MIT", 28 | "readmeFilename": "README.md", 29 | "bugs": { 30 | "url": "https://github.com/blakeembrey/code-problems/issues" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /solutions/javascript/search-unknown-length-array.js: -------------------------------------------------------------------------------- 1 | module.exports = function searchArray (array, num) { 2 | var index = 0; 3 | 4 | // Increment the index by doubling until we pass the search number. 5 | while (index in array && array[index] <= num) { 6 | if (array[index] === num) { 7 | return index; 8 | } 9 | 10 | // Double the index at which we are seaching. 11 | index = (index * 2) || 1; 12 | } 13 | 14 | // If the index hasn't been incremented beyond the first index, it won't be 15 | // found. 16 | if (index < 2) { return -1; } 17 | 18 | // Track the found index so we can continue to return `-1` down the stack. 19 | var foundIndex = searchArray(array.slice(index / 2, index), num); 20 | 21 | // Return `-1` or old index plus new found index. 22 | return foundIndex > -1 ? (index / 2) + foundIndex : -1; 23 | }; 24 | -------------------------------------------------------------------------------- /tests/javascript/anagram-detection.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var anagramDetection = require('../../solutions/javascript/anagram-detection'); 3 | 4 | describe('Anagram Detection', function () { 5 | it('should detect no change in the characters', function () { 6 | expect(anagramDetection('abc', 'abc')).to.equal(1); 7 | }); 8 | 9 | it('should detect anagrams of itself', function () { 10 | expect(anagramDetection('aab', 'baa')).to.equal(1); 11 | }); 12 | 13 | it('should detect child anagrams', function () { 14 | expect(anagramDetection('AbrAcadAbRa', 'cAda')).to.equal(2); 15 | expect(anagramDetection('AdnBndAndBdaBn', 'dAn')).to.equal(4); 16 | }); 17 | 18 | it('should not fail with a larger child than parent string', function () { 19 | expect(anagramDetection('test', 'testing')).to.equal(0); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /solutions/javascript/string-permutations.js: -------------------------------------------------------------------------------- 1 | module.exports = function (string) { 2 | var result = {}; 3 | 4 | // Using an immediately invoked named function for recursion. 5 | (function makeWord (word, remaining) { 6 | // If there are no more remaining characters, break and set to true 7 | // in the result object. 8 | if (!remaining) { return result[word] = true; } 9 | 10 | // Loop through all the remaining letters and recurse slicing the character 11 | // out of the remaining stack and into the solution word. 12 | for (var i = 0; i < remaining.length; i++) { 13 | makeWord( 14 | word + remaining[i], 15 | remaining.substr(0, i) + remaining.substr(i + 1) 16 | ); 17 | } 18 | })('', string); 19 | 20 | // Using the ES5 Object.keys to grab the all the keys as an array. 21 | return Object.keys(result); 22 | }; 23 | -------------------------------------------------------------------------------- /solutions/javascript/tree-level-order-print.js: -------------------------------------------------------------------------------- 1 | module.exports = function (root) { 2 | // Doing a breadth first search using recursion. 3 | (function walkLevel (children) { 4 | // Create a new queue for the next level. 5 | var queue = [], 6 | output; 7 | 8 | // Use the map function to easily join all the nodes together while pushing 9 | // it's children into the next level queue. 10 | output = children.map(function (node) { 11 | // Assuming the node has children stored in an array. 12 | queue = queue.concat(node.children || []); 13 | return node.value; 14 | }).join(' '); 15 | 16 | // Log the output at each level. 17 | console.log(output); 18 | 19 | // If the queue has values in it, recurse to the next level and walk 20 | // along it. 21 | queue.length && walkLevel(queue); 22 | })([root]); 23 | }; 24 | -------------------------------------------------------------------------------- /problems/longest-compound-word/Readme.md: -------------------------------------------------------------------------------- 1 | # Longest Compound Word 2 | 3 | Given a sorted list of words, find the longest compound word in the list that is constructed by concatenating the words in the list. For example, if the input list is: `['cat', 'cats', 'catsdogcats', 'catxdogcatsrat', 'dog', 'dogcatsdog', 'hippopotamuses', 'rat', 'ratcat', 'ratcatdog', 'ratcatdogcat']`. Then the longest compound word is ‘ratcatdogcat’ with 12 letters. Note that the longest individual words are ‘catxdogcatsrat’ and ‘hippopotamuses’ with 14 letters, but they’re not fully constructed by other words. Former one has an extra ‘x’ letter, and latter is an individual word by itself not a compound word. 4 | 5 | ## Source 6 | 7 | [http://www.ardendertat.com/2012/06/15/programming-interview-questions-28-longest-compound-word/](http://www.ardendertat.com/2012/06/15/programming-interview-questions-28-longest-compound-word/) 8 | -------------------------------------------------------------------------------- /solutions/coffeescript/kth-largest-element-in-array.coffee: -------------------------------------------------------------------------------- 1 | kthLargestElementInArray = (k, array) -> 2 | # I believe we can store it in a hash to achieve an O(n) complexity 3 | hash = {} 4 | count = 0 5 | 6 | # Loop through each of the array items putting the values as keys in the hash 7 | array.forEach (num) -> 8 | hash[num] = hash[num] + 1 or 1 9 | 10 | # Loop through each of the keys in the hash and keep track of the total count 11 | for i of hash 12 | # Check if `k` is smaller or equal to the current count plus the current 13 | # hash index, but also greater than the previous count (this will mean it 14 | # is stored in this integer key) 15 | 16 | # Coerce the output back to a number, since that is expected 17 | return +i if k <= count + hash[i] and k > count 18 | 19 | # Increment the total count 20 | count += hash[i] 21 | -1 22 | -------------------------------------------------------------------------------- /tests/javascript/sorted-array-search.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sortedSearch = require('../../solutions/javascript/sorted-array-search'); 3 | 4 | describe('Sorted Array Search', function () { 5 | it('should be able to find the number', function () { 6 | expect(sortedSearch([2, 5, 6, 9, 23, 45, 85, 102], 9)).to.equal(3); 7 | expect(sortedSearch([2, 8, 9, 10, 53, 63, 73, 83], 83)).to.equal(7); 8 | expect(sortedSearch([1, 4, 6, 7, 9, 11, 45, 98, 99], 1)).to.equal(0); 9 | }); 10 | 11 | it('should find negative numbers', function () { 12 | expect(sortedSearch([-11, -10, -7, -5, -3, -2, 5, 8], -10)).to.equal(1); 13 | expect(sortedSearch([-99, -67, -45, -33, -10, -9, -8], -8)).to.equal(6); 14 | }); 15 | 16 | it('should fail to find the number', function () { 17 | expect(sortedSearch([3, 4, 7, 9, 44], 23)).to.equal(-1); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /solutions/coffeescript/flatten-array.coffee: -------------------------------------------------------------------------------- 1 | # Create a new flattened array 2 | flatten = (input) -> 3 | output = [] 4 | i = 0 5 | 6 | while i < input.length 7 | # Using Array.isArray for new browsers, in older browsers this can be 8 | # polyfilled using `Object.prototype.toString.call(input[i]) === '[object Array]'` 9 | if Array.isArray(input[i]) 10 | output.push.apply output, flatten(input[i]) 11 | else 12 | output.push input[i] 13 | i++ 14 | output 15 | 16 | # In place array flatten 17 | flatten = (array) -> 18 | i = 0 19 | while i < array.length 20 | if Array.isArray(array[i]) 21 | array.splice.apply array, [i, 1].concat(array[i]) 22 | else 23 | i += 1 24 | array 25 | 26 | # Flatten array using ES5 reduce method 27 | flatten = (array) -> array.reduce ((arr, val) -> arr.concat (if Array.isArray(val) then flatten(val) else val)), [] 28 | -------------------------------------------------------------------------------- /solutions/java/IntegerDifference.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | 3 | public class IntegerDifference { 4 | public static void main(String[] args) { 5 | IntegerDifference id = new IntegerDifference(); 6 | int[] input = { 1, 1, 3, 3 }; 7 | int diff = 2; 8 | System.out.print(id.getNumberOfElements(input, diff)); 9 | } 10 | 11 | public int getNumberOfElements(int[] input, int diff) { 12 | int numberOfElements = 0; 13 | HashMap sums = new HashMap(); 14 | for (int i = 0; i < input.length; i++) { 15 | int sum = diff + input[i]; 16 | if (sums.containsKey(sum)) 17 | sums.put(sum, sums.get(sum) + 1); 18 | else 19 | sums.put(sum, 1); 20 | } 21 | for (int i = 0; i < input.length; i++) { 22 | if (sums.containsKey(input[i])) { 23 | numberOfElements += sums.get(input[i]); 24 | } 25 | } 26 | return numberOfElements; 27 | } 28 | } -------------------------------------------------------------------------------- /solutions/ruby/quick_sort.rb: -------------------------------------------------------------------------------- 1 | # NOTE: Ruby has a built in sorting method, `sort!`, that actually uses a quick-sort process; this just demonstrates an implementation. 2 | 3 | def quick_sort(array) # quick sort algorithm 4 | array.quick_sort! 5 | end 6 | 7 | def self.quick_sort!(array) 8 | process(array, 0, array.size - 1) 9 | end 10 | 11 | private 12 | 13 | def self.process(array, left, right) 14 | if left < right 15 | pivot = partition(array, left, right) 16 | process(array, left, pivot - 1) 17 | process(array, pivot + 1, right) 18 | end 19 | array 20 | end 21 | 22 | def self.partition(array, left, right) 23 | x = array[right] 24 | i = left - 1 25 | (left..right - 1).each do |j| 26 | if array[j] <= x 27 | i += 1 28 | array[i], array[j] = array[j], array[i] 29 | end 30 | end 31 | array[i + 1], array[right] = array[right], array[i + 1] 32 | i + 1 33 | end 34 | -------------------------------------------------------------------------------- /solutions/javascript/selection-sort.js: -------------------------------------------------------------------------------- 1 | module.exports = function (array, compare) { 2 | // Not an array, empty or array of 1 is already sorted 3 | if (!Array.isArray(array) || array.length < 2) { 4 | return array; 5 | } 6 | 7 | var swap = function (array, first, second) { 8 | var temp = array[first]; 9 | array[first] = array[second]; 10 | array[second] = temp; 11 | return array; 12 | }; 13 | 14 | // Create a compare func if not passed in 15 | if (typeof compare !== 'function') { 16 | compare = function (a, b) { 17 | return a > b ? 1 : -1; 18 | }; 19 | } 20 | 21 | var min, i, j; 22 | 23 | for (i = 0; i < array.length; i++) { 24 | min = i; 25 | for (j = i + 1; j < array.length; j++) { 26 | if (compare(array[j], array[min]) < 0) { 27 | min = j; 28 | } 29 | } 30 | 31 | swap(array, i, min); 32 | } 33 | 34 | return array; 35 | }; 36 | -------------------------------------------------------------------------------- /solutions/javascript/queen-threatens-king.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if two points (p1 and p2) defined by the coordinates 3 | * passed as arguments are either horizontally, vertically or 4 | * diagonally (45°) aligned with one another. 5 | * 6 | * @param {Number} x1 x-coordinate of p1 7 | * @param {Number} y1 y-coordinate of p1 8 | * @param {Number} x2 x-coordinate of p2 9 | * @param {Number} y2 y-coordinate of p2 10 | * @return {Boolean} True if the points are aligned (horz / vert / diag) 11 | */ 12 | module.exports = function (x1, y1, x2, y2) { 13 | 14 | // Validate coordinate values 15 | var validArgs = Array.prototype.slice.call(arguments).every(function (coord) { 16 | return typeof coord === 'number'; 17 | }); 18 | 19 | if (!validArgs) { 20 | throw new Error('All coordinates must numbers'); 21 | } 22 | 23 | return x1 === x2 || y1 === y2 || Math.abs(x1 - x2) === Math.abs(y1 - y2); 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /solutions/javascript/sorted-array-search.js: -------------------------------------------------------------------------------- 1 | module.exports = function (array, number) { 2 | return (function searchNumber (left, right) { 3 | var center = left + Math.floor((right - left) / 2); 4 | 5 | // If the numbers match, return the center index. 6 | if (array[center] === number) { return center; } 7 | 8 | // If the left position is the same as the center position, return -1. 9 | if (left === center) { return -1; } 10 | 11 | // When the current number is larger than the search input, recurse 12 | // moving the left and right indexes to the search area. 13 | if (array[center] > number) { 14 | return searchNumber(left, center); 15 | } 16 | 17 | // When the current number is smaller move the search parameters to the 18 | // right. 19 | if (array[center] < number) { 20 | return searchNumber(center, right); 21 | } 22 | 23 | return -1; 24 | })(0, array.length); 25 | }; 26 | -------------------------------------------------------------------------------- /tests/javascript/next-highest-number.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var nextHighest = require('../../solutions/javascript/next-highest-number'); 3 | 4 | describe('next highest number', function () { 5 | it('should return the next highest number', function () { 6 | assert.equal(nextHighest(1524), 1542); 7 | assert.equal(nextHighest(1542), 2145); 8 | assert.equal(nextHighest(1543), 3145); 9 | assert.equal(nextHighest(1544), 4145); 10 | assert.equal(nextHighest(63254), 63425); 11 | assert.equal(nextHighest(63542), 64235); 12 | assert.equal(nextHighest(1112), 1121); 13 | assert.equal(nextHighest(1243), 1324); 14 | assert.equal(nextHighest(348932), 349238); 15 | assert.equal(nextHighest(15895), 15958); 16 | }); 17 | 18 | it('should work when there isn\'t a higher number', function () { 19 | assert.equal(nextHighest(98765), 98765); 20 | assert.equal(nextHighest(11111), 11111); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /problems/spreadsheet/README.md: -------------------------------------------------------------------------------- 1 | # Programming Challenge 2 | 3 | A spreadsheet consists of a two-dimensional array of cells, labeled A1, A2, etc. Rows are identified using letters, columns by numbers. Each cell contains either an integer (its value) or an expression. Expressions contain integers, cell references, and the operators '+', '-', '\*', '/' with the usual rules of evaluation – note that the input is RPN and should be evaluated in stack order. 4 | 5 | The spreadsheet input is defined as follows: 6 | 7 | 1. Line 1: two integers, defining the width and height of the spreadsheet (n, m) 8 | 9 | 2. n\*m lines each containing an expression which is the value of the corresponding cell (cells enumerated in the order A1, A2, A, B1, ...) 10 | 11 | ## The Input 12 | 3 2 13 | A2 14 | 4 5 * 15 | A1 16 | A1 B2 / 2 + 17 | 3 18 | 39 B1 B2 * / 19 | 20 | ## The Output 21 | 3 2 22 | 20.00000 23 | 20.00000 24 | 20.00000 25 | 8.66667 26 | 3.00000 27 | 1.50000 28 | -------------------------------------------------------------------------------- /solutions/php/hotel-room.php: -------------------------------------------------------------------------------- 1 | 0;) { 6 | $remainder = $number % $i; 7 | if (!$remainder) { 8 | $divisors[] = $i; 9 | } 10 | } 11 | return $divisors; 12 | }; 13 | 14 | $getSubsets = function ($divisors) { 15 | $subsets = [[]]; 16 | foreach ($divisors as $division) { 17 | foreach ($subsets as $subset) { 18 | $subsets[] = array_merge([$division], $subset); 19 | } 20 | } 21 | return $subsets; 22 | }; 23 | 24 | $isRoom = function($subsets, $room) { 25 | foreach ($subsets as $subset) { 26 | if (array_sum($subset) == $room) { 27 | return false; 28 | } 29 | } 30 | return true; 31 | }; 32 | 33 | for ($i = 0; ++$i < 101;) { 34 | $divisors = $getDivisors($i); 35 | 36 | $sum = array_sum($divisors); 37 | 38 | if ($sum <= $i) { 39 | continue; 40 | } 41 | 42 | if ($isRoom($getSubsets($divisors), $i)) { 43 | echo $i . "\n"; 44 | exit; 45 | } 46 | } 47 | 48 | echo "?\n"; 49 | 50 | 51 | -------------------------------------------------------------------------------- /problems/array-pair-sum/Readme.md: -------------------------------------------------------------------------------- 1 | # Array Pair Sum 2 | 3 | Given an integer array, output all distinct pairs that sum up to a specific value k. Consider the fact that the same number can add up to `k` with its duplicates in the array. 4 | 5 | > For example the array is [1, 1, 2, 3, 4] and the desired sum is 4. Should we output the pair (1, 3) twice or just once? Also do we output the reverse of a pair, meaning both (3, 1) and (1, 3)? Let’s keep the output as short as possible and print each pair only once. So, we will output only one copy of (1, 3). Also note that we shouldn’t output (2, 2) because it’s not a pair of two distinct elements. 6 | 7 | ## Example 8 | 9 | ``` 10 | f(10, [3, 4, 5, 6, 7]) // [ [4, 6], [3, 7] ] 11 | f(8, [3, 4, 5, 4, 4]) // [ [3, 5], [4, 4], [4, 4], [4, 4] ] 12 | f(10, [3, 5, 6, 8]) // [] 13 | ``` 14 | 15 | ## Source 16 | 17 | [http://www.ardendertat.com/2011/09/17/programming-interview-questions-1-array-pair-sum/](http://www.ardendertat.com/2011/09/17/programming-interview-questions-1-array-pair-sum/) 18 | -------------------------------------------------------------------------------- /solutions/javascript/kth-largest-element-in-array.js: -------------------------------------------------------------------------------- 1 | module.exports = function (k, array) { 2 | // I believe we can store it in a hash to achieve an O(n) complexity 3 | var hash = {}, 4 | count = 0; 5 | 6 | // Loop through each of the array items putting the values as keys in the hash 7 | array.forEach(function (num) { 8 | hash[num] = hash[num] + 1 || 1; 9 | }); 10 | 11 | // Loop through each of the keys in the hash and keep track of the total count 12 | for (var i in hash) { 13 | if (hash.hasOwnProperty(i)) { 14 | // Check if `k` is smaller or equal to the current count plus the current 15 | // hash index, but also greater than the previous count (this will mean it 16 | // is stored in this integer key) 17 | if (k <= count + hash[i] && k > count) { 18 | // Coerce the output back to a number, since that is expected 19 | return +i; 20 | } 21 | // Increment the total count 22 | count += hash[i]; 23 | } 24 | } 25 | 26 | return -1; 27 | }; 28 | -------------------------------------------------------------------------------- /solutions/coffeescript/find-missing-element.coffee: -------------------------------------------------------------------------------- 1 | # Simple solution using a hash to look up numbers from the second array in the 2 | # first array. When the number doesn't exist in the hash - you know we have 3 | # found the missing number 4 | findMissingElement = (a, b) -> 5 | hash = {} 6 | i = undefined 7 | i = 0 8 | while i < b.length 9 | hash[b[i]] = hash[b[i]] + 1 or 1 10 | i++ 11 | i = 0 12 | while i < a.length 13 | return a[i] unless hash[a[i]] 14 | hash[a[i]] -= 1 15 | i++ 16 | 17 | # Bitwise solution using XOR to cancel each of the corresponding numbers out 18 | # with eachother until we end up with a number that isn't cancelled out 19 | findMissingElement = (a, b) -> 20 | result = 0 21 | a.concat(b).forEach (num) -> 22 | result ^= num 23 | result 24 | 25 | # Maybe the simplest solution, but you can very easily add the two arrays and 26 | # take the result of `b` away from `a` to get the missing number 27 | findMissingElement = (a, b) -> 28 | add = (a, b) -> 29 | a + b 30 | a.reduce(add) - b.reduce(add) 31 | -------------------------------------------------------------------------------- /solutions/java/BalancedBrackets.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashMap; 3 | import java.util.Stack; 4 | 5 | 6 | public class BalancedBrackets { 7 | 8 | public boolean isBalanced(String s) { 9 | HashMap bracketMap = new HashMap(); 10 | bracketMap.put('{', '}'); 11 | bracketMap.put('[', ']'); 12 | bracketMap.put('(', ')'); 13 | Stack bracketStack = new Stack(); 14 | for (char c: s.toCharArray()) { 15 | if (!bracketStack.isEmpty() && bracketMap.get(bracketStack.peek()) == c) { 16 | bracketStack.pop(); 17 | } else if (bracketMap.containsKey(c)) { 18 | bracketStack.push(c); 19 | } else { 20 | return false; 21 | } 22 | } 23 | return bracketStack.isEmpty(); 24 | } 25 | 26 | public static void main(String[] args) { 27 | BalancedBrackets b = new BalancedBrackets(); 28 | System.out.println(b.isBalanced("()[]{}(([])){[()][]}")); 29 | System.out.println(b.isBalanced("())[]{}")); 30 | System.out.println(b.isBalanced("[(])")); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /solutions/java/LargestPalindrome.java: -------------------------------------------------------------------------------- 1 | public class LargestPalindrome { 2 | public static void main(String[] args) { 3 | LargestPalindrome lp = new LargestPalindrome(); 4 | String input = "I am a red racecar driver"; 5 | System.out.println(lp.getPalindrome(input)); 6 | } 7 | 8 | public String getPalindrome(String input) { 9 | if (input == null || input.length() == 0) 10 | return ""; 11 | if (input.length() == 1) 12 | return input; 13 | 14 | String largestPalindrome = input.charAt(0) + ""; 15 | // Run across the string 16 | for (int i = 1; i < input.length(); i++) { 17 | String curPalindrome = checkSides(input, i, i); 18 | if (curPalindrome.length() > largestPalindrome.length()) 19 | largestPalindrome = curPalindrome; 20 | } 21 | return largestPalindrome; 22 | } 23 | 24 | public String checkSides(String input, int left, int right) { 25 | while (left >= 0 && right < input.length() 26 | && input.charAt(left) == input.charAt(right)) { 27 | left--; 28 | right++; 29 | } 30 | return input.substring(left + 1, right); 31 | } 32 | } -------------------------------------------------------------------------------- /solutions/java/ConvertArray.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | 4 | public class ConvertArray { 5 | 6 | public int getOriginalIndex(int currentIndex, int length) { 7 | return (currentIndex % 3) * length + currentIndex/3; 8 | } 9 | 10 | public int[] convert(int[] input) { 11 | // When array size is less than 3, returns an error. 12 | if (input.length % 3 != 0 ) { 13 | System.out.println("Error! Array cannot be divided into three equal parts"); 14 | return; 15 | } 16 | for (int i = 0; i < input.length; ++i) { 17 | int originalIndex = getOriginalIndex(i, input.length/3); 18 | while (originalIndex < i) { 19 | originalIndex = getOriginalIndex(originalIndex, input.length/3); 20 | } 21 | int temp = input[i]; 22 | input[i] = input[originalIndex]; 23 | input[originalIndex] = temp; 24 | } 25 | return input; 26 | } 27 | 28 | public static void main(String[] args) { 29 | ConvertArray c = new ConvertArray(); 30 | int[] test1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 31 | System.out.println(Arrays.toString(c.convert(test1))); 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/javascript/queen-threatens-king.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var threatens = require('../../solutions/javascript/queen-threatens-king'); 3 | 4 | describe('queen-threatens-king', function () { 5 | 6 | it('should throw if called with invalid parameters', function () { 7 | var coordinates = [ 0, 0, null, 0 ]; 8 | var threatensWithInvalidParams = Function.prototype.bind.apply(threatens, coordinates); 9 | expect(threatensWithInvalidParams).to.throw(Error); 10 | }); 11 | 12 | it('the queen should threaten the king (in the same row)', function () { 13 | expect(threatens(0, 0, 0, 1)).to.be.true; 14 | }); 15 | 16 | it('the queen should threaten the king (in the same column)', function () { 17 | expect(threatens(0, 0, 1, 0)).to.be.true; 18 | }); 19 | 20 | it('the queen should threaten the king (in the same diagonal)', function () { 21 | expect(threatens(0, 0, 1, 1)).to.be.true; 22 | }); 23 | 24 | it('the queen should not threaten the king', function () { 25 | expect(threatens(0, 0, 1, 2)).to.be.false; 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /solutions/java/NextHighestNumber.java: -------------------------------------------------------------------------------- 1 | public class NextHighestNumber { 2 | /*** 3 | * Convert int into character array. Starting from the end, compare each 4 | * number with all numbers before it, one at a time. At any moment we find a 5 | * number greater than any of its previous numbers, we swap them, and return 6 | * the converted int. 7 | */ 8 | public static void main(String[] args) { 9 | // TODO Auto-generated method stub 10 | NextHighestNumber nhn = new NextHighestNumber(); 11 | Integer next = nhn.getNextHighestNumber(32233); 12 | if (next != null) 13 | System.out.println(next); 14 | } 15 | 16 | public Integer getNextHighestNumber(int n) { 17 | String sNumber = String.valueOf(n); 18 | char[] nums = sNumber.toCharArray(); 19 | for (int i = nums.length - 1; i > 0; i--) { 20 | for (int j = i - 1; j >= 0; j--) 21 | if (Integer.valueOf(nums[i]) > Integer.valueOf(nums[j])) { 22 | char t = nums[i]; 23 | nums[i] = nums[j]; 24 | nums[j] = t; 25 | return Integer.valueOf(new String(nums)); 26 | } 27 | } 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /solutions/coffeescript/linked-list.coffee: -------------------------------------------------------------------------------- 1 | LinkedList = (value) -> 2 | @value = value 3 | @prev = this 4 | @next = this 5 | 6 | LinkedList::appendNode = (value) -> 7 | node = new LinkedList(value) 8 | node.prev = this 9 | node.next = @next 10 | 11 | # Fix the linked list references 12 | @next = @next.prev = node 13 | node 14 | 15 | LinkedList::prependNode = (value) -> 16 | node = new LinkedList(value) 17 | node.prev = @prev 18 | node.next = this 19 | 20 | # Fix the linked list references 21 | @prev = @prev.next = node 22 | node 23 | 24 | LinkedList::removeNode = -> 25 | # Create a reference around the node to be removed 26 | @prev.next = @next 27 | @next.prev = @prev 28 | 29 | # Remove existing references to the current list 30 | @next = @prev = this 31 | this 32 | 33 | LinkedList::containsNode = (value) -> 34 | return true if @value is value 35 | node = @next 36 | 37 | # Loop through the connections until we hit ourselves again 38 | while node isnt this 39 | return true if node.value is value 40 | node = node.next 41 | false 42 | -------------------------------------------------------------------------------- /solutions/javascript/next-palindrome-number.js: -------------------------------------------------------------------------------- 1 | module.exports = function nextPalindrome (number) { 2 | var numberString = ('' + number), 3 | numberLength = numberString.length, 4 | oddDigits = numberLength & 1, 5 | leftHalf = numberString.substr(0, ~~(numberLength / 2)), 6 | middleNumber = numberString.charAt(Math.ceil(numberLength / 2)), 7 | increment, newNumber, reverseString; 8 | 9 | reverseString = function (string) { 10 | return string.length > 1 ? string.split('').reverse().join('') : string; 11 | }; 12 | 13 | if (oddDigits) { 14 | increment = Math.pow(10, numberLength / 2); 15 | newNumber = +(leftHalf + middleNumber + reverseString(leftHalf)); 16 | } else { 17 | increment = 1.1 * Math.pow(10, numberLength / 2); 18 | newNumber = +(leftHalf + reverseString(leftHalf)); 19 | } 20 | 21 | if (newNumber > number) { 22 | return newNumber; 23 | } 24 | 25 | if (middleNumber === '9') { 26 | return nextPalindrome(+numberString[0] * Math.pow(10, numberLength)); 27 | } else { 28 | return newNumber + increment; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /solutions/javascript/flatten-array.js: -------------------------------------------------------------------------------- 1 | // Create a new flattened array 2 | exports.newArray = function flatten (input) { 3 | var output = []; 4 | 5 | for (var i = 0; i < input.length; i++) { 6 | // Using Array.isArray for new browsers, in older browsers this can be done 7 | // using `Object.prototype.toString.call(input[i]) === '[object Array]'` 8 | if (Array.isArray(input[i])) { 9 | output.push.apply(output, flatten(input[i])); 10 | } else { 11 | output.push(input[i]); 12 | } 13 | } 14 | 15 | return output; 16 | }; 17 | 18 | // In place array flatten 19 | exports.inPlace = function (array) { 20 | var i = 0; 21 | 22 | while (i < array.length) { 23 | if (Array.isArray(array[i])) { 24 | array.splice.apply(array, [i, 1].concat(array[i])); 25 | } else { 26 | i += 1; 27 | } 28 | } 29 | 30 | return array; 31 | }; 32 | 33 | // Flatten array using ES5 reduce method 34 | exports.es5 = function flatten (array) { 35 | return array.reduce(function (arr, val) { 36 | return arr.concat(Array.isArray(val) ? flatten(val) : val); 37 | }, []); 38 | }; 39 | -------------------------------------------------------------------------------- /solutions/java/EvenOccuringElement.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Iterator; 3 | import java.util.Map; 4 | import java.util.Map.Entry; 5 | 6 | public class EvenOccuringElement { 7 | public static void main(String[] args) { 8 | EvenOccuringElement eoe = new EvenOccuringElement(); 9 | int[] input = { 1, 2, 3, 3, 3, 4, 4, 4, 5, 6 }; 10 | Integer evenElement = eoe.getElement(input); 11 | if (evenElement != null) 12 | System.out.println(evenElement); 13 | } 14 | 15 | public Integer getElement(int[] input) { 16 | HashMap counter = new HashMap(); 17 | for (int i = 0; i < input.length; i++) { 18 | if (counter.containsKey(input[i])) 19 | counter.put(input[i], counter.get(input[i]) + 1); 20 | else 21 | counter.put(input[i], 1); 22 | } 23 | Iterator> it = counter.entrySet().iterator(); 24 | while (it.hasNext()) { 25 | Map.Entry pairs = (Entry) it 26 | .next(); 27 | if (((Integer) pairs.getValue() % 2) == 0) 28 | return (Integer) pairs.getKey(); 29 | } 30 | return null; 31 | } 32 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Structure 4 | 5 | ### Adding a new problem 6 | 7 | To add a new problem to the repo, no solution needs to be present. Just add a folder to the problems directory with a readme detailing the complete problem and expected result. 8 | 9 | ### Adding a new solution 10 | 11 | To add a new solution to the repo, add the solution to the correct language directory in the solutions directory. Make the solution file name match the problem. If a solution already exists, but your solution is distinctly different to the current solution, place both solutions in a directory named after the problem. The file names should then accurately represent the type of solution used in each solution. If you must use multiple files for your solution, create a solution directory and another directory for your solution assets. 12 | 13 | ## Style Guide 14 | 15 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. 16 | 17 | Please lint and test your code with any means available - currently JavaScript has tests and linting via Mocha and JSHint. 18 | -------------------------------------------------------------------------------- /solutions/coffeescript/csv-parsing.coffee: -------------------------------------------------------------------------------- 1 | # Elegant solution using built-in JavaScript functions 2 | parseCSV = (csv) -> 3 | JSON.parse "[" + csv + "]" 4 | 5 | # Crazy parser which was the original solution 6 | parseCSV = (csv) -> 7 | isNumber = false 8 | isInput = false 9 | curr = "" 10 | stack = [] 11 | i = 0 12 | char = undefined 13 | pushStack = undefined 14 | csv = csv.trim() 15 | pushStack = (input) -> 16 | isNumber and (input = +input) 17 | 18 | # Resets 19 | curr = "" 20 | isInput = false 21 | isNumber = false 22 | stack.push input 23 | 24 | while char = csv.charAt(i++) 25 | if char is "\"" 26 | isInput = not curr 27 | else if char is "," 28 | if isInput and not isNumber 29 | curr += char 30 | else 31 | pushStack curr 32 | else if (isNumber or not curr) and not Number.isNaN(+char) 33 | curr += char 34 | isInput = true 35 | isNumber = true 36 | else 37 | throw new Error("Unexpected character") if isNumber or not isInput 38 | curr += char 39 | 40 | # Push the trailing entry 41 | pushStack curr 42 | stack 43 | -------------------------------------------------------------------------------- /solutions/javascript/queue.js: -------------------------------------------------------------------------------- 1 | var Queue = module.exports = function () { 2 | this.head = null; 3 | this.tail = null; 4 | this.length = 0; 5 | }; 6 | 7 | Queue.prototype.enqueue = function (value) { 8 | var node = { 9 | value: value, 10 | next: null 11 | }; 12 | 13 | // If there is currently no head node, set it to the current node. 14 | if (!this.head) { 15 | this.head = node; 16 | } 17 | 18 | // If we have a tail node already, set it's next property to be the current 19 | // node. 20 | if (this.tail) { 21 | this.tail.next = node; 22 | } 23 | 24 | // Update the tail to be the next node. 25 | this.tail = node; 26 | 27 | return this.length += 1; 28 | }; 29 | 30 | Queue.prototype.dequeue = function () { 31 | if (!this.head) { return; } 32 | 33 | var node = this.head; 34 | 35 | // Update the head reference and remove the next node reference from the 36 | // previous head. 37 | this.head = node.next; 38 | node.next = null; 39 | 40 | // Remove the tail node if we have no more head node. 41 | if (!this.head) { this.tail = null; } 42 | 43 | this.length -= 1; 44 | 45 | return node.value; 46 | }; 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /solutions/javascript/longest-words.js: -------------------------------------------------------------------------------- 1 | module.exports = function (string) { 2 | var length = 0; 3 | // Store the list of longest words in an object to automatically filter 4 | // for duplicates. 5 | var hash = {}; 6 | 7 | // Simplistic splitting on spaces, could improve to trim punctuation as well. 8 | string.split(' ').forEach(function (word) { 9 | // If the word's length is longer than the previous longest, we want to 10 | // update the length and reset the hash back to be empty. 11 | if (word.length > length) { 12 | length = word.length; 13 | hash = {}; 14 | } 15 | 16 | // If the word length is the same as the current longest length, add the 17 | // lowercase version to the hash. Here, we could store the value as some 18 | // arbitrary value since it doesn't matter - if though we needed to return 19 | // the instance of the word we could store how we found the word as the 20 | // value and grab it out when we return. 21 | if (word.length === length) { 22 | return hash[word.toLowerCase()] = true; 23 | } 24 | }); 25 | 26 | // Return an array with all the words. 27 | return Object.keys(hash); 28 | }; 29 | -------------------------------------------------------------------------------- /solutions/javascript/find-missing-element.js: -------------------------------------------------------------------------------- 1 | // Simple solution using a hash to look up numbers from the second array in the 2 | // first array. When the number doesn't exist in the hash - you know we have 3 | // found the missing number 4 | exports.iterative = function (a, b) { 5 | var hash = {}, i; 6 | 7 | for (i = 0; i < b.length; i++) { 8 | hash[b[i]] = hash[b[i]] + 1 || 1; 9 | } 10 | 11 | for (i = 0; i < a.length; i++) { 12 | if (!hash[a[i]]) { 13 | return a[i]; 14 | } 15 | hash[a[i]] -= 1; 16 | } 17 | }; 18 | 19 | // Bitwise solution using XOR to cancel each of the corresponding numbers out 20 | // with eachother until we end up with a number that isn't cancelled out 21 | exports.bitwise = function (a, b) { 22 | var result = 0; 23 | a.concat(b).forEach(function (num) { 24 | result ^= num; 25 | }); 26 | return result; 27 | }; 28 | 29 | // Maybe the simplest solution, but you can very easily add the two arrays and 30 | // take the result of `b` away from `a` to get the missing number 31 | exports.sum = function (a, b) { 32 | var add = function (a, b) { 33 | return a + b; 34 | }; 35 | 36 | return a.reduce(add) - b.reduce(add); 37 | }; 38 | -------------------------------------------------------------------------------- /solutions/javascript/csv-parsing.js: -------------------------------------------------------------------------------- 1 | // Please note: This can be accomplished using `JSON.parse('[' + csv + ']')` 2 | module.exports = function (csv) { 3 | var isNumber = false, 4 | isInput = false, 5 | curr = '', 6 | stack = [], 7 | i = 0, 8 | char, 9 | pushStack; 10 | 11 | csv = csv.trim(); 12 | 13 | pushStack = function (input) { 14 | isNumber && (input = +input); 15 | // Resets 16 | curr = ''; 17 | isInput = false; 18 | isNumber = false; 19 | stack.push(input); 20 | }; 21 | 22 | while (char = csv.charAt(i++)) { 23 | if (char === '"') { 24 | isInput = !curr; 25 | } else if (char === ',') { 26 | if (isInput && !isNumber) { 27 | curr += char; 28 | } else { 29 | pushStack(curr); 30 | } 31 | } else if ((isNumber || !curr) && !Number.isNaN(+char)) { 32 | curr += char; 33 | isInput = true; 34 | isNumber = true; 35 | } else { 36 | if (isNumber || !isInput) { throw new Error('Unexpected character'); } 37 | curr += char; 38 | } 39 | } 40 | 41 | // Push the trailing entry 42 | pushStack(curr); 43 | 44 | return stack; 45 | }; 46 | -------------------------------------------------------------------------------- /solutions/javascript/quick-sort.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function quickSort(input, compare) { 4 | var lesser = [], 5 | greater = [], 6 | pivot; 7 | 8 | if (!Array.isArray(input)) { 9 | throw new Error('Can only sort arrays.'); 10 | } 11 | 12 | var array = input.slice(0); // make a copy of the array 13 | 14 | if (array.length < 2) { 15 | return array; 16 | } 17 | 18 | // Create a compare func if not passed in 19 | if (typeof compare !== 'function') { 20 | compare = function (a, b) { 21 | return a > b ? 1 : -1; 22 | }; 23 | } 24 | 25 | // Get our pivot, this can be random 26 | pivot = array.splice(~~(Math.random() * array.length), 1); 27 | 28 | // Iterate and put vals into either lesser or greater lists compared 29 | // to the pivot 30 | for (var i = 0; i < array.length; i++) { 31 | if (compare(array[i], pivot) < 1) { 32 | lesser.push(array[i]); 33 | } else { 34 | greater.push(array[i]); 35 | } 36 | } 37 | 38 | // Sort lesser and greater lists, concat results 39 | return Array.prototype.concat( 40 | quickSort(lesser, compare), 41 | pivot, 42 | quickSort(greater, compare) 43 | ); 44 | }; 45 | -------------------------------------------------------------------------------- /solutions/coffeescript/word-positions.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (text) -> 2 | trie = {} 3 | pos = 0 4 | active = trie # Start the active structure as the root trie structure 5 | 6 | # Suffix a space after the text to make life easier 7 | text += " " 8 | 9 | # Loop through the input text adding it to the trie structure 10 | i = 0 11 | 12 | while i < text.length 13 | 14 | # When the character is a space, restart 15 | if text[i] is " " 16 | 17 | # If the current active doesn't equal the root, set the position 18 | (active.positions = active.positions or []).push pos if active isnt trie 19 | 20 | # Reset the positions and the active part of the data structure 21 | pos = i 22 | active = trie 23 | continue 24 | 25 | # Set the next character in the structure up 26 | active[text[i]] = (active[text[i]] or {}) 27 | active = active[text[i]] 28 | i++ 29 | 30 | # Return a function that accepts a word and looks it up in the trie structure 31 | (word) -> 32 | i = -1 33 | active = trie 34 | while word[++i] 35 | return [] unless active[word[i]] 36 | active = active[word[i]] 37 | active.positions 38 | -------------------------------------------------------------------------------- /solutions/javascript/merge-sort.js: -------------------------------------------------------------------------------- 1 | // Sort the array by breaking it down into smaller chunks 2 | module.exports = function mergeSort (array, compare) { 3 | // If's not an array or an array of just one element, it's already sorted 4 | if (!Array.isArray(array) || array.length < 2) { return array; } 5 | 6 | var length = array.length, 7 | middle = Math.floor(length * 0.5), 8 | left = array.slice(0, middle), 9 | right = array.slice(middle, length); 10 | 11 | // Create a compare func if not passed in 12 | if (typeof compare !== 'function') { 13 | compare = function (a, b) { 14 | return a > b ? 1 : -1; 15 | }; 16 | } 17 | 18 | var merge = function (left, right) { 19 | var result = []; 20 | while (left.length || right.length) { 21 | if (left.length && right.length) { 22 | if (compare(left[0], right[0]) < 1) { 23 | result.push(left.shift()); 24 | } else { 25 | result.push(right.shift()); 26 | } 27 | } else if (left.length) { 28 | result.push(left.shift()); 29 | } else { 30 | result.push(right.shift()); 31 | } 32 | } 33 | return result; 34 | }; 35 | 36 | return merge(mergeSort(left), mergeSort(right)); 37 | }; 38 | -------------------------------------------------------------------------------- /solutions/javascript/queen-threatens-king/readme.md: -------------------------------------------------------------------------------- 1 | Visualizing the different ways the Queen and the King can be located relative to each other should help solve the problem. As the Queen can only move horizontally, vertically or diagonally (45°) it should be easy to deduce that the King is always threatened by the Queen if they are located in the same row (horizontally aligned) or column (vertically aligned): 2 | 3 | ![The Queen and the King are in the same row](queen-threatens-king-solution-horizontal.png) 4 | ![The Queen and the King are in the same column](queen-threatens-king-solution-vertical.png) 5 | 6 | The somewhat less trivial case is to check if the Queen and the King are in the same diagonal. The problem can be however greatly simplified by only focusing on the part of the board that is covered by the rectangle given by the Queen's and the King's coordinates: 7 | 8 | ![The Queen and the King define a rectangle](queen-threatens-king-solution-diagonal-1.png) 9 | 10 | From here it should become obvious that the Queen and the King will be located on the same diagonal only if the rectangle they form is a square, i.e. Δx == Δy: 11 | 12 | ![The Queen and the King define a rectangle](queen-threatens-king-solution-diagonal-2.png) 13 | 14 | 15 | -------------------------------------------------------------------------------- /solutions/java/SearchUnknownLengthArray.java: -------------------------------------------------------------------------------- 1 | public class SearchUnknownLengthArray { 2 | public static void main(String[] args) { 3 | SearchUnknownLengthArray sla = new SearchUnknownLengthArray(); 4 | int[] input = { 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 5, 6, 7, 8, 9, 5 | 9, 9, 9}; 6 | int search = 4; 7 | System.out.println(sla.findElement(input, search)); 8 | } 9 | 10 | /** 11 | * Algorithm: ardendertat.com 12 | * http://www.ardendertat.com/2011/11/21/programming-interview-questions-17-search-unknown-length-array/ 13 | */ 14 | 15 | public int findElement(int[] input, int search) { 16 | int index = 1; 17 | try { 18 | if (input[0] == search) { 19 | return 0; 20 | } 21 | while (index < Integer.MAX_VALUE) { 22 | if (input[index] == search) 23 | return index; 24 | else if (input[index] > search) { 25 | return findBetween(input, search, index); 26 | } 27 | index = (int) Math.pow(2, index); 28 | } 29 | } catch (Exception e) { 30 | return -1; 31 | } 32 | return -1; 33 | } 34 | 35 | public int findBetween(int[] input, int search, int index) { 36 | if (input[index] < search) 37 | return -1; 38 | if (input[index] == search) 39 | return index; 40 | return findBetween(input, search, index - 1); 41 | } 42 | } -------------------------------------------------------------------------------- /solutions/javascript/combine-two-strings.js: -------------------------------------------------------------------------------- 1 | module.exports = function combineTwoStrings (str1, str2, str3) { 2 | // Simple optimisation to break when impossible. 3 | if ((str1.length + str2.length) !== str3.length) { 4 | return false; 5 | } 6 | 7 | return isCombineTwoStrings(str1, str2, str3); 8 | }; 9 | 10 | function isCombineTwoStrings (str1, str2, str3) { 11 | // No more solutions to find. 12 | if (str3.length === 0) { 13 | return true; 14 | } 15 | 16 | var newStr3 = str3.substr(1); 17 | 18 | // Path for when the first string matches. 19 | if (str1[0] === str3[0]) { 20 | // When both paths are possible, we implement a simple backtracking 21 | // mechanism for when the first was wrong. E.g. `aac`, `aab`, `aaacab`. 22 | if (str2[0] === str3[0]) { 23 | return isCombineTwoStrings(str1.substr(1), str2, newStr3) || 24 | isCombineTwoStrings(str1, str2.substr(1), newStr3); 25 | } 26 | 27 | return isCombineTwoStrings(str1.substr(1), str2, newStr3); 28 | } 29 | 30 | // Path for when the second string matches. 31 | if (str2[0] === str3[0]) { 32 | return isCombineTwoStrings(str1, str2.substr(1), newStr3); 33 | } 34 | 35 | // When neither path is possible, the combination is `false`. 36 | return false; 37 | } 38 | -------------------------------------------------------------------------------- /solutions/javascript/insertion-sort.js: -------------------------------------------------------------------------------- 1 | // insertion-sort 2 | 'use strict'; 3 | 4 | module.exports = function (array, compare) { 5 | // Not an array, empty or array of 1 is already sorted 6 | if (!Array.isArray(array) || array.length < 2) { 7 | return array; 8 | } 9 | 10 | // Swap elements of the array 11 | var swap = function (array, first, second) { 12 | var temp = array[first]; 13 | array[first] = array[second]; 14 | array[second] = temp; 15 | return array; 16 | }; 17 | 18 | // Create a compare function if one is not passed in 19 | if (typeof compare !== 'function') { 20 | compare = function (a, b) { 21 | return a > b ? 1 : -1; 22 | }; 23 | } 24 | 25 | var i, j; 26 | 27 | /* 28 | * Assume first element is sorted 29 | * Add first unsorted element to sorted array 30 | * Compare new element in sorted array with previous elements 31 | * to determine correct destination index in sorted array 32 | */ 33 | 34 | for (i = 1; i < array.length; i++) { 35 | j = i; 36 | // Make sure we don't walk off the array and compare until sorted 37 | while ((j - 1) >= 0 && compare(array[j], array[j - 1]) < 0) { 38 | swap(array, j, j-1); 39 | j--; 40 | } 41 | } 42 | 43 | return array; 44 | }; 45 | -------------------------------------------------------------------------------- /tests/cpp/common.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_HPP_INCLUDED 2 | #define COMMON_HPP_INCLUDED 3 | 4 | #include // std::deque 5 | #include // std::tuple 6 | 7 | enum class Event { 8 | DefaultConstructorCalled, 9 | CopyConstructorCalled, 10 | MoveConstructorCalled, 11 | AssignmentOperatorCalled, 12 | DestructorCalled 13 | }; 14 | 15 | extern std::deque> eventLog; 16 | extern int nextId; 17 | 18 | inline const int getId() { 19 | return nextId++; 20 | }; 21 | 22 | inline void log(int id, Event e) { 23 | eventLog.push_back(std::make_tuple(id, e)); 24 | }; 25 | 26 | class eventLogger { 27 | private: 28 | int id; 29 | public: 30 | eventLogger() : id{getId()} { 31 | log(id, Event::DefaultConstructorCalled); 32 | }; 33 | eventLogger(eventLogger const& t) : id{getId()} { 34 | log(id, Event::CopyConstructorCalled); 35 | }; 36 | eventLogger(eventLogger&& t) : id{getId()} { 37 | log(id, Event::MoveConstructorCalled); 38 | }; 39 | ~eventLogger() { 40 | log(id, Event::DestructorCalled); 41 | }; 42 | eventLogger& operator=(eventLogger const& t) { 43 | log(id, Event::AssignmentOperatorCalled); 44 | return *this; 45 | }; 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /solutions/java/BubbleSort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Bubble sort is a simple sorting algorithm that repeatedly steps through the list to be sorted, 3 | * compares each pair of adjacent items and swaps them if they are in the wrong order. 4 | * The pass through the list is repeated until no swaps are needed, which indicates that the list is sorted. 5 | * Author : Viveka Aggarwal 6 | * Author : Jayesh Chandrapal 7 | */ 8 | 9 | public class BubbleSort { 10 | public static void sort(int[] arr) { 11 | int len = arr.length; 12 | boolean unsorted = true; 13 | 14 | while(unsorted) { 15 | unsorted = false; 16 | 17 | for(int j = 0 ; j < len - 1; j++) { 18 | if(arr[j] > arr[j + 1]) { 19 | swap(j, j + 1, arr); 20 | unsorted = true; 21 | } 22 | } 23 | } 24 | } 25 | 26 | public static void swap(int a, int b, int[] arr) { 27 | int temp = arr[a]; 28 | arr[a] = arr[b]; 29 | arr[b] = temp; 30 | } 31 | 32 | public static void main(String[] a) { 33 | int[] arr = {23, 3, 12, 54, 34, 77, 78, 87, 92, 12}; // unsorted input 34 | //int[] arr = {3,12, 12, 23, 34, 54, 77, 78, 87, 92}; // sorted input 35 | 36 | sort(arr); 37 | 38 | for(int i : arr) { 39 | System.out.print(i + " "); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /solutions/coffeescript/hotel-room.coffee: -------------------------------------------------------------------------------- 1 | findRoom = (totalRooms) -> 2 | findDivisors = (number) -> 3 | divisors = [] 4 | iterator = number 5 | divisors.push iterator if number % iterator is 0 while iterator-- 6 | divisors 7 | 8 | # Returns true or false based on whether the number is found in the sum of array subsets 9 | isSubsetSum = (number, array) -> 10 | hasSubset = false 11 | (findSubset = (total, numbers) -> 12 | not hasSubset and (hasSubset = total is number) 13 | return if hasSubset or total > number 14 | numbers.forEach (num, index) -> 15 | findSubset total + num, numbers.slice(0, index).concat(numbers.slice(index + 1)) 16 | ) 0, array 17 | hasSubset 18 | 19 | # Need a simple helper method that returns the sum of an array 20 | sumArray = (array) -> 21 | array.reduce ((memo, num) -> 22 | memo + num 23 | ), 0 24 | 25 | # Find the room using the provided functions 26 | divisors = undefined 27 | room = 0 28 | 29 | while room <= totalRooms 30 | divisors = findDivisors(room) 31 | 32 | # The sum of all the divisors must be greater than the number 33 | return room if sumArray(divisors) > room and not isSubsetSum(room, divisors) 34 | room++ 35 | 0 # No room number found 36 | -------------------------------------------------------------------------------- /solutions/go/merge-sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | func mergeSort(ary []int) []int { 9 | if len(ary) <= 1 { 10 | return ary 11 | } 12 | left := make([]int, 0) 13 | right := make([]int, 0) 14 | middle := math.Floor(float64(len(ary) / 2)) 15 | 16 | left = ary[0:int(middle)] 17 | right = ary[int(middle):] 18 | 19 | return merge(mergeSort(left), mergeSort(right)) 20 | } 21 | 22 | func merge(left, right []int) []int { 23 | 24 | result := make([]int, 0) 25 | 26 | for len(left) > 0 || len(right) > 0 { 27 | if len(left) > 0 && len(right) > 0 { 28 | if left[0] <= right[0] { 29 | result = append(result, left[0]) 30 | left = left[1:len(left)] 31 | } else { 32 | result = append(result, right[0]) 33 | right = right[1:len(right)] 34 | } 35 | } else if len(left) > 0 { 36 | result = append(result, left[0]) 37 | left = left[1:len(left)] 38 | } else { 39 | result = append(result, right[0]) 40 | right = right[1:len(right)] 41 | } 42 | } 43 | 44 | return result 45 | } 46 | 47 | func main() { 48 | random := []int{1,73,7,1,72,58,933,574,24,74,52} 49 | fmt.Println("Unsorted: ", random) 50 | random = mergeSort(random) 51 | fmt.Println("Sorted: ", random) 52 | } -------------------------------------------------------------------------------- /solutions/javascript/async-task-runner.js: -------------------------------------------------------------------------------- 1 | function TaskRunner(concurrency) { 2 | this.concurrency = concurrency; 3 | this.currentThreads = 0; 4 | } 5 | 6 | TaskRunner.prototype.push = function push(task) { /* TODO */ 7 | 8 | if( this.currentThreads >= this.concurrency ){ 9 | //wait 10 | console.log('the task is being pushed to queue...'); 11 | var self = this; 12 | setTimeout(function(){ 13 | self.push(task); 14 | }, 1000); 15 | 16 | }else{ 17 | this.currentThreads++; 18 | var self = this; 19 | task(this.done.bind(this)); 20 | } 21 | return; 22 | } 23 | 24 | TaskRunner.prototype.done = function done() { 25 | console.log('current threads ' , this.currentThreads ); 26 | this.currentThreads--; 27 | return; 28 | } 29 | 30 | 31 | function exampleSimpleTask(done) { 32 | setTimeout(function(){ 33 | console.log('task is done...'); 34 | done(); 35 | }, 1000); 36 | } 37 | 38 | 39 | var runner = new TaskRunner(3); 40 | 41 | 42 | runner.push(exampleSimpleTask); // executes immediately 43 | runner.push(exampleSimpleTask); // executes immediately 44 | runner.push(exampleSimpleTask); // executes immediately 45 | 46 | runner.push(exampleSimpleTask); 47 | runner.push(exampleSimpleTask); 48 | runner.push(exampleSimpleTask); 49 | -------------------------------------------------------------------------------- /solutions/javascript/word-positions.js: -------------------------------------------------------------------------------- 1 | module.exports = function (text) { 2 | var trie = {}, 3 | pos = 0, 4 | active = trie; // Start the active structure as the root trie structure 5 | 6 | // Suffix a space after the text to make life easier 7 | text += ' '; 8 | 9 | // Loop through the input text adding it to the trie structure 10 | for (var i = 0; i < text.length; i++) { 11 | // When the character is a space, restart 12 | if (text[i] === ' ') { 13 | // If the current active doesn't equal the root, set the position 14 | if (active !== trie) { 15 | (active.positions = active.positions || []).push(pos); 16 | } 17 | // Reset the positions and the active part of the data structure 18 | pos = i; 19 | active = trie; 20 | continue; 21 | } 22 | 23 | // Set the next character in the structure up 24 | active[text[i]] = (active[text[i]] || {}); 25 | active = active[text[i]]; 26 | } 27 | 28 | // Return a function that accepts a word and looks it up in the trie structure 29 | return function (word) { 30 | var i = -1, 31 | active = trie; 32 | 33 | while (word[++i]) { 34 | if (!active[word[i]]) { return []; } 35 | active = active[word[i]]; 36 | } 37 | 38 | return active.positions; 39 | }; 40 | }; 41 | -------------------------------------------------------------------------------- /solutions/javascript/next-highest-number.js: -------------------------------------------------------------------------------- 1 | module.exports = function (number) { 2 | var numberString = ('' + number); 3 | var length = numberString.length - 1; 4 | var string = ''; 5 | var sorter; 6 | 7 | // Loop in reverse comparing all the digits to the one beside it. 8 | while (length--) { 9 | // Compare the numbers beside each other. 10 | if (numberString.charAt(length) < numberString.charAt(length + 1)) { 11 | // Start the string using the numbers up until the pivot point. 12 | string = numberString.substr(0, length); 13 | // Sort all the numbers after the pivot. 14 | sorter = numberString.substr(length).split('').sort(); 15 | 16 | // Loop through all the numbers and if the next largest number than the 17 | // pivot. 18 | for (var i = 0; i < sorter.length; i++) { 19 | if (sorter[i] > numberString.charAt(length)) { 20 | // Splice the number from it's position and append it to the current 21 | // string. 22 | string += sorter.splice(i, 1)[0]; 23 | break; 24 | } 25 | } 26 | 27 | // Append the rest of the numbers already in ascending order. 28 | string += sorter.join(''); 29 | // Return the string typecast back to a number. 30 | return +string; 31 | } 32 | } 33 | 34 | return number; 35 | }; 36 | -------------------------------------------------------------------------------- /solutions/coffeescript/anagram-detection.coffee: -------------------------------------------------------------------------------- 1 | # Simple function that will take a string of latin characters and return a unique hash 2 | hashString = (str) -> 3 | # Map characters to prime numbers to multiply 4 | charMap = 5 | a: 2 6 | b: 3 7 | c: 5 8 | d: 7 9 | e: 11 10 | f: 13 11 | g: 17 12 | h: 19 13 | i: 23 14 | j: 29 15 | k: 31 16 | l: 37 17 | m: 41 18 | n: 43 19 | o: 47 20 | p: 53 21 | q: 59 22 | r: 61 23 | s: 67 24 | t: 71 25 | u: 73 26 | v: 79 27 | w: 83 28 | x: 89 29 | y: 97 30 | z: 101 31 | A: 103 32 | B: 107 33 | C: 109 34 | D: 113 35 | E: 127 36 | F: 131 37 | G: 137 38 | H: 139 39 | I: 149 40 | J: 151 41 | K: 163 42 | L: 167 43 | M: 173 44 | N: 179 45 | O: 181 46 | P: 191 47 | Q: 193 48 | R: 197 49 | S: 199 50 | T: 211 51 | U: 223 52 | V: 227 53 | W: 229 54 | X: 233 55 | Y: 239 56 | Z: 241 57 | 58 | str.split("").reduce ((memo, char) -> memo * charMap[char]), 1 59 | 60 | anagramDetection = (parent, child) -> 61 | length = child.length 62 | anagram = hashString(child) 63 | total = 0 64 | i = 0 65 | 66 | while i < (parent.length - length) 67 | total += 1 if hashString(parent.substr(i, length)) is anagram 68 | i++ 69 | total 70 | -------------------------------------------------------------------------------- /solutions/javascript/linked-list.js: -------------------------------------------------------------------------------- 1 | var LinkedList = module.exports = function (value) { 2 | this.value = value; 3 | this.prev = this; 4 | this.next = this; 5 | }; 6 | 7 | LinkedList.prototype.appendNode = function (value) { 8 | var node = new LinkedList(value); 9 | node.prev = this; 10 | node.next = this.next; 11 | // Fix the linked list references 12 | this.next = this.next.prev = node; 13 | return node; 14 | }; 15 | 16 | LinkedList.prototype.prependNode = function (value) { 17 | var node = new LinkedList(value); 18 | node.prev = this.prev; 19 | node.next = this; 20 | // Fix the linked list references 21 | this.prev = this.prev.next = node; 22 | return node; 23 | }; 24 | 25 | LinkedList.prototype.removeNode = function () { 26 | // Create a reference around the node to be removed 27 | this.prev.next = this.next; 28 | this.next.prev = this.prev; 29 | // Remove existing references to the current list 30 | this.next = this.prev = this; 31 | return this; 32 | }; 33 | 34 | LinkedList.prototype.containsNode = function (value) { 35 | if (this.value === value) { return true; } 36 | 37 | var node = this.next; 38 | // Loop through the connections until we hit ourselves again 39 | while (node !== this) { 40 | if (node.value === value) { 41 | return true; 42 | } 43 | node = node.next; 44 | } 45 | 46 | return false; 47 | }; 48 | -------------------------------------------------------------------------------- /solutions/javascript/matching-nodes.js: -------------------------------------------------------------------------------- 1 | /* global isMatchingNode */ 2 | 3 | // Make the function accept the node from the first tree and the second tree 4 | // where we need to find the matching node 5 | module.exports = function (node, tree) { 6 | // Easiest way to optimize this is to store the path from the node to the root 7 | // and then we can traverse back down the second tree following the same path 8 | var path = [node], 9 | // Use the child variable to find the matching node in the second tree 10 | child = tree; 11 | 12 | // Loop through all the parent nodes, pushing it into the stack as the pathway 13 | while (node = node.parentNode) { 14 | path.push(node); 15 | } 16 | 17 | // Pop the last thing we pushed onto the path since it'll be the root node 18 | // E.g. It'll be the tree that we are passing in anyway 19 | path.pop(); 20 | 21 | // Once the loop is done, we have the root node and can go back down the tree 22 | while (node = path.pop()) { 23 | for (var i = 0; i < child.childNodes.length; i++) { 24 | // Here we assume we have a function called `isMatchingNode` that returns 25 | // us a boolean in the case of two nodes matching each other 26 | if (isMatchingNode(node, child.childNodes[i])) { 27 | child = child.childNodes[i]; 28 | break; // Break looping over more nodes 29 | } 30 | } 31 | } 32 | 33 | return child; 34 | }; 35 | -------------------------------------------------------------------------------- /solutions/java/RemoveDuplicatesFromString.java: -------------------------------------------------------------------------------- 1 | // Program to remove duplicates from a given string 2 | // 1. getUniqueString(String) method uses a boolean array. 3 | // 2. removeDuplicates(String) method uses a hash map. 4 | // Both the methods have O(n) space and time complexity. (n being the string length) 5 | 6 | import java.util.HashMap; 7 | 8 | public class RemoveDuplicatesFromString { 9 | public static void main(String[] args) { 10 | RemoveDuplicatesFromString rsd = new RemoveDuplicatesFromString(); 11 | String input = "Tree Traversal"; 12 | System.out.println("Method 1: " +rsd.getUniqueString(input)); 13 | System.out.println("Method 2: " +rsd.removeDuplicates(input)); 14 | } 15 | 16 | public String getUniqueString(String input) { 17 | boolean[] isUsed = new boolean[256]; 18 | StringBuffer sb = new StringBuffer(); 19 | for (int i = 0; i < input.length(); i++) { 20 | int position = input.charAt(i); 21 | if (!isUsed[position]) { 22 | sb.append(input.charAt(i)); 23 | isUsed[position] = true; 24 | } 25 | } 26 | return sb.toString(); 27 | } 28 | 29 | public String removeDuplicates(String input) { 30 | HashMap map = new HashMap<>(); 31 | StringBuffer sb = new StringBuffer(""); 32 | for (int i = 0; i < input.length(); i++) { 33 | char c = input.charAt(i); 34 | if (!map.containsKey(c)) { 35 | sb.append(c); 36 | map.put(c, 1); 37 | } 38 | } 39 | return sb.toString(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/javascript/factorial.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var factorial = require('../../solutions/javascript/factorial'); 3 | 4 | describe('factorial', function () { 5 | // We have multiple factorial solutions to test, so loop through them 6 | Object.keys(factorial).forEach(function (name) { 7 | // Set the value in the object as the current solution to work against 8 | var solution = factorial[name]; 9 | // Use the name as part of the assertion name 10 | it(name + ' solution returns factorials', function () { 11 | // Bunch of simple assertions we know to be true 12 | assert.equal(solution(1), 1); 13 | assert.equal(solution(2), 2); 14 | assert.equal(solution(3), 6); 15 | assert.equal(solution(4), 24); 16 | assert.equal(solution(5), 120); 17 | assert.equal(solution(6), 720); 18 | assert.equal(solution(7), 5040); 19 | assert.equal(solution(8), 40320); 20 | assert.equal(solution(9), 362880); 21 | assert.equal(solution(10), 3628800); 22 | assert.equal(solution(11), 39916800); 23 | assert.equal(solution(12), 479001600); 24 | assert.equal(solution(13), 6227020800); 25 | assert.equal(solution(14), 87178291200); 26 | assert.equal(solution(15), 1307674368000); 27 | assert.equal(solution(16), 20922789888000); 28 | assert.equal(solution(17), 355687428096000); 29 | assert.equal(solution(18), 6402373705728000); 30 | assert.equal(solution(19), 121645100408832000); 31 | assert.equal(solution(20), 2432902008176640000); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /solutions/coffeescript/get-elements-by-class-name.coffee: -------------------------------------------------------------------------------- 1 | getElementsByClassName = (element, className) -> 2 | found = [] 3 | (traverseDom = (node) -> 4 | # Store the current node and current nodes class in a temporary variable 5 | currentNode = undefined 6 | currentClass = undefined 7 | 8 | # Loop through all the child nodes 9 | i = 0 10 | 11 | while i < node.childNodes.length 12 | currentNode = node.childNodes[i] 13 | currentClass = currentNode.className 14 | 15 | # Check if the class name exists within the current nodes class 16 | # I believe I learnt of this technique from jQuery source code 17 | found.push currentNode if currentClass and ~(" " + currentClass + " ").indexOf(" " + className + " ") 18 | 19 | # If the current node have more child nodes, continue traversing 20 | currentNode.childNodes and traverseDom(currentNode) 21 | i++ 22 | ) element 23 | found 24 | 25 | getElementsByClassName = (element, className) -> 26 | # This function takes an easier approach, using a regular expression and 27 | # getting all elements straight up using the asterisk selector 28 | found = [] 29 | regex = new RegExp("(^| )" + className + "($| )") 30 | elements = element.getElementsByTagName("*") 31 | 32 | # Loop through all the elements checking the class names against the 33 | # regular expression - when it suceeds just push it into the output array 34 | i = 0 35 | 36 | while i < elements.length 37 | found.push elements[i] if regex.test(elements[i].className) 38 | i++ 39 | found 40 | -------------------------------------------------------------------------------- /solutions/javascript/get-elements-by-class-name.js: -------------------------------------------------------------------------------- 1 | exports.traversal = function (element, className) { 2 | var found = []; 3 | var search = ' ' + className + ' '; 4 | 5 | (function traverse (node) { 6 | // Loop through all the child nodes 7 | for (var i = 0; i < node.childNodes.length; i++) { 8 | var currentNode = node.childNodes[i]; 9 | var currentClass = currentNode.className; 10 | 11 | // Check if the class name exists within the current nodes class 12 | // I believe I learnt of this technique from jQuery source code. 13 | if (currentClass && ~(' ' + currentClass + ' ').indexOf(search)) { 14 | found.push(currentNode); 15 | } 16 | 17 | // If the current node have more child nodes, continue traversing. 18 | currentNode.childNodes && traverse(currentNode); 19 | } 20 | })(element); 21 | 22 | return found; 23 | }; 24 | 25 | exports.regexp = function (element, className) { 26 | // This function takes an easier approach, using a regular expression and 27 | // getting all elements straight up using the asterisk selector. 28 | var found = []; 29 | var regex = new RegExp('(^| )' + className + '($| )'); 30 | var elements = element.getElementsByTagName('*'); 31 | 32 | // Loop through all the elements checking the class names against the 33 | // regular expression - when it suceeds just push it into the output array. 34 | for (var i = 0; i < elements.length; i++) { 35 | if (regex.test(elements[i].className)) { 36 | found.push(elements[i]); 37 | } 38 | } 39 | 40 | return found; 41 | }; 42 | -------------------------------------------------------------------------------- /tests/javascript/quick-sort.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var assert = require('assert'); 4 | var quickSort = require('../../solutions/javascript/quick-sort'); 5 | 6 | describe('Quick Sort', function(){ 7 | 8 | it('throws error if input not an array', function() { 9 | 10 | try { 11 | quickSort(null); 12 | } catch (err) { 13 | return; 14 | } 15 | 16 | assert(false, 'Expected exception to be thrown.'); 17 | }); 18 | 19 | it('handles empty list', function() { 20 | var results = quickSort([]); 21 | assert(Array.isArray(results), 'Expected result to be array'); 22 | assert(results.length === 0, 'Expected array to be empty'); 23 | }); 24 | 25 | it('handles list of one', function() { 26 | var results = quickSort([1]); 27 | assert.deepEqual(results, [1], 'Expected arrays to match'); 28 | }); 29 | 30 | it('sorts an array of numbers', function() { 31 | var unsorted = [9, 8, 7, 6, 5, 4, 3, 2, 1]; 32 | var sorted = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 33 | var results = quickSort(unsorted); 34 | assert.deepEqual(results, sorted, 'Expected arrays to match'); 35 | }); 36 | 37 | it('sorts an array of words', function() { 38 | var words = ['carrot','beta','apple']; 39 | var sorted = ['apple','beta','carrot']; 40 | var results = quickSort(words); 41 | 42 | assert.deepEqual(results, sorted, 'Expected arrays to match'); 43 | }); 44 | 45 | it('leaves input array intact', function() { 46 | var words = ['apple','beta','carrot']; 47 | quickSort(words); 48 | assert(words.length === 3); 49 | }); 50 | 51 | 52 | }); 53 | -------------------------------------------------------------------------------- /solutions/coffeescript/fibonacci.coffee: -------------------------------------------------------------------------------- 1 | # Implementing recursive solution 2 | fibonacci = (n) -> 3 | return fibonacci[n] if n of fibonacci 4 | 5 | # Store the fibonacci values on the function itself 6 | fibonacci[n] = (if (n < 2) then n else fibonacci(n - 1) + fibonacci(n - 2)) 7 | 8 | # Implementing iterative solution 9 | fibonacci = (n) -> 10 | results = [0, 1] 11 | if n > 2 12 | i = 2 13 | 14 | while i < n 15 | results[i] = results[i - 2] + results[i - 1] 16 | i++ 17 | results[n - 1] 18 | 19 | # Implementing O(logn) matrix solution 20 | fibonacci = (n) -> 21 | memo = [0, [[0, 1], [1, 1]]] 22 | matrixMultiply = (A, B) -> 23 | C = undefined 24 | if Array.isArray(B[0]) 25 | C = [[], []] 26 | C[0][0] = A[0][0] * B[0][0] + A[1][0] * B[0][1] 27 | C[0][1] = A[0][1] * B[0][0] + A[1][1] * B[0][1] 28 | C[1][0] = A[0][0] * B[1][0] + A[1][0] * B[1][1] 29 | C[1][1] = A[0][1] * B[1][0] + A[1][1] * B[1][1] 30 | else 31 | C = [] 32 | C[0] = A[0][0] * B[0] + A[1][0] * B[1] 33 | C[1] = A[0][1] * B[0] + A[1][1] * B[1] 34 | C 35 | 36 | # Calculates fibonacci spiral transformation matrix 37 | calcFibSpiral = (n) -> 38 | count = 1 39 | T = undefined 40 | if n & 1 41 | T = [[0, 1], [1, 1]] 42 | n -= 1 43 | else 44 | T = [[1, 0], [0, 1]] 45 | while n > 0 46 | count++ 47 | memo[count] = matrixMultiply(memo[count - 1], memo[count - 1]) unless memo[count] 48 | T = matrixMultiply(T, memo[count]) if (n >>= 1) & 1 49 | T 50 | 51 | matrixMultiply(calcFibSpiral(n - 2), [1, 1])[1] 52 | -------------------------------------------------------------------------------- /solutions/javascript/hotel-room.js: -------------------------------------------------------------------------------- 1 | module.exports = function (totalRooms) { 2 | var findDivisors = function (number) { 3 | var divisors = [], 4 | iterator = number; 5 | 6 | while (iterator--) { 7 | if (number % iterator === 0) { 8 | divisors.push(iterator); 9 | } 10 | } 11 | 12 | return divisors; 13 | }; 14 | 15 | // Returns true or false based on whether the number is found in the sum of 16 | // array subsets. 17 | var isSubsetSum = function (number, array) { 18 | var hasSubset = false; 19 | 20 | (function findSubset (total, numbers) { 21 | !hasSubset && (hasSubset = total === number); 22 | 23 | if (hasSubset || total > number) { return; } 24 | 25 | numbers.forEach(function (num, index) { 26 | return findSubset( 27 | total + num, 28 | numbers.slice(0, index).concat(numbers.slice(index + 1)) 29 | ); 30 | }); 31 | })(0, array); 32 | 33 | return hasSubset; 34 | }; 35 | 36 | // Need a simple helper method that returns the sum of an array. 37 | var sumArray = function (array) { 38 | return array.reduce(function (memo, num) { 39 | return memo + num; 40 | }, 0); 41 | }; 42 | 43 | // Find the room using the provided functions. 44 | var divisors; 45 | 46 | for (var room = 0; room <= totalRooms; room++) { 47 | divisors = findDivisors(room); 48 | 49 | // The sum of all the divisors must be greater than the number. 50 | if (sumArray(divisors) > room && !isSubsetSum(room, divisors)) { 51 | return room; 52 | } 53 | } 54 | 55 | return 0; // No room number found. 56 | }; 57 | -------------------------------------------------------------------------------- /solutions/java/BinarySearchTree.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Program to create a binary search tree. 3 | * Author: Viveka Aggarwal 4 | */ 5 | 6 | public class BinarySearchTree { 7 | Node root; 8 | public class Node { 9 | Node left; 10 | Node right; 11 | Integer data; 12 | 13 | Node() { 14 | } 15 | 16 | Node(Integer data) { 17 | left = right = null; 18 | this.data = data; 19 | } 20 | } 21 | 22 | BinarySearchTree() { 23 | root = new Node(); 24 | } 25 | 26 | BinarySearchTree(Integer data) { 27 | root = new Node(data); 28 | } 29 | 30 | public void addToTree(Integer data) { 31 | addToTree(root, data); 32 | } 33 | 34 | private void addToTree(Node curr, Integer data) { 35 | if(curr == null) { 36 | curr = new Node(data); 37 | } else if(curr.data.compareTo(data) >= 0) { 38 | if(curr.left == null) 39 | curr.left = new Node(data); 40 | else 41 | addToTree(curr.left, data); 42 | } else { 43 | if(curr.right == null) 44 | curr.right = new Node(data); 45 | else 46 | addToTree(curr.right, data); 47 | } 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | return toString(this.root); 53 | } 54 | 55 | String toString(Node curr) { 56 | if(curr == null) 57 | return ""; 58 | return toString(curr.left) + " " + curr.data + " " + toString(curr.right); 59 | } 60 | 61 | public static void main(String[] args) { 62 | BinarySearchTree tree = new BinarySearchTree(1); 63 | tree.addToTree(5); 64 | tree.addToTree(3); 65 | tree.addToTree(89); 66 | tree.addToTree(43); 67 | tree.addToTree(43); 68 | tree.addToTree(67); 69 | 70 | System.out.println(tree.toString()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/sh 2 | TEST_DIR := tests 3 | GTEST_DIR := $(TEST_DIR)/cpp/gtest 4 | 5 | 6 | # C++11 tests 7 | CPP_TESTS := stack-machine.cpp once.cpp stack.cpp queue.cpp spiral.cpp 8 | CPP_SOURCES := $(addprefix $(TEST_DIR)/cpp/, $(CPP_TESTS)) 9 | 10 | 11 | # OS specific settings 12 | UNAME_S = $(shell uname -s) 13 | ifeq ($(UNAME_S),Darwin) 14 | CXXFLAGS += -std=c++11 -stdlib=libc++ 15 | LDFLAGS += -lc++ 16 | CXX := clang++ 17 | else ifeq ($(UNAME_S),Linux) 18 | CXXFLAGS += --std=c++11 -g 19 | CXX := g++ 20 | endif 21 | 22 | 23 | # Languages 24 | default: 25 | @echo "Usage: make " 26 | @echo "Available languages: cpp, js" 27 | 28 | 29 | # Not recommended 30 | .IGNORE: cpp js 31 | all: .IGNORE 32 | 33 | 34 | # C++ build rules 35 | OTHER_SOURCES := $(TEST_DIR)/cpp/common.cpp 36 | FUSED_GTEST_SOURCES := $(GTEST_DIR)/gtest-all.cc $(GTEST_DIR)/gtest_main.cc 37 | CXXFLAGS += -DGTEST_HAS_PTHREAD=0 -DGTEST_HAS_TR1_TUPLE=0 -g 38 | CPP_OBJECTS := $(CPP_SOURCES:.cpp=.o) 39 | FUSED_GTEST_OBJECTS := $(FUSED_GTEST_SOURCES:.cc=.o) 40 | OTHER_OBJECTS := $(OTHER_SOURCES:.cpp=.o) 41 | cpp: hasGTest $(FUSED_GTEST_OBJECTS) $(CPP_OBJECTS) $(OTHER_OBJECTS) 42 | @$(CXX) $(LDFLAGS) \ 43 | $(CPP_OBJECTS) $(FUSED_GTEST_OBJECTS) $(OTHER_OBJECTS)\ 44 | -o cpp 45 | @./cpp 46 | @rm -rf cpp 47 | hasGTest: 48 | @if [ ! -f $(GTEST_DIR)/gtest.h ]; then \ 49 | git submodule update --init -f $(GTEST_DIR); \ 50 | fi 51 | .cpp.o: 52 | @$(CXX) $(CXXFLAGS) -c $< -o $@ 53 | .cc.o: 54 | @$(CXX) $(CXXFLAGS) -c $< -o $@ 55 | 56 | 57 | # JS build rules 58 | js: 59 | @npm install 2> /dev/null 60 | @npm test 61 | 62 | 63 | # Cleanup 64 | clean: 65 | @rm -f $(CPP_OBJECTS) $(FUSED_GTEST_OBJECTS) 66 | -------------------------------------------------------------------------------- /tests/javascript/byte-format.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var byteFormat = require('../../solutions/javascript/byte-format'); 3 | 4 | describe('Byte format', function() { 5 | it('should show B format', function() { 6 | expect(byteFormat(1022)).to.equal('1022 B'); 7 | }); 8 | 9 | it('should show KB format', function() { 10 | expect(byteFormat(10221)).to.equal('9.99 KB'); 11 | }); 12 | 13 | it('should show KB format rounded to 3 digital', function() { 14 | expect(byteFormat(10221, 3)).to.equal('9.982 KB'); 15 | }); 16 | 17 | it('should show MB format', function() { 18 | expect(byteFormat(1022932324)).to.equal('975.55 MB'); 19 | }); 20 | 21 | it('should show GB format', function() { 22 | expect(byteFormat(1022932123237)).to.equal('952.68 GB'); 23 | }); 24 | 25 | it('should show TB format', function() { 26 | expect(byteFormat(1022932453333234)).to.equal('930.36 TB'); 27 | }); 28 | 29 | it('should show PB format', function() { 30 | expect(byteFormat(1022932453333234444)).to.equal('908.55 PB'); 31 | }); 32 | 33 | it('should show EB format', function() { 34 | expect(byteFormat(1022932453333234444324)).to.equal('887.26 EB'); 35 | }); 36 | 37 | it('should show ZB format', function() { 38 | expect(byteFormat(1022932453333234444324454)).to.equal('866.46 ZB'); 39 | }); 40 | 41 | it('should show YB format', function() { 42 | expect(byteFormat(10243245333323444432445431)).to.equal('8.48 YB'); 43 | }); 44 | 45 | it('should show YB format when number larger than 1024YB', function() { 46 | var result = byteFormat(232932453333234444324454333424324); 47 | 48 | expect(result).to.equal('192677209.44 YB'); 49 | }); 50 | 51 | it('should not show any decimals', function () { 52 | expect(byteFormat(9999, 0)).to.equal('10 KB'); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /solutions/java/AnagramDetection.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Map; 3 | 4 | 5 | public class AnagramDetection { 6 | 7 | private Map charToPrimeMap; 8 | 9 | public AnagramDetection() { 10 | charToPrimeMap = new HashMap(); 11 | populateCharToPrimeMap(); 12 | } 13 | 14 | private boolean isPrime(int n) { 15 | for (int i = 2; i < Math.ceil(Math.sqrt(n)); ++i) { 16 | if (n % i == 0) { 17 | return false; 18 | } 19 | } 20 | return true; 21 | } 22 | 23 | private int getNthPrime(int n) { 24 | int nthPrime = 2; 25 | while(n > 0) { 26 | if (isPrime(nthPrime)) { 27 | --n; 28 | } 29 | ++nthPrime; 30 | } 31 | return nthPrime; 32 | } 33 | 34 | private void populateCharToPrimeMap() { 35 | for (int i = 0; i < 52; i += 2) { 36 | charToPrimeMap.put((char)('a'+i/2), getNthPrime(i/2)); 37 | charToPrimeMap.put(Character.toUpperCase((char)('a'+i/2)), getNthPrime(i/2+1)); 38 | } 39 | } 40 | 41 | private int hashString(String input) { 42 | int hash = 1; 43 | for (char c: input.toCharArray()) { 44 | hash *= charToPrimeMap.get(c); 45 | } 46 | return hash; 47 | } 48 | 49 | public int detectAnagrams(String original, String anagram) { 50 | char[] originalChars = original.toCharArray(); 51 | int anagramCount = 0; 52 | for (int i = 0; i < original.length() - anagram.length(); ++i) { 53 | String currentSubstring = String.copyValueOf(originalChars, i, anagram.length()); 54 | if (hashString(currentSubstring) == hashString(anagram)) { 55 | ++anagramCount; 56 | } 57 | } 58 | return anagramCount; 59 | } 60 | 61 | public static void main(String[] args) { 62 | AnagramDetection a = new AnagramDetection(); 63 | System.out.println(a.detectAnagrams("AdnBndAndBdaBn", "dAn")); 64 | System.out.println(a.detectAnagrams("AbrAcadAbRa", "cAda")); 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /solutions/java/TreeLevelOrderPrint.java: -------------------------------------------------------------------------------- 1 | // Program to create a Binary Search Tree and implement level order traversal. 2 | // Author: Viveka Aggarwal 3 | 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | 7 | public class TreeLevelOrderPrint { 8 | node root; 9 | class node { 10 | Integer value; 11 | node left; 12 | node right; 13 | 14 | node() { 15 | } 16 | 17 | node (Integer value) { 18 | this.value = value; 19 | } 20 | } 21 | 22 | public TreeLevelOrderPrint() { 23 | root = new node(); 24 | } 25 | 26 | public treelevelorderprint(Integer value) { 27 | root = new node(value); 28 | } 29 | 30 | public void addToTree(Integer value) { 31 | if (root.value == null) { 32 | root = new node(value); 33 | } else { 34 | addToTree(value, root); 35 | } 36 | } 37 | 38 | public void addToTree(Integer value, node curr) { 39 | if (value <= curr.value) { 40 | if (curr.left == null) 41 | curr.left = new node(value); 42 | else 43 | addToTree(value, curr.left); 44 | } else { 45 | if (curr.right == null) 46 | curr.right = new node(value); 47 | else 48 | addToTree(value, curr.right); 49 | } 50 | } 51 | 52 | public void levelOrder() { 53 | if (root == null || root.value == null) { 54 | System.out.println(); 55 | System.out.println("Empty tree!!!"); 56 | return; 57 | } 58 | 59 | Queue q = new LinkedList(); 60 | q.add(root); 61 | 62 | while(!q.isEmpty()) { 63 | node curr = q.poll(); 64 | System.out.print(curr.value + " "); 65 | 66 | if(curr.left != null) 67 | q.add(curr.left); 68 | 69 | if(curr.right != null) 70 | q.add(curr.right); 71 | } 72 | } 73 | 74 | public static void main(String[] args) { 75 | TreeLevelOrderPrint tree = new TreeLevelOrderPrint(); 76 | for (int i = 0; i <= 10; i++) { 77 | tree.addToTree(i); 78 | } 79 | tree.addToTree(5); 80 | tree.levelOrder(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /problems/async-task-runner/Readme.md: -------------------------------------------------------------------------------- 1 | # Async Task Runner 2 | 3 | Implement Asynchronous Task Runner 4 | 5 | A "TaskRunner" Constructor takes one argument, "concurrency", and exposes one method "push" on its prototype. The "push" method takes one argument "task" which is a "function": 6 | ```js 7 | function TaskRunner(concurrency) { /* TODO */ } 8 | 9 | TaskRunner.prototype.push = function push(task) { /* TODO */ } 10 | ``` 11 | 12 | "task" functions that can be passed to the push method have the following signature: 13 | 14 | ```js 15 | function exampleTask(done) { /* calls done() at some point */ } 16 | ``` 17 | 18 | Calling done signifies that a task is complete. 19 | 20 | A requirement of a task is that is has to call done at some point. 21 | 22 | done takes no arguments and merely signifies the task completion. 23 | 24 | Here are some examples of tasks: 25 | 26 | ```js 27 | function exampleSimpleTask(done) { 28 | setTimeout(done, Math.random() * 1000); 29 | } 30 | 31 | function exampleXhrTask(done) { 32 | makeARequestSomehow('http://website.api/foo', function (err, res) { 33 | doSomethingWithRes(res); 34 | done(); 35 | } 36 | } 37 | ``` 38 | 39 | Passing a task to a push method of a TaskRunner instance should immediately execute (call/run/invoke) the task, unless the number of currently running tasks exceeds the concurrency limit. 40 | 41 | If the number of tasks exceeds concurrency limit (which is passed to the TaskRunner constructor), the pushed task should wait until one of the running tasks has finished (has called done). 42 | 43 | Here's an example: 44 | 45 | ```js 46 | var runner = new TaskRunner(3); 47 | // use the exampleSimpleTask from above; 48 | 49 | runner.push(exampleSimpleTask); // executes immediately 50 | runner.push(exampleSimpleTask); // executes immediately 51 | runner.push(exampleSimpleTask); // executes immediately 52 | 53 | runner.push(exampleSimpleTask); // should wait until one of the running tasks completes 54 | runner.push(exampleSimpleTask); // should wait until one of the running tasks completes 55 | // ... 56 | ``` 57 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "maxerr": 100, // Maximum errors before stopping. 3 | "maxlen": 80, // Maximum line length. 4 | "quotmark": "single", // Consistent quotation mark usage. 5 | "bitwise": false, // Prohibit bitwise operators (&, |, ^, etc.). 6 | "curly": true, // Require {} for every new block or scope. 7 | "eqeqeq": true, // Require triple equals i.e. `===`. 8 | "forin": false, // Tolerate `for in` loops without `hasOwnPrototype`. 9 | "immed": true, // Require immediate invocations to be wrapped in parens. E.g. `(function(){})();`. 10 | "latedef": false, // Prohibit variable use before definition. 11 | "newcap": true, // Require capitalization of all constructor functions. E.g. `new F()`. 12 | "noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`. 13 | "noempty": true, // Prohibit use of empty blocks. 14 | "nonew": true, // Prohibit use of constructors for side-effects. 15 | "undef": true, // Require all non-global variables be declared before they are used. 16 | "unused": true, // Warn when creating a variable but never using it. 17 | "plusplus": false, // Prohibit use of `++` & `--`. 18 | "regexp": false, // Prohibit `.` and `[^...]` in regular expressions. 19 | "strict": false, // Require `use strict` pragma in every file. 20 | "trailing": true, // Prohibit trailing whitespaces. 21 | "boss": true, // Tolerate assignments inside if, for and while. Usually conditions and loops are for comparison, not assignments. 22 | "multistr": false, // Prohibit the use of multi-line strings. 23 | "eqnull": true, // Tolerate use of `== null`. 24 | "expr": true, // Tolerate `ExpressionStatement` as Programs. 25 | "browser": true, // Standard browser globals e.g. `window`, `document`. 26 | "node": true, // Enable standard globals available when code is running inside of the NodeJS runtime environment. 27 | "globals": { 28 | "it": true, 29 | "describe": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /solutions/java/HotelRoom.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | public class HotelRoom { 4 | public static void main(String[] args) { 5 | HotelRoom hr = new HotelRoom(); 6 | Integer found = hr.getRoomNumber(100); 7 | if (found != null) 8 | System.out.print(found); 9 | } 10 | 11 | public Integer getRoomNumber(int n) { 12 | for (int i = 2; i <= n; i = i + 2) { 13 | // We know off the bat that its not a prime number, nor an odd number. 14 | ArrayList factors = new ArrayList(); 15 | int index = 1; 16 | int factorSum = 0; 17 | while (index <= i / 2) { 18 | // If i is a factor 19 | if (i % index == 0) { 20 | factorSum += index; 21 | factors.add(index); 22 | } 23 | index++; 24 | } 25 | // We have the sum of factors here. Check if its greater than the 26 | // number itself. 27 | if (factorSum > i) { 28 | // Find sums of all the subsets of the factors 29 | Integer foundNumber = checkSubsetSum(factors, i); 30 | if (foundNumber != null) 31 | return foundNumber; 32 | else 33 | continue; 34 | } else { 35 | continue; 36 | } 37 | } 38 | return null; 39 | } 40 | 41 | public Integer checkSubsetSum(ArrayList factors, int n) { 42 | ArrayList> result = new ArrayList>(); 43 | for (Integer i : factors) { 44 | ArrayList> temp = new ArrayList>(); 45 | // Get all the elements already in the result 46 | for (ArrayList a : result) 47 | temp.add(new ArrayList(a)); 48 | 49 | // Add i to each of these subsets 50 | for (ArrayList a : temp) 51 | a.add(i); 52 | 53 | // Add i by itself 54 | ArrayList single = new ArrayList(); 55 | single.add(i); 56 | temp.add(single); 57 | result.addAll(temp); 58 | } 59 | 60 | boolean matched = true; 61 | for (ArrayList al : result) { 62 | int sum = 0; 63 | for (Integer i : al) 64 | sum += i; 65 | if (sum == n) 66 | matched = false; 67 | } 68 | if (matched) 69 | return n; 70 | return null; 71 | } 72 | } -------------------------------------------------------------------------------- /solutions/javascript/spiral.js: -------------------------------------------------------------------------------- 1 | var generateGrid = function (width, height) { 2 | var output = [], 3 | number = 0; 4 | 5 | for (var i = 0; i < height; i++) { 6 | for (var l = 0; l < width; l++) { 7 | output[i] || (output[i] = []); 8 | output[i].push(number += 1); 9 | } 10 | } 11 | 12 | return output; 13 | }; 14 | 15 | var spiralTraversal = function (grid, top, left) { 16 | var length = 1, // This will be the length to traverse to 17 | output = [], 18 | UP = 0, 19 | LEFT = 1, 20 | DOWN = 2, 21 | RIGHT = 3, 22 | maxLength, 23 | pushNumber; 24 | 25 | top = top - 1; 26 | left = left - 1; 27 | 28 | maxLength = (grid.length > grid[0].length ? grid.length : grid[0].length); 29 | 30 | pushNumber = function (y, x) { 31 | top = y; 32 | left = x; 33 | return grid[top] && grid[top][left] && output.push(grid[top][left]); 34 | }; 35 | 36 | // Push the first number into the output array 37 | pushNumber(top, left); 38 | 39 | (function traverse (direction, length) { 40 | var i = length; 41 | 42 | while (i--) { 43 | if (direction === UP) { 44 | pushNumber(top - 1, left); 45 | } else if (direction === LEFT) { 46 | pushNumber(top, left - 1); 47 | } else if (direction === DOWN) { 48 | pushNumber(top + 1, left); 49 | } else if (direction === RIGHT) { 50 | pushNumber(top, left + 1); 51 | } 52 | } 53 | 54 | // When the length is longer than the max length, break recursion 55 | if (length > maxLength) { return; } 56 | 57 | // When we are finished going left or rigth, increase the length 58 | if (direction === LEFT || direction === RIGHT) { length += 1; } 59 | 60 | // Change the direction of traversal 61 | direction += 1; 62 | if (direction > RIGHT) { direction = 0; } 63 | 64 | traverse(direction, length); 65 | 66 | })(UP, length); 67 | 68 | return output; 69 | }; 70 | 71 | // Generate the traversed output 72 | module.exports = function (h, w, r, c) { 73 | return spiralTraversal(generateGrid(w, h), r, c); 74 | }; 75 | -------------------------------------------------------------------------------- /solutions/javascript/fibonnaci.js: -------------------------------------------------------------------------------- 1 | // Implementing recursive solution 2 | exports.recursive = function fibonacci (n) { 3 | if (n in fibonacci) { return fibonacci[n]; } 4 | // Store the fibonacci values on the function itself 5 | return fibonacci[n] = (n < 2) ? n : fibonacci(n - 1) + fibonacci(n - 2); 6 | }; 7 | 8 | // Implementing iterative solution 9 | exports.iterative = function fibonacci (n) { 10 | var results = [0, 1]; 11 | 12 | if (n > 2) { 13 | for (var i = 2; i < n; i++) { 14 | results[i] = results[i - 2] + results[i - 1]; 15 | } 16 | } 17 | 18 | return results[n - 1]; 19 | }; 20 | 21 | // Implementing O(logn) matrix solution 22 | exports.matrix = function (n) { 23 | var memo = [0, [[0, 1], [1, 1]]]; 24 | 25 | var matrixMultiply = function (A, B) { 26 | var C; 27 | 28 | if (Array.isArray(B[0])) { 29 | C = [[], []]; 30 | C[0][0] = A[0][0] * B[0][0] + A[1][0] * B[0][1]; 31 | C[0][1] = A[0][1] * B[0][0] + A[1][1] * B[0][1]; 32 | C[1][0] = A[0][0] * B[1][0] + A[1][0] * B[1][1]; 33 | C[1][1] = A[0][1] * B[1][0] + A[1][1] * B[1][1]; 34 | } else { 35 | C = []; 36 | C[0] = A[0][0] * B[0] + A[1][0] * B[1]; 37 | C[1] = A[0][1] * B[0] + A[1][1] * B[1]; 38 | } 39 | 40 | return C; 41 | }; 42 | 43 | // Calculates fibonacci spiral transformation matrix 44 | var calcFibSpiral = function (n) { 45 | var count = 1; 46 | var T; 47 | 48 | if (n & 1) { 49 | T = [[0, 1], [1, 1]]; 50 | n -= 1; 51 | } else { 52 | T = [[1, 0], [0,1 ]]; 53 | } 54 | 55 | while (n > 0) { 56 | count++; 57 | if (!memo[count]) { 58 | memo[count] = matrixMultiply(memo[count - 1], memo[count - 1]); 59 | } 60 | if ((n >>= 1) & 1) { 61 | T = matrixMultiply(T, memo[count]); 62 | } 63 | } 64 | 65 | return T; 66 | }; 67 | 68 | return matrixMultiply(calcFibSpiral(n - 2), [1, 1])[1]; 69 | }; 70 | 71 | // Implements closed form solution. 72 | exports.closedForm = (function (phi) { 73 | return function (n) { 74 | return Math.floor(Math.pow(phi, n) / Math.sqrt(5) + 0.5); 75 | }; 76 | })((1 + Math.sqrt(5)) / 2); 77 | -------------------------------------------------------------------------------- /solutions/java/LongestCompoundWord.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashMap; 3 | 4 | public class LongestCompoundWord { 5 | HashMap suffixTree = new HashMap(); 6 | ArrayList queue = new ArrayList(); 7 | 8 | public static void main(String[] args) { 9 | LongestCompoundWord lcw = new LongestCompoundWord(); 10 | String[] input = { "cat", "cats", "catsdogcats", "catxdogcatsrat", 11 | "dog", "dogcatsdog", "hippopotamuses", "rat", "ratcat", 12 | "ratcatdog", "ratcatdogcat" }; 13 | System.out.println(lcw.getWord(input)); 14 | } 15 | 16 | public String getWord(String[] input) { 17 | String LongestWord = ""; 18 | // First round 19 | for (int i = 0; i < input.length; i++) { 20 | ArrayList suffixes = getSuffixesForPrefixes(input[i], 21 | input[i]); 22 | if (suffixes.size() > 0) { 23 | // Add the pair of original word and suffix to the queue 24 | queue.addAll(suffixes); 25 | } 26 | suffixTree.put(input[i], input[i]); 27 | } 28 | 29 | // Empty the queue while searching for longest word 30 | while (!queue.isEmpty()) { 31 | String[] probePair = queue.get(0); 32 | // Find possible valid and compound words 33 | if (suffixTree.containsKey(probePair[1])) { // Valid word 34 | if (probePair[0].length() > LongestWord.length()) 35 | LongestWord = probePair[0]; 36 | } else { 37 | ArrayList suffixes = getSuffixesForPrefixes( 38 | probePair[0], probePair[1]); 39 | if (suffixes.size() > 0) { 40 | // Add the pair of original word and suffix to the queue 41 | queue.addAll(suffixes); 42 | } 43 | } 44 | queue.remove(0); 45 | } 46 | return LongestWord; 47 | } 48 | 49 | public ArrayList getSuffixesForPrefixes(String originalWord, 50 | String word) { 51 | ArrayList suffixes = new ArrayList(); 52 | for (int i = 1; i <= word.length(); i++) { 53 | if (suffixTree.containsKey(word.substring(0, i))) { 54 | String[] pair = new String[2]; 55 | pair[0] = originalWord; 56 | pair[1] = word.substring(i); 57 | suffixes.add(pair); 58 | } 59 | } 60 | return suffixes; 61 | } 62 | } -------------------------------------------------------------------------------- /tests/javascript/binary-search-tree-check.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var isBST = require('../../solutions/javascript/binary-search-tree-check'); 3 | 4 | var pass = { 5 | value: 8, 6 | left: { 7 | value: 3, 8 | left: { 9 | value: 1 10 | }, 11 | right: { 12 | value: 6, 13 | left: { 14 | value: 4 15 | }, 16 | right: { 17 | value: 7 18 | } 19 | } 20 | }, 21 | right: { 22 | value: 10, 23 | right: { 24 | value: 14, 25 | left: { 26 | value: 13 27 | } 28 | } 29 | } 30 | }; 31 | 32 | var failLeft = { 33 | value: 10, 34 | left: { 35 | value: 8, 36 | left: { 37 | value: 9 38 | }, 39 | right: { 40 | value: 10 41 | } 42 | }, 43 | right: { 44 | value: 12 45 | } 46 | }; 47 | 48 | var failRight = { 49 | value: 22, 50 | left: { 51 | value: 19 52 | }, 53 | right: { 54 | value: 29, 55 | left: { 56 | value: 26 57 | }, 58 | right: { 59 | value: 27 60 | } 61 | } 62 | }; 63 | 64 | var failDuplicate = { 65 | value: 13, 66 | left: { 67 | value: 10, 68 | left: { 69 | value: 7 70 | }, 71 | right: { 72 | value: 13 73 | } 74 | }, 75 | right: { 76 | value: 15 77 | } 78 | }; 79 | 80 | var bstFalse = { 81 | value: 3, 82 | left: { 83 | value: 2, 84 | right: { 85 | value: 10 86 | } 87 | }, 88 | right: { 89 | value: 5 90 | } 91 | }; 92 | 93 | describe('binary search tree check', function () { 94 | it('should pass a valid binary search tree', function () { 95 | assert.ok(isBST(pass)); 96 | }); 97 | 98 | it('should fail with a left subtree that is greater', function () { 99 | assert.ok(!isBST(failLeft)); 100 | }); 101 | 102 | it('should fail with a right subtree that is smaller', function () { 103 | assert.ok(!isBST(failRight)); 104 | }); 105 | 106 | it('should fail with duplicate nodes', function () { 107 | assert.ok(!isBST(failDuplicate)); 108 | }); 109 | 110 | it('should fail with bstFalse', function () { 111 | assert.ok(!isBST(bstFalse)); 112 | }); 113 | }); 114 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Code Problems 2 | 3 | This is my repo full of code problems that I have completed prior to or during an interview, as well as general problem snippets. I hope that all these problems (and solutions) are useful to others for practice and review. Feel free to contribute any solutions and optimisations, and add your own problems that you find as well, as I would love to see them. 4 | 5 | ## Problems 6 | 7 | ### Sorting Algorithms 8 | 9 | * [Quick Sort](https://github.com/blakeembrey/code-problems/tree/master/problems/quick-sort) 10 | * [Bubble Sort](https://github.com/blakeembrey/code-problems/tree/master/problems/bubble-sort) 11 | * [Merge Sort](https://github.com/blakeembrey/code-problems/tree/master/problems/merge-sort) 12 | * [Selection Sort](https://github.com/blakeembrey/code-problems/tree/master/problems/selection-sort) 13 | * [Insertion Sort](https://github.com/blakeembrey/code-problems/tree/master/problems/insertion-sort) 14 | 15 | ### Data Structures 16 | 17 | * [Stack](https://github.com/blakeembrey/code-problems/tree/master/problems/stack) 18 | * [Queue](https://github.com/blakeembrey/code-problems/tree/master/problems/queue) 19 | * [Linked List](https://github.com/blakeembrey/code-problems/tree/master/problems/linked-list) 20 | * [Binary Search Tree Check](https://github.com/blakeembrey/code-problems/tree/master/problems/binary-search-tree-check) *Not an implementation, checks for a valid implementation* 21 | 22 | ### DOM Problems 23 | 24 | * [Get Elements By Class Name](https://github.com/blakeembrey/code-problems/tree/master/problems/get-elements-by-class-name) 25 | 26 | ### Shortest Code Problems 27 | 28 | * [Shortest Fizz Buzz](https://github.com/blakeembrey/code-problems/tree/master/problems/shortest-fizz-buzz) 29 | 30 | ## Tests 31 | 32 | ```sh 33 | npm install # Installs `mocha` and any other dependencies needed to run 34 | npm test # Runs the testing scripts 35 | ``` 36 | 37 | ## Contributing 38 | 39 | If you have a problem or solution that's not currently not included, please open an issue or pull request! If you're including new content, please make sure you have permission to publish the content you are adding. Under no circumstance should you copy problems online without a visible license or attributions, or from coding interview websites such as [Codility](https://codility.com/). 40 | -------------------------------------------------------------------------------- /solutions/javascript/anagram-detection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * An key, value map of characters to unique prime numbers. 3 | * 4 | * @type {Object} 5 | */ 6 | var primeMap = (function () { 7 | var map = {}; 8 | 9 | var primes = [ 10 | 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 11 | 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 12 | 151, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 13 | 239, 241 14 | ]; 15 | 16 | var alphabet = [ 17 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 18 | 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 19 | 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 20 | 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' 21 | ]; 22 | 23 | // Merge the primes and alphabet together, using the letters as keys. 24 | alphabet.forEach(function (letter, index) { 25 | map[letter] = primes[index]; 26 | }); 27 | 28 | return map; 29 | })(); 30 | 31 | /** 32 | * Hash a string using the prime number map. 33 | * 34 | * @param {String} str 35 | * @return {Number} 36 | */ 37 | var hash = function (str) { 38 | return str.split('').reduce(function (memo, char) { 39 | return memo * primeMap[char]; 40 | }, 1); 41 | }; 42 | 43 | /** 44 | * Count the number of times a child or anagram of the child appears in the 45 | * parent string. 46 | * 47 | * @param {String} parent 48 | * @param {String} child 49 | * @return {Number} 50 | */ 51 | module.exports = function (parent, child) { 52 | var found = 0; 53 | 54 | // Safety first, confirm that the child is actually smaller than the parent. 55 | if (parent.length < child.length) { 56 | return found; 57 | } 58 | 59 | var value = hash(parent.substr(0, child.length)); 60 | var anagram = hash(child); 61 | 62 | // Iterate over all substring possibilities and check the hash values. 63 | for (var i = child.length; i <= parent.length; i++) { 64 | if (value === anagram) { 65 | found += 1; 66 | } 67 | 68 | // Instead of naively hashing every substring, we can just recompute the 69 | // changed characters. 70 | value *= primeMap[parent[i]]; 71 | value /= primeMap[parent[i - child.length]]; 72 | } 73 | 74 | return found; 75 | }; 76 | -------------------------------------------------------------------------------- /problems/skiing-in-singapore/README.md: -------------------------------------------------------------------------------- 1 | # Skiing in Singapore 2 | Sometimes it's nice to take a break and code up a solution to a small, fun problem. Here is one some of our engineers enjoyed recently called Skiing In Singapore. 3 | 4 | Well you can’t really ski in Singapore. But let’s say you hopped on a flight to the Niseko ski resort in Japan. Being a software engineer you can’t help but value efficiency, so naturally you want to ski as long as possible and as fast as possible without having to ride back up on the ski lift. So you take a look at the map of the mountain and try to find the longest ski run down. 5 | 6 | In digital form the map looks like the number grid below. 7 | 8 | 4 4 9 | 4 8 7 3 10 | 2 5 9 3 11 | 6 3 2 5 12 | 4 4 1 6 13 | 14 | The first line (4 4) indicates that this is a 4x4 map. Each number represents the elevation of that area of the mountain. From each area (i.e. box) in the grid you can go north, south, east, west - but only if the elevation of the area you are going into is less than the one you are in. I.e. you can only ski downhill. You can start anywhere on the map and you are looking for a starting point with the longest possible path down as measured by the number of boxes you visit. And if there 15 | are several paths down of the same length, you want to take the one with the steepest vertical drop, i.e. the largest difference between your starting elevation and your ending elevation. 16 | 17 | On this particular map the longest path down is of length=5 and it’s highlighted in bold below: 9-5-3-2-1. 18 | 19 | 4 4 20 | 4 8 7 3 21 | 2 5 9 3 22 | 6 3 2 5 23 | 4 4 1 6 24 | 25 | There is another path that is also length five: 8-5-3-2-1. However the tie is broken by the first path being steeper, dropping from 9 to 1, a drop of 8, rather than just 8 to 1, a drop of 7. 26 | 27 | Your challenge is to write a program in your favorite programming language to find the longest (and then steepest) path on this map specified in the format above. It’s 1000x1000 in size, and all the numbers on it are between 0 and 1500. 28 | 29 | Send your code or a github link (and a resume if you like) to [?????? at redmart dot com], replacing “??????” with the concatenation of the length of the longest path with the largest drop, and the size of the drop. So in the simple example above length=5, drop=8, so the email address would be [58 at redmart dot com]. If your e-mail gets through - you got the right answer. 30 | 31 | Good luck and have fun! 32 | -------------------------------------------------------------------------------- /solutions/java/CombineTwoStrings.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Stack; 3 | 4 | /** 5 | * 6 | * One possible solution is to concatenate first and second string, then find 7 | * all possible anagrams of that string, and finally check if the third string 8 | * is present in one of the anagrams. Works! But the problem is generating the 9 | * anagrams. Deteriorates the complexity. 10 | * 11 | * Another solution is to compromise of the space complexity a little, and make 12 | * use of a stack as below. 13 | * 14 | * Addition: We could also use a HashMap to record the rank of each character 15 | * in the combined string and check the two input strings as below. 16 | */ 17 | public class CombineTwoStrings { 18 | public static void main(String[] args) { 19 | CombineTwoStrings cts = new CombineTwoStrings(); 20 | String one = "rohit"; 21 | String two = "deepthi"; 22 | String three = "viveka"; 23 | String combined = "rodehepitht"; 24 | String combined2 = "rviovehkiat"; 25 | System.out.println(cts.isValid(one, two, combined)); 26 | System.out.println(cts.isValidTwo(one, three, combined2)); 27 | 28 | } 29 | 30 | public boolean isValid(String one, String two, String combined) { 31 | Stack s = new Stack(); 32 | if ((one.length() + two.length()) != combined.length()) 33 | return false; 34 | for (int i = combined.length() - 1; i >= 0; i--) { 35 | s.push(combined.charAt(i)); 36 | } 37 | int oneIndex = 0; 38 | int twoIndex = 0; 39 | while (!s.isEmpty() && oneIndex < one.length() 40 | && twoIndex < two.length()) { 41 | char comparer = s.pop(); 42 | if (comparer == one.charAt(oneIndex)) 43 | oneIndex++; 44 | else if (comparer == two.charAt(twoIndex)) 45 | twoIndex++; 46 | else 47 | return false; 48 | } 49 | return true; 50 | } 51 | 52 | // Used a hashMap to save the rank of each character in the combined string. 53 | // Incrementing the pointer of respective string as per the rank in the 54 | // combined string. 55 | public boolean isValidTwo(String one, String two, String combined) { 56 | if(one.length() + two.length() != combined.length()) 57 | return false; 58 | HashMap map = new HashMap<>(); 59 | int key = 0, p1 = 0, p2 = 0, pT = 0; 60 | for(Character i : combined.toCharArray()) { 61 | map.put(key++, i); 62 | } 63 | 64 | while(p1 <= one.length() - 1 && p2 <= two.length() - 1 && pT <= combined.length() - 1) { 65 | char temp = map.get(pT++); 66 | if(one.charAt(p1) == temp) 67 | p1++; 68 | else if (two.charAt(p2) == temp) 69 | p2++; 70 | else 71 | return false; 72 | } 73 | return true; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /solutions/javascript/median-integer-stream.js: -------------------------------------------------------------------------------- 1 | // This question is easier for me to visualise using a linked list and keeping 2 | // track of the median node in the linked list - then inserting either before 3 | // or after the node and moving the node left/right. 4 | 5 | var LinkedList = function (value) { 6 | this.value = value; 7 | }; 8 | 9 | LinkedList.prototype.append = function (value) { 10 | var node = new LinkedList(value); 11 | node.prev = this; 12 | node.next = this.next; 13 | // Fix the linked list node references. 14 | this.next && (this.next.prev = node); 15 | this.next = node; 16 | return node; 17 | }; 18 | 19 | LinkedList.prototype.prepend = function (value) { 20 | var node = new LinkedList(value); 21 | node.prev = this.prev; 22 | node.next = this; 23 | // Fix the linked list node references. 24 | this.prev && (this.prev.next = node); 25 | this.prev = node; 26 | return node; 27 | }; 28 | 29 | module.exports = function () { 30 | return { 31 | insert: function (number) { 32 | if (!this._median) { 33 | this._median = new LinkedList(number); 34 | return; 35 | } 36 | 37 | var node = this._median; 38 | var prevNode; 39 | 40 | // If the number is greater than the median value, need to insert 41 | // somewhere after the current median node. 42 | if (number > this._median.value) { 43 | while (node && node.value < number) { 44 | prevNode = node; 45 | node = node.next; 46 | } 47 | (node || prevNode).append(number); 48 | // Increment the counter of right nodes. 49 | ++this._right; 50 | } else { 51 | while (node && node.value > number) { 52 | prevNode = node; 53 | node = node.prev; 54 | } 55 | (node || prevNode).prepend(number); 56 | // Increment the counter of left nodes. 57 | ++this._left; 58 | } 59 | 60 | // If the left nodes are larger than the right nodes, move the median 61 | // pointer. 62 | if (this._left > this._right + 1) { 63 | this._median = this._median.prev; 64 | --this._left; 65 | ++this._right; 66 | } else if (this._left < this._right) { 67 | this._median = this._median.next; 68 | ++this._left; 69 | --this._right; 70 | } 71 | }, 72 | getMedian: function () { 73 | // If the left and right node counts are identical, we can return the 74 | // value exactly. 75 | if (this._left === this._right) { 76 | return this._median.value; 77 | } 78 | 79 | return (this._median.value + (this._median.prev.value)) / 2; 80 | }, 81 | // Hold the median node in the list. 82 | _median: null, 83 | // Keep track of how many left and right nodes have been. 84 | _left: 0, 85 | _right: 0 86 | }; 87 | }; 88 | -------------------------------------------------------------------------------- /solutions/javascript/longest-compound-word.js: -------------------------------------------------------------------------------- 1 | module.exports = function (list) { 2 | var prefixes = {}; 3 | var possibleWords = []; 4 | var longestWords = []; 5 | var longestLength = 0; 6 | 7 | // Inserts a word into the prefix tree structure. 8 | var insertWord = function (word) { 9 | var index = 0; 10 | var active = prefixes; 11 | var char; 12 | 13 | while (char = word[index++]) { 14 | active = (active[char] = active[char] || {}); 15 | } 16 | 17 | active.word = true; 18 | }; 19 | 20 | // Finds the longest prefix we can make using the word. 21 | var findPrefixes = function (word) { 22 | var prefix = ''; 23 | var found = []; 24 | var index = 0; 25 | var active = prefixes; 26 | var char; 27 | 28 | while (char = word[index++]) { 29 | if (!active[char]) { break; } 30 | // Move to the next character and add to the prefix. 31 | active = active[char]; 32 | prefix += char; 33 | // If this index is a word, set it found to true. 34 | active.word && found.push(prefix); 35 | } 36 | 37 | return found; 38 | }; 39 | 40 | // Loop through each of words in the list, adding them to the prefixes tree 41 | list.forEach(function (word) { 42 | var prefix; 43 | 44 | // If we can find a closest possible word, it may be possible to create a 45 | // compound word - but we won't be able to check until we reach the end. 46 | if ((prefix = findPrefixes(word)) && prefix.length) { 47 | possibleWords.push([ word, prefix ]); 48 | } 49 | 50 | // Insert the word into the prefix tree. 51 | insertWord(word); 52 | }); 53 | 54 | possibleWords.forEach(function (possible) { 55 | var word = possible[0]; 56 | var prefixes = possible[1]; 57 | var found = false; 58 | 59 | var findCompoundWord = function (suffix) { 60 | // Find all future prefixes and continue search. 61 | if (suffix) { 62 | return findPrefixes(suffix).forEach(function (prefix) { 63 | !found && loopPrefixes(prefix, suffix); 64 | }); 65 | } 66 | 67 | // If the suffix doesn't exist, it must be because we have found an 68 | // exact compound word. 69 | if (word.length > longestLength) { 70 | longestWords = []; 71 | longestLength = word.length; 72 | } 73 | 74 | // If the word is equal to the length of the current longest word, push it 75 | // into the result array, then set found to be true so we can break the 76 | // other recursions. 77 | if (word.length === longestLength) { 78 | found = true; 79 | longestWords.push(word); 80 | } 81 | }; 82 | 83 | var loopPrefixes = function (prefix, word) { 84 | findCompoundWord(word.substr(prefix.length)); 85 | }; 86 | 87 | prefixes.forEach(function (prefix) { 88 | loopPrefixes(prefix, word); 89 | }); 90 | }); 91 | 92 | return longestWords; 93 | }; 94 | -------------------------------------------------------------------------------- /solutions/java/Spiral.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Spiral { 4 | 5 | private enum Direction { 6 | UP, DOWN, LEFT, RIGHT 7 | } 8 | 9 | private boolean isCoordinateValid(int height, int width, int row, int column) { 10 | return (row > 0 && row <= height) && (column > 0 && column <= width); 11 | } 12 | 13 | private int getNumberAtCoordinate(int width, int row, int column) { 14 | return column + (row - 1) * width; 15 | } 16 | 17 | private int[] getNextCoordinate(int row, int column, Direction currentDirection) { 18 | int[] nextCoordinate = new int[2]; 19 | nextCoordinate[0] = row; 20 | nextCoordinate[1] = column; 21 | switch (currentDirection) { 22 | case UP: 23 | nextCoordinate[0] -= 1; 24 | break; 25 | case LEFT: 26 | nextCoordinate[1] -= 1; 27 | break; 28 | case DOWN: 29 | nextCoordinate[0] += 1; 30 | break; 31 | case RIGHT: 32 | nextCoordinate[1] += 1; 33 | break; 34 | } 35 | return nextCoordinate; 36 | } 37 | 38 | private Direction getNextDirection(Direction currentDirection) { 39 | switch (currentDirection) { 40 | case UP: 41 | return Direction.LEFT; 42 | case LEFT: 43 | return Direction.DOWN; 44 | case DOWN: 45 | return Direction.RIGHT; 46 | case RIGHT: 47 | return Direction.UP; 48 | default: 49 | return currentDirection; 50 | } 51 | } 52 | 53 | public int[] spiral(int height, int width, int row, int column) { 54 | int numberOfElements = height * width; 55 | int[] output = new int[numberOfElements]; 56 | int outputIndex = 0; 57 | Direction currentDirection = Direction.UP; 58 | int stepsTaken = 0; 59 | int stepsNeeded = 1; 60 | while (outputIndex < numberOfElements) { 61 | if (isCoordinateValid(height, width, row, column)) { 62 | output[outputIndex++] = getNumberAtCoordinate(width, row, column); 63 | } 64 | int[] nextCoordinate = getNextCoordinate(row, column, currentDirection); 65 | row = nextCoordinate[0]; 66 | column = nextCoordinate[1]; 67 | ++stepsTaken; 68 | if (stepsTaken == stepsNeeded) { 69 | if (currentDirection == Direction.LEFT || currentDirection == Direction.RIGHT) { 70 | ++stepsNeeded; 71 | } 72 | stepsTaken = 0; 73 | currentDirection = getNextDirection(currentDirection); 74 | } 75 | } 76 | return output; 77 | } 78 | 79 | public static void main(String[] args) { 80 | Spiral s = new Spiral(); 81 | System.out.println(Arrays.toString(s.spiral(5, 5, 3, 3))); 82 | System.out.println(Arrays.toString(s.spiral(2, 4, 1, 2))); 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /solutions/javascript/binary-search-tree.js: -------------------------------------------------------------------------------- 1 | var root, 2 | createNode, 3 | add, 4 | search, 5 | addSubNode, 6 | findRightMost, 7 | replaceNodeInParent, 8 | binaryTreeDelete; // not overwrite keyword. 9 | 10 | createNode = function createNode(num) { 11 | return { 12 | add: add, 13 | search: search, 14 | delete: binaryTreeDelete, 15 | left: undefined, 16 | right: undefined, 17 | value: num 18 | }; 19 | }; 20 | 21 | addSubNode = function(node, direct, num) { 22 | if (node[direct] === undefined) { 23 | node[direct] = createNode(num); 24 | } else { 25 | node[direct].add(num); 26 | } 27 | }; 28 | 29 | add = function(num) { 30 | // Add the value to the correct side of the binary search tree. 31 | // If the value is the same as the current node, we'll just ignore it. 32 | if (this.value === undefined) { 33 | this.value = num; 34 | } else { 35 | if (num < this.value) { 36 | addSubNode(this, 'left', num); 37 | } else if (num > this.value) { 38 | addSubNode(this, 'right', num); 39 | } 40 | } 41 | return root; 42 | }; 43 | 44 | search = function(num) { 45 | if (num === this.value) { 46 | return this; 47 | } else if (num < this.value && this.left) { 48 | return this.left.search(num); 49 | } else if (num > this.value && this.right) { 50 | return this.right.search(num); 51 | } else { 52 | return false; 53 | } 54 | }; 55 | 56 | findRightMost = function(node) { 57 | if (node.right === undefined) { 58 | return node; 59 | } 60 | return findRightMost(node.right); 61 | }; 62 | 63 | replaceNodeInParent = function(node, parent, newNode) { 64 | // root's parent is undefined. 65 | if (parent === undefined) { 66 | if (newNode) { 67 | root.value = newNode.value, 68 | root.left = newNode.left, 69 | root.right = newNode.right; 70 | }else{ 71 | root.value=undefined; 72 | } 73 | return; 74 | } 75 | 76 | if (parent.left === node) { 77 | parent.left = newNode; 78 | } else { 79 | parent.right = newNode; 80 | } 81 | }; 82 | 83 | 84 | binaryTreeDelete = function(num, parent) { 85 | var successor; 86 | if (num < this.value) { 87 | return this.left ? this.left.delete(num, this) : root; 88 | } else if (num > this.value) { 89 | return this.right ? this.right.delete(num, this) : root; 90 | } else { 91 | // delete key here 92 | if (this.left !== undefined && this.right !== undefined) { 93 | successor = findRightMost(this.left); 94 | this.value = successor.value; 95 | this.left.delete(successor.value, this); 96 | } else if (this.left) { 97 | replaceNodeInParent(this, parent, this.left); 98 | } else if (this.right) { 99 | replaceNodeInParent(this, parent, this.right); 100 | } else { 101 | replaceNodeInParent(this, parent); // replace with undefined 102 | } 103 | } 104 | return root; 105 | }; 106 | 107 | module.exports = (root = createNode(undefined)); -------------------------------------------------------------------------------- /solutions/javascript/transform-word.js: -------------------------------------------------------------------------------- 1 | module.exports = function (dictionary, start, end) { 2 | // Create a function that will return an object which represents a graph 3 | // structure. 4 | var createGraph = function (dictionary) { 5 | var graph = {}; 6 | 7 | // Create a simple helper function that will return a boolean whether the 8 | // words are one character apart 9 | var isOneCharDifference = function (word1, word2) { 10 | // If the second word is larger than the first word, reverse the 11 | // arguments and run again. 12 | if (word2.length > word1.length) { 13 | return isOneCharDifference(word2, word1); 14 | } 15 | 16 | // If the difference in length between the words is greater than one, 17 | // or the words are identical anyway, it's impossible. 18 | if (word1 === word2 || word2.length < word1.length - 1) { 19 | return false; 20 | } 21 | 22 | for (var i = 0; i < word1.length; i++) { 23 | // First we check whether replacing the character with the equivelent 24 | // from the second word with make the second word. 25 | if (word1.substr(0, i) + word2[i] + word1.substr(i + 1) === word2) { 26 | return true; 27 | } 28 | 29 | // Next we check if removing a single letter from the first word will 30 | // result in the second word. 31 | if (word1.substr(0, i) + word1.substr(i + 1) === word2) { 32 | return true; 33 | } 34 | } 35 | 36 | return false; 37 | }; 38 | 39 | dictionary.forEach(function (word) { 40 | // Add the word to the graph structure with an array for the connecting 41 | // nodes. 42 | graph[word] = []; 43 | 44 | // Check all the other words in the graph so far and see if they are 45 | // connections. 46 | Object.keys(graph).forEach(function (connection) { 47 | if (isOneCharDifference(word, connection)) { 48 | graph[word].push(connection); 49 | // Push the word into the connection if it's been created. 50 | graph[connection] && graph[connection].push(word); 51 | } 52 | }); 53 | }); 54 | 55 | return graph; 56 | }; 57 | 58 | // Find the solution. 59 | var graph = createGraph(dictionary); 60 | var shortestRoute; 61 | 62 | (function findRoute (word, route) { 63 | // If the word doesn't exist in the graph or we have gone to the word 64 | // before, break early. 65 | if (!graph[word] || ~route.indexOf(word)) { return; } 66 | 67 | // If the route is longer than a previous route, stop trying to loop around. 68 | if (shortestRoute && route.length >= shortestRoute.length) { return; } 69 | 70 | // Push the word into the current route 71 | route.push(word); 72 | 73 | // If the word now matches the final word, set it as the route. 74 | if (word === end) { 75 | return shortestRoute = route; 76 | } 77 | 78 | graph[word].forEach(function (connection) { 79 | return findRoute(connection, route.slice()); 80 | }); 81 | })(start, []); 82 | 83 | return shortestRoute; 84 | }; 85 | -------------------------------------------------------------------------------- /solutions/java/MedianIntegerStream.java: -------------------------------------------------------------------------------- 1 | public class MedianIntegerStream { 2 | 3 | /** 4 | * This solution is a replica of the one suggested in javascript solutions 5 | * for MedianIntegerStream, and I think its one of the best possible solutions. 6 | */ 7 | 8 | MyLinkedList ll; 9 | 10 | public MedianIntegerStream() { 11 | // TODO Auto-generated constructor stub 12 | ll = new MyLinkedList(); 13 | } 14 | 15 | public static void main(String[] args) { 16 | MedianIntegerStream mis = new MedianIntegerStream(); 17 | System.out.println("Median: " + mis.ll.insertIntoLL(10)); 18 | System.out.println("Median: " + mis.ll.insertIntoLL(15)); 19 | System.out.println("Median: " + mis.ll.insertIntoLL(25)); 20 | System.out.println("Median: " + mis.ll.insertIntoLL(5)); 21 | } 22 | 23 | public class MyLinkedList { 24 | Node median; 25 | int leftNodes; 26 | int rightNodes; 27 | 28 | public MyLinkedList() { 29 | median = null; 30 | leftNodes = 0; 31 | rightNodes = 0; 32 | } 33 | 34 | public MyLinkedList(Node median) { 35 | this.median = median; 36 | leftNodes = 0; 37 | rightNodes = 0; 38 | } 39 | 40 | public class Node { 41 | Integer value; 42 | Node left; 43 | Node right; 44 | 45 | Node() { 46 | value = null; 47 | left = null; 48 | right = null; 49 | } 50 | 51 | Node(int value) { 52 | this.value = value; 53 | left = null; 54 | right = null; 55 | } 56 | 57 | Node(int value, Node left, Node right) { 58 | this.value = value; 59 | this.left = left; 60 | this.right = right; 61 | } 62 | } 63 | 64 | public void prepend(int value) { 65 | Node cur = median; 66 | while (cur.left != null && cur.left.value > value) 67 | cur = cur.left; 68 | Node newNode = new Node(value, cur.left, cur); 69 | if (cur.left != null) 70 | cur.left.right = newNode; 71 | cur.left = newNode; 72 | leftNodes++; 73 | updateMedian(); 74 | } 75 | 76 | public void append(int value) { 77 | Node cur = median; 78 | while (cur.right != null && cur.right.value < value) 79 | cur = cur.right; 80 | Node newNode = new Node(value, cur, cur.right); 81 | if (cur.right != null) 82 | cur.right.left = newNode; 83 | cur.right = newNode; 84 | rightNodes++; 85 | updateMedian(); 86 | } 87 | 88 | public void updateMedian() { 89 | if (this.leftNodes - this.rightNodes > 1) { 90 | median = median.left; 91 | rightNodes++; 92 | leftNodes--; 93 | } else if (this.rightNodes - this.leftNodes > 1) { 94 | median = median.right; 95 | leftNodes++; 96 | rightNodes--; 97 | } 98 | } 99 | 100 | public int insertIntoLL(int value) { 101 | if (median == null) { 102 | median = new Node(value); 103 | } else { 104 | if (value <= median.value) 105 | prepend(value); 106 | else 107 | append(value); 108 | } 109 | if (this.leftNodes == this.rightNodes) 110 | return median.value; 111 | else if (leftNodes < rightNodes) 112 | return (median.value + median.right.value) / 2; 113 | else 114 | return (median.value + median.left.value) / 2; 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /problems/word-analytics/Readme.md: -------------------------------------------------------------------------------- 1 | # Word Analytics 2 | 3 | You're a newly hired engineer for a brand-new company that's building a "killer Word-like application". You've been specifically assigned to implement a tool that gives the user some details on common word usage, letter usage, and some other analytics for a given document! More specifically, you must read a given text file (no special formatting, just a plain ASCII text file) and print off the following details: 4 | 5 | 1. Number of words 6 | 2. Number of letters 7 | 3. Number of symbols (any non-letter and non-digit character, excluding white spaces) 8 | 4. Top three most common words (you may count "small words", such as "it" or "the") 9 | 5. Top three most common letters 10 | 6. Most common first word of a paragraph (paragraph being defined as a block of text with an empty line above it) (Optional bonus) 11 | 7. Number of words only used once (Optional bonus) 12 | 8. All letters not used in the document (Optional bonus) 13 | 14 | Please note that your tool does not have to be case sensitive, meaning the word "Hello" is the same as "hello" and "HELLO". 15 | 16 | *Author: nint22* 17 | 18 | ## Formal Inputs & Outputs 19 | 20 | ### Input Description 21 | 22 | As an argument to your program on the command line, you will be given a text file location (such as "C:\Users\nint22\Document.txt" on Windows or "/Users/nint22/Document.txt" on any other sane file system). This file may be empty, but will be guaranteed well-formed (all valid ASCII characters). You can assume that line endings will follow the UNIX-style new-line ending (unlike the Windows carriage-return & new-line format ). 23 | 24 | ### Output Description 25 | 26 | For each analytic feature, you must print the results in a special string format. Simply you will print off 6 to 8 sentences with the following format: 27 | 28 | ``` 29 | "A words", where A is the number of words in the given document 30 | "B letters", where B is the number of letters in the given document 31 | "C symbols", where C is the number of non-letter and non-digit character, excluding white spaces, in the document 32 | "Top three most common words: D, E, F", where D, E, and F are the top three most common words 33 | "Top three most common letters: G, H, I", where G, H, and I are the top three most common letters 34 | "J is the most common first word of all paragraphs", where J is the most common word at the start of all paragraphs in the document (paragraph being defined as a block of text with an empty line above it) (*Optional bonus*) 35 | "Words only used once: K", where K is a comma-delimited list of all words only used once (*Optional bonus*) 36 | "Letters not used in the document: L", where L is a comma-delimited list of all alphabetic characters not in the document (*Optional bonus*) 37 | ``` 38 | 39 | If there are certain lines that have no answers (such as the situation in which a given document has no paragraph structures), simply do not print that line of text. In this example, I've just generated some random Lorem Ipsum text. 40 | 41 | ## Testing 42 | 43 | ``` 44 | cat huckleberry-finn.txt | node index.js 45 | ``` 46 | 47 | ## Source 48 | 49 | [http://www.reddit.com/r/dailyprogrammer/comments/1e97ob/051313_challenge_125_easy_word_analytics/](http://www.reddit.com/r/dailyprogrammer/comments/1e97ob/051313_challenge_125_easy_word_analytics/) 50 | -------------------------------------------------------------------------------- /problems/stack-machine/Readme.md: -------------------------------------------------------------------------------- 1 | # Stack Machine 2 | 3 | A stack machine is a simple system that performs arithmetic operations on an input string of numbers and operators. It contains a stack that can store an arbitrary number of 12-bit unsigned integers. Initially the stack is empty. The machine processes a string of characters in the following way: 4 | 5 | - the characters of the string are processed one by one; 6 | - if the current character is a digit `[0-9]`, the machine pushes the value of that digit onto its stack; 7 | - if the current character is `+`, the machine pops the two topmost values from its stack, adds them and pushes the result onto the stack; 8 | - if the current character is `*`, the machine pops the two topmost values from its stack, multiplies them and pushes the result onto the stack; 9 | - after the machine has processed the whole string it returns the topmost value of its stack as the result; 10 | - the machine reports an error if any operation it performs (addition or multiplication) results in an overflow; 11 | - the machine reports an error if it tries to pop an element from its stack when the stack is empty, or if the stack is empty after the machine has processed the whole string. 12 | 13 | For example, given the string "13+62*7+*" the machine will perform the following operations: 14 | ``` 15 | character | comment | stack 16 | ----------------------------------------------- 17 | | | [empty] 18 | '1' | push 1 onto the stack | 19 | | | 1 20 | '3' | push 3 onto the stack | 21 | | | 1, 3 22 | '+' | perform addition | 23 | | | 4 24 | '6' | push 6 onto the stack | 25 | | | 4, 6 26 | '2' | push 2 onto the stack | 27 | | | 4, 6, 2 28 | '*' | perform multiplication | 29 | | | 4, 12 30 | '7' | push 7 onto the stack | 31 | | | 4, 12, 7 32 | '+' | perform addition | 33 | | | 4, 19 34 | '*' | perform multiplication | 35 | | | 76 36 | ``` 37 | 38 | The machine will return `76` as the result as it is the topmost element of its stack. 39 | 40 | Write a function: 41 | class Solution { public int solution(string S); } 42 | 43 | that, given a string S consisting of N characters containing input for the stack machine, returns the result the machine would return if given this string. The function should return −1 if the machine would report an error when processing the string. 44 | 45 | For example, given `String S = "13+62*7+*"` the function should return `76`, as explained in the example above. Given `String S = "11++"` the function should return `-1`. 46 | 47 | Assume that: 48 | - the length of S is within the range [0..200,000]; 49 | - string S consists only of the following characters: "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+" and/or "*". 50 | 51 | In your solution, focus on **correctness**. The performance of your solution will not be the focus of the assessment. 52 | 53 | **Solution:** https://github.com/AntonioRedondo/CodingInterviewProblems/blob/master/src/StackMachine.java 54 | -------------------------------------------------------------------------------- /tests/cpp/once.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | 3 | #include "../../solutions/cpp/once.hpp" 4 | #include 5 | #include 6 | using std::string; 7 | using std::to_string; 8 | using std::multiplies; 9 | 10 | std::size_t fibonacci(std::size_t n) { 11 | if(n == 0) return 0; 12 | if(n == 1) return 1; 13 | 14 | std::size_t a = 0, b = 1, c; 15 | for(; n > 1; --n) { 16 | c = a + b; 17 | a = b; 18 | b = c; 19 | } 20 | return b; 21 | } 22 | 23 | struct HolderOfTruth { 24 | bool theTruth; 25 | 26 | bool getTruth() const { 27 | return theTruth; 28 | }; 29 | 30 | void setTruth(bool newTruth) { 31 | theTruth = newTruth; 32 | } 33 | }; 34 | 35 | TEST(OnceTest, VoidLambdaJustOnce) { 36 | int i = 0; 37 | auto f = once( [&i](){ ++i; } ); 38 | ASSERT_EQ(0, i); 39 | 40 | f(); 41 | EXPECT_EQ(1, i); 42 | 43 | EXPECT_NO_THROW(f()); 44 | EXPECT_EQ(1, i); 45 | } 46 | 47 | TEST(OnceTest, VoidLambdaManyTimes) { 48 | int i = 0; 49 | auto f = once( [&i](){ ++i; }, 30); 50 | ASSERT_EQ(0, i); 51 | 52 | for(int j = 1; j <= 30; ++j) { 53 | f(); 54 | EXPECT_EQ(j, i); 55 | } 56 | 57 | EXPECT_NO_THROW(f()); 58 | EXPECT_EQ(30, i); 59 | } 60 | 61 | TEST(OnceTest, IntReturningLambda) { 62 | int i = 10; 63 | auto f = once( [&i](){ return i; }, 2); 64 | ASSERT_EQ(10, i); 65 | 66 | EXPECT_EQ(10, f()); 67 | i = 13; 68 | EXPECT_EQ(13, f()); 69 | 70 | EXPECT_THROW(f(), out_of_calls); 71 | } 72 | 73 | TEST(OnceTest, StringReturningLambda) { 74 | auto s = string{"Hi there!"}; 75 | auto f = once( [](){ return string{"Hi there!"}; } ); 76 | 77 | EXPECT_EQ(s, f()); 78 | 79 | EXPECT_THROW(f(), out_of_calls); 80 | } 81 | 82 | TEST(OnceTest, LambdaWithArgs) { 83 | auto f = once( [](int i, string s){ return to_string(i) + " " + s; }, 2); 84 | EXPECT_EQ("1 time", f(1, "time")); 85 | EXPECT_EQ("2 times", f(2, "times")); 86 | EXPECT_THROW(f(3, "times"), out_of_calls); 87 | } 88 | 89 | TEST(OnceTest, FunctorStruct) { 90 | auto f = once( multiplies(), 3); 91 | 92 | EXPECT_FLOAT_EQ(120.0, f(2.4, 50.0)); 93 | EXPECT_FLOAT_EQ(16.5, f(0.5, 33.0)); 94 | EXPECT_FLOAT_EQ(145.64, f(11., 13.24)); 95 | EXPECT_THROW(f(1.0, 1.0), out_of_calls); 96 | } 97 | 98 | TEST(OnceTest, FunctionPointer) { 99 | auto f = once( fibonacci, 30 ); 100 | for(int i = 0; i < 30; ++i) 101 | EXPECT_EQ(fibonacci(i), f(i)); 102 | EXPECT_THROW(f(0), out_of_calls); 103 | } 104 | 105 | TEST(OnceTest, MemberFunctions) { 106 | auto f = once(&HolderOfTruth::getTruth, 6); 107 | auto g = once(&HolderOfTruth::setTruth, 3); 108 | 109 | auto TrueHolder = new HolderOfTruth{true}; 110 | auto FakeHolder = new HolderOfTruth{false}; 111 | 112 | ASSERT_TRUE( TrueHolder->getTruth()); 113 | ASSERT_FALSE(FakeHolder->getTruth()); 114 | 115 | EXPECT_TRUE( f(TrueHolder)); 116 | EXPECT_FALSE(f(FakeHolder)); 117 | 118 | EXPECT_NO_THROW(g(TrueHolder, false)); 119 | EXPECT_NO_THROW(g(FakeHolder, true)); 120 | 121 | EXPECT_FALSE(f(TrueHolder)); 122 | EXPECT_TRUE( f(FakeHolder)); 123 | 124 | EXPECT_NO_THROW(g(TrueHolder, true)); 125 | EXPECT_NO_THROW(g(FakeHolder, false)); 126 | 127 | EXPECT_TRUE(f(TrueHolder)); 128 | EXPECT_TRUE(f(FakeHolder)); 129 | 130 | EXPECT_THROW(f(TrueHolder), out_of_calls); 131 | } 132 | --------------------------------------------------------------------------------