Skip to content

Commit e94cc6f

Browse files
lpalmapetertseng
authored andcommitted
bracket-push: Add new exercise
1 parent 78232d0 commit e94cc6f

File tree

7 files changed

+168
-0
lines changed

7 files changed

+168
-0
lines changed

config.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,13 @@
279279
"topics": [
280280
]
281281
},
282+
{
283+
"slug": "bracket-push",
284+
"difficulty": 5,
285+
"topics": [
286+
"Stack"
287+
]
288+
},
282289
{
283290
"slug": "crypto-square",
284291
"difficulty": 5,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: bracket-push
2+
3+
dependencies:
4+
- base
5+
6+
library:
7+
exposed-modules: Brackets
8+
source-dirs: src
9+
10+
tests:
11+
test:
12+
main: Tests.hs
13+
source-dirs: test
14+
dependencies:
15+
- bracket-push
16+
- hspec
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module Brackets (arePaired) where
2+
3+
data BracketType = Opening | Closing
4+
data Stack a = Empty | Elem a (Stack a)
5+
6+
push :: Char -> Stack Char -> Stack Char
7+
push = Elem
8+
9+
pop :: Stack Char -> Stack Char
10+
pop Empty = Empty
11+
pop (Elem _ stack) = stack
12+
13+
arePaired :: String -> Bool
14+
arePaired xs = checkBalance xs Empty
15+
16+
checkBalance :: String -> Stack Char -> Bool
17+
checkBalance [] Empty = True
18+
checkBalance [] _ = False
19+
checkBalance (x:xs) stack =
20+
case classify x of
21+
Just Opening -> checkBalance xs $ push x stack
22+
Just Closing -> (x `closes` stack) && checkBalance xs (pop stack)
23+
_ -> checkBalance xs stack
24+
25+
classify :: Char -> Maybe BracketType
26+
classify x
27+
| x `elem` "([{" = Just Opening
28+
| x `elem` ")]}" = Just Closing
29+
| otherwise = Nothing
30+
31+
closes :: Char -> Stack Char -> Bool
32+
closes _ Empty = False
33+
closes x (Elem y _) =
34+
x == ')' && y == '('
35+
|| x == ']' && y == '['
36+
|| x == '}' && y == '{'

exercises/bracket-push/package.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: bracket-push
2+
3+
dependencies:
4+
- base
5+
6+
library:
7+
exposed-modules: Brackets
8+
source-dirs: src
9+
dependencies:
10+
# - foo # List here the packages you
11+
# - bar # want to use in your solution.
12+
13+
tests:
14+
test:
15+
main: Tests.hs
16+
source-dirs: test
17+
dependencies:
18+
- bracket-push
19+
- hspec
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Brackets (arePaired) where
2+
3+
arePaired :: String -> Bool
4+
arePaired xs = error "You need to implement this function."

exercises/bracket-push/stack.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
resolver: lts-8.2

exercises/bracket-push/test/Tests.hs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
{-# LANGUAGE RecordWildCards #-}
2+
3+
import Data.Foldable (for_)
4+
import Test.Hspec (Spec, describe, it, shouldBe)
5+
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
6+
7+
import Brackets (arePaired)
8+
9+
main :: IO ()
10+
main = hspecWith defaultConfig {configFastFail = True} specs
11+
12+
specs :: Spec
13+
specs = describe "bracket-push" $
14+
describe "isPaired" $ for_ cases test
15+
where
16+
test Case{..} = it description $ arePaired input `shouldBe` expected
17+
18+
-- Adapted from
19+
-- Source: exercism/x-common/exercises/bracket-push/canonical-data.json
20+
-- Version: 1.1.0
21+
-- Date: 2017-04-07.
22+
23+
data Case = Case { description :: String
24+
, input :: String
25+
, expected :: Bool
26+
}
27+
28+
cases :: [Case]
29+
cases = [ Case { description = "paired square brackets"
30+
, input = "[]"
31+
, expected = True
32+
}
33+
, Case { description = "empty string"
34+
, input = ""
35+
, expected = True
36+
}
37+
, Case { description = "unpaired brackets"
38+
, input = "[["
39+
, expected = False
40+
}
41+
, Case { description = "wrong ordered brackets"
42+
, input = "}{"
43+
, expected = False
44+
}
45+
, Case { description = "wrong closing brackets"
46+
, input = "{]"
47+
, expected = False
48+
}
49+
, Case { description = "paired with whitespace"
50+
, input = "{ }"
51+
, expected = True
52+
}
53+
, Case { description = "simple nested brackets"
54+
, input = "{[]}"
55+
, expected = True
56+
}
57+
, Case { description = "several paired brackets"
58+
, input = "{}[]"
59+
, expected = True
60+
}
61+
, Case { description = "paired and nested brackets"
62+
, input = "([{}({}[])])"
63+
, expected = True
64+
}
65+
, Case { description = "unopened closing brackets"
66+
, input = "{[)][]}"
67+
, expected = False
68+
}
69+
, Case { description = "unpaired and nested brackets"
70+
, input = "([{])"
71+
, expected = False
72+
}
73+
, Case { description = "paired and wrong nested brackets"
74+
, input = "[({]})"
75+
, expected = False
76+
}
77+
, Case { description = "math expression"
78+
, input = "(((185 + 223.85) * 15) - 543)/2"
79+
, expected = True
80+
}
81+
, Case { description = "complex latex expression"
82+
, input = "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)"
83+
, expected = True
84+
}
85+
]

0 commit comments

Comments
 (0)