Add matching-brackets exercise (#143)

* Add `matching-brackets` exercise

* Update exercises/practice/matching-brackets/.meta/example.8th

* Use break
This commit is contained in:
Erik Schierboom
2024-04-24 11:12:07 +02:00
committed by GitHub
parent 2f714b3358
commit ec41592664
9 changed files with 377 additions and 0 deletions

View File

@@ -269,6 +269,14 @@
"prerequisites": [],
"difficulty": 1
},
{
"slug": "matching-brackets",
"name": "Matching Brackets",
"uuid": "01c66794-36f0-4134-a9a9-4d09011beb5a",
"practices": [],
"prerequisites": [],
"difficulty": 5
},
{
"slug": "grains",
"name": "Grains",

View File

@@ -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.

View File

@@ -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™.

View File

@@ -0,0 +1,18 @@
{
"authors": [
"erikschierboom"
],
"files": {
"solution": [
"matching-brackets.8th"
],
"test": [
"test.8th"
],
"example": [
".meta/example.8th"
]
},
"blurb": "Make sure the brackets and braces all match.",
"source": "Ginna Baker"
}

View File

@@ -0,0 +1,14 @@
: paired? \ s -- T
a:new >r
(
dup '[ n:= if r> '] a:push >r drop ;then
dup '( n:= if r> ') a:push >r drop ;then
dup '{ n:= if r> '} a:push >r drop ;then
dup '] n:= if r> a:len 0 n:= if a:push >r break ;then a:pop swap >r n:= !if r> '] a:push >r break ;then ;then
dup ') n:= if r> a:len 0 n:= if a:push >r break ;then a:pop swap >r n:= !if r> ') a:push >r break ;then ;then
dup '} n:= if r> a:len 0 n:= if a:push >r break ;then a:pop swap >r n:= !if r> '} a:push >r break ;then ;then
drop
)
s:each!
r> a:len 0 n:= nip
;

View File

@@ -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"

View File

@@ -0,0 +1,162 @@
needs console/loaded
\ -----------------------------------------------------------------
ns: test
-1 var, test-count
var tests-passed
var tests-failed
var tests-skipped
true var, run-test
\ Some utility words
: array-insens-dot \ x -- \\ removes leading space on stringified arrays
dup >kind ns:a n:=
if
>s s:trim
then
.
;
: test-passed \ s x x -- \\ test name, expected value, actual value
2drop
1 tests-passed n:+!
con:green con:onBlack . space " ... OK" . con:white con:onBlack cr
;
: test-skipped \ s --
1 tests-skipped n:+!
con:cyan con:onBlack . space " ... SKIPPED" . con:white con:onBlack cr
;
: test-failed \ s x x -- \\ test name, expected value, actual value
1 tests-failed n:+!
rot
con:red con:onBlack . space " ... FAIL" . con:white con:onBlack cr
" Actual: «" . array-insens-dot "»" . cr
" Expected: «" . array-insens-dot "»" . cr cr
;
: isword? \ x -- x f
dup >kind ns:w n:=
;
: run-test? \ -- T
run-test @ if true else "RUN_ALL_TESTS" getenv n:>bool then
;
\ Num passed + num skipped + num failed should == num tests
: all-tests-run? \ -- T
tests-passed @ tests-skipped @ tests-failed @ n:+ n:+
test-count @ n:=
;
\ returns true if x is a date, false otherwise
: date? \ x -- x T
dup >kind ns:d n:=
;
\ adapted from 8th forum -- https://8th-dev.com/forum/index.php/topic,2745.0.html
: eq? \ x x -- T
\ are the items the same kind?
2dup >kind swap >kind n:=
!if 2drop false ;then
\ same kind: try different comparators
number? if n:= ;then
string? if s:= ;then
array? if ' eq? a:= 2nip ;then
map? if ' eq? m:= 2nip ;then
date? if d:= ;then
\ otherwise fall back to 'lazy evaluation'
l: =
;
: check-depth \ ... n -- ...
dup>r
n:1+ depth n:=
!if
con:red con:onBlack
"PANIC: expected stack depth to be " . r> . cr
"Stack is:" . cr
.s cr
255 die
then
rdrop
;
\ -----------------------------------------------------------------
\ status report at end of run
( all-tests-run?
!if con:red con:onBlack "... FAIL - not all tests completed" . con:white con:onBlack cr then
) onexit
\ Print a summary of the tests run
( con:white con:onBlack
test-count @ . space "tests planned - " .
tests-passed @ . space "passed - " .
tests-skipped @ . space "skipped - " .
tests-failed @ . space "failed" . cr
) onexit
\ -----------------------------------------------------------------
\ The public-facing words
\ -----------------------------------------------------------------
: equal? \ s x w -- | s w x --
run-test? !if 2drop test-skipped ;; then
isword? !if swap then
w:exec
3 check-depth
2dup \ so test-failed can show actual and expected
eq? if test-passed else test-failed then
;
: true? \ s w --
run-test? !if drop test-skipped ;; then
w:exec
2 check-depth
true swap dup \ so test-failed can show actual and expected
if test-passed else test-failed then
;
: false? \ s w --
run-test? !if drop test-skipped ;; then
w:exec
2 check-depth
false swap dup \ so test-failed can show actual and expected
!if test-passed else test-failed then
;
: null? \ s w --
run-test? !if drop test-skipped ;; then
w:exec
2 check-depth
null swap dup \ so test-failed can show actual and expected
G:null? nip if test-passed else test-failed then
;
: SKIP-REST-OF-TESTS false run-test ! ;
: tests \ n --
test-count !
;
\ Set the exit status:
\ 0 = all OK
\ 1 = not all tests were run (some error occurred)
\ 2 = some tests failed
: end-of-tests \ --
all-tests-run?
if
tests-failed @ 0 n:= if 0 else 2 then
else
1
then
die
;

View File

@@ -0,0 +1,3 @@
: paired? \ s -- T
;

View File

@@ -0,0 +1,89 @@
"matching-brackets.8th" f:include
needs exercism/test
with: test
20 tests
"paired square brackets"
( "[]" paired? )
true?
SKIP-REST-OF-TESTS
"empty string"
( "" paired? )
true?
"unpaired brackets"
( "[[" paired? )
false?
"wrong ordered brackets"
( "}{" paired? )
false?
"wrong closing bracket"
( "{]" paired? )
false?
"paired with whitespace"
( "{ }" paired? )
true?
"partially paired brackets"
( "{[])" paired? )
false?
"simple nested brackets"
( "{[]}" paired? )
true?
"several paired brackets"
( "{}[]" paired? )
true?
"paired and nested brackets"
( "([{}({}[])])" paired? )
true?
"unopened closing brackets"
( "{[)][]}" paired? )
false?
"unpaired and nested brackets"
( "([{])" paired? )
false?
"paired and wrong nested brackets"
( "[({]})" paired? )
false?
"paired and wrong nested brackets but innermost are correct"
( "[({}])" paired? )
false?
"paired and incomplete brackets"
( "{}[" paired? )
false?
"too many closing brackets"
( "[]]" paired? )
false?
"early unexpected brackets"
( ")()" paired? )
false?
"early mismatched brackets"
( "{)()" paired? )
false?
"math expression"
( "(((185 + 223.85) * 15) - 543)/2" paired? )
true?
"complex latex expression"
( "\left(\begin{array}{cc} \frac{1}{3} & x\\ \mathrm{e}^{x} &... x^2 \end{array}\right)" paired? )
true?
end-of-tests
;with