diff --git a/.gitignore b/.gitignore index a59ae71..a8dec1e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .idea node_modules *.o +vendor diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 48d058a..0000000 --- a/.jshintrc +++ /dev/null @@ -1,31 +0,0 @@ -{ - "maxerr": 100, // Maximum errors before stopping. - "maxlen": 80, // Maximum line length. - "quotmark": "single", // Consistent quotation mark usage. - "bitwise": false, // Prohibit bitwise operators (&, |, ^, etc.). - "curly": true, // Require {} for every new block or scope. - "eqeqeq": true, // Require triple equals i.e. `===`. - "forin": false, // Tolerate `for in` loops without `hasOwnPrototype`. - "immed": true, // Require immediate invocations to be wrapped in parens. E.g. `(function(){})();`. - "latedef": false, // Prohibit variable use before definition. - "newcap": true, // Require capitalization of all constructor functions. E.g. `new F()`. - "noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`. - "noempty": true, // Prohibit use of empty blocks. - "nonew": true, // Prohibit use of constructors for side-effects. - "undef": true, // Require all non-global variables be declared before they are used. - "unused": true, // Warn when creating a variable but never using it. - "plusplus": false, // Prohibit use of `++` & `--`. - "regexp": false, // Prohibit `.` and `[^...]` in regular expressions. - "strict": false, // Require `use strict` pragma in every file. - "trailing": true, // Prohibit trailing whitespaces. - "boss": true, // Tolerate assignments inside if, for and while. Usually conditions and loops are for comparison, not assignments. - "multistr": false, // Prohibit the use of multi-line strings. - "eqnull": true, // Tolerate use of `== null`. - "expr": true, // Tolerate `ExpressionStatement` as Programs. - "browser": true, // Standard browser globals e.g. `window`, `document`. - "node": true, // Enable standard globals available when code is running inside of the NodeJS runtime environment. - "globals": { - "it": true, - "describe": true - } -} diff --git a/Readme.md b/README.md similarity index 57% rename from Readme.md rename to README.md index e16f367..a9aa95f 100644 --- a/Readme.md +++ b/README.md @@ -1,10 +1,14 @@ # Code Problems -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. +> Looking for a new job? Take Triplebyte's [quiz](https://triplebyte.com/a/QW7kzKo/d) and have top tech companies pitch you! + +This is an incomplete repo full of code problems used prior to or during an interview. I hope these problems will be useful for you to practice and review. If you have practiced on or designed an interesting problem, we'd love to see it! Open a PR or issue with your suggestions or optimizations. ## Problems -### Sorting Algorithms +View [all problems](./problems), or start here: + +**Sorting Algorithms** * [Quick Sort](https://github.com/blakeembrey/code-problems/tree/master/problems/quick-sort) * [Bubble Sort](https://github.com/blakeembrey/code-problems/tree/master/problems/bubble-sort) @@ -12,18 +16,18 @@ This is my repo full of code problems that I have completed prior to or during a * [Selection Sort](https://github.com/blakeembrey/code-problems/tree/master/problems/selection-sort) * [Insertion Sort](https://github.com/blakeembrey/code-problems/tree/master/problems/insertion-sort) -### Data Structures +**Data Structures** * [Stack](https://github.com/blakeembrey/code-problems/tree/master/problems/stack) * [Queue](https://github.com/blakeembrey/code-problems/tree/master/problems/queue) * [Linked List](https://github.com/blakeembrey/code-problems/tree/master/problems/linked-list) * [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* -### DOM Problems +**DOM Problems** * [Get Elements By Class Name](https://github.com/blakeembrey/code-problems/tree/master/problems/get-elements-by-class-name) -### Shortest Code Problems +**Shortest Code Problems** * [Shortest Fizz Buzz](https://github.com/blakeembrey/code-problems/tree/master/problems/shortest-fizz-buzz) @@ -33,3 +37,7 @@ This is my repo full of code problems that I have completed prior to or during a npm install # Installs `mocha` and any other dependencies needed to run npm test # Runs the testing scripts ``` + +## Contributing + +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 attribution, or from coding interview websites such as [Codility](https://codility.com/). diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..65658fb --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "phpunit/phpunit": "5.5.*" + } +} diff --git a/package.json b/package.json index c3cc4a3..11c4b07 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,13 @@ { "name": "code-problems", - "version": null, "private": true, - "description": "Repository full of code problems and common solutions.", - "main": null, - "dependencies": {}, + "description": "Repository full of code problems and common solutions", "devDependencies": { - "mocha": "~1.16.2", - "jshint": "~2.4.0", - "chai": "~1.8.1" + "chai": "^3.5.0", + "mocha": "^3.2.0" }, "scripts": { - "test": "jshint solutions/javascript && mocha tests/javascript" + "test": "mocha tests/javascript" }, "repository": { "type": "git", diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..ae3c20e --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,6 @@ + + + + tests/php + + \ No newline at end of file diff --git a/problems/array-pair-sum/Readme.md b/problems/array-pair-sum/Readme.md index aa6298e..0e7bd24 100644 --- a/problems/array-pair-sum/Readme.md +++ b/problems/array-pair-sum/Readme.md @@ -1,14 +1,15 @@ # Array Pair Sum -Given an integer array, output all 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. +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. > 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. ## Example ``` -f(10, [3, 4, 5, 6, 7]) // [ [6, 4], [7, 3] ] +f(10, [3, 4, 5, 6, 7]) // [ [4, 6], [3, 7] ] f(8, [3, 4, 5, 4, 4]) // [ [3, 5], [4, 4], [4, 4], [4, 4] ] +f(10, [3, 5, 6, 8]) // [] ``` ## Source diff --git a/problems/balanced-brackets/Readme.md b/problems/balanced-brackets/Readme.md index 80085da..21eead1 100644 --- a/problems/balanced-brackets/Readme.md +++ b/problems/balanced-brackets/Readme.md @@ -1,6 +1,6 @@ # Balanced Brackets -Write a function that accepts a string consisting entiring 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. +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. ```js f('()[]{}(([])){[()][]}') // true diff --git a/problems/closest-sum/problem.txt b/problems/closest-sum/problem.txt new file mode 100644 index 0000000..f2f2d9d --- /dev/null +++ b/problems/closest-sum/problem.txt @@ -0,0 +1,9 @@ +Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. +Return the sum of the three integers. +You may assume that each input would have exactly one solution. + +Example: +given array S = {-1 2 1 -4}, +and target = 1. + +The sum that is closest to the target is 2. (-1 + 2 + 1 = 2) \ No newline at end of file diff --git a/problems/shop-in-candy-store/Readme.md b/problems/shop-in-candy-store/Readme.md new file mode 100644 index 0000000..fdfc400 --- /dev/null +++ b/problems/shop-in-candy-store/Readme.md @@ -0,0 +1,41 @@ +# Shop in Candy Store + +In a candy store there are N different types of candies available and the prices of all the N different types of candies are provided to you. +You are now provided with an attractive offer. +You can buy a single candy from the store and get atmost K other candies ( all are different types ) for free. +Now you have to answer two questions. Firstly, you have to tell what is the minimum amount of money you have to spend to buy all the N different candies. Secondly, you have to tell what is the maximum amount of money you have to spend to buy all the N different candies. +In both the cases you must utilize the offer i.e. you buy one candy and get K other candies for free. + + +# Input +The first line of the input contains T the number of test cases. Each test case consists of two lines. The first line of each test case contains the values of N and K as described above. Then in the next line N integers follow denoting the price of each of the N different candies. + + +# Output +For each test case output a single line containing 2 space separated integers , the first denoting the minimum amount of money required to be spent and the second denoting the maximum amount of money to be spent. +Remember to output the answer of each test case in a new line. + +# Constraints +1 <= T <= 50 +1 <= N <= 1000 + 0 <= K <= N-1 +1 <= Ai <= 100 + +# Example: +Input + 1 + 4 2 + 3 2 1 4 + +Output + 3 7 + +# Explanation +As according to the offer if you but one candy you can take atmost two more for free. +So in the first case you buy the candy which costs 1 and take candies worth 3 and 4 for free, also you buy candy worth 2 as well. +So min cost = 1+2 =3. +In the second case I buy the candy which costs 4 and take candies worth 1 and 2 for free, also I buy candy worth 3 as well. +So max cost = 3+4 =7. + +# Topics : +Greedy || Sorting \ No newline at end of file diff --git a/problems/skiing-in-singapore/README.md b/problems/skiing-in-singapore/README.md new file mode 100644 index 0000000..7520198 --- /dev/null +++ b/problems/skiing-in-singapore/README.md @@ -0,0 +1,31 @@ +# Skiing in Singapore +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. + +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. + +In digital form the map looks like the number grid below. + +4 4 +4 8 7 3 +2 5 9 3 +6 3 2 5 +4 4 1 6 + +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 +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. + +On this particular map the longest path down is of length=5 and it’s highlighted in bold below: 9-5-3-2-1. + +4 4 +4 8 7 3 +2 5 9 3 +6 3 2 5 +4 4 1 6 + +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. + +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. + +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. + +Good luck and have fun! diff --git a/problems/spreadsheet/README.md b/problems/spreadsheet/README.md new file mode 100644 index 0000000..21805ce --- /dev/null +++ b/problems/spreadsheet/README.md @@ -0,0 +1,27 @@ +# Programming Challenge + +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. + +The spreadsheet input is defined as follows: + +1. Line 1: two integers, defining the width and height of the spreadsheet (n, m) + +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, ...) + +## The Input +3 2 +A2 +4 5 * +A1 +A1 B2 / 2 + +3 +39 B1 B2 * / + +## The Output +3 2 +20.00000 +20.00000 +20.00000 +8.66667 +3.00000 +1.50000 diff --git a/problems/stack-machine/Readme.md b/problems/stack-machine/Readme.md new file mode 100644 index 0000000..648bd75 --- /dev/null +++ b/problems/stack-machine/Readme.md @@ -0,0 +1,53 @@ +# Stack Machine + +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: + +- the characters of the string are processed one by one; +- if the current character is a digit `[0-9]`, the machine pushes the value of that digit onto its stack; +- if the current character is `+`, the machine pops the two topmost values from its stack, adds them and pushes the result onto the stack; +- if the current character is `*`, the machine pops the two topmost values from its stack, multiplies them and pushes the result onto the stack; +- after the machine has processed the whole string it returns the topmost value of its stack as the result; +- the machine reports an error if any operation it performs (addition or multiplication) results in an overflow; +- 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. + +For example, given the string "13+62*7+*" the machine will perform the following operations: +``` +character | comment | stack + ----------------------------------------------- + | | [empty] + '1' | push 1 onto the stack | + | | 1 + '3' | push 3 onto the stack | + | | 1, 3 + '+' | perform addition | + | | 4 + '6' | push 6 onto the stack | + | | 4, 6 + '2' | push 2 onto the stack | + | | 4, 6, 2 + '*' | perform multiplication | + | | 4, 12 + '7' | push 7 onto the stack | + | | 4, 12, 7 + '+' | perform addition | + | | 4, 19 + '*' | perform multiplication | + | | 76 +``` + +The machine will return `76` as the result as it is the topmost element of its stack. + +Write a function: +class Solution { public int solution(string S); } + +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. + +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`. + +Assume that: +- the length of S is within the range [0..200,000]; +- string S consists only of the following characters: "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+" and/or "*". + +In your solution, focus on **correctness**. The performance of your solution will not be the focus of the assessment. + +**Solution:** https://github.com/AntonioRedondo/CodingInterviewProblems/blob/master/src/StackMachine.java diff --git a/problems/transitive-dependencies/Readme.md b/problems/transitive-dependencies/Readme.md new file mode 100644 index 0000000..e8a32ec --- /dev/null +++ b/problems/transitive-dependencies/Readme.md @@ -0,0 +1,35 @@ +# Transitive Dependencies + +A class that calculates how dependencies propagate between things such as classes in a program. One of the insidious things about dependencies is that they are transitive—if A depends on B and B depends on C, then A also depends on C. So, this code that calculates the full set of dependencies for a group of items. Example class for test: + +```php + +dependencies = new DependenciesList(); + } + + public function add_direct_test() { + $this->dependencies->add_direct('A', 'B,C'); + $this->dependencies->add_direct('B', 'C,E'); + $this->dependencies->add_direct('C', 'G'); + $this->dependencies->add_direct('D', 'A,F'); + $this->dependencies->add_direct('E', 'F'); + $this->dependencies->add_direct('F', 'H'); + } + + } + +$test = new Dependencies_Test(); +$test->add_direct_test(); +$resultado = $test->dependencies->dependencies_for("A"); + +//print dependencies array in screen +var_dump($resultado); diff --git a/solutions/c/find-missing-element.c b/solutions/c/find-missing-element.c new file mode 100644 index 0000000..1f145ce --- /dev/null +++ b/solutions/c/find-missing-element.c @@ -0,0 +1,20 @@ +#include +#include +// The differnce in sum of two arrays will give us the desired value. +// The other approach could be to look up for element each time but that will increase the time complexity of the program. + int find_missing(int orig[],int On,int shuffled[]) +{ + int i,sum=0; + for(i=0;i + +int sum_of_multiples(int n) +{ int sum=0; + n=n-1; + sum=((n/3)*((n/3)*3 +3))/2 + ((n/5)*((n/5)*5 +5))/2 - ((n/15)*((n/15)*15 + 15))/2; // sum of airthmetic progressions & De-Morgan's Law + return sum; +} +int main() +{ + printf("%d\n",sum_of_multiples(1000)); + return 0; +} \ No newline at end of file diff --git a/solutions/c/sgski.c b/solutions/c/sgski.c new file mode 100644 index 0000000..2bb6f82 --- /dev/null +++ b/solutions/c/sgski.c @@ -0,0 +1,262 @@ +// required; otherwise clang will complain that getline has not been declared +#define _XOPEN_SOURCE 700 +#include +#include +#include +#include + +typedef struct { + int **matrix; + int rowCount; + int colCount; +} matrix; + +typedef struct { + char* solution; + int distance; + int drop; +} solution; + +typedef struct { + int row; + int col; +} cellIndex; + +// input file reading routines +void readfile(matrix *m, FILE* fp); +void initMatrix(matrix *m, char* line); +void readline(matrix *m, char* line, int rowIndex); + +// solution finder +void findSkiPath(matrix *m, solution *sol); +void checkAdjacentCells(const char* path, matrix *m, cellIndex index, solution *sol, int currentValue); +void evaluateSolution(solution *sol, const char* path); + +// miscellaneous routines +void showContents(matrix *m); + +int main(int argc, char* argv[]) { + + if(argc != 2) { + printf("usage: sgski \n"); + exit(1); + } + + char* filename = argv[1]; + FILE *ifp = fopen(filename, "r"); + if (ifp == NULL) { + printf("Unable to open input file %s\n", filename); + exit(EXIT_FAILURE); + } + + // initialize the solution structure + solution *sol = malloc(sizeof(solution)); + sol->solution = malloc(sizeof(char) * 100); + sol->distance = 0; + sol->drop = 0; + + matrix *m = malloc(sizeof(matrix)); + + // read the input file into the matrix + readfile(m, ifp); + + // close file after reading + fclose(ifp); + + findSkiPath(m, sol); + + printf("Ski Path: %s; Distance: %d; Drop: %d\n", sol->solution, sol->distance, sol->drop); + + // release resources + free(sol); + free(m); + + return 0; +} + +void findSkiPath(matrix *m, solution *sol) { + for (int i = 0; i < m->rowCount; i++) { + for (int j = 0; j < m->colCount; j++) { + int value = m->matrix[i][j]; + char* path = malloc(sizeof(char) * 6); + sprintf(path, "%d ", value); + + cellIndex index; + + // check east + index.row = i; + index.col = j + 1; + checkAdjacentCells(path, m, index, sol, value); + + // check west + index.row = i; + index.col = j - 1; + checkAdjacentCells(path, m, index, sol, value); + + // check north + index.row = i - 1; + index.col = j; + checkAdjacentCells(path, m, index, sol, value); + + // check south + index.row = i + 1; + index.col = j; + checkAdjacentCells(path, m, index, sol, value); + } + } +} + +void checkAdjacentCells(const char* path, matrix *m, cellIndex index, solution *sol, int currentValue) { + + // The base case - If we go beyond the limits of the matrix + if(index.row < 0 || index.row > (m->rowCount - 1) + || index.col < 0 || index.col > (m->colCount - 1)) { + evaluateSolution(sol, path); + return; + } + + // check if the next cell has a lower value than the current cell + int val = m->matrix[index.row][index.col]; + if(val < currentValue) { + char* newPath = malloc(sizeof(char) * (strlen(path) + 4 + 1 + 1)); // the 4-digit value + space + \0 + strcpy(newPath, path); + + char *ch = malloc(sizeof(char) * (5 + 1)); // support upto 4-digit value and \0 (string terminator) + if(ch == NULL) { + printf("Unable to allocate memory\n"); + exit(EXIT_FAILURE); + } + sprintf(ch, "%d ", val); + strcat(newPath, ch); + free(ch); + + int r = index.row, c = index.col; + + // check east + index.row = r; + index.col = c + 1; + checkAdjacentCells((const char*) newPath, m, index, sol, val); + + // check west + index.row = r; + index.col = c - 1; + checkAdjacentCells((const char*) newPath, m, index, sol, val); + + // check north + index.row = r - 1; + index.col = c; + checkAdjacentCells((const char*) newPath, m, index, sol, val); + + // check south + index.row = r + 1; + index.col = c; + checkAdjacentCells((const char*) newPath, m, index, sol, val); + + free(newPath); + } + + // all ajacent cells have bigger value then the current cell + evaluateSolution(sol, path); + return; +} + +/** + * Checks if the longest path with the steepest drop has been found. + */ +void evaluateSolution(solution *sol, const char* path) { + // split the string by the space delimiter + int distance = 1; + char *dropTemp[2]; + dropTemp[0] = strtok(strdup(path), " "); + char* end = dropTemp[1] = strdup(dropTemp[0]); + + while ((end = strtok(NULL, " ")) != NULL) { + dropTemp[1] = end; + distance++; + } + + if(distance < sol->distance) { + return; + } + + int drop = atoi(dropTemp[0]) - atoi(dropTemp[1]); + if(distance > sol->distance || drop > sol->drop) { + strcpy(sol->solution, path); + sol->distance = distance; + sol->drop = drop; + } +} + +void readfile(matrix *m, FILE* fp) { + int rowIndex = 0; + size_t len = 0; + size_t read = -1; + char *line; + + while ((read = getline(&line, &len, fp) != -1)) { + if (rowIndex == 0) { + // the first row of the input file + // contains the size of the matrix. + initMatrix(m, line); + } else { + readline(m, line, rowIndex); + } + + rowIndex++; + } +} + +/** + * Reads the size of the matrix from the first line of the input file and + * sets the row and column counts into the parameters rowCount and colCount + * attributes of matrix m. + * + * This function is to be called on the first line of the input file. + */ +void initMatrix(matrix *m, char* line) { + + // reads the row count - the first value on the line string + char *ch = strtok(line, " "); + m->rowCount = atoi(ch); + + // reads the column count - the second value on the line string + ch = strtok(NULL, " "); + m->colCount = atoi(ch); + + // initialize a two-dimentional array of size rowCount * columnCount + int** matrix = (int **) malloc(sizeof(int *) * m->rowCount); + for(int i = 0; i < m->rowCount; i++) { + matrix[i] = (int *) malloc(sizeof(int) * m->colCount); + } + + m->matrix = matrix; +} + +void readline(matrix *m, char* line, int rowIndex) { + int colIndex = 0; + char *ch = strtok(line, " "); + + while(ch != NULL) { + int val = atoi(ch); + if(val > 9999) { + printf("Invalid input file. Cannot have value greater than 9999\n"); + exit(EXIT_FAILURE); + } + + m->matrix[rowIndex - 1][colIndex] = atoi(ch); + ch = strtok(NULL, " "); + colIndex++; + } +} + +/** + * Prints the contents of the matrix into the console + */ +void showContents(matrix *m) { + for(int i = 0; i < m->rowCount; i++) { + for (int j = 0; j < m->colCount; j++) { + printf("%d ", m->matrix[i][j]); + } + printf("\n"); + } +} diff --git a/solutions/c/shortest-fizz-buzz.c b/solutions/c/shortest-fizz-buzz.c index 3516a76..557d84a 100644 --- a/solutions/c/shortest-fizz-buzz.c +++ b/solutions/c/shortest-fizz-buzz.c @@ -1 +1 @@ -main(i){for(;i<101;puts(i++%5?"":"Buzz"))printf(i%3?i%5?"%d":"":"Fizz",i);} +main(i){while(printf("%i\r%s%s\n",i++,i%3?"":"Fizz",i%5?"":"Buzz")-9);} diff --git a/solutions/c/spreadsheet/3x2.txt b/solutions/c/spreadsheet/3x2.txt new file mode 100644 index 0000000..05f2106 --- /dev/null +++ b/solutions/c/spreadsheet/3x2.txt @@ -0,0 +1,7 @@ +3 2 +A2 +4 5 * +A1 +A1 B2 / 2 + +3 +39 B1 B2 * / diff --git a/solutions/c/spreadsheet/Makefile b/solutions/c/spreadsheet/Makefile new file mode 100644 index 0000000..549b86d --- /dev/null +++ b/solutions/c/spreadsheet/Makefile @@ -0,0 +1,11 @@ + +all: spreadsheet + +spreadsheet: spreadsheet.c matrix.c matrix.h stackcalc.h stackcalc.c regex.h regex.c commons.h commons.c + clang -ggdb3 -O0 -std=c99 -Wall -Werror -o spreadsheet spreadsheet.c matrix.c regex.c commons.c stackcalc.c -I/usr/local/include -L/usr/local/lib/ -lpcre2-8 + +test: matrix_test.c regex.c commons.c regex.h matrix.h stackcalc.h stackcalc.c + clang -o matrixTest -ggdb3 -Wall -Werror -O0 -std=c99 -I/usr/local/include matrix_test.c matrix.c regex.c commons.c stackcalc.c -L/usr/local/lib/ -lpcre2-8 -lcmocka + +clean: + rm -f *.o a.out spreadsheet core diff --git a/solutions/c/spreadsheet/README.md b/solutions/c/spreadsheet/README.md new file mode 100644 index 0000000..78ef85e --- /dev/null +++ b/solutions/c/spreadsheet/README.md @@ -0,0 +1,12 @@ +# Dependencies + +This program depends on the following: +1. pcre2-10.20 - Pattern matching, regular expression +2. cmocka-1.0.0 - For Unit Tests + +Please refer to their respective documentations on how to install these libraries into your respective system + +# Execution +It is required that the $LD\_LIBRARY\_PATH environment variable be set to the directory where the pcre.so is located if it is located other than /usr/lib + + diff --git a/solutions/c/spreadsheet/commons.c b/solutions/c/spreadsheet/commons.c new file mode 100644 index 0000000..3e01306 --- /dev/null +++ b/solutions/c/spreadsheet/commons.c @@ -0,0 +1,14 @@ +#include "commons.h" + +int getNumberOfDigits(int n) +{ + if (n < 0) return -1; + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + + return -1; +} diff --git a/solutions/c/spreadsheet/commons.h b/solutions/c/spreadsheet/commons.h new file mode 100644 index 0000000..b52873e --- /dev/null +++ b/solutions/c/spreadsheet/commons.h @@ -0,0 +1,6 @@ + +/** + * Returns the number of digits in the integer n + */ +int getNumberOfDigits(int n); + diff --git a/solutions/c/spreadsheet/matrix.c b/solutions/c/spreadsheet/matrix.c new file mode 100644 index 0000000..98c713d --- /dev/null +++ b/solutions/c/spreadsheet/matrix.c @@ -0,0 +1,215 @@ +#define _XOPEN_SOURCE 700 +#define PCRE2_CODE_UNIT_WIDTH 8 + +#include +#include +#include +#include +#include + +#include "regex.h" +#include "matrix.h" +#include "commons.h" + +// ~ Static function propotypes ================== +static int isCyclicError(const Worksheet *worksheet, const char *visitedCells, CellReference *cellReference); + +/** + * Initializes the worksheet cells of size rows * columns. + * + * Returns 0 if an error is encountered. + */ +int initWorksheet(Worksheet *worksheet, int rows, int columns) { + worksheet->rows = rows; + worksheet->cols = columns; + + char ***matrix = (char ***) malloc(sizeof(char **) * rows); + for(int i = 0; i < rows; i++) { + matrix[i] = (char **) malloc(sizeof(char *) * columns); + + for(int j = 0; j < columns; j++) { + matrix[i][j] = (char *) calloc(sizeof(char) * CELL_CONTENT_LIMIT, sizeof(char)); + } + } + + worksheet->cells = matrix; + return 1; +} + +int closeWorksheet(Worksheet *w) +{ + for(int i = 0; i < w->rows; i++) + { + for(int j = 0; j < w->cols; j++) + { + free(w->cells[i][j]); + } + free(w->cells[i]); + } + free(w->cells); + free(w); + return 1; +} + +/** + * Sets s to the worksheet cell at row, column. + * + * Returns 0 if strlen(s) > CELL_CONTENT_LIMIT + */ +int setValue(Worksheet *worksheet, int row, int column, char* s) { + if (strlen(s) <= CELL_CONTENT_LIMIT) { + strncpy(worksheet->cells[row][column], s, strlen(s)); + return 1; + } else { + return 0; + } +} + +/** + * Returns the value at row, col + */ +char* getValue(const Worksheet *worksheet, int row, int column) { + return worksheet->cells[row][column]; +} + +int getValue2(const Worksheet *w, char **buffer, int row, int column) +{ + if (w == NULL) return 0; + if (w->cells[row][column] == NULL) return 0; + + *buffer = malloc(sizeof(char) * strlen(w->cells[row][column]) + 1); + strcpy(*buffer, w->cells[row][column]); + + return 1; +} + +/** + * Converts the given location (row, column) to a spreadsheet cell reference i.e. A1 + */ +CellReference *convertToCellReference(const MatrixLocation *location) +{ + CellReference *ref = malloc(sizeof(CellReference)); + + char *colRef = malloc(sizeof(char) * getNumberOfDigits(location->col) + 1); + sprintf(colRef, "%d", location->col + 1); + + // row ref + col ref + null terminator + ref->cellReference = malloc(sizeof(char) * (1 + strlen(colRef) + 1) + 1); + sprintf(ref->cellReference, "%c%s", (char)(location->row + ROW_TO_ASCII_OFFSET), colRef); + free(colRef); + + return ref; +} + +/** + * Returns a pointer to a MatrixLocation structure + */ +MatrixLocation *convertToMatrixLocation(const CellReference *ref) +{ + MatrixLocation *loc = malloc(sizeof(MatrixLocation)); + loc->row = ((int) toupper(ref->cellReference[0])) - ROW_TO_ASCII_OFFSET; + + char *col = calloc(sizeof(char) + strlen(ref->cellReference), sizeof(char)); + col = strncpy(col, ref->cellReference + 1, strlen(ref->cellReference) - 1); + loc->col = atoi(col) - 1; + free(col); + return loc; +} + +/** + * Checks if a given formula at row, col refers to some cells which themselves + * refer back to row,col + * + * Returns 0 if an error is encountered. + */ +int isCyclicRefError(const Worksheet *worksheet, int row, int col) +{ + MatrixLocation m = { row, col }; + + CellReference *cellRef = convertToCellReference(&m); + int result = isCyclicError(worksheet, "", cellRef); + + free(cellRef->cellReference); + free(cellRef); + return result; +} + +/** + * An internal function for checking cyclic reference dependency error. + * + * ========== + * Returns 1 if cyclic dependency is found, 0 if otherwise + */ +static int isCyclicError(const Worksheet *worksheet, const char *visitedCells, CellReference *cellRef) +{ + pcre2_match_data *match_data = NULL; + char *saveptr = NULL; + int rc = 0; + + MatrixLocation *m = convertToMatrixLocation(cellRef); + + char *cellValue = NULL; + getValue2(worksheet, &cellValue, m->row, m->col); + free(m); + + if (cellValue == NULL) + { + return 0; + } + + // do work on working copy + char *token = NULL; + token = strtok_r(cellValue, " ", &saveptr); + pcre2_code *re = getCellReferencePattern(); + while(token != NULL) + { + match_data = pcre2_match_data_create(20, NULL); + int subjectLength = strlen(token); + rc = pcre2_match(re, (PCRE2_SPTR) token, subjectLength, 0, 0, match_data, NULL); + + if (rc > 0) + { + // search if current cellref is in the visited cells + pcre2_code *searchVal = compilePattern(token); + int isCyclicDependency = pcre2_match(searchVal, (PCRE2_SPTR) visitedCells, strlen(visitedCells), 0, 0, match_data, NULL); + if (isCyclicDependency > 0) + { + free(cellValue); + free(match_data); + free(searchVal); + free(re); + return 1; + } + + free(searchVal); + + //length of existing visitedCells + space character + length of cellRef to be appended + null terminator + char *newVisitedCells = malloc(sizeof(char) * (strlen(visitedCells) + 1 + strlen(cellRef->cellReference)) + 1); + strcpy(newVisitedCells, visitedCells); + strcat(newVisitedCells, " "); + strcat(newVisitedCells, cellRef->cellReference); + + CellReference *tokenCellRef = malloc(sizeof(CellReference)); + tokenCellRef->cellReference = token; + + if(isCyclicError(worksheet, (const char *) newVisitedCells, tokenCellRef)) + { + free(cellValue); + free(newVisitedCells); + free(match_data); + free(re); + return 1; + } + + free(newVisitedCells); + free(tokenCellRef); + } + token = strtok_r(NULL, " ", &saveptr); + free(match_data); + } + + free(cellValue); + free(re); + return 0; +} + diff --git a/solutions/c/spreadsheet/matrix.h b/solutions/c/spreadsheet/matrix.h new file mode 100644 index 0000000..5ee4d72 --- /dev/null +++ b/solutions/c/spreadsheet/matrix.h @@ -0,0 +1,73 @@ + +typedef struct +{ + char ***cells; + int rows; + int cols; +} Worksheet; + +typedef struct +{ + int row; + int col; +} MatrixLocation; + +typedef struct +{ + char *cellReference; +} CellReference; + +// The maximum content of a cell (4k) +#define CELL_CONTENT_LIMIT 2048 + +#define ROW_TO_ASCII_OFFSET 65 + +/** + * Initializes the 2d matrix of size rows * columns. + * + * Returns 0 if an error is encountered. + */ +int initWorksheet(Worksheet *worksheet, int rows, int columns); + +/** + * Closes and releases the resources of the worksheet + */ +int closeWorksheet(Worksheet *w); + +/** + * Returns 1 if a cyclic dependency is detected. 0 if otherwise. + */ +int isCyclicRefError(const Worksheet *worksheet, int row, int col); + +/** + * Sets cellContent into the worksheet + */ +int setValue(Worksheet *worksheet, int row, int column, char *cellContent); + +/** + * Returns the value at row, col + */ +char* getValue(const Worksheet *worksheet, int row, int column); + +/** + * Returns the value at row, col and writes it into the buffer. + * + * Usage: + * + * char *buffer; + * getValue2(w, &buffer, row, column); + * + */ +int getValue2(const Worksheet *w, char **buffer, int row, int column); + +/** + * Returns a pointer to a CellReference structure + */ +CellReference *convertToCellReference(const MatrixLocation *matrixLocation); + +/** + * Returns a pointer to a MatrixLocation structure + */ +MatrixLocation *convertToMatrixLocation(const CellReference *cellReference); + + diff --git a/solutions/c/spreadsheet/matrixTest b/solutions/c/spreadsheet/matrixTest new file mode 100755 index 0000000..4d6f10b Binary files /dev/null and b/solutions/c/spreadsheet/matrixTest differ diff --git a/solutions/c/spreadsheet/regex.c b/solutions/c/spreadsheet/regex.c new file mode 100644 index 0000000..6fc1b2a --- /dev/null +++ b/solutions/c/spreadsheet/regex.c @@ -0,0 +1,29 @@ +#include "regex.h" + +pcre2_code * getCellReferencePattern(void) +{ + int errorcode = 0; + PCRE2_SIZE erroroffset; + pcre2_code *re = pcre2_compile((PCRE2_SPTR8) CELL_REFERENCE_PATTERN, -1, 0, + &errorcode, &erroroffset, NULL); + if (re == NULL) + { + return 0; + } + + return re; +} + +pcre2_code *compilePattern(char *pattern) +{ + int errorcode = 0; + PCRE2_SIZE erroroffset; + pcre2_code *re = pcre2_compile((PCRE2_SPTR8) pattern, -1, 0, + &errorcode, &erroroffset, NULL); + if (re == NULL) + { + return 0; + } + + return re; +} diff --git a/solutions/c/spreadsheet/regex.h b/solutions/c/spreadsheet/regex.h new file mode 100644 index 0000000..f3d8c7e --- /dev/null +++ b/solutions/c/spreadsheet/regex.h @@ -0,0 +1,17 @@ +#define PCRE2_CODE_UNIT_WIDTH 8 + +#include +#include +#include +#include + +static const char *CELL_REFERENCE_PATTERN = "[A-Za-z]\\d+"; + +pcre2_code *getCellReferencePattern(void); + +/** + * Creates a regular expression pattern based on {pattern} + */ +pcre2_code *compilePattern(char *pattern); + + diff --git a/solutions/c/spreadsheet/spreadsheet b/solutions/c/spreadsheet/spreadsheet new file mode 100755 index 0000000..df3da78 Binary files /dev/null and b/solutions/c/spreadsheet/spreadsheet differ diff --git a/solutions/c/spreadsheet/spreadsheet.c b/solutions/c/spreadsheet/spreadsheet.c new file mode 100644 index 0000000..8540238 --- /dev/null +++ b/solutions/c/spreadsheet/spreadsheet.c @@ -0,0 +1,211 @@ +#define _XOPEN_SOURCE 700 +#define PCRE2_CODE_UNIT_WIDTH 8 + +#include +#include +#include +#include +#include + +#include "regex.h" +#include "matrix.h" +#include "stackcalc.h" + +static void matrix_size(char *line, int *row, int *col); +static void matrix_readinput(Worksheet *w, char *file); +static void matrix_evaluate_worksheet(Worksheet *w); +static double matrix_evaluate_expression(const Worksheet *w, char *expression, int row, int col); +static int matrix_is_operator(char *val); + + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + printf("Usage: spreadsheet \n"); + exit(1); + } + + Worksheet *w = malloc(sizeof(Worksheet)); + matrix_readinput(w, argv[1]); + matrix_evaluate_worksheet(w); + closeWorksheet(w); + +} + +static void matrix_readinput(Worksheet *w, char *file) +{ + FILE *fp = fopen(file, "r"); + if (fp == NULL) + { + fprintf(stderr, "Cant open input file\n"); + exit(1); + } + + int colCounter = -1, rowCounter = 0; + char *line = NULL; + size_t read = 0, len = 0; + while((read = getline(&line, &len, fp)) != -1) + { + if(colCounter == -1) + { + int r = 0, c = 0; + + // reads the matrix size from the + // first line of the input file + matrix_size(line, &r, &c); + + // initilizes the matrix of size r * c + initWorksheet(w, r, c); + } + else + { + setValue(w, rowCounter, colCounter, line); + if (isCyclicRefError(w, rowCounter, colCounter)) + { + printf("Cycling dependency starting at row: %d, col: %d\n", rowCounter, colCounter); + exit(1); + } + } + + colCounter++; + + if (colCounter > 0 && (colCounter % w->cols) == 0) + { + colCounter = 0; + rowCounter++; + } + } + + free(line); + fclose(fp); +} + +/** + * Reads the matrix size given in the line and stores it in the + * row and col parameters + */ +static void matrix_size(char *line, int *row, int *col) +{ + char *token = strtok(line, " "); + *col = atoi(token); + + token = strtok(NULL, " "); + *row = atoi(token); +} + +static void matrix_evaluate_worksheet(Worksheet *w) +{ + for(int i = 0; i < w->rows; i++) + { + for(int j = 0; j< w->cols; j++) + { + char *expression = NULL; + getValue2(w, &expression, i, j); + double d = matrix_evaluate_expression(w, expression, i, j); + printf("Row: %d; Col: %d; Value: %.5f\n", i, j, d); + free(expression); + } + } +} + +static double matrix_evaluate_expression(const Worksheet *w, char *expression, int row, int col) +{ + if (expression == NULL) return 0; + + pcre2_code *re = getCellReferencePattern(); + Stack *stack = malloc(sizeof(Stack)); + pcre2_match_data *match_data = NULL; + int rc = 0; + + char *saveptr = NULL; + char *token = NULL; + + expression[strlen(expression) - 1] = '\0'; + token = strtok_r(expression, " ", &saveptr); + + while(token != NULL) + { + int len = strlen(token); + match_data = pcre2_match_data_create(20, NULL); + rc = pcre2_match(re, (PCRE2_SPTR) token, len, 0, 0, match_data, NULL); + + if (rc > 0) + { + CellReference *cellRef = malloc(sizeof(CellReference)); + cellRef->cellReference = malloc((sizeof(char) * strlen(token)) + 1); + strcpy(cellRef->cellReference, token); + + MatrixLocation *loc = convertToMatrixLocation(cellRef); + char *cellExpression = NULL; + getValue2(w, &cellExpression, loc->row, loc->col); + + double result = matrix_evaluate_expression(w, cellExpression, loc->row, loc->col); + + Node *node = malloc(sizeof(Node)); + node->value = result; + push(stack, node); + + free(cellExpression); + free(cellRef->cellReference); + free(cellRef); + free(loc); + } + else + { + if (matrix_is_operator(token)) + { + Node *op1 = pop(stack); + Node *op2 = pop(stack); + + double val1 = op1->value; + double val2 = op2->value; + + double result = 0.0; + + if (strcmp(token, "+") == 0) result = val1 + val2; + if (strcmp(token, "-") == 0) result = val2 - val1; + if (strcmp(token, "*") == 0) result = val1 * val2; + if (strcmp(token, "/") == 0) result = val2 / val1; + + free(op1); + free(op2); + + Node *newValue = malloc(sizeof(Node)); + newValue->value = result; + push(stack, newValue); + } + else + { + Node *newValue = malloc(sizeof(Node)); + newValue->value = atoi(token); + push(stack, newValue); + } + } + + token = strtok_r(NULL, " ", &saveptr); + free(match_data); + } + + Node *node = pop(stack); + double retVal = node->value; + + free(stack); + free(node); + free(re); + return retVal; +} + +static int matrix_is_operator(char *val) +{ + if (strcmp(val, "+") == 0 || + strcmp(val, "-") == 0 || + strcmp(val, "*") == 0 || + strcmp(val, "/") == 0) + { + return 1; + } + + return 0; +} + diff --git a/solutions/c/spreadsheet/stackcalc.c b/solutions/c/spreadsheet/stackcalc.c new file mode 100644 index 0000000..6d54ac9 --- /dev/null +++ b/solutions/c/spreadsheet/stackcalc.c @@ -0,0 +1,27 @@ +#define PCRE2_CODE_UNIT_WIDTH 8 + +#include +#include + +#include "matrix.h" +#include "stackcalc.h" + +void push(Stack *stack, Node *node) +{ + // create new nodelist head + node->next = stack->nodeList; + stack->nodeList = node; + stack->len++; +} + +Node *pop(Stack *stack) +{ + Node *nodeList = stack->nodeList; + Node *newHead = nodeList->next; + + // remove reference to the next + nodeList->next = NULL; + stack->nodeList = newHead; + + return nodeList; +} diff --git a/solutions/c/spreadsheet/stackcalc.h b/solutions/c/spreadsheet/stackcalc.h new file mode 100644 index 0000000..b1ec9c2 --- /dev/null +++ b/solutions/c/spreadsheet/stackcalc.h @@ -0,0 +1,22 @@ + +typedef struct Node +{ + double value; + struct Node *next; +} Node; + +typedef struct +{ + Node *nodeList; + int len; +} Stack; + +/** + * Pushes node into the stack + */ +void push(Stack *stack, Node *node); + +/** + * Pops a node from the stack. Returns NULL if stack is empty + */ +Node *pop(Stack *stack); diff --git a/solutions/c/spreadsheet/tests/Makefile b/solutions/c/spreadsheet/tests/Makefile new file mode 100644 index 0000000..41c3e39 --- /dev/null +++ b/solutions/c/spreadsheet/tests/Makefile @@ -0,0 +1,6 @@ +all: tests + +tests: matrix_test.c ../regex.c ../commons.c ../regex.h ../matrix.h ../stackcalc.h + clang -o matrixTest -ggdb3 -Wall -Werror -O0 -std=c99 -I/usr/local/include matrix_test.c ../matrix.c ../regex.c ../commons.c ../stackcalc.c -L/usr/local/lib/ -lpcre2-8 -lcmocka + + diff --git a/solutions/c/spreadsheet/tests/core b/solutions/c/spreadsheet/tests/core new file mode 100644 index 0000000..07f2ecf Binary files /dev/null and b/solutions/c/spreadsheet/tests/core differ diff --git a/solutions/c/spreadsheet/tests/matrixTest b/solutions/c/spreadsheet/tests/matrixTest new file mode 100755 index 0000000..151851f Binary files /dev/null and b/solutions/c/spreadsheet/tests/matrixTest differ diff --git a/solutions/c/spreadsheet/tests/matrix_test.c b/solutions/c/spreadsheet/tests/matrix_test.c new file mode 100644 index 0000000..202a429 --- /dev/null +++ b/solutions/c/spreadsheet/tests/matrix_test.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include +#include + +#include "../matrix.h" +#include "../regex.h" +#include "../commons.h" +#include "../stackcalc.h" + +static void testConvertToCellReference(void **state) +{ + MatrixLocation m; + m.row = 0; + m.col = 0; + + CellReference *ref = convertToCellReference(&m); + assert_string_equal("A1", ref->cellReference); + + free(ref); + + m.row = 1; + m.col = 2; + + ref = convertToCellReference(&m); + assert_string_equal("B3", ref->cellReference); + + free(ref); +} + +static void testConvertToMatrixLocation(void **state) +{ + CellReference c; + c.cellReference = "A1"; + + MatrixLocation *m = convertToMatrixLocation(&c); + + assert_int_equal(0, m->row); + assert_int_equal(0, m->col); + + free(m); + + c.cellReference = "B5"; + m = convertToMatrixLocation(&c); + assert_int_equal(1, m->row); + assert_int_equal(4, m->col); + + free(m); +} + +static void testSetAndGetWorkSheetValue(void **state) +{ + Worksheet *w = malloc(sizeof(Worksheet)); + initWorksheet(w, 4, 4); + setValue(w, 0, 0, "A2 + 1"); + assert_string_equal("A2 + 1", getValue(w, 0, 0)); + free(w); +} + +static void testCyclicDependency(void **state) +{ + Worksheet *w = malloc(sizeof(Worksheet)); + initWorksheet(w, 4, 4); + + setValue(w, 0, 0, "A2 + 1"); + assert_string_equal("A2 + 1", getValue(w, 0, 0)); + assert_int_equal(0, isCyclicRefError(w, 0, 0)); + + setValue(w, 0, 1, "A1"); + assert_string_equal("A1", getValue(w, 0, 1)); + assert_int_equal(1, isCyclicRefError(w, 0, 1)); +} + +static void testStack(void **state) +{ + Stack *stack = malloc(sizeof(Stack)); + stack->len = 0; + + Node *node = malloc(sizeof(Node)); + node->value = 10.0; + push(stack, node); + + Node *node2 = malloc(sizeof(Node)); + node2->value = 12.0; + push(stack, node2); + + Node *poppedNode1 = pop(stack); + assert_true(12.0 == poppedNode1->value); + + Node *poppedNode2 = pop(stack); + assert_true(10.0 == poppedNode2->value); + + free(node); + free(node2); + free(stack); +} + +int main(int argc, char *argv[]) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(testConvertToCellReference), + cmocka_unit_test(testConvertToMatrixLocation), + cmocka_unit_test(testSetAndGetWorkSheetValue), + cmocka_unit_test(testCyclicDependency), + cmocka_unit_test(testStack), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/solutions/cpp/ShopInCandyStore.hpp b/solutions/cpp/ShopInCandyStore.hpp new file mode 100644 index 0000000..a1a04c0 --- /dev/null +++ b/solutions/cpp/ShopInCandyStore.hpp @@ -0,0 +1,18 @@ +#include +using namespace std; +int main() +{ + int t; cin>>t; + while(t--) + { + int n,k; cin>>n>>k; long int a[n],min=0,max=0,c=0; + for(int i=0;i>a[i]; + sort(a,a+n); + int x=(n/(k+1)); if((n%(k+1))>0) {x++;} + + for(int i=0;i= 0; j-- { + if a.Less(j, j+1) { + k = j + break + } + } + if k == -1 { // if k not found, all done + return false + } + // Find largest index l greater than k such that a[k] < a[l] + l := -1 + for j := n - 1; j >= k+1; j-- { + if a.Less(k, j) { + l = j + break + } + } + // swap a[k] <-> a[l] + a.Swap(k, l) + // Reverse a[k+1:n] + for i, j := k+1, n-1; i < j; i, j = i+1, j-1 { + a.Swap(i, j) + } + current++ + return true + } +} + +/*************** Create a sortable type ***************/ + +// MyPermSeq satisfy interface sort.Interface +type MyPermSeq []byte + +// Len of the sequence +func (ps MyPermSeq) Len() int { + return len(ps) +} + +// Less implements < +func (ps MyPermSeq) Less(i, j int) bool { + return ps[i] < ps[j] +} + +// Swap in place +func (ps MyPermSeq) Swap(i, j int) { + ps[i], ps[j] = ps[j], ps[i] +} + +func main() { + + // Let's permutate ABCD in-place: output will be ordered in lexicographical order + mySeq := MyPermSeq([]byte("ABCD")) + next := PermutationsIter(mySeq) + fmt.Println("Generating permutations for", string(mySeq), ": ") + for next() { + fmt.Print(string(mySeq), " ") + } + fmt.Println("") + + // Let's permutate ABBB in-place: shows algorithm handles repeated elements well + mySeq = MyPermSeq([]byte("ABBB")) + next = PermutationsIter(mySeq) + fmt.Println("Generating permutations for", string(mySeq), ": ") + for next() { + fmt.Print(string(mySeq), " ") + } + fmt.Println("") + +} diff --git a/solutions/java/BinarySearchTree.java b/solutions/java/BinarySearchTree.java new file mode 100644 index 0000000..1d47c28 --- /dev/null +++ b/solutions/java/BinarySearchTree.java @@ -0,0 +1,72 @@ +/* + * Program to create a binary search tree. + * Author: Viveka Aggarwal + */ + +public class BinarySearchTree { + Node root; + public class Node { + Node left; + Node right; + Integer data; + + Node() { + } + + Node(Integer data) { + left = right = null; + this.data = data; + } + } + + BinarySearchTree() { + root = new Node(); + } + + BinarySearchTree(Integer data) { + root = new Node(data); + } + + public void addToTree(Integer data) { + addToTree(root, data); + } + + private void addToTree(Node curr, Integer data) { + if(curr == null) { + curr = new Node(data); + } else if(curr.data.compareTo(data) >= 0) { + if(curr.left == null) + curr.left = new Node(data); + else + addToTree(curr.left, data); + } else { + if(curr.right == null) + curr.right = new Node(data); + else + addToTree(curr.right, data); + } + } + + @Override + public String toString() { + return toString(this.root); + } + + String toString(Node curr) { + if(curr == null) + return ""; + return toString(curr.left) + " " + curr.data + " " + toString(curr.right); + } + + public static void main(String[] args) { + BinarySearchTree tree = new BinarySearchTree(1); + tree.addToTree(5); + tree.addToTree(3); + tree.addToTree(89); + tree.addToTree(43); + tree.addToTree(43); + tree.addToTree(67); + + System.out.println(tree.toString()); + } +} diff --git a/solutions/java/BinarySearchTreeCheck.java b/solutions/java/BinarySearchTreeCheck.java index efdda83..7380076 100644 --- a/solutions/java/BinarySearchTreeCheck.java +++ b/solutions/java/BinarySearchTreeCheck.java @@ -1,105 +1,144 @@ -/* Uses Inorder traversal. Only works on unique element BT */ -public class BinarySearchTreeCheck { - Node root; - - public BinarySearchTreeCheck() { - root = null; - } - - public class Node { - int value; - Node left; - Node right; - - public Node(int value) { - this.value = value; - this.left = null; - this.right = null; - } - - public void setLeft(Node left) { - this.left = left; - } - - public Node getLeft() { - return left; - } - - public void setRight(Node right) { - this.right = right; - } - - public Node getRight() { - return right; - } - - public int getValue() { - return value; - } - } - - public void createBinaryTree(int option) { - root = new Node(10); - Node one = new Node(8); - Node two = new Node(5); - Node three = new Node(9); - Node four = new Node(15); - switch (option) { - case 1: /* Is BST (Only unique elements) */ - root.setLeft(one); - root.setRight(four); - one.setLeft(two); - one.setRight(three); - break; - case 2: /* Not BST (Only unique elements) */ - root.setRight(two); - root.setLeft(one); - one.setLeft(four); - one.setRight(three); - break; - default: - break; - } - } +/* checks if a given tree is a BST + 1. isBSTBetter checks for a BST with unique elements + 2. isBST checks for a BST with unique or non Unique elements + */ - public boolean isBSTBetter() { - if (root == null) - return true; - return isBSTBetter(root); - } - - private Integer prev = null; - - public boolean isBSTBetter(Node cur) { - if (cur == null) - return true; - - // Check for the left subtree - if (!isBSTBetter(cur.getLeft())) { - return false; - } - - // Check the cur value and update prev - if (prev != null && cur.getValue() <= prev) - return false; - prev = cur.getValue(); - - // Check for the right subtree - if (!isBSTBetter(cur.getRight())) { - return false; - } - - return true; - } - - public static void main(String[] args) { - BinarySearchTreeCheck btOne = new BinarySearchTreeCheck(); - btOne.createBinaryTree(1); - BinarySearchTreeCheck btTwo = new BinarySearchTreeCheck(); - btTwo.createBinaryTree(2); - - // Only works if all the elements in the Binary Tree are unique. - System.out.println(btOne.isBSTBetter()); - System.out.println(btTwo.isBSTBetter()); - } +public class BinarySearchTreeCheck { + Node root; + + public BinarySearchTreeCheck() { + root = null; + } + + public class Node { + int value; + Node left; + Node right; + + public Node(int value) { + this.value = value; + this.left = null; + this.right = null; + } + + public void setLeft(Node left) { + this.left = left; + } + + public Node getLeft() { + return left; + } + + public void setRight(Node right) { + this.right = right; + } + + public Node getRight() { + return right; + } + + public int getValue() { + return value; + } + } + + public void createBinaryTree(int option) { + root = new Node(10); + Node one = new Node(8); + Node two = new Node(5); + Node three = new Node(9); + Node four = new Node(15); + Node five = new Node(8); + switch (option) { + case 1: /* Is BST (Only unique elements) */ + root.setLeft(one); + root.setRight(four); + one.setLeft(two); + one.setRight(three); + break; + case 2: /* Not BST (Only unique elements) */ + root.setRight(two); + root.setLeft(one); + one.setLeft(four); + one.setRight(three); + break; + case 3: /* Is BST (Non-unique elements) */ + root.setLeft(one); + root.setRight(four); + one.setLeft(five); + one.setRight(three); + break; + default: + break; + } + } + + public boolean isBSTBetter() { + if (root == null) + return true; + return isBSTBetter(root); + } + + private Integer prev = null; + + public boolean isBSTBetter(Node cur) { + if (cur == null) + return true; + + // Check for the left subtree + if (!isBSTBetter(cur.getLeft())) { + return false; + } + + // Check the cur value and update prev + if (prev != null && cur.getValue() <= prev) + return false; + prev = cur.getValue(); + + // Check for the right subtree + if (!isBSTBetter(cur.getRight())) { + return false; + } + + return true; + } + + // Checks for tree with non unique elements by comparing the + // minimum and maximum values. + // Author: Viveka Aggarwal + public boolean isBST() { + return isBST(root, Integer.MIN_VALUE, Integer.MAX_VALUE); + } + + public static boolean isBST(Node n, int min, int max) { + if(n == null) + return true; + + if(n.getValue() <= min || n.getValue() > max) + return false; + + if(!isBST(n.left, min, n.getValue()) || !isBST(n.right, n.getValue(), max)) + return false; + + return true; + } + + + public static void main(String[] args) { + BinarySearchTreeCheck btOne = new BinarySearchTreeCheck(); + btOne.createBinaryTree(1); + BinarySearchTreeCheck btTwo = new BinarySearchTreeCheck(); + btTwo.createBinaryTree(2); + BinarySearchTreeCheck btThree = new BinarySearchTreeCheck(); + btThree.createBinaryTree(3); + + // Only works if all the elements in the Binary Tree are unique. + System.out.println(btOne.isBSTBetter()); + System.out.println(btTwo.isBSTBetter()); + + // Works with both unique and non unique elements in a tree. + System.out.println(btOne.isBST()); + System.out.println(btTwo.isBST()); + System.out.println(btThree.isBST()); + } } \ No newline at end of file diff --git a/solutions/java/BubbleSort.java b/solutions/java/BubbleSort.java new file mode 100644 index 0000000..7a877d2 --- /dev/null +++ b/solutions/java/BubbleSort.java @@ -0,0 +1,42 @@ +/* + * Bubble sort is a simple sorting algorithm that repeatedly steps through the list to be sorted, + * compares each pair of adjacent items and swaps them if they are in the wrong order. + * The pass through the list is repeated until no swaps are needed, which indicates that the list is sorted. + * Author : Viveka Aggarwal + * Author : Jayesh Chandrapal + */ + +public class BubbleSort { + public static void sort(int[] arr) { + int len = arr.length; + boolean unsorted = true; + + while(unsorted) { + unsorted = false; + + for(int j = 0 ; j < len - 1; j++) { + if(arr[j] > arr[j + 1]) { + swap(j, j + 1, arr); + unsorted = true; + } + } + } + } + + public static void swap(int a, int b, int[] arr) { + int temp = arr[a]; + arr[a] = arr[b]; + arr[b] = temp; + } + + public static void main(String[] a) { + int[] arr = {23, 3, 12, 54, 34, 77, 78, 87, 92, 12}; // unsorted input + //int[] arr = {3,12, 12, 23, 34, 54, 77, 78, 87, 92}; // sorted input + + sort(arr); + + for(int i : arr) { + System.out.print(i + " "); + } + } +} diff --git a/solutions/java/CombineTwoStrings.java b/solutions/java/CombineTwoStrings.java index ba4834f..5f0c431 100644 --- a/solutions/java/CombineTwoStrings.java +++ b/solutions/java/CombineTwoStrings.java @@ -1,3 +1,4 @@ +import java.util.HashMap; import java.util.Stack; /** @@ -9,14 +10,21 @@ * * Another solution is to compromise of the space complexity a little, and make * use of a stack as below. + * + * Addition: We could also use a HashMap to record the rank of each character + * in the combined string and check the two input strings as below. */ public class CombineTwoStrings { public static void main(String[] args) { CombineTwoStrings cts = new CombineTwoStrings(); String one = "rohit"; String two = "deepthi"; + String three = "viveka"; String combined = "rodehepitht"; - System.out.print(cts.isValid(one, two, combined)); + String combined2 = "rviovehkiat"; + System.out.println(cts.isValid(one, two, combined)); + System.out.println(cts.isValidTwo(one, three, combined2)); + } public boolean isValid(String one, String two, String combined) { @@ -40,4 +48,28 @@ else if (comparer == two.charAt(twoIndex)) } return true; } -} \ No newline at end of file + + // Used a hashMap to save the rank of each character in the combined string. + // Incrementing the pointer of respective string as per the rank in the + // combined string. + public boolean isValidTwo(String one, String two, String combined) { + if(one.length() + two.length() != combined.length()) + return false; + HashMap map = new HashMap<>(); + int key = 0, p1 = 0, p2 = 0, pT = 0; + for(Character i : combined.toCharArray()) { + map.put(key++, i); + } + + while(p1 <= one.length() - 1 && p2 <= two.length() - 1 && pT <= combined.length() - 1) { + char temp = map.get(pT++); + if(one.charAt(p1) == temp) + p1++; + else if (two.charAt(p2) == temp) + p2++; + else + return false; + } + return true; + } +} diff --git a/solutions/java/ConvertArray.java b/solutions/java/ConvertArray.java index c3ce1ab..422b188 100644 --- a/solutions/java/ConvertArray.java +++ b/solutions/java/ConvertArray.java @@ -8,6 +8,11 @@ public int getOriginalIndex(int currentIndex, int length) { } public int[] convert(int[] input) { + // When array size is less than 3, returns an error. + if (input.length % 3 != 0 ) { + System.out.println("Error! Array cannot be divided into three equal parts"); + return; + } for (int i = 0; i < input.length; ++i) { int originalIndex = getOriginalIndex(i, input.length/3); while (originalIndex < i) { diff --git a/solutions/java/Fibonacci.java b/solutions/java/Fibonacci.java new file mode 100644 index 0000000..0721264 --- /dev/null +++ b/solutions/java/Fibonacci.java @@ -0,0 +1,26 @@ +// program to print the fibonacci series +import java.util.Scanner; + +public class Fibonacci { + // computes and displays the value at nth position using dynamic programming + static void printSeries(int n) { + long first = 0,second = 1,third = 0; + + for (int i = 2 ; i < n ; i++) { + third = first + second; + first = second; + second = third; + } + System.out.print("The number at position " +n+" of the fibonacci series is: " +third); + } + + public static void main (String[] a) { + Scanner in = new Scanner(System.in); + System.out.print("Enter the position of the element to displayed in the fibonacci series: "); + int n = in.nextInt(); + System.out.println(); + printSeries(n); + in.close(); + } +} + diff --git a/solutions/java/FindingMissingElement.java b/solutions/java/FindingMissingElement.java new file mode 100644 index 0000000..42d3080 --- /dev/null +++ b/solutions/java/FindingMissingElement.java @@ -0,0 +1,24 @@ +import java.util.*; +public class FindingMissingElement { + + /** + *The difference in the sum of the two arrays will give us the desired value + */ + static int find_missing(int a[],int b[]) + { + int sum=0; + for(int i:a) + sum+=i; + for(int i:b) + sum-=i; + return sum; + } + public static void main(String[] args) { + int[] arr={1,3,5,6,2,5,6,8,9,23,45,67,87}; + int[] shuffled_ar={1,2,5,6,8,9,3,45,87,6,67,5}; + System.out.println("The missing value is:"+find_missing(arr,shuffled_ar)); + + + } + +} diff --git a/solutions/java/RemoveDuplicatesFromString.java b/solutions/java/RemoveDuplicatesFromString.java index 1dfe597..77ec01f 100644 --- a/solutions/java/RemoveDuplicatesFromString.java +++ b/solutions/java/RemoveDuplicatesFromString.java @@ -1,8 +1,16 @@ +// Program to remove duplicates from a given string +// 1. getUniqueString(String) method uses a boolean array. +// 2. removeDuplicates(String) method uses a hash map. +// Both the methods have O(n) space and time complexity. (n being the string length) + +import java.util.HashMap; + public class RemoveDuplicatesFromString { public static void main(String[] args) { RemoveDuplicatesFromString rsd = new RemoveDuplicatesFromString(); String input = "Tree Traversal"; - System.out.println(rsd.getUniqueString(input)); + System.out.println("Method 1: " +rsd.getUniqueString(input)); + System.out.println("Method 2: " +rsd.removeDuplicates(input)); } public String getUniqueString(String input) { @@ -17,4 +25,17 @@ public String getUniqueString(String input) { } return sb.toString(); } -} \ No newline at end of file + + public String removeDuplicates(String input) { + HashMap map = new HashMap<>(); + StringBuffer sb = new StringBuffer(""); + for (int i = 0; i < input.length(); i++) { + char c = input.charAt(i); + if (!map.containsKey(c)) { + sb.append(c); + map.put(c, 1); + } + } + return sb.toString(); + } +} diff --git a/solutions/java/TreeLevelOrderPrint.java b/solutions/java/TreeLevelOrderPrint.java new file mode 100644 index 0000000..cdbab77 --- /dev/null +++ b/solutions/java/TreeLevelOrderPrint.java @@ -0,0 +1,82 @@ +// Program to create a Binary Search Tree and implement level order traversal. +// Author: Viveka Aggarwal + +import java.util.LinkedList; +import java.util.Queue; + +public class TreeLevelOrderPrint { + node root; + class node { + Integer value; + node left; + node right; + + node() { + } + + node (Integer value) { + this.value = value; + } + } + + public TreeLevelOrderPrint() { + root = new node(); + } + + public treelevelorderprint(Integer value) { + root = new node(value); + } + + public void addToTree(Integer value) { + if (root.value == null) { + root = new node(value); + } else { + addToTree(value, root); + } + } + + public void addToTree(Integer value, node curr) { + if (value <= curr.value) { + if (curr.left == null) + curr.left = new node(value); + else + addToTree(value, curr.left); + } else { + if (curr.right == null) + curr.right = new node(value); + else + addToTree(value, curr.right); + } + } + + public void levelOrder() { + if (root == null || root.value == null) { + System.out.println(); + System.out.println("Empty tree!!!"); + return; + } + + Queue q = new LinkedList(); + q.add(root); + + while(!q.isEmpty()) { + node curr = q.poll(); + System.out.print(curr.value + " "); + + if(curr.left != null) + q.add(curr.left); + + if(curr.right != null) + q.add(curr.right); + } + } + + public static void main(String[] args) { + TreeLevelOrderPrint tree = new TreeLevelOrderPrint(); + for (int i = 0; i <= 10; i++) { + tree.addToTree(i); + } + tree.addToTree(5); + tree.levelOrder(); + } +} diff --git a/solutions/javascript/array-pair-sum.js b/solutions/javascript/array-pair-sum.js index 705790b..781c473 100644 --- a/solutions/javascript/array-pair-sum.js +++ b/solutions/javascript/array-pair-sum.js @@ -1,19 +1,19 @@ -module.exports = function (k, array) { - var hash = {}, - pairs = []; +module.exports = function arraypairsum (k, array) { + var hash = {}; + var pairs = []; - // Loop through the array once, storing the results in an object for a - // time complexity of O(n) - the naive solution consists of two for loops - // which results in a complexity of O(n^2) + // Iterate over the array, tracking the times each number appears. For each + // new number, we calculate the difference to `k` and look up the number of + // times that number has been seen and push those occurances in pairs output. array.forEach(function (number) { - // Make sure the value in unused and it's a unique pair - if (hash[k - number] === false && k - number !== number) { - pairs.push([number, k - number]); - hash[k - number] = true; // Set it to "used" + var diff = k - number; + var len = hash[diff]; + + while (len--) { + pairs.push([diff, number]); } - // If the hash value is not true, set the hash to "unused" - !hash[k - number] && (hash[number] = false); + hash[number] = (hash[number] + 1) || 1; }); return pairs; diff --git a/solutions/javascript/combine-two-strings.js b/solutions/javascript/combine-two-strings.js index 9cf6764..e7e3e4f 100644 --- a/solutions/javascript/combine-two-strings.js +++ b/solutions/javascript/combine-two-strings.js @@ -1,20 +1,37 @@ -module.exports = function (str1, str2, combined) { - // Generate all the posible paths between `str1` and `str2` - var paths = {}; - - // Check the string lengths are the same to begin - if ((str1 + str2).length !== combined.length) { +module.exports = function combineTwoStrings (str1, str2, str3) { + // Simple optimisation to break when impossible. + if ((str1.length + str2.length) !== str3.length) { return false; } - // Finding paths is essentially the anagrams solution - (function findPath (str1, str2, path) { - if (path.length === combined.length) { return paths[path] = true; } + return isCombineTwoStrings(str1, str2, str3); +}; - // Find the next path from the first character of either strings - str1 && findPath(str1.substr(1), str2, path + str1.substr(0, 1)); - str2 && findPath(str1, str2.substr(1), path + str2.substr(0, 1)); - })(str1, str2, ''); +function isCombineTwoStrings (str1, str2, str3) { + // No more solutions to find. + if (str3.length === 0) { + return true; + } - return combined in paths; -}; + var newStr3 = str3.substr(1); + + // Path for when the first string matches. + if (str1[0] === str3[0]) { + // When both paths are possible, we implement a simple backtracking + // mechanism for when the first was wrong. E.g. `aac`, `aab`, `aaacab`. + if (str2[0] === str3[0]) { + return isCombineTwoStrings(str1.substr(1), str2, newStr3) || + isCombineTwoStrings(str1, str2.substr(1), newStr3); + } + + return isCombineTwoStrings(str1.substr(1), str2, newStr3); + } + + // Path for when the second string matches. + if (str2[0] === str3[0]) { + return isCombineTwoStrings(str1, str2.substr(1), newStr3); + } + + // When neither path is possible, the combination is `false`. + return false; +} diff --git a/solutions/javascript/convert-array.js b/solutions/javascript/convert-array.js new file mode 100644 index 0000000..5fda35b --- /dev/null +++ b/solutions/javascript/convert-array.js @@ -0,0 +1,26 @@ +'use strict'; + +function getSwapIndex(currentInd, n) { + var swapInd = (currentInd % 3) * n + parseInt(currentInd/3); + while (swapInd < currentInd) { + swapInd = getSwapIndex(swapInd, n); + } + + return swapInd; +} + +function convert(arr) { + var n = parseInt(arr.length / 3); + + for(var i = 0; i < arr.length; i++) { + var swapInd = getSwapIndex(i, n); + + var tmp = arr[i]; + arr[i] = arr[swapInd]; + arr[swapInd] = tmp; + } + + return arr; +} + +module.exports = convert; diff --git a/solutions/javascript/largest-palindrome.js b/solutions/javascript/largest-palindrome.js index 2ef75d5..8a09214 100644 --- a/solutions/javascript/largest-palindrome.js +++ b/solutions/javascript/largest-palindrome.js @@ -1,24 +1,29 @@ -module.exports = function (str) { - var palindromes = []; +function isPalindrome (str) { + const mid = Math.floor(str.length / 2) - var walkPalindrome = function (result, str, leftIndex, rightIndex) { - while (str[leftIndex - 1] === str[rightIndex + 1]) { - result = str[leftIndex -= 1] + result + str[rightIndex += 1]; + for (let i = 0; i < mid; i++) { + if (str[i] !== str[str.length - 1 - i]) { + return false } - palindromes.push(result); - }; + } + + return true +} + +module.exports = function longestPalindrome (str) { + let longest = '' + + for (let i = 0; i < str.length; i++) { + let len = str.length + + while (len > i && len - i > longest.length) { + const substring = str.substring(i, len--) - for (var i = 0; i < str.length; i++) { - if (str[i] === str[i - 1]) { - walkPalindrome(str[i] + str[i - 1], str, i - 1, i); - } else if (str[i] === str[i + 1]) { - walkPalindrome(str[i] + str[i + 1], str, i, i + 1); - } else if (str[i - 1] === str[i + 1]) { - walkPalindrome(str[i - 1] + str[i] + str[i + 1], str, i - 1, i + 1); + if (isPalindrome(substring)) { + longest = substring + } } } - return palindromes.reduce(function (memo, str) { - return str.length > memo.length ? str : memo; - }, ''); -}; + return longest +} diff --git a/solutions/php/factorial.php b/solutions/php/factorial.php index c2dfc48..2beb022 100644 --- a/solutions/php/factorial.php +++ b/solutions/php/factorial.php @@ -1,35 +1,36 @@ +} diff --git a/solutions/php/reverse-words-in-string.php b/solutions/php/reverse-words-in-string.php index 53fd495..3ede846 100644 --- a/solutions/php/reverse-words-in-string.php +++ b/solutions/php/reverse-words-in-string.php @@ -2,7 +2,5 @@ function reverseWordsInStrings($string) { - return implode(array_reverse(preg_split('/\s+/', $string)), ' '); + return trim(implode(array_reverse(preg_split('/\s+/', $string)), ' ')); } - -?> \ No newline at end of file diff --git a/solutions/php/sum-of-array-plus-one.php b/solutions/php/sum-of-array-plus-one.php index 0110036..c3783f1 100644 --- a/solutions/php/sum-of-array-plus-one.php +++ b/solutions/php/sum-of-array-plus-one.php @@ -1,11 +1,10 @@ diff --git a/solutions/php/transitive-dependencies.php b/solutions/php/transitive-dependencies.php new file mode 100644 index 0000000..34e3f2d --- /dev/null +++ b/solutions/php/transitive-dependencies.php @@ -0,0 +1,55 @@ +dependencies_matrix = array(); + } + + public function add_direct($index, $dependencies) + { + $this->dependencies_matrix[$index] = explode(",", $dependencies); + } + + public function dependencies_for($element) + { + //array where dependencies of the element parameter will be stored + $dependents = array(); + //process get element dependencies + $process = $this->dependencies_matrix[$element]; + + while (!empty($process)) { + + //get an item from process + $x = array_shift($process); + + //if x is not element itself, and is not in dependents array + if ($x != $element && !in_array($x, $dependents)) { + + //put in dependents array + $dependents[] = $x; + + //if x exists in dependencies_matrix + if (array_key_exists($x, $this->dependencies_matrix)) { + + //break the next dependencies list in strings + if (gettype($this->dependencies_matrix[$x]) == "array") { + foreach ($this->dependencies_matrix[$x] as $key => $value) { + array_push($process, $value); + } + } + + else { + //put the x line in process + array_push($process, array_values($this->dependencies_matrix[$x])); + } + } + } + } + return $dependents; + } +} //endclass diff --git a/solutions/python/bubble-sort.py b/solutions/python/bubble-sort.py new file mode 100644 index 0000000..902f5b6 --- /dev/null +++ b/solutions/python/bubble-sort.py @@ -0,0 +1,31 @@ +import unittest + +def bubblesort(lst): + for i in range(0, len(lst) - 1): + for j in range(i + 1, len(lst)): + if lst[i] > lst[j]: + # swap values + lst[i], lst[j] = lst[j], lst[i] + return lst + +class Test(unittest.TestCase): + def testUnsortedSmall(self): + self.assertEqual([1,2,3,4], bubblesort([4,3,2,1])) + + def testSortedSmall(self): + self.assertEqual([1,2,3,4], bubblesort([1,2,3,4])) + + def testUnsortedLarge(self): + self.assertEqual([1,2,3,4,5,6,7,8,9,10], bubblesort([6,3,4,8,7,9,5,10,1,2])) + + def testSortedLarge(self): + self.assertEqual([1,2,3,4,5,6,7,8,9,10], bubblesort([1,2,3,4,5,6,7,8,9,10])) + + def testSingleInput(self): + self.assertEqual([1], bubblesort([1])) + + def testBlankInput(self): + self.assertEqual([], bubblesort([])) + +if __name__ == '__main__': + unittest.main() diff --git a/solutions/python/closetsum.py b/solutions/python/closetsum.py new file mode 100644 index 0000000..ed7a431 --- /dev/null +++ b/solutions/python/closetsum.py @@ -0,0 +1,24 @@ +# In given A, find three elements whose sum is closest to give value. +#author: Pankaj Kumar + +import sys +def threeSumClosest(A, B): + i , n = 0 , len(A) + A = sorted(A) + diff = sys.maxint + close_sum = 0 + while i <= n-3: + j , k = i+1 , n-1 + sum = A[i] + A[j] + A[k] + if sum == B: + return sum + if diff > abs(sum - B): + diff += abs(sum-B) + close_sum = sum + if sum < B: + j += 1 + else: + k -= 1 + i += 1 + return close_sum +print threeSumClosest([-1, 2, 1, -4], 1) diff --git a/solutions/python/multiples-of-3-and-5.py b/solutions/python/multiples-of-3-and-5.py index d03184e..af44b5d 100644 --- a/solutions/python/multiples-of-3-and-5.py +++ b/solutions/python/multiples-of-3-and-5.py @@ -17,3 +17,10 @@ def getSumOfMultiples(multiples, limit): result += sign * getSumOfMultiple(reduce(mul, x, 1), limit) sign *= -1 return result + +def getSumOfMultiples(): + count=0 + for i in range(1000): + if i%3==0 or i%5==0: + count+=i + return count diff --git a/solutions/python/shortest-fizz-buzz.py b/solutions/python/shortest-fizz-buzz.py new file mode 100644 index 0000000..7fee772 --- /dev/null +++ b/solutions/python/shortest-fizz-buzz.py @@ -0,0 +1,4 @@ +for i in range(1,101): + o=''if i%3else'Fizz' + if i%5==0:o+='Buzz' + print(o if o else i) diff --git a/solutions/python/string-permutations.py b/solutions/python/string-permutations.py new file mode 100644 index 0000000..d613fc9 --- /dev/null +++ b/solutions/python/string-permutations.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python + +""" +This module presents two different solutions for the problem of generating the permutations of a sequence. +""" + +from math import factorial +import unittest + + +def perm_recursive(S): + """ + Return a list with all permutations of the iterable passed as argument. + Uses the simple recursive solution. This Algorithm does not handle repeated elements well. + """ + + def expand_inserting(c, L): + return [L[0:i] + [c] + L[i:] for i in range(len(L) + 1)] + + if not isinstance(S, list): + S = list(S) # to handle strings + if len(S) == 0: + return [] + elif len(S) == 1: + return [S] + + c, L = S[0], S[1:] + res = [] + for newL in perm_recursive(L): + res.extend(expand_inserting(c, newL)) + return res + + +def perm_generator(A): + """ + Generates all permutations of elements of the iterable passed as argument. + Uses Non-recursive lexicographic order (Knuth's L-Algorithm). + Requires all A elements are comparable to each other (list has to be sortable). + The algorithm handles repeated elements gracefully. + Reference: https://en.wikipedia.org/wiki/Permutation#Permutations_in_computing + """ + n = len(A) + a = sorted(list(A)) + ok = False if n == 0 else True + + while ok: + yield a[:] + # Find the largest index k such that a[k] < a[k + 1] + k = next((j for j in range(n-2, -1, -1) if a[j] < a[j+1]), -1) + if k == -1: # if no such index, is last permutation + break + # Find the largest index l greater than k such that a[k] < a[l] + l = next((j for j in range(n-1, k, -1) if a[k] < a[j]), -1) + # Swap values + a[k], a[l] = a[l], a[k] + # Reverse the sequence from a[k + 1] up to and including the final element a[n] + a[k+1:] = a[n-1:k:-1] + + +class Test(unittest.TestCase): + + def setUp(self): + self.perm_ABC = (('A', 'B', 'C'), ('B', 'A', 'C'), ('B', 'C', 'A'), ('A', 'C', 'B'), ('C', 'A', 'B'), + ('C', 'B', 'A')) + + def test_recursive1(self): + """ Permutations of list [A,B,C] correct """ + A = ['A', 'B', 'C'] + r = perm_recursive(A) + self.assertEqual(set(tuple([tuple(l) for l in r])), set(self.perm_ABC)) + self.assertEqual(len(r), factorial(len(A))) + + def test_recursive2(self): + """ Permutations of str "ABC" correct """ + A = "ABC" + r = perm_recursive(A) + self.assertEqual(set(tuple([tuple(l) for l in r])), set(self.perm_ABC)) + self.assertEqual(len(r), factorial(len(A))) + + def test_recursive3(self): + """ Empty string produces empty list """ + A = "" + r = perm_recursive(A) + self.assertEqual(r, []) + + def test_recursive4(self): + """ A sigle letter produces only one permutation """ + A = "A" + r = perm_recursive(A) + self.assertEqual(r, [['A']]) + + def test_recursive5(self): + """ Two repeated letter wrongly produce 2 permutations. Algorithm does not handle repeated elements! """ + A = "AA" + r = perm_recursive(A) + self.assertEqual(r, [['A', 'A'], ['A', 'A']]) + + def test_generator1(self): + """ Generated permutations of list [A,B,C] correct """ + A = ['A', 'B', 'C'] + r = list(perm_generator(A)) + self.assertEqual(set(tuple([tuple(l) for l in r])), set(self.perm_ABC)) + self.assertEqual(len(r), factorial(len(A))) + + def test_generator2(self): + """ Generated Permutations of str "ABC" correct """ + A = "BAC" + r = list(perm_generator(A)) + self.assertEqual(set(tuple([tuple(l) for l in r])), set(self.perm_ABC)) + self.assertEqual(len(r), factorial(len(A))) + + def test_generator3(self): + """ Two repeated letters generate only one permutation. Algorithm handles repeated elements well. """ + A = "AA" + r = list(perm_generator(A)) + self.assertEqual(r, [['A', 'A']]) + + +if __name__ == '__main__': + unittest.main() diff --git a/solutions/python/sum-of-array-plus-one.py b/solutions/python/sum-of-array-plus-one.py new file mode 100644 index 0000000..16490e5 --- /dev/null +++ b/solutions/python/sum-of-array-plus-one.py @@ -0,0 +1,3 @@ +def plusOneSum(arr): + """returns the sum of the integers after adding 1 to each element""" + return sum(arr)+len(arr) \ No newline at end of file diff --git a/solutions/ruby/flatten_array.rb b/solutions/ruby/flatten_array.rb new file mode 100644 index 0000000..fd63c80 --- /dev/null +++ b/solutions/ruby/flatten_array.rb @@ -0,0 +1,21 @@ +# Note that there is already an implementation in the core ruby library +# http://ruby-doc.org/core-2.2.0/Array.html#method-i-flatten + +def flatten_array(arr = []) + return arr unless arr.is_a? Array + + result = [] + arr.each do |elem| + if elem.is_a? Array + result += flatten_array(elem) + else + result << elem + end + end + + result +end + +flatten_array([]) # => [] +flatten_array([[["a"]]]) # => ["a"] +flatten_array([0, ["damn"], [[["a", "b"]]], 0]) # => [0, "damn", "a", "b", 0] diff --git a/tests/javascript/array-pair-sum.js b/tests/javascript/array-pair-sum.js new file mode 100644 index 0000000..41821a6 --- /dev/null +++ b/tests/javascript/array-pair-sum.js @@ -0,0 +1,16 @@ +var expect = require('chai').expect; +var arrayPairSum = require('../../solutions/javascript/array-pair-sum'); + +describe('Array Pair Sum', function () { + it('should find pairs that equal the expected sum', function () { + expect(arrayPairSum(10, [3, 4, 5, 6, 7])).to.eql([[4, 6], [3, 7]]); + }); + + it('should not output duplicate results', function () { + expect(arrayPairSum(8, [3, 4, 5, 4, 4])).to.eql([[3, 5], [4, 4], [4, 4], [4, 4]]); + }); + + it('should work not find any matches', function () { + expect(arrayPairSum(10, [3, 5, 6, 8])).to.eql([]); + }) +}); diff --git a/tests/javascript/balanced-brackets.js b/tests/javascript/balanced-brackets.js new file mode 100644 index 0000000..5844ae7 --- /dev/null +++ b/tests/javascript/balanced-brackets.js @@ -0,0 +1,22 @@ +var expect = require('chai').expect; +var balancedBrackets = require('../../solutions/javascript/balanced-brackets'); + + +describe('Balanced brackets', function () { + + it('should detect pairing brackets', function () { + expect(balancedBrackets('()[]{}')).to.be.true; + }); + it('should detect nested brackets', function () { + expect(balancedBrackets('(([])){[()][]}')).to.be.true; + }); + + it('should detect non pairing brackets ', function () { + expect(balancedBrackets('())[]{}')).to.be.false; + }); + + it('should detect wrong nesting ', function () { + expect(balancedBrackets('[(])')).to.be.false; + }); + +}); diff --git a/tests/javascript/bubble-sort.js b/tests/javascript/bubble-sort.js new file mode 100644 index 0000000..0cdc1bd --- /dev/null +++ b/tests/javascript/bubble-sort.js @@ -0,0 +1,13 @@ +var expect = require('chai').expect; +var bubble_sort = require('../../solutions/javascript/insertion-sort'); + +describe('it tests bubble sort function', function(){ + var sorted = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + var array = [9, 8, 7, 6, 5, 4, 3, 2, 1]; + + it("sort array: " + sorted, function(){ + array = bubble_sort(array); + expect(array).deep.equal(sorted); + }) + +}); diff --git a/tests/javascript/combine-two-strings.js b/tests/javascript/combine-two-strings.js new file mode 100644 index 0000000..7a10b0b --- /dev/null +++ b/tests/javascript/combine-two-strings.js @@ -0,0 +1,20 @@ +var expect = require('chai').expect; +var combineTwoStrings = require('../../solutions/javascript/combine-two-strings'); + +describe('it tests combine two strings function', function(){ + var str1 = 'abc'; + var str2 = 'def'; + var str3valid = 'dabecf'; + var str3invalid = 'dabfce'; + + it("it tests that f('" + str1 + "," +str2 + ",'" +str3valid + "')' is valid " , function(){ + var result = combineTwoStrings(str1, str2, str3valid); + expect(result).to.be.true; + }); + + it("it tests that f('" + str1 + "," +str2 + ",'" +str3invalid + "')' is invalid " , function(){ + var result = combineTwoStrings(str1, str2, str3invalid); + expect(result).to.be.false; + }); + +}); diff --git a/tests/javascript/convert-array.js b/tests/javascript/convert-array.js new file mode 100644 index 0000000..0056872 --- /dev/null +++ b/tests/javascript/convert-array.js @@ -0,0 +1,26 @@ +var assert = require('assert'); +var convert = require('../../solutions/javascript/convert-array'); + +describe('Convert Array', function() { + it('should convert an array', function() { + var arr = [ + 'a1', 'a2', 'a3', 'a4', 'a5', + 'b1', 'b2', 'b3', 'b4', 'b5', + 'c1', 'c2', 'c3', 'c4', 'c5' + ]; + + var expectedArr = [ + 'a1', 'b1', 'c1', + 'a2', 'b2', 'c2', + 'a3', 'b3', 'c3', + 'a4', 'b4', 'c4', + 'a5', 'b5', 'c5' + ]; + + convert(arr); + + for(var i = 0; i < arr.length; i++) { + assert.equal(arr[i], expectedArr[i]); + } + }) +}) diff --git a/tests/php/IntegerLengthTest.php b/tests/php/IntegerLengthTest.php new file mode 100644 index 0000000..f718471 --- /dev/null +++ b/tests/php/IntegerLengthTest.php @@ -0,0 +1,16 @@ +assertEquals(1, IntegerLength(1)); + $this->assertEquals(2, IntegerLength(22)); + $this->assertEquals(3, IntegerLength(333)); + $this->assertEquals(10, IntegerLength(1234567890)); + + } +} diff --git a/tests/php/factorialTest.php b/tests/php/factorialTest.php new file mode 100644 index 0000000..b06e01e --- /dev/null +++ b/tests/php/factorialTest.php @@ -0,0 +1,37 @@ +verifyFactorial("factorial"); + } + + public function test_factorialReverse() + { + $this->verifyFactorial("factorialReverse"); + } + + public function test_factorialRecursive() + { + $this->verifyFactorial("factorialRecursive"); + } + + private function verifyFactorial($fn) + { + $testDataMap = [ + ["input" => 1, "expect" => 1], + ["input" => 2, "expect" => 2], + ["input" => 3, "expect" => 6], + ["input" => 5, "expect" => 120], + ["input" => 20, "expect" => 2432902008176640000], + ]; + + foreach ($testDataMap as $data) { + $this->assertEquals($data["expect"], call_user_func($fn, $data["input"])); + } + } +} diff --git a/tests/php/reverseWordsInStringTest.php b/tests/php/reverseWordsInStringTest.php new file mode 100644 index 0000000..100f648 --- /dev/null +++ b/tests/php/reverseWordsInStringTest.php @@ -0,0 +1,16 @@ +assertEquals("awesome! are Interviews", reverseWordsInStrings("Interviews are awesome!")); + $this->assertEquals("degree CS", reverseWordsInStrings(" CS degree")); + $this->assertEquals("degree CS", reverseWordsInStrings("CS degree")); + $this->assertEquals("degree CS", reverseWordsInStrings("CS degree ")); + $this->assertEquals("degree CS", reverseWordsInStrings(" CS degree ")); + } +} diff --git a/tests/php/sumOfArrayPlusOneTest.php b/tests/php/sumOfArrayPlusOneTest.php new file mode 100644 index 0000000..d9e7028 --- /dev/null +++ b/tests/php/sumOfArrayPlusOneTest.php @@ -0,0 +1,13 @@ +assertEquals(14, SumOfArrayPlusOne([1, 2, 3, 4])); + + } +}