Skip to content

Commit

Permalink
feat: add practice exercise spiral-matrix (#807)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahans authored Feb 20, 2024
1 parent cdaf146 commit 425a050
Show file tree
Hide file tree
Showing 12 changed files with 18,225 additions and 2 deletions.
12 changes: 10 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -999,9 +999,9 @@
"name": "Linked List ",
"uuid": "6f6c55dd-db6b-40ca-96f2-d9b7232dcbb0",
"practices": [],
"prerequisites":[],
"prerequisites": [],
"difficulty": 6,
"topics": [
"topics": [
"classes",
"conditionals",
"loops",
Expand Down Expand Up @@ -1160,6 +1160,14 @@
"practices": [],
"prerequisites": [],
"difficulty": 3
},
{
"slug": "spiral-matrix",
"name": "Spiral Matrix",
"uuid": "d5569902-5815-4b05-ab13-13826fef7826",
"practices": [],
"prerequisites": [],
"difficulty": 5
}
],
"foregone": [
Expand Down
24 changes: 24 additions & 0 deletions exercises/practice/spiral-matrix/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Instructions

Given the size, return a square matrix of numbers in spiral order.

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:

## Examples

### Spiral matrix of size 3

```text
1 2 3
8 9 4
7 6 5
```

### Spiral matrix of size 4

```text
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
```
21 changes: 21 additions & 0 deletions exercises/practice/spiral-matrix/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"authors": [
"ahans"
],
"files": {
"solution": [
"spiral_matrix.cpp",
"spiral_matrix.h"
],
"test": [
"spiral_matrix_test.cpp"
],
"example": [
".meta/example.cpp",
".meta/example.h"
]
},
"blurb": "Given the size, return a square matrix of numbers in spiral order.",
"source": "Reddit r/dailyprogrammer challenge #320 [Easy] Spiral Ascension.",
"source_url": "https://web.archive.org/web/20230607064729/https://old.reddit.com/r/dailyprogrammer/comments/6i60lr/20170619_challenge_320_easy_spiral_ascension/"
}
53 changes: 53 additions & 0 deletions exercises/practice/spiral-matrix/.meta/example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <tuple>

#include "spiral_matrix.h"

namespace spiral_matrix {

namespace {

using Coords = std::tuple<int32_t, int32_t>;
using Dir = std::tuple<int32_t, int32_t>;

[[nodiscard]] Coords operator+(Coords const coords, Dir const dir) {
auto const [row, col] = coords;
auto const [dr, dc] = dir;
return {row + dr, col + dc};
}

} // namespace

std::vector<std::vector<uint32_t>> spiral_matrix(uint32_t const size) {
std::vector<std::vector<uint32_t>> matrix(size,
std::vector<uint32_t>(size));

constexpr auto rotate_clockwise = [](Dir const dir) {
auto const [dr, dc] = dir;
return Dir{dc, -dr};
};

auto const matrix_elem = [&matrix](Coords coords) -> auto& {
auto const [row, col] = coords;
return matrix[row][col];
};

auto const in_bounds = [size](Coords const coords) {
auto const [row, col] = coords;
return 0 <= row && row < static_cast<int32_t>(size) && 0 <= col &&
col < static_cast<int32_t>(size);
};

Coords coords{};
Dir dir{0, 1};
for (uint32_t i = 1; i <= size * size; ++i) {
matrix_elem(coords) = i;
if (!in_bounds(coords + dir) || matrix_elem(coords + dir) != 0) {
dir = rotate_clockwise(dir);
}
coords = coords + dir;
}

return matrix;
}

} // namespace spiral_matrix
13 changes: 13 additions & 0 deletions exercises/practice/spiral-matrix/.meta/example.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#if !defined(SPIRAL_MATRIX_H)
#define SPIRAL_MATRIX_H

#include <cstdint>
#include <vector>

namespace spiral_matrix {

[[nodiscard]] std::vector<std::vector<uint32_t>> spiral_matrix(uint32_t size);

} // namespace spiral_matrix

#endif // SPIRAL_MATRIX_H
28 changes: 28 additions & 0 deletions exercises/practice/spiral-matrix/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 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.

[8f584201-b446-4bc9-b132-811c8edd9040]
description = "empty spiral"

[e40ae5f3-e2c9-4639-8116-8a119d632ab2]
description = "trivial spiral"

[cf05e42d-eb78-4098-a36e-cdaf0991bc48]
description = "spiral of size 2"

[1c475667-c896-4c23-82e2-e033929de939]
description = "spiral of size 3"

[05ccbc48-d891-44f5-9137-f4ce462a759d]
description = "spiral of size 4"

[f4d2165b-1738-4e0c-bed0-c459045ae50d]
description = "spiral of size 5"
64 changes: 64 additions & 0 deletions exercises/practice/spiral-matrix/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Get the exercise name from the current directory
get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME)

# Basic CMake project
cmake_minimum_required(VERSION 3.5.1)

# Name the project after the exercise
project(${exercise} CXX)

# Get a source filename from the exercise name by replacing -'s with _'s
string(REPLACE "-" "_" file ${exercise})

# Implementation could be only a header
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp)
set(exercise_cpp ${file}.cpp)
else()
set(exercise_cpp "")
endif()

# Use the common Catch library?
if(EXERCISM_COMMON_CATCH)
# For Exercism track development only
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h $<TARGET_OBJECTS:catchlib>)
elseif(EXERCISM_TEST_SUITE)
# The Exercism test suite is being run, the Docker image already
# includes a pre-built version of Catch.
find_package(Catch2 REQUIRED)
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h)
target_link_libraries(${exercise} PRIVATE Catch2::Catch2WithMain)
# When Catch is installed system wide we need to include a different
# header, we need this define to use the correct one.
target_compile_definitions(${exercise} PRIVATE EXERCISM_TEST_SUITE)
else()
# Build executable from sources and headers
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h test/tests-main.cpp)
endif()

set_target_properties(${exercise} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED OFF
CXX_EXTENSIONS OFF
)

set(CMAKE_BUILD_TYPE Debug)

if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)")
set_target_properties(${exercise} PROPERTIES
COMPILE_FLAGS "-Wall -Wextra -Wpedantic -Werror"
)
endif()

# Configure to run all the tests?
if(${EXERCISM_RUN_ALL_TESTS})
target_compile_definitions(${exercise} PRIVATE EXERCISM_RUN_ALL_TESTS)
endif()

# Tell MSVC not to warn us about unchecked iterators in debug builds
if(${MSVC})
set_target_properties(${exercise} PROPERTIES
COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS)
endif()

# Run the tests on every build
add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise})
5 changes: 5 additions & 0 deletions exercises/practice/spiral-matrix/spiral_matrix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "spiral_matrix.h"

namespace spiral_matrix {

} // namespace spiral_matrix
8 changes: 8 additions & 0 deletions exercises/practice/spiral-matrix/spiral_matrix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#if !defined(SPIRAL_MATRIX_H)
#define SPIRAL_MATRIX_H

namespace spiral_matrix {

} // namespace spiral_matrix

#endif // SPIRAL_MATRIX_H
60 changes: 60 additions & 0 deletions exercises/practice/spiral-matrix/spiral_matrix_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "spiral_matrix.h"

#ifdef EXERCISM_TEST_SUITE
#include <catch2/catch.hpp>
#else
#include "test/catch.hpp"
#endif

#include <cstdint>
#include <vector>

TEST_CASE("empty spiral", "[8f584201-b446-4bc9-b132-811c8edd9040]") {
std::vector<std::vector<uint32_t>> const expected{};
REQUIRE(expected == spiral_matrix::spiral_matrix(0));
}

#if defined(EXERCISM_RUN_ALL_TESTS)
TEST_CASE("trivial spiral", "[e40ae5f3-e2c9-4639-8116-8a119d632ab2]") {
std::vector<std::vector<uint32_t>> const expected = {{1}};
REQUIRE(expected == spiral_matrix::spiral_matrix(1));
}

TEST_CASE("spiral of size 2", "[cf05e42d-eb78-4098-a36e-cdaf0991bc48]") {
std::vector<std::vector<uint32_t>> const expected = {
{1, 2}, //
{4, 3} //
};
REQUIRE(expected == spiral_matrix::spiral_matrix(2));
}

TEST_CASE("spiral of size 3", "[1c475667-c896-4c23-82e2-e033929de939]") {
std::vector<std::vector<uint32_t>> expected = {
{1, 2, 3}, //
{8, 9, 4}, //
{7, 6, 5} //
};
REQUIRE(expected == spiral_matrix::spiral_matrix(3));
}

TEST_CASE("spiral of size 4", "[05ccbc48-d891-44f5-9137-f4ce462a759d]") {
std::vector<std::vector<uint32_t>> const expected = {
{1, 2, 3, 4}, //
{12, 13, 14, 5}, //
{11, 16, 15, 6}, //
{10, 9, 8, 7} //
};
REQUIRE(expected == spiral_matrix::spiral_matrix(4));
}

TEST_CASE("spiral of size 5", "[f4d2165b-1738-4e0c-bed0-c459045ae50d]") {
std::vector<std::vector<uint32_t>> const expected = {
{1, 2, 3, 4, 5}, //
{16, 17, 18, 19, 6}, //
{15, 24, 25, 20, 7}, //
{14, 23, 22, 21, 8}, //
{13, 12, 11, 10, 9} //
};
REQUIRE(expected == spiral_matrix::spiral_matrix(5));
}
#endif
Loading

0 comments on commit 425a050

Please sign in to comment.