├── 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 |
--------------------------------------------------------------------------------