├── src └── index.js ├── .prettierrc ├── .editorconfig ├── .eslintrc.js ├── extensions └── it-optional.js ├── package.json ├── LICENSE ├── .gitignore ├── test └── test.js └── README.md /src/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function check(/* str, bracketsConfig */) { 2 | throw new Error('Not implemented'); 3 | }; 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 80, 7 | "endOfLine": "auto" 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.js] 12 | quote_type = single 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | 17 | [*.json] 18 | insert_final_newline = false 19 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | commonjs: true, 5 | es2024: true, 6 | node: true, 7 | mocha: true, 8 | }, 9 | extends: ['airbnb-base', 'plugin:prettier/recommended'], 10 | globals: { 11 | Atomics: 'readonly', 12 | SharedArrayBuffer: 'readonly', 13 | }, 14 | parserOptions: { 15 | ecmaVersion: 2024, 16 | }, 17 | noInlineConfig: true, 18 | }; 19 | -------------------------------------------------------------------------------- /extensions/it-optional.js: -------------------------------------------------------------------------------- 1 | function testOptional(title, fn, isAsyncTest) { 2 | if (isAsyncTest) { 3 | it(title, function test(done) { 4 | try { 5 | fn.call(this, done); 6 | } catch (err) { 7 | if (err.message === 'Not implemented') { 8 | this.test.skip(); 9 | } else { 10 | throw err; 11 | } 12 | } 13 | }); 14 | } else { 15 | it(title, function test() { 16 | try { 17 | fn.call(this); 18 | } catch (err) { 19 | if (err.message === 'Not implemented') { 20 | this.test.skip(); 21 | } else { 22 | throw err; 23 | } 24 | } 25 | }); 26 | } 27 | } 28 | 29 | module.exports = testOptional; 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "brackets", 3 | "version": "1.0.0", 4 | "description": "Brackets", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npm run lint && mocha", 8 | "lint": "node node_modules/eslint/bin/eslint.js ./src", 9 | "lint:fix": "node node_modules/eslint/bin/eslint.js ./src --fix" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/rolling-scopes-school/brackets.git" 14 | }, 15 | "author": "max@shas.tel", 16 | "license": "MIT", 17 | "homepage": "https://github.com/rolling-scopes-school/brackets", 18 | "devDependencies": { 19 | "eslint": "^8.57.1", 20 | "eslint-config-airbnb-base": "^15.0.0", 21 | "eslint-config-prettier": "^10.1.1", 22 | "eslint-plugin-prettier": "^5.2.3", 23 | "mocha": "^10.8.2", 24 | "prettier": "^3.5.3" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const check = require('../src'); 3 | it.optional = require('../extensions/it-optional'); 4 | 5 | const config1 = [['(', ')']]; 6 | const config2 = [ 7 | ['(', ')'], 8 | ['[', ']'], 9 | ]; 10 | const config3 = [ 11 | ['(', ')'], 12 | ['[', ']'], 13 | ['{', '}'], 14 | ]; 15 | const config4 = [['|', '|']]; 16 | const config5 = [ 17 | ['(', ')'], 18 | ['|', '|'], 19 | ]; 20 | const config6 = [ 21 | ['1', '2'], 22 | ['3', '4'], 23 | ['5', '6'], 24 | ['7', '7'], 25 | ['8', '8'], 26 | ]; 27 | const config7 = [ 28 | ['(', ')'], 29 | ['[', ']'], 30 | ['{', '}'], 31 | ['|', '|'], 32 | ]; 33 | 34 | it.optional('should check if brackets sequence is correct 1', () => { 35 | assert.equal(check('()', config1), true); 36 | }); 37 | 38 | it.optional('should check if brackets sequence is correct 2', () => { 39 | assert.equal(check('((()))()', config1), true); 40 | }); 41 | 42 | it.optional('should check if brackets sequence is not correct 3', () => { 43 | assert.equal(check('())(', config1), false); 44 | }); 45 | 46 | it.optional('should check if brackets sequence is correct 4', () => { 47 | assert.equal(check('([{}])', config3), true); 48 | }); 49 | 50 | it.optional('should check if brackets sequence is not correct 5', () => { 51 | assert.equal(check('[(])', config2), false); 52 | }); 53 | 54 | it.optional('should check if brackets sequence is correct 6', () => { 55 | assert.equal(check('[]()', config2), true); 56 | }); 57 | 58 | it.optional('should check if brackets sequence is correct 7', () => { 59 | assert.equal(check('[]()(', config2), false); 60 | }); 61 | 62 | it.optional('should check if brackets sequence is correct 8', () => { 63 | assert.equal(check('||', config4), true); 64 | }); 65 | 66 | it.optional('should check if brackets sequence is correct 9', () => { 67 | assert.equal(check('|()|', config5), true); 68 | }); 69 | 70 | it.optional('should check if brackets sequence is not correct 10', () => { 71 | assert.equal(check('|(|)', config5), false); 72 | }); 73 | 74 | it.optional('should check if brackets sequence is correct 11', () => { 75 | assert.equal(check('|()|(||)||', config5), true); 76 | }); 77 | 78 | it.optional('should check if brackets sequence is correct 12', () => { 79 | assert.equal( 80 | check( 81 | '111115611111111222288888822225577877778775555666677777777776622222', 82 | config6 83 | ), 84 | true 85 | ); 86 | }); 87 | 88 | it.optional('should check if brackets sequence is correct 13', () => { 89 | assert.equal( 90 | check( 91 | '5555512575557777777555566667888888667661133833448441111222233333444442266666', 92 | config6 93 | ), 94 | false 95 | ); 96 | }); 97 | 98 | it.optional('should check if brackets sequence is correct 14', () => { 99 | assert.equal( 100 | check( 101 | '8888877878887777777888888887777777887887788788887887777777788888888887788888', 102 | config6 103 | ), 104 | false 105 | ); 106 | }); 107 | 108 | it.optional('should check if brackets sequence is correct 15', () => { 109 | assert.equal( 110 | check( 111 | '111115611111111156111111112222888888222255778777787755556666777777777766222221111222288888822225577877778775555666677777777776622222', 112 | config6 113 | ), 114 | true 115 | ); 116 | }); 117 | 118 | it.optional('should check if brackets sequence is not correct 16', () => { 119 | assert.equal(check('[]][[]', config3), false); 120 | }); 121 | 122 | it.optional('should check if brackets sequence is not correct 17', () => { 123 | assert.equal(check('[]][[]', config2), false); 124 | }); 125 | 126 | it.optional('should check if brackets sequence is not correct 18', () => { 127 | assert.equal( 128 | check( 129 | '([[[[(({{{}}}(([](((((((())))||||||))))[[{{|{{}}|}}[[[[]]]]{{{{{}}}}}]]))))]]]]))()', 130 | config7 131 | ), 132 | false 133 | ); 134 | }); 135 | 136 | it.optional('should check if brackets sequence is correct 19', () => { 137 | assert.equal( 138 | check( 139 | '([[[[(({{{}}}(([](((((((())))||||||))))[[{{|{{}}|}}[[[[]]]]{{{{{}}}}}]]))))]]]])(())', 140 | config7 141 | ), 142 | true 143 | ); 144 | }); 145 | 146 | it.optional('should check if brackets sequence is correct 20', () => { 147 | assert.equal( 148 | check( 149 | '([[[[(({{{}}}(([](((((((())))||||||))))[[{{|{{}}|}}[[[[]]]]{{{{{}}}}}]]))))]]]])((([[[[(({{{}}}(([](((((((())))||||||))))[[{{|{{}}|}}[[[[]]]]{{{{{}}}}}]]))))]]]])))', 150 | config7 151 | ), 152 | true 153 | ); 154 | }); 155 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Brackets 2 | 3 | :warning: **Please note that you mustn't open PRs that contains the answers to this repo!** 4 | 5 | However, PRs with the fixes or proposals are welcomed! 6 | 7 | ## Task 8 | Implement function `check(str, bracketsConfig)`, that for given brackets sequence will return `true` if it is correct and `false` otherwise 9 | 10 | In the second param there is `bracketsConfig` - the array of pairs open-closed brackets. Each subarray includes only 2 elements - opening and closing bracket 11 | 12 | ```js 13 | check('()', [['(', ')']]) // -> true 14 | check('((()))()', [['(', ')']]) // -> true 15 | check('())(', [['(', ')']]) // -> false 16 | check('([{}])', [['(', ')'], ['[', ']'], ['{', '}']]) // -> true 17 | check('[(])', [['(', ')'], ['[', ']']]) // -> false 18 | check('[]()', [['(', ')'], ['[', ']']]) // -> true 19 | check('[]()(', [['(', ')'], ['[', ']']]) // -> false 20 | 21 | // special case: opening and closing bracket can be the same :) 22 | 23 | check('||', [['|', '|']]) // -> true 24 | check('|()|', [['(', ')'], ['|', '|']]) // -> true 25 | check('|(|)', [['(', ')'], ['|', '|']]) // -> false 26 | check('|()|(||)||', [['(', ')'], ['|', '|']]) // -> true 27 | ``` 28 | You can find even more examples in `test.js` 29 | 30 | **Active usage of [documentation](https://developer.mozilla.org/en-US/) is strongly recommended!** 31 | 32 | ## Prepare and test 33 | 1. Install Node.js 34 | 2. Fork this repository: https://github.com/rolling-scopes-school/brackets/ 35 | 3. Clone your newly created repo: `https://github.com/<%your_github_username%>/brackets/` 36 | 4. Go to folder `brackets` 37 | 5. To install all dependencies use `npm install` 38 | 6. Read the task description. Try to understand the idea. You can see the tests prepared if you don't understand it. 39 | 7. Write your code in `src/index.js`. 40 | 41 | Uncomment the incoming parameters: 42 | 43 | ```javascript 44 | function check(/* str, bracketsConfig */) 45 | ``` 46 | 47 | Remove the throwing error line from function body: 48 | ```javascript 49 | throw new Error('Not implemented'); 50 | ``` 51 | Implement the function by any way and verify your solution by running tests until the failed test become passed (green). 52 | 8. Save the solution and run `npm test` in command line. 53 | 9. You will see the number of passing and pending tests. 54 | 55 | ## Submit to [rs app](https://app.rs.school/) 56 | 1. Commit and push your solutions to your fork 57 | 2. Open rs app and login 58 | 3. Go to submit task page 59 | 4. Select your task ( JS: Brackets) 60 | 5. Press submit button and enjoy 61 | 62 | ## Notes 63 | * We recommend you to use nodejs of version 22. If you using any of features that does not supported by node `v22`, score won't be submitted. 64 | * Installing nodejs `v22` is optional, you can run jobs using your version and not use methods that are not in nodejs `v22`. 65 | * Please be sure that each of your test in limit of 30sec. 66 | * You will get 0 (zero) if you have any eslint's errors or warnings. 67 | 68 | ## FAQ 69 | **Question:** I use Windows machine and have received a lot of errors like "Expected linebreaks to be 'LF' but found 'CRLF'". How to handle it? 70 | 71 | **Answer**: 72 | - First, you need to install Gitbash properly: you need to choose option "Checkout as-is, commit as-is" in section "Configuring the line ending conversions". It'll let you download repos with line endings set "as-is" as well as commit. In other words, not to change them at all, because by default it converts them. 73 | - Second, install `editorconfig` plugin to your editor. For VS Code you can find it here: 74 | https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig 75 | 76 | I'll let you apply some rules when you saving your files in the repo. This plugin will use config-file `.editorconfig` that you can see in the root folder. It lets you save the file with needed line endings, trim whitespaces, etc. 77 | - Finally, you need to apply linter's autofix feature in order to fix all linebreaks that was already changed to "CLRF": 78 | ``` 79 | $ npm run lint -- --fix 80 | ``` 81 | 82 | **Question:** Execution of tests "hangs" on one of them and does not display the result. What to do?
83 | **Answer**: Check your solution for an infinite loop, fix it, and rerun the test. 84 | 85 | **Question:** The solution in the local repository succeeds and all tests are "green", but in the application some tests don't count. What to do?
86 | **Answer**: [Update your repository fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork), update the local repository from the fork, run tests and fix your solution. After fixing, resubmit your solution for testing. 87 | 88 | ___ 89 | The task based on https://github.com/rolling-scopes-school/js-assignments. 90 | --------------------------------------------------------------------------------