From 9cbc6c4cbc7cc764ff8acfb11d63c08f4e586414 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Mon, 1 Sep 2025 12:32:43 +0200 Subject: [PATCH] Comment code. --- main.cc | 112 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 40 deletions(-) diff --git a/main.cc b/main.cc index 0ceda9e..474ffab 100644 --- a/main.cc +++ b/main.cc @@ -1,6 +1,10 @@ -// -// Created by Matthew Gretton-Dann on 31/08/2025. -// +/** \file main.cc + * \author Matthew Gretton-Dann + * \brief Solves the partirige problem for user specified size. + * + * Copyright 2025, Matthew-Gretton-Dann + * SPDX: Apache-2.0 + */ #include #include @@ -8,13 +12,23 @@ #include #include +/** (x, y) pair storing a position. */ using Pos = std::pair; +/** Get x co-ordinate from position */ auto x(Pos const &p) noexcept -> int { return p.first; } + +/** Get y co-ordinate from position */ auto y(Pos const &p) noexcept -> int { return p.second; } +/** A square - consisting of position of closest corner to origin, and side-length. + */ struct Square { - Square(Pos const &pos, int length) noexcept : pos_(pos), length_(length) { + /** Construct a square. + * \param pos Position of closest corner to origin + * \param length Side length. + */ + Square(Pos const &pos, int const length) noexcept : pos_(pos), length_(length) { } Square(Square const &other) noexcept = default; @@ -27,20 +41,24 @@ struct Square { ~Square() noexcept = default; + /** Get x co-ordinate of closest corner to origin. */ auto x() const noexcept -> int { return ::x(pos_); } + + /** Get y co-ordinate of closest corner to origin. */ auto y() const noexcept -> int { return ::y(pos_); } + + /** Get side length. */ auto length() const noexcept -> int { return length_; } - Pos pos_; - int length_; -}; - -struct OverlappingSquares { - Pos pos_; +private: + Pos pos_; ///< Position of corner closest to origin + int length_; ///< Side length }; +/** An N * N grid of characters. */ struct Grid { - Grid(int length) : grid_(length * length, '.'), length_(length) { + /** Construct a grid of given side-length. */ + Grid(int length) : grid_(length * length, empty), length_(length) { } Grid(Grid const &other) = delete; @@ -53,22 +71,11 @@ struct Grid { ~Grid() noexcept = default; + /** Get grid length */ auto length() const noexcept -> int { return length_; } - auto set(int x, int y, char c) noexcept -> void { - assert(x < length_); - assert(y < length_); - assert(grid_[x + y * length_] != c); - grid_[x + y * length_] = c; - } - - auto get(int x, int y) const noexcept -> char { - assert(x < length_); - assert(y < length_); - return grid_[x + y * length_]; - } - - auto add(Square const &sq) -> void { + /** Add a square to the grid. */ + auto add(Square const &sq) noexcept -> void { switch (sq.length()) { case 1: set(sq.x(), sq.y(), '*'); break; @@ -102,18 +109,19 @@ struct Grid { } } - auto clear(Square const &sq) { + /** Clear a square from the grid. */ + auto clear(Square const &sq) noexcept -> void { for (auto i = sq.x(); i < sq.x() + sq.length(); ++i) { for (auto j = sq.y(); j < sq.y() + sq.length(); ++j) { - set(i, j, '.'); + set(i, j, empty); } } } - auto output() const { - for (auto i = 0; i < length_; ++i) { - std::cout << - std::string_view(grid_.data() + i * length_, length_) << '\n'; + /** Output the grid. */ + auto output() const -> void { + for (auto idx = 0; idx < length_ * length_; idx += length_) { + std::cout << std::string_view(grid_.data() + idx, length_) << '\n'; } } @@ -148,23 +156,44 @@ struct Grid { */ auto next_pos(Pos const &pos, int n) const noexcept -> Pos { auto const b = grid_.begin() + x(pos) + n + y(pos) * length_; - auto const p = std::find(b, grid_.end(), '.'); - if (p == grid_.end()) { - return std::make_pair(0, length_); - } + auto const p = std::find(b, grid_.end(), empty); auto const v = p - grid_.begin(); return std::make_pair(v % length_, v / length_); } - std::vector grid_; - int length_; +private: + /** Set the grid position (x, y) to the character c. + * + * It is an error if (x, y) is already set to c - as that means we have overlapping + * squares. + */ + auto set(int x, int y, char c) noexcept -> void { + assert(x < length_); + assert(y < length_); + assert(grid_[x + y * length_] != c); + grid_[x + y * length_] = c; + } + + std::vector grid_; ///< The grid + int length_; ///< Side length + + static const int empty = '.'; ///< Character used for an empty cell. }; -auto triangle_num(int n) { return (n * (n + 1)) / 2; } +/** Get the n'th triangular number. */ +auto triangle_num(int n) noexcept -> int { return (n * (n + 1)) / 2; } +/** Vector used to identify the available squares. */ using Avail = std::vector; -auto find_solution_impl(Grid &grid, int n, Pos const &pos, Avail &avail_sqs) -> bool { +/** Recursive part of solution finder. + * + * Fills \a grid with squares from \a avail_sqs, starting at the current + * position \a pos. \a n is the side-length of the largest square. + * + * Returns \c true if a solution is found, \a c false if not. + */ +auto find_solution_impl(Grid &grid, int n, Pos const &pos, Avail &avail_sqs) noexcept -> bool { if (x(pos) == 0 && y(pos) == grid.length()) { return true; } /* Walk through the possible squares from the largest that will fit down to 0. @@ -176,7 +205,6 @@ auto find_solution_impl(Grid &grid, int n, Pos const &pos, Avail &avail_sqs) -> * If we know a square of side length N will fit then we know a square of side length * N - 1 will fit. */ - assert(x(pos) + grid.largest_square(pos, n) <= grid.length()); for (auto idx = grid.largest_square(pos, n); idx != 0; --idx) { if (avail_sqs[idx] == 0) { continue; } @@ -191,6 +219,10 @@ auto find_solution_impl(Grid &grid, int n, Pos const &pos, Avail &avail_sqs) -> return false; } +/** Find a solution to the partridge problem of size n. + * + * Returns the solution grid. + */ auto find_solution(int n) -> Grid { auto length = triangle_num(n); Grid grid(length);