From cc66f4ab37b2fc140f9c27625220671a81aab3cd Mon Sep 17 00:00:00 2001 From: Glenn Jackman Date: Wed, 24 Dec 2025 19:03:21 -0500 Subject: [PATCH] saddle-points --- config.json | 8 ++ exercises/practice/saddle-points/.busted | 5 + .../saddle-points/.docs/instructions.md | 27 +++++ .../saddle-points/.docs/introduction.md | 11 ++ .../practice/saddle-points/.meta/config.json | 19 ++++ .../practice/saddle-points/.meta/example.moon | 20 ++++ .../saddle-points/.meta/spec_generator.moon | 33 ++++++ .../practice/saddle-points/.meta/tests.toml | 37 ++++++ .../practice/saddle-points/saddle_points.moon | 4 + .../saddle-points/saddle_points_spec.moon | 105 ++++++++++++++++++ 10 files changed, 269 insertions(+) create mode 100644 exercises/practice/saddle-points/.busted create mode 100644 exercises/practice/saddle-points/.docs/instructions.md create mode 100644 exercises/practice/saddle-points/.docs/introduction.md create mode 100644 exercises/practice/saddle-points/.meta/config.json create mode 100644 exercises/practice/saddle-points/.meta/example.moon create mode 100644 exercises/practice/saddle-points/.meta/spec_generator.moon create mode 100644 exercises/practice/saddle-points/.meta/tests.toml create mode 100644 exercises/practice/saddle-points/saddle_points.moon create mode 100644 exercises/practice/saddle-points/saddle_points_spec.moon diff --git a/config.json b/config.json index d911970..14259b1 100644 --- a/config.json +++ b/config.json @@ -390,6 +390,14 @@ "practices": [], "prerequisites": [], "difficulty": 4 + }, + { + "slug": "saddle-points", + "name": "Saddle Points", + "uuid": "cbffab05-8db3-438f-bf16-490d19a403a7", + "practices": [], + "prerequisites": [], + "difficulty": 4 } ] }, diff --git a/exercises/practice/saddle-points/.busted b/exercises/practice/saddle-points/.busted new file mode 100644 index 0000000..86b84e7 --- /dev/null +++ b/exercises/practice/saddle-points/.busted @@ -0,0 +1,5 @@ +return { + default = { + ROOT = { '.' } + } +} diff --git a/exercises/practice/saddle-points/.docs/instructions.md b/exercises/practice/saddle-points/.docs/instructions.md new file mode 100644 index 0000000..f69cdab --- /dev/null +++ b/exercises/practice/saddle-points/.docs/instructions.md @@ -0,0 +1,27 @@ +# Instructions + +Your task is to find the potential trees where you could build your tree house. + +The data company provides the data as grids that show the heights of the trees. +The rows of the grid represent the east-west direction, and the columns represent the north-south direction. + +An acceptable tree will be the largest in its row, while being the smallest in its column. + +A grid might not have any good trees at all. +Or it might have one, or even several. + +Here is a grid that has exactly one candidate tree. + +```text + ↓ + 1 2 3 4 + |----------- + 1 | 9 8 7 8 +→ 2 |[5] 3 2 4 + 3 | 6 6 7 1 +``` + +- Row 2 has values 5, 3, 2, and 4. The largest value is 5. +- Column 1 has values 9, 5, and 6. The smallest value is 5. + +So the point at `[2, 1]` (row: 2, column: 1) is a great spot for a tree house. diff --git a/exercises/practice/saddle-points/.docs/introduction.md b/exercises/practice/saddle-points/.docs/introduction.md new file mode 100644 index 0000000..34b2c77 --- /dev/null +++ b/exercises/practice/saddle-points/.docs/introduction.md @@ -0,0 +1,11 @@ +# Introduction + +You plan to build a tree house in the woods near your house so that you can watch the sun rise and set. + +You've obtained data from a local survey company that show the height of every tree in each rectangular section of the map. +You need to analyze each grid on the map to find good trees for your tree house. + +A good tree is both: + +- taller than every tree to the east and west, so that you have the best possible view of the sunrises and sunsets. +- shorter than every tree to the north and south, to minimize the amount of tree climbing. diff --git a/exercises/practice/saddle-points/.meta/config.json b/exercises/practice/saddle-points/.meta/config.json new file mode 100644 index 0000000..ea61c82 --- /dev/null +++ b/exercises/practice/saddle-points/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "glennj" + ], + "files": { + "solution": [ + "saddle_points.moon" + ], + "test": [ + "saddle_points_spec.moon" + ], + "example": [ + ".meta/example.moon" + ] + }, + "blurb": "Detect saddle points in a matrix.", + "source": "J Dalbey's Programming Practice problems", + "source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html" +} diff --git a/exercises/practice/saddle-points/.meta/example.moon b/exercises/practice/saddle-points/.meta/example.moon new file mode 100644 index 0000000..6ad8956 --- /dev/null +++ b/exercises/practice/saddle-points/.meta/example.moon @@ -0,0 +1,20 @@ +{ + saddle_points: (mtx) -> + nrow, ncol = #mtx, #mtx[1] + + row_max = [math.mininteger for _ = 1, nrow] + col_min = [math.maxinteger for _ = 1, ncol] + + for r = 1, nrow + for c = 1, ncol + row_max[r] = math.max row_max[r], mtx[r][c] + col_min[c] = math.min col_min[c], mtx[r][c] + + results = {} + for r = 1, nrow + for c = 1, ncol + if row_max[r] == mtx[r][c] and col_min[c] == mtx[r][c] + table.insert results, {row: r, column: c} + + results +} diff --git a/exercises/practice/saddle-points/.meta/spec_generator.moon b/exercises/practice/saddle-points/.meta/spec_generator.moon new file mode 100644 index 0000000..2fe7267 --- /dev/null +++ b/exercises/practice/saddle-points/.meta/spec_generator.moon @@ -0,0 +1,33 @@ +int_list = (list) -> "{#{table.concat list, ', '}}" + +int_lists = (lists, level) -> + if #lists == 1 + "{#{int_list lists[1]}}" + else + rows = [indent int_list(row) .. ',', level + 1 for row in *lists] + table.insert rows, 1, '{' + table.insert rows, indent '}', level + table.concat rows, '\n' + +result_obj = (obj) -> "{row: #{obj.row}, column: #{obj.column}}" +result_list = (list) -> "{#{table.concat [result_obj obj for obj in *list], ', '}}" + +{ + module_imports: {'saddle_points'}, + + test_helpers: [[ + cmp_saddle_points = (a, b) -> + a.row < b.row or (a.row == b.row and a.column < b.column) +]] + + generate_test: (case, level) -> + lines = { + "matrix = #{int_lists case.input.matrix, level}", + "result = saddle_points matrix" + "expected = #{result_list case.expected}", + "table.sort result, cmp_saddle_points", + "table.sort expected, cmp_saddle_points", + "assert.are.same expected, result" + } + table.concat [indent line, level for line in *lines], '\n' +} diff --git a/exercises/practice/saddle-points/.meta/tests.toml b/exercises/practice/saddle-points/.meta/tests.toml new file mode 100644 index 0000000..ca00852 --- /dev/null +++ b/exercises/practice/saddle-points/.meta/tests.toml @@ -0,0 +1,37 @@ +# 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. + +[3e374e63-a2e0-4530-a39a-d53c560382bd] +description = "Can identify single saddle point" + +[6b501e2b-6c1f-491f-b1bb-7f278f760534] +description = "Can identify that empty matrix has no saddle points" + +[8c27cc64-e573-4fcb-a099-f0ae863fb02f] +description = "Can identify lack of saddle points when there are none" + +[6d1399bd-e105-40fd-a2c9-c6609507d7a3] +description = "Can identify multiple saddle points in a column" + +[3e81dce9-53b3-44e6-bf26-e328885fd5d1] +description = "Can identify multiple saddle points in a row" + +[88868621-b6f4-4837-bb8b-3fad8b25d46b] +description = "Can identify saddle point in bottom right corner" + +[5b9499ca-fcea-4195-830a-9c4584a0ee79] +description = "Can identify saddle points in a non square matrix" + +[ee99ccd2-a1f1-4283-ad39-f8c70f0cf594] +description = "Can identify that saddle points in a single column matrix are those with the minimum value" + +[63abf709-a84b-407f-a1b3-456638689713] +description = "Can identify that saddle points in a single row matrix are those with the maximum value" diff --git a/exercises/practice/saddle-points/saddle_points.moon b/exercises/practice/saddle-points/saddle_points.moon new file mode 100644 index 0000000..a0f4577 --- /dev/null +++ b/exercises/practice/saddle-points/saddle_points.moon @@ -0,0 +1,4 @@ +{ + saddle_points: (mtx) -> + error 'Implement me' +} diff --git a/exercises/practice/saddle-points/saddle_points_spec.moon b/exercises/practice/saddle-points/saddle_points_spec.moon new file mode 100644 index 0000000..5f54f10 --- /dev/null +++ b/exercises/practice/saddle-points/saddle_points_spec.moon @@ -0,0 +1,105 @@ +import saddle_points from require 'saddle_points' + +describe 'saddle-points', -> + cmp_saddle_points = (a, b) -> + a.row < b.row or (a.row == b.row and a.column < b.column) + + it 'Can identify single saddle point', -> + matrix = { + {9, 8, 7}, + {5, 3, 2}, + {6, 6, 7}, + } + result = saddle_points matrix + expected = {{row: 2, column: 1}} + table.sort result, cmp_saddle_points + table.sort expected, cmp_saddle_points + assert.are.same expected, result + + pending 'Can identify that empty matrix has no saddle points', -> + matrix = {{}} + result = saddle_points matrix + expected = {} + table.sort result, cmp_saddle_points + table.sort expected, cmp_saddle_points + assert.are.same expected, result + + pending 'Can identify lack of saddle points when there are none', -> + matrix = { + {1, 2, 3}, + {3, 1, 2}, + {2, 3, 1}, + } + result = saddle_points matrix + expected = {} + table.sort result, cmp_saddle_points + table.sort expected, cmp_saddle_points + assert.are.same expected, result + + pending 'Can identify multiple saddle points in a column', -> + matrix = { + {4, 5, 4}, + {3, 5, 5}, + {1, 5, 4}, + } + result = saddle_points matrix + expected = {{row: 1, column: 2}, {row: 2, column: 2}, {row: 3, column: 2}} + table.sort result, cmp_saddle_points + table.sort expected, cmp_saddle_points + assert.are.same expected, result + + pending 'Can identify multiple saddle points in a row', -> + matrix = { + {6, 7, 8}, + {5, 5, 5}, + {7, 5, 6}, + } + result = saddle_points matrix + expected = {{row: 2, column: 1}, {row: 2, column: 2}, {row: 2, column: 3}} + table.sort result, cmp_saddle_points + table.sort expected, cmp_saddle_points + assert.are.same expected, result + + pending 'Can identify saddle point in bottom right corner', -> + matrix = { + {8, 7, 9}, + {6, 7, 6}, + {3, 2, 5}, + } + result = saddle_points matrix + expected = {{row: 3, column: 3}} + table.sort result, cmp_saddle_points + table.sort expected, cmp_saddle_points + assert.are.same expected, result + + pending 'Can identify saddle points in a non square matrix', -> + matrix = { + {3, 1, 3}, + {3, 2, 4}, + } + result = saddle_points matrix + expected = {{row: 1, column: 3}, {row: 1, column: 1}} + table.sort result, cmp_saddle_points + table.sort expected, cmp_saddle_points + assert.are.same expected, result + + pending 'Can identify that saddle points in a single column matrix are those with the minimum value', -> + matrix = { + {2}, + {1}, + {4}, + {1}, + } + result = saddle_points matrix + expected = {{row: 2, column: 1}, {row: 4, column: 1}} + table.sort result, cmp_saddle_points + table.sort expected, cmp_saddle_points + assert.are.same expected, result + + pending 'Can identify that saddle points in a single row matrix are those with the maximum value', -> + matrix = {{2, 5, 3, 5}} + result = saddle_points matrix + expected = {{row: 1, column: 2}, {row: 1, column: 4}} + table.sort result, cmp_saddle_points + table.sort expected, cmp_saddle_points + assert.are.same expected, result