diff --git a/config.json b/config.json index cbb8ac7..31d6c4d 100644 --- a/config.json +++ b/config.json @@ -437,6 +437,14 @@ "prerequisites": [], "difficulty": 5 }, + { + "slug": "matching-brackets", + "name": "Matching Brackets", + "uuid": "3104857d-f658-429e-b5d8-d6a73c8c75e5", + "practices": [], + "prerequisites": [], + "difficulty": 5 + }, { "slug": "meetup", "name": "Meetup", diff --git a/exercises/practice/matching-brackets/.docs/instructions.md b/exercises/practice/matching-brackets/.docs/instructions.md new file mode 100644 index 0000000..ea17084 --- /dev/null +++ b/exercises/practice/matching-brackets/.docs/instructions.md @@ -0,0 +1,5 @@ +# Instructions + +Given a string containing brackets `[]`, braces `{}`, parentheses `()`, or any combination thereof, verify that any and all pairs are matched and nested correctly. +Any other characters should be ignored. +For example, `"{what is (42)}?"` is balanced and `"[text}"` is not. diff --git a/exercises/practice/matching-brackets/.docs/introduction.md b/exercises/practice/matching-brackets/.docs/introduction.md new file mode 100644 index 0000000..0618221 --- /dev/null +++ b/exercises/practice/matching-brackets/.docs/introduction.md @@ -0,0 +1,8 @@ +# Introduction + +You're given the opportunity to write software for the Bracketeer™, an ancient but powerful mainframe. +The software that runs on it is written in a proprietary language. +Much of its syntax is familiar, but you notice _lots_ of brackets, braces and parentheses. +Despite the Bracketeer™ being powerful, it lacks flexibility. +If the source code has any unbalanced brackets, braces or parentheses, the Bracketeer™ crashes and must be rebooted. +To avoid such a scenario, you start writing code that can verify that brackets, braces, and parentheses are balanced before attempting to run it on the Bracketeer™. diff --git a/exercises/practice/matching-brackets/.gitignore b/exercises/practice/matching-brackets/.gitignore new file mode 100644 index 0000000..6dd20ff --- /dev/null +++ b/exercises/practice/matching-brackets/.gitignore @@ -0,0 +1,11 @@ +## -*- conf -*- +.rebar3 +_build/ +ebin/ +erl_crash.dump +rebar3.crashdump + +tmp +bin/configlet +bin/configlet.exe +CHECKLIST diff --git a/exercises/practice/matching-brackets/.meta/config.json b/exercises/practice/matching-brackets/.meta/config.json new file mode 100644 index 0000000..9248790 --- /dev/null +++ b/exercises/practice/matching-brackets/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "src/matching-brackets.lfe" + ], + "test": [ + "test/matching-brackets-tests.lfe" + ], + "example": [ + ".meta/example.lfe" + ] + }, + "blurb": "Make sure the brackets and braces all match.", + "source": "Ginna Baker" +} diff --git a/exercises/practice/matching-brackets/.meta/example.lfe b/exercises/practice/matching-brackets/.meta/example.lfe new file mode 100644 index 0000000..aa7cfdb --- /dev/null +++ b/exercises/practice/matching-brackets/.meta/example.lfe @@ -0,0 +1,33 @@ +(defmodule matching-brackets + (export (paired? 1))) + +(include-lib "lfe/include/clj.lfe") + +(defun paired? (string) + (paired-helper string '())) + +(defun paired-helper + (('() '()) + 'true) + (('() _) + 'false) + (((cons #\{ string) stack) + (paired-helper string (cons #\{ stack))) + (((cons #\[ string) stack) + (paired-helper string (cons #\[ stack))) + (((cons #\( string) stack) + (paired-helper string (cons #\( stack))) + (((cons #\} string) (cons #\{ stack)) + (paired-helper string stack)) + (((cons #\] string) (cons #\[ stack)) + (paired-helper string stack)) + (((cons #\) string) (cons #\( stack)) + (paired-helper string stack)) + (((cons #\} _) _) + 'false) + (((cons #\] _) _) + 'false) + (((cons #\) _) _) + 'false) + (((cons _ string) stack) + (paired-helper string stack))) diff --git a/exercises/practice/matching-brackets/.meta/tests.toml b/exercises/practice/matching-brackets/.meta/tests.toml new file mode 100644 index 0000000..35a98a0 --- /dev/null +++ b/exercises/practice/matching-brackets/.meta/tests.toml @@ -0,0 +1,70 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[81ec11da-38dd-442a-bcf9-3de7754609a5] +description = "paired square brackets" + +[287f0167-ac60-4b64-8452-a0aa8f4e5238] +description = "empty string" + +[6c3615a3-df01-4130-a731-8ef5f5d78dac] +description = "unpaired brackets" + +[9d414171-9b98-4cac-a4e5-941039a97a77] +description = "wrong ordered brackets" + +[f0f97c94-a149-4736-bc61-f2c5148ffb85] +description = "wrong closing bracket" + +[754468e0-4696-4582-a30e-534d47d69756] +description = "paired with whitespace" + +[ba84f6ee-8164-434a-9c3e-b02c7f8e8545] +description = "partially paired brackets" + +[3c86c897-5ff3-4a2b-ad9b-47ac3a30651d] +description = "simple nested brackets" + +[2d137f2c-a19e-4993-9830-83967a2d4726] +description = "several paired brackets" + +[2e1f7b56-c137-4c92-9781-958638885a44] +description = "paired and nested brackets" + +[84f6233b-e0f7-4077-8966-8085d295c19b] +description = "unopened closing brackets" + +[9b18c67d-7595-4982-b2c5-4cb949745d49] +description = "unpaired and nested brackets" + +[a0205e34-c2ac-49e6-a88a-899508d7d68e] +description = "paired and wrong nested brackets" + +[1d5c093f-fc84-41fb-8c2a-e052f9581602] +description = "paired and wrong nested brackets but innermost are correct" + +[ef47c21b-bcfd-4998-844c-7ad5daad90a8] +description = "paired and incomplete brackets" + +[a4675a40-a8be-4fc2-bc47-2a282ce6edbe] +description = "too many closing brackets" + +[a345a753-d889-4b7e-99ae-34ac85910d1a] +description = "early unexpected brackets" + +[21f81d61-1608-465a-b850-baa44c5def83] +description = "early mismatched brackets" + +[99255f93-261b-4435-a352-02bdecc9bdf2] +description = "math expression" + +[8e357d79-f302-469a-8515-2561877256a1] +description = "complex latex expression" diff --git a/exercises/practice/matching-brackets/Makefile b/exercises/practice/matching-brackets/Makefile new file mode 100644 index 0000000..fbb5a7d --- /dev/null +++ b/exercises/practice/matching-brackets/Makefile @@ -0,0 +1,21 @@ +ERL := $(shell which erl) +REBAR3 := $(shell which rebar3) + +null := +space := $(null) # +comma := , + +ifeq ($(ERL),) + $(error Can't find Erlang executable 'erl') +else ifeq ($(REBAR3),) + $(error Can't find rebar3) +endif + +compile: ; $(REBAR3) compile + +clean: ; $(REBAR3) clean + +.PHONY: test +test: + $(REBAR3) eunit \ + -m $(subst $(space),$(comma),$(basename $(notdir $(wildcard test/*.lfe)))) diff --git a/exercises/practice/matching-brackets/rebar.config b/exercises/practice/matching-brackets/rebar.config new file mode 100644 index 0000000..3025789 --- /dev/null +++ b/exercises/practice/matching-brackets/rebar.config @@ -0,0 +1,11 @@ +{plugins, [{rebar3_lfe, "0.4.10"}]}. + +{provider_hooks, [{post, [{compile, {lfe, compile}}]}]}. + +{deps, [{lfe, "2.1.3"}]}. + +{profiles, + [{test, + [{eunit_compile_opts, [{src_dirs, ["src", "test"]}]}, + {deps, + [{ltest, "0.13.8"}]}]}]}. diff --git a/exercises/practice/matching-brackets/rebar.lock b/exercises/practice/matching-brackets/rebar.lock new file mode 100644 index 0000000..4583682 --- /dev/null +++ b/exercises/practice/matching-brackets/rebar.lock @@ -0,0 +1,8 @@ +{"1.2.0", +[{<<"lfe">>,{pkg,<<"lfe">>,<<"2.1.3">>},0}]}. +[ +{pkg_hash,[ + {<<"lfe">>, <<"6EFCB2BBC1FFC21DC5D1C092F00EFDB397EAC889474AC5C86EDF78A3557CC730">>}]}, +{pkg_hash_ext,[ + {<<"lfe">>, <<"4E4BAD515A169AE418FEB7374EA1C8D741FAEA9D95E266CE343B45BCC377F55B">>}]} +]. diff --git a/exercises/practice/matching-brackets/src/matching-brackets.app.src b/exercises/practice/matching-brackets/src/matching-brackets.app.src new file mode 100644 index 0000000..0368972 --- /dev/null +++ b/exercises/practice/matching-brackets/src/matching-brackets.app.src @@ -0,0 +1,11 @@ +%% -*- erlang -*- +{application, 'matching-brackets', + [{description, ""}, + {vsn, "0.0.1"}, + {modules, + ['matching-brackets']}, + {registered, []}, + {applications, + [kernel, stdlib]}, + {included_applications, []}, + {env, []}]}. diff --git a/exercises/practice/matching-brackets/src/matching-brackets.lfe b/exercises/practice/matching-brackets/src/matching-brackets.lfe new file mode 100644 index 0000000..f1c45dc --- /dev/null +++ b/exercises/practice/matching-brackets/src/matching-brackets.lfe @@ -0,0 +1,4 @@ +(defmodule matching-brackets + (export (paired? 1))) + + ; Please implement the paired? function. diff --git a/exercises/practice/matching-brackets/test/matching-brackets-tests.lfe b/exercises/practice/matching-brackets/test/matching-brackets-tests.lfe new file mode 100644 index 0000000..95f47e4 --- /dev/null +++ b/exercises/practice/matching-brackets/test/matching-brackets-tests.lfe @@ -0,0 +1,66 @@ +(defmodule matching-brackets-tests + (behaviour ltest-unit) + (export all)) + +(include-lib "ltest/include/ltest-macros.lfe") + +(deftest paired-square-brackets + (is (matching-brackets:paired? "[]"))) + +(deftest empty-string + (is (matching-brackets:paired? ""))) + +(deftest unpaired-brackets + (is-not (matching-brackets:paired? "[["))) + +(deftest wrong-ordered-brackets + (is-not (matching-brackets:paired? "}{"))) + +(deftest wrong-closing-bracket + (is-not (matching-brackets:paired? "{]"))) + +(deftest paired-with-whitespace + (is (matching-brackets:paired? "{ }"))) + +(deftest partially-paired-brackets + (is-not (matching-brackets:paired? "{[])"))) + +(deftest simple-nested-brackets + (is (matching-brackets:paired? "{[]}"))) + +(deftest several-paired-brackets + (is (matching-brackets:paired? "{}[]"))) + +(deftest paired-and-nested-brackets + (is (matching-brackets:paired? "([{}({}[])])"))) + +(deftest unopened-closing-brackets + (is-not (matching-brackets:paired? "{[)][]}"))) + +(deftest unpaired-and-nested-brackets + (is-not (matching-brackets:paired? "([{])"))) + +(deftest paired-and-wrong-nested-brackets + (is-not (matching-brackets:paired? "[({]})"))) + +(deftest paired-and-wrong-nested-brackets-but-innermost-are-correct + (is-not (matching-brackets:paired? "[({}])"))) + +(deftest paired-and-incomplete-brackets + (is-not (matching-brackets:paired? "{}["))) + +(deftest too-many-closing-brackets + (is-not (matching-brackets:paired? "[]]"))) + +(deftest early-unexpected-brackets + (is-not (matching-brackets:paired? ")()"))) + +(deftest early-mismatched-brackets + (is-not (matching-brackets:paired? "{)()"))) + +(deftest math-expression + (is (matching-brackets:paired? "(((185 + 223.85) * 15) - 543)/2"))) + +(deftest complex-latex-expression + (let ((expr "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)")) + (is (matching-brackets:paired? expr))))