Skip to content

Commit 5169c49

Browse files
Add saddle-points exercise (#512)
1 parent 519b967 commit 5169c49

File tree

8 files changed

+299
-0
lines changed

8 files changed

+299
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,14 @@
10031003
"prerequisites": [],
10041004
"difficulty": 5
10051005
},
1006+
{
1007+
"slug": "saddle-points",
1008+
"name": "Saddle Points",
1009+
"uuid": "f4028015-f47c-4826-9f19-814f452a27ce",
1010+
"practices": [],
1011+
"prerequisites": [],
1012+
"difficulty": 5
1013+
},
10061014
{
10071015
"slug": "spiral-matrix",
10081016
"name": "Spiral Matrix",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Instructions
2+
3+
Your task is to find the potential trees where you could build your tree house.
4+
5+
The data company provides the data as grids that show the heights of the trees.
6+
The rows of the grid represent the east-west direction, and the columns represent the north-south direction.
7+
8+
An acceptable tree will be the largest in its row, while being the smallest in its column.
9+
10+
A grid might not have any good trees at all.
11+
Or it might have one, or even several.
12+
13+
Here is a grid that has exactly one candidate tree.
14+
15+
```text
16+
17+
1 2 3 4
18+
|-----------
19+
1 | 9 8 7 8
20+
→ 2 |[5] 3 2 4
21+
3 | 6 6 7 1
22+
```
23+
24+
- Row 2 has values 5, 3, 2, and 4. The largest value is 5.
25+
- Column 1 has values 9, 5, and 6. The smallest value is 5.
26+
27+
So the point at `[2, 1]` (row: 2, column: 1) is a great spot for a tree house.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Introduction
2+
3+
You plan to build a tree house in the woods near your house so that you can watch the sun rise and set.
4+
5+
You've obtained data from a local survey company that show the height of every tree in each rectangular section of the map.
6+
You need to analyze each grid on the map to find good trees for your tree house.
7+
8+
A good tree is both:
9+
10+
- taller than every tree to the east and west, so that you have the best possible view of the sunrises and sunsets.
11+
- shorter than every tree to the north and south, to minimize the amount of tree climbing.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"saddle_points.zig"
8+
],
9+
"test": [
10+
"test_saddle_points.zig"
11+
],
12+
"example": [
13+
".meta/example.zig"
14+
]
15+
},
16+
"blurb": "Detect saddle points in a matrix.",
17+
"source": "J Dalbey's Programming Practice problems",
18+
"source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html"
19+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const std = @import("std");
2+
const math = std.math;
3+
const mem = std.mem;
4+
5+
pub const Point = struct {
6+
row: u16,
7+
column: u16,
8+
};
9+
10+
pub fn saddlePoints(comptime m: usize, comptime n: usize, allocator: mem.Allocator, matrix: [m][n]i32) mem.Allocator.Error![]Point {
11+
var results = std.array_list.Managed(Point).init(allocator);
12+
defer results.deinit();
13+
14+
if (m == 0 or n == 0) {
15+
return results.toOwnedSlice();
16+
}
17+
18+
var tallest = try allocator.alloc(i32, m);
19+
defer allocator.free(tallest);
20+
for (0..m) |i| {
21+
var best: i32 = math.minInt(i32);
22+
for (0..n) |j| {
23+
if (best < matrix[i][j]) {
24+
best = matrix[i][j];
25+
}
26+
}
27+
tallest[i] = best;
28+
}
29+
30+
var shortest = try allocator.alloc(i32, n);
31+
defer allocator.free(shortest);
32+
for (0..n) |j| {
33+
var best: i32 = math.maxInt(i32);
34+
for (0..m) |i| {
35+
if (best > matrix[i][j]) {
36+
best = matrix[i][j];
37+
}
38+
}
39+
shortest[j] = best;
40+
}
41+
42+
for (0..m) |i| {
43+
for (0..n) |j| {
44+
if (matrix[i][j] == tallest[i] and matrix[i][j] == shortest[j]) {
45+
try results.append(.{
46+
.row = @as(u16, @intCast(i + 1)), //
47+
.column = @as(u16, @intCast(j + 1)), //
48+
});
49+
}
50+
}
51+
}
52+
return results.toOwnedSlice();
53+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[3e374e63-a2e0-4530-a39a-d53c560382bd]
13+
description = "Can identify single saddle point"
14+
15+
[6b501e2b-6c1f-491f-b1bb-7f278f760534]
16+
description = "Can identify that empty matrix has no saddle points"
17+
18+
[8c27cc64-e573-4fcb-a099-f0ae863fb02f]
19+
description = "Can identify lack of saddle points when there are none"
20+
21+
[6d1399bd-e105-40fd-a2c9-c6609507d7a3]
22+
description = "Can identify multiple saddle points in a column"
23+
24+
[3e81dce9-53b3-44e6-bf26-e328885fd5d1]
25+
description = "Can identify multiple saddle points in a row"
26+
27+
[88868621-b6f4-4837-bb8b-3fad8b25d46b]
28+
description = "Can identify saddle point in bottom right corner"
29+
30+
[5b9499ca-fcea-4195-830a-9c4584a0ee79]
31+
description = "Can identify saddle points in a non square matrix"
32+
33+
[ee99ccd2-a1f1-4283-ad39-f8c70f0cf594]
34+
description = "Can identify that saddle points in a single column matrix are those with the minimum value"
35+
36+
[63abf709-a84b-407f-a1b3-456638689713]
37+
description = "Can identify that saddle points in a single row matrix are those with the maximum value"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const std = @import("std");
2+
const mem = std.mem;
3+
4+
pub const Point = struct {
5+
row: u16,
6+
column: u16,
7+
};
8+
9+
pub fn saddlePoints(comptime m: usize, comptime n: usize, allocator: mem.Allocator, matrix: [m][n]i32) mem.Allocator.Error![]Point {
10+
_ = allocator;
11+
_ = matrix;
12+
@compileError("please implement the saddlePoints function");
13+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
const std = @import("std");
2+
const testing = std.testing;
3+
4+
const saddle_points = @import("saddle_points.zig");
5+
const saddlePoints = saddle_points.saddlePoints;
6+
const Point = saddle_points.Point;
7+
8+
test "Can identify single saddle point" {
9+
const matrix = [3][3]i32{
10+
[3]i32{ 9, 8, 7 }, //
11+
[3]i32{ 5, 3, 2 }, //
12+
[3]i32{ 6, 6, 7 }, //
13+
};
14+
const expected = [_]Point{
15+
.{ .row = 2, .column = 1 }, //
16+
};
17+
const actual = try saddlePoints(3, 3, testing.allocator, matrix);
18+
defer testing.allocator.free(actual);
19+
try testing.expectEqualSlices(Point, &expected, actual);
20+
}
21+
22+
test "Can identify that empty matrix has no saddle points" {
23+
const matrix = [1][0]i32{
24+
[0]i32{}, //
25+
};
26+
const expected = [_]Point{};
27+
const actual = try saddlePoints(1, 0, testing.allocator, matrix);
28+
defer testing.allocator.free(actual);
29+
try testing.expectEqualSlices(Point, &expected, actual);
30+
}
31+
32+
test "Can identify lack of saddle points when there are none" {
33+
const matrix = [3][3]i32{
34+
[3]i32{ 1, 2, 3 }, //
35+
[3]i32{ 3, 1, 2 }, //
36+
[3]i32{ 2, 3, 1 }, //
37+
};
38+
const expected = [_]Point{};
39+
const actual = try saddlePoints(3, 3, testing.allocator, matrix);
40+
defer testing.allocator.free(actual);
41+
try testing.expectEqualSlices(Point, &expected, actual);
42+
}
43+
44+
test "Can identify multiple saddle points in a column" {
45+
const matrix = [3][3]i32{
46+
[3]i32{ 4, 5, 4 }, //
47+
[3]i32{ 3, 5, 5 }, //
48+
[3]i32{ 1, 5, 4 }, //
49+
};
50+
const expected = [_]Point{
51+
.{ .row = 1, .column = 2 }, //
52+
.{ .row = 2, .column = 2 }, //
53+
.{ .row = 3, .column = 2 }, //
54+
};
55+
const actual = try saddlePoints(3, 3, testing.allocator, matrix);
56+
defer testing.allocator.free(actual);
57+
try testing.expectEqualSlices(Point, &expected, actual);
58+
}
59+
60+
test "Can identify multiple saddle points in a row" {
61+
const matrix = [3][3]i32{
62+
[3]i32{ 6, 7, 8 }, //
63+
[3]i32{ 5, 5, 5 }, //
64+
[3]i32{ 7, 5, 6 }, //
65+
};
66+
const expected = [_]Point{
67+
.{ .row = 2, .column = 1 }, //
68+
.{ .row = 2, .column = 2 }, //
69+
.{ .row = 2, .column = 3 }, //
70+
};
71+
const actual = try saddlePoints(3, 3, testing.allocator, matrix);
72+
defer testing.allocator.free(actual);
73+
try testing.expectEqualSlices(Point, &expected, actual);
74+
}
75+
76+
test "Can identify saddle point in bottom right corner" {
77+
const matrix = [3][3]i32{
78+
[3]i32{ 8, 7, 9 }, //
79+
[3]i32{ 6, 7, 6 }, //
80+
[3]i32{ 3, 2, 5 }, //
81+
};
82+
const expected = [_]Point{
83+
.{ .row = 3, .column = 3 }, //
84+
};
85+
const actual = try saddlePoints(3, 3, testing.allocator, matrix);
86+
defer testing.allocator.free(actual);
87+
try testing.expectEqualSlices(Point, &expected, actual);
88+
}
89+
90+
test "Can identify saddle points in a non square matrix" {
91+
const matrix = [2][3]i32{
92+
[3]i32{ 3, 1, 3 }, //
93+
[3]i32{ 3, 2, 4 }, //
94+
};
95+
const expected = [_]Point{
96+
.{ .row = 1, .column = 1 }, //
97+
.{ .row = 1, .column = 3 }, //
98+
};
99+
const actual = try saddlePoints(2, 3, testing.allocator, matrix);
100+
defer testing.allocator.free(actual);
101+
try testing.expectEqualSlices(Point, &expected, actual);
102+
}
103+
104+
test "Can identify that saddle points in a single column matrix are those with the minimum value" {
105+
const matrix = [4][1]i32{
106+
[1]i32{2}, //
107+
[1]i32{1}, //
108+
[1]i32{4}, //
109+
[1]i32{1}, //
110+
};
111+
const expected = [_]Point{
112+
.{ .row = 2, .column = 1 }, //
113+
.{ .row = 4, .column = 1 }, //
114+
};
115+
const actual = try saddlePoints(4, 1, testing.allocator, matrix);
116+
defer testing.allocator.free(actual);
117+
try testing.expectEqualSlices(Point, &expected, actual);
118+
}
119+
120+
test "Can identify that saddle points in a single row matrix are those with the maximum value" {
121+
const matrix = [1][4]i32{
122+
[4]i32{ 2, 5, 3, 5 }, //
123+
};
124+
const expected = [_]Point{
125+
.{ .row = 1, .column = 2 }, //
126+
.{ .row = 1, .column = 4 }, //
127+
};
128+
const actual = try saddlePoints(1, 4, testing.allocator, matrix);
129+
defer testing.allocator.free(actual);
130+
try testing.expectEqualSlices(Point, &expected, actual);
131+
}

0 commit comments

Comments
 (0)