Skip to content

Commit 425a050

Browse files
authored
feat: add practice exercise spiral-matrix (#807)
1 parent cdaf146 commit 425a050

File tree

12 files changed

+18225
-2
lines changed

12 files changed

+18225
-2
lines changed

config.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -999,9 +999,9 @@
999999
"name": "Linked List ",
10001000
"uuid": "6f6c55dd-db6b-40ca-96f2-d9b7232dcbb0",
10011001
"practices": [],
1002-
"prerequisites":[],
1002+
"prerequisites": [],
10031003
"difficulty": 6,
1004-
"topics": [
1004+
"topics": [
10051005
"classes",
10061006
"conditionals",
10071007
"loops",
@@ -1160,6 +1160,14 @@
11601160
"practices": [],
11611161
"prerequisites": [],
11621162
"difficulty": 3
1163+
},
1164+
{
1165+
"slug": "spiral-matrix",
1166+
"name": "Spiral Matrix",
1167+
"uuid": "d5569902-5815-4b05-ab13-13826fef7826",
1168+
"practices": [],
1169+
"prerequisites": [],
1170+
"difficulty": 5
11631171
}
11641172
],
11651173
"foregone": [
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Instructions
2+
3+
Given the size, return a square matrix of numbers in spiral order.
4+
5+
The matrix should be filled with natural numbers, starting from 1 in the top-left corner, increasing in an inward, clockwise spiral order, like these examples:
6+
7+
## Examples
8+
9+
### Spiral matrix of size 3
10+
11+
```text
12+
1 2 3
13+
8 9 4
14+
7 6 5
15+
```
16+
17+
### Spiral matrix of size 4
18+
19+
```text
20+
1 2 3 4
21+
12 13 14 5
22+
11 16 15 6
23+
10 9 8 7
24+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"authors": [
3+
"ahans"
4+
],
5+
"files": {
6+
"solution": [
7+
"spiral_matrix.cpp",
8+
"spiral_matrix.h"
9+
],
10+
"test": [
11+
"spiral_matrix_test.cpp"
12+
],
13+
"example": [
14+
".meta/example.cpp",
15+
".meta/example.h"
16+
]
17+
},
18+
"blurb": "Given the size, return a square matrix of numbers in spiral order.",
19+
"source": "Reddit r/dailyprogrammer challenge #320 [Easy] Spiral Ascension.",
20+
"source_url": "https://web.archive.org/web/20230607064729/https://old.reddit.com/r/dailyprogrammer/comments/6i60lr/20170619_challenge_320_easy_spiral_ascension/"
21+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include <tuple>
2+
3+
#include "spiral_matrix.h"
4+
5+
namespace spiral_matrix {
6+
7+
namespace {
8+
9+
using Coords = std::tuple<int32_t, int32_t>;
10+
using Dir = std::tuple<int32_t, int32_t>;
11+
12+
[[nodiscard]] Coords operator+(Coords const coords, Dir const dir) {
13+
auto const [row, col] = coords;
14+
auto const [dr, dc] = dir;
15+
return {row + dr, col + dc};
16+
}
17+
18+
} // namespace
19+
20+
std::vector<std::vector<uint32_t>> spiral_matrix(uint32_t const size) {
21+
std::vector<std::vector<uint32_t>> matrix(size,
22+
std::vector<uint32_t>(size));
23+
24+
constexpr auto rotate_clockwise = [](Dir const dir) {
25+
auto const [dr, dc] = dir;
26+
return Dir{dc, -dr};
27+
};
28+
29+
auto const matrix_elem = [&matrix](Coords coords) -> auto& {
30+
auto const [row, col] = coords;
31+
return matrix[row][col];
32+
};
33+
34+
auto const in_bounds = [size](Coords const coords) {
35+
auto const [row, col] = coords;
36+
return 0 <= row && row < static_cast<int32_t>(size) && 0 <= col &&
37+
col < static_cast<int32_t>(size);
38+
};
39+
40+
Coords coords{};
41+
Dir dir{0, 1};
42+
for (uint32_t i = 1; i <= size * size; ++i) {
43+
matrix_elem(coords) = i;
44+
if (!in_bounds(coords + dir) || matrix_elem(coords + dir) != 0) {
45+
dir = rotate_clockwise(dir);
46+
}
47+
coords = coords + dir;
48+
}
49+
50+
return matrix;
51+
}
52+
53+
} // namespace spiral_matrix
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#if !defined(SPIRAL_MATRIX_H)
2+
#define SPIRAL_MATRIX_H
3+
4+
#include <cstdint>
5+
#include <vector>
6+
7+
namespace spiral_matrix {
8+
9+
[[nodiscard]] std::vector<std::vector<uint32_t>> spiral_matrix(uint32_t size);
10+
11+
} // namespace spiral_matrix
12+
13+
#endif // SPIRAL_MATRIX_H
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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+
[8f584201-b446-4bc9-b132-811c8edd9040]
13+
description = "empty spiral"
14+
15+
[e40ae5f3-e2c9-4639-8116-8a119d632ab2]
16+
description = "trivial spiral"
17+
18+
[cf05e42d-eb78-4098-a36e-cdaf0991bc48]
19+
description = "spiral of size 2"
20+
21+
[1c475667-c896-4c23-82e2-e033929de939]
22+
description = "spiral of size 3"
23+
24+
[05ccbc48-d891-44f5-9137-f4ce462a759d]
25+
description = "spiral of size 4"
26+
27+
[f4d2165b-1738-4e0c-bed0-c459045ae50d]
28+
description = "spiral of size 5"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Get the exercise name from the current directory
2+
get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME)
3+
4+
# Basic CMake project
5+
cmake_minimum_required(VERSION 3.5.1)
6+
7+
# Name the project after the exercise
8+
project(${exercise} CXX)
9+
10+
# Get a source filename from the exercise name by replacing -'s with _'s
11+
string(REPLACE "-" "_" file ${exercise})
12+
13+
# Implementation could be only a header
14+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp)
15+
set(exercise_cpp ${file}.cpp)
16+
else()
17+
set(exercise_cpp "")
18+
endif()
19+
20+
# Use the common Catch library?
21+
if(EXERCISM_COMMON_CATCH)
22+
# For Exercism track development only
23+
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h $<TARGET_OBJECTS:catchlib>)
24+
elseif(EXERCISM_TEST_SUITE)
25+
# The Exercism test suite is being run, the Docker image already
26+
# includes a pre-built version of Catch.
27+
find_package(Catch2 REQUIRED)
28+
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h)
29+
target_link_libraries(${exercise} PRIVATE Catch2::Catch2WithMain)
30+
# When Catch is installed system wide we need to include a different
31+
# header, we need this define to use the correct one.
32+
target_compile_definitions(${exercise} PRIVATE EXERCISM_TEST_SUITE)
33+
else()
34+
# Build executable from sources and headers
35+
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h test/tests-main.cpp)
36+
endif()
37+
38+
set_target_properties(${exercise} PROPERTIES
39+
CXX_STANDARD 17
40+
CXX_STANDARD_REQUIRED OFF
41+
CXX_EXTENSIONS OFF
42+
)
43+
44+
set(CMAKE_BUILD_TYPE Debug)
45+
46+
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)")
47+
set_target_properties(${exercise} PROPERTIES
48+
COMPILE_FLAGS "-Wall -Wextra -Wpedantic -Werror"
49+
)
50+
endif()
51+
52+
# Configure to run all the tests?
53+
if(${EXERCISM_RUN_ALL_TESTS})
54+
target_compile_definitions(${exercise} PRIVATE EXERCISM_RUN_ALL_TESTS)
55+
endif()
56+
57+
# Tell MSVC not to warn us about unchecked iterators in debug builds
58+
if(${MSVC})
59+
set_target_properties(${exercise} PROPERTIES
60+
COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS)
61+
endif()
62+
63+
# Run the tests on every build
64+
add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise})
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "spiral_matrix.h"
2+
3+
namespace spiral_matrix {
4+
5+
} // namespace spiral_matrix
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#if !defined(SPIRAL_MATRIX_H)
2+
#define SPIRAL_MATRIX_H
3+
4+
namespace spiral_matrix {
5+
6+
} // namespace spiral_matrix
7+
8+
#endif // SPIRAL_MATRIX_H
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include "spiral_matrix.h"
2+
3+
#ifdef EXERCISM_TEST_SUITE
4+
#include <catch2/catch.hpp>
5+
#else
6+
#include "test/catch.hpp"
7+
#endif
8+
9+
#include <cstdint>
10+
#include <vector>
11+
12+
TEST_CASE("empty spiral", "[8f584201-b446-4bc9-b132-811c8edd9040]") {
13+
std::vector<std::vector<uint32_t>> const expected{};
14+
REQUIRE(expected == spiral_matrix::spiral_matrix(0));
15+
}
16+
17+
#if defined(EXERCISM_RUN_ALL_TESTS)
18+
TEST_CASE("trivial spiral", "[e40ae5f3-e2c9-4639-8116-8a119d632ab2]") {
19+
std::vector<std::vector<uint32_t>> const expected = {{1}};
20+
REQUIRE(expected == spiral_matrix::spiral_matrix(1));
21+
}
22+
23+
TEST_CASE("spiral of size 2", "[cf05e42d-eb78-4098-a36e-cdaf0991bc48]") {
24+
std::vector<std::vector<uint32_t>> const expected = {
25+
{1, 2}, //
26+
{4, 3} //
27+
};
28+
REQUIRE(expected == spiral_matrix::spiral_matrix(2));
29+
}
30+
31+
TEST_CASE("spiral of size 3", "[1c475667-c896-4c23-82e2-e033929de939]") {
32+
std::vector<std::vector<uint32_t>> expected = {
33+
{1, 2, 3}, //
34+
{8, 9, 4}, //
35+
{7, 6, 5} //
36+
};
37+
REQUIRE(expected == spiral_matrix::spiral_matrix(3));
38+
}
39+
40+
TEST_CASE("spiral of size 4", "[05ccbc48-d891-44f5-9137-f4ce462a759d]") {
41+
std::vector<std::vector<uint32_t>> const expected = {
42+
{1, 2, 3, 4}, //
43+
{12, 13, 14, 5}, //
44+
{11, 16, 15, 6}, //
45+
{10, 9, 8, 7} //
46+
};
47+
REQUIRE(expected == spiral_matrix::spiral_matrix(4));
48+
}
49+
50+
TEST_CASE("spiral of size 5", "[f4d2165b-1738-4e0c-bed0-c459045ae50d]") {
51+
std::vector<std::vector<uint32_t>> const expected = {
52+
{1, 2, 3, 4, 5}, //
53+
{16, 17, 18, 19, 6}, //
54+
{15, 24, 25, 20, 7}, //
55+
{14, 23, 22, 21, 8}, //
56+
{13, 12, 11, 10, 9} //
57+
};
58+
REQUIRE(expected == spiral_matrix::spiral_matrix(5));
59+
}
60+
#endif

0 commit comments

Comments
 (0)