Comment code.

This commit is contained in:
2025-09-01 12:32:43 +02:00
parent e865b2a567
commit 9cbc6c4cbc

112
main.cc
View File

@@ -1,6 +1,10 @@
// /** \file main.cc
// Created by Matthew Gretton-Dann on 31/08/2025. * \author Matthew Gretton-Dann
// * \brief Solves the partirige problem for user specified size.
*
* Copyright 2025, Matthew-Gretton-Dann
* SPDX: Apache-2.0
*/
#include <cassert> #include <cassert>
#include <utility> #include <utility>
@@ -8,13 +12,23 @@
#include <vector> #include <vector>
#include <iostream> #include <iostream>
/** (x, y) pair storing a position. */
using Pos = std::pair<int, int>; using Pos = std::pair<int, int>;
/** Get x co-ordinate from position */
auto x(Pos const &p) noexcept -> int { return p.first; } 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; } 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 { 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; Square(Square const &other) noexcept = default;
@@ -27,20 +41,24 @@ struct Square {
~Square() noexcept = default; ~Square() noexcept = default;
/** Get x co-ordinate of closest corner to origin. */
auto x() const noexcept -> int { return ::x(pos_); } 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_); } auto y() const noexcept -> int { return ::y(pos_); }
/** Get side length. */
auto length() const noexcept -> int { return length_; } auto length() const noexcept -> int { return length_; }
Pos pos_; private:
int length_; Pos pos_; ///< Position of corner closest to origin
}; int length_; ///< Side length
struct OverlappingSquares {
Pos pos_;
}; };
/** An N * N grid of characters. */
struct Grid { 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; Grid(Grid const &other) = delete;
@@ -53,22 +71,11 @@ struct Grid {
~Grid() noexcept = default; ~Grid() noexcept = default;
/** Get grid length */
auto length() const noexcept -> int { return length_; } auto length() const noexcept -> int { return length_; }
auto set(int x, int y, char c) noexcept -> void { /** Add a square to the grid. */
assert(x < length_); auto add(Square const &sq) noexcept -> void {
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 {
switch (sq.length()) { switch (sq.length()) {
case 1: set(sq.x(), sq.y(), '*'); case 1: set(sq.x(), sq.y(), '*');
break; 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 i = sq.x(); i < sq.x() + sq.length(); ++i) {
for (auto j = sq.y(); j < sq.y() + sq.length(); ++j) { for (auto j = sq.y(); j < sq.y() + sq.length(); ++j) {
set(i, j, '.'); set(i, j, empty);
} }
} }
} }
auto output() const { /** Output the grid. */
for (auto i = 0; i < length_; ++i) { auto output() const -> void {
std::cout << for (auto idx = 0; idx < length_ * length_; idx += length_) {
std::string_view(grid_.data() + i * length_, length_) << '\n'; 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 next_pos(Pos const &pos, int n) const noexcept -> Pos {
auto const b = grid_.begin() + x(pos) + n + y(pos) * length_; auto const b = grid_.begin() + x(pos) + n + y(pos) * length_;
auto const p = std::find(b, grid_.end(), '.'); auto const p = std::find(b, grid_.end(), empty);
if (p == grid_.end()) {
return std::make_pair(0, length_);
}
auto const v = p - grid_.begin(); auto const v = p - grid_.begin();
return std::make_pair(v % length_, v / length_); return std::make_pair(v % length_, v / length_);
} }
std::vector<char> grid_; private:
int length_; /** 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<char> 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<int>; using Avail = std::vector<int>;
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; } if (x(pos) == 0 && y(pos) == grid.length()) { return true; }
/* Walk through the possible squares from the largest that will fit down to 0. /* 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 * If we know a square of side length N will fit then we know a square of side length
* N - 1 will fit. * 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) { for (auto idx = grid.largest_square(pos, n); idx != 0; --idx) {
if (avail_sqs[idx] == 0) { continue; } 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; return false;
} }
/** Find a solution to the partridge problem of size n.
*
* Returns the solution grid.
*/
auto find_solution(int n) -> Grid { auto find_solution(int n) -> Grid {
auto length = triangle_num(n); auto length = triangle_num(n);
Grid grid(length); Grid grid(length);