Compare commits
	
		
			2 Commits
		
	
	
		
			ff43ba5287
			...
			65c748aab3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 65c748aab3 | |||
| 5a01260281 | 
							
								
								
									
										57
									
								
								main.cc
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								main.cc
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| /** \file main.cc | /** \file main.cc | ||||||
|  *  \author Matthew Gretton-Dann |  *  \author Matthew Gretton-Dann | ||||||
|  *  \brief Solves the partirige problem for user specified size. |  *  \brief Solves the Partridge problem for user specified size. | ||||||
|  * |  * | ||||||
|  * Copyright 2025, Matthew-Gretton-Dann |  * Copyright 2025, Matthew-Gretton-Dann | ||||||
|  * SPDX: Apache-2.0 |  * SPDX: Apache-2.0 | ||||||
| @@ -11,13 +11,12 @@ | |||||||
| #include <string_view> | #include <string_view> | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <set> |  | ||||||
|  |  | ||||||
| using size_t = std::size_t; |  | ||||||
|  |  | ||||||
| namespace { | namespace { | ||||||
|  |   using size_t = std::uint64_t; | ||||||
|  |  | ||||||
|   /** (x, y) pair storing a position. */ |   /** (x, y) pair storing a position. */ | ||||||
|   using Pos = std::size_t; |   using Pos = size_t; | ||||||
|  |  | ||||||
|   /** A square - consisting of position of closest corner to origin, and side-length. |   /** A square - consisting of position of closest corner to origin, and side-length. | ||||||
|    */ |    */ | ||||||
| @@ -40,10 +39,10 @@ namespace { | |||||||
|     ~Square() noexcept = default; |     ~Square() noexcept = default; | ||||||
|  |  | ||||||
|     /** Get x co-ordinate of closest corner to origin. */ |     /** Get x co-ordinate of closest corner to origin. */ | ||||||
|     auto pos() const noexcept -> Pos { return pos_; } |     [[nodiscard]] auto pos() const noexcept -> Pos { return pos_; } | ||||||
|  |  | ||||||
|     /** Get side length. */ |     /** Get side length. */ | ||||||
|     auto length() const noexcept -> size_t { return length_; } |     [[nodiscard]] auto length() const noexcept -> size_t { return length_; } | ||||||
|  |  | ||||||
|   private: |   private: | ||||||
|     Pos pos_; ///< Position of corner closest to origin |     Pos pos_; ///< Position of corner closest to origin | ||||||
| @@ -66,7 +65,7 @@ namespace { | |||||||
|  |  | ||||||
|     ~Results() noexcept = default; |     ~Results() noexcept = default; | ||||||
|  |  | ||||||
|     auto length() const noexcept -> size_t { return length_; } |     [[nodiscard]] auto length() const noexcept -> size_t { return length_; } | ||||||
|  |  | ||||||
|     /** Output the grid. */ |     /** Output the grid. */ | ||||||
|     auto output() const -> void { |     auto output() const -> void { | ||||||
| @@ -87,8 +86,8 @@ namespace { | |||||||
|       s[x + y * length_] = c; |       s[x + y * length_] = c; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     auto sq_x(Square const &sq) const noexcept -> size_t { return sq.pos() % length_; } |     [[nodiscard]] auto sq_x(Square const &sq) const noexcept -> size_t { return sq.pos() % length_; } | ||||||
|     auto sq_y(Square const &sq) const noexcept -> size_t { return sq.pos() / length_; } |     [[nodiscard]] auto sq_y(Square const &sq) const noexcept -> size_t { return sq.pos() / length_; } | ||||||
|  |  | ||||||
|     auto prettify_sq(std::string &s, Square const &sq) const noexcept -> void { |     auto prettify_sq(std::string &s, Square const &sq) const noexcept -> void { | ||||||
|       switch (sq.length()) { |       switch (sq.length()) { | ||||||
| @@ -117,7 +116,7 @@ namespace { | |||||||
|  |  | ||||||
|           size_t i = sq_x(sq) + n - 1; |           size_t i = sq_x(sq) + n - 1; | ||||||
|           while (n != 0) { |           while (n != 0) { | ||||||
|             set(s, --i, sq_y(sq) + 1, '0' + (n % 10)); |             set(s, --i, sq_y(sq) + 1, static_cast<char>('0' + static_cast<char>(n % 10))); | ||||||
|             n /= 10; |             n /= 10; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| @@ -134,7 +133,7 @@ namespace { | |||||||
|     using T = std::int_fast64_t; |     using T = std::int_fast64_t; | ||||||
|  |  | ||||||
|     /** Construct a grid of given side-length. */ |     /** Construct a grid of given side-length. */ | ||||||
|     Grid(size_t length) : grid_(length * length, empty), length_(length) { |     explicit Grid(size_t length) : grid_(length * length, empty), length_(length) { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Grid(Grid const &other) = delete; |     Grid(Grid const &other) = delete; | ||||||
| @@ -148,12 +147,12 @@ namespace { | |||||||
|     ~Grid() noexcept = default; |     ~Grid() noexcept = default; | ||||||
|  |  | ||||||
|     /** Get grid length */ |     /** Get grid length */ | ||||||
|     auto end() const noexcept -> size_t { return grid_.size(); } |     [[nodiscard]] auto end() const noexcept -> size_t { return static_cast<size_t>(grid_.size()); } | ||||||
|  |  | ||||||
|     /** Add a square to the grid. */ |     /** Add a square to the grid. */ | ||||||
|     auto add(Square const &sq) noexcept -> void { |     auto add(Square const &sq) noexcept -> void { | ||||||
|       /* One would expect the fastest way to do this would be to have x be the |       /* One would expect the fastest way to do this would be to have x be the | ||||||
|        * fastest increasing index so we stores [pos, pos + 1,..., pos+length, ...] |        * fastest increasing index so we store [pos, pos + 1,..., pos+length, ...] | ||||||
|        * But experimentation tells us this isn't so, and storing |        * But experimentation tells us this isn't so, and storing | ||||||
|        * [pos, pos + length, ..., pos + 1, ...] is faster! |        * [pos, pos + length, ..., pos + 1, ...] is faster! | ||||||
|        */ |        */ | ||||||
| @@ -175,7 +174,7 @@ namespace { | |||||||
|  |  | ||||||
|     /** \brief Get length of the largest square that fits at \a pos in the grid. |     /** \brief Get length of the largest square that fits at \a pos in the grid. | ||||||
|      */ |      */ | ||||||
|     auto largest_square(Pos pos, size_t n) const noexcept -> size_t { |     [[nodiscard]] auto largest_square(Pos pos, size_t n) const noexcept -> size_t { | ||||||
|       assert(pos < end()); |       assert(pos < end()); | ||||||
|  |  | ||||||
|       /* Because of how we walk through the grid (starting at 0,0 then increasing |       /* Because of how we walk through the grid (starting at 0,0 then increasing | ||||||
| @@ -203,27 +202,15 @@ namespace { | |||||||
|  |  | ||||||
|     /** Get the next position to check starting at pos. |     /** Get the next position to check starting at pos. | ||||||
|      * |      * | ||||||
|      * Returns grid_.length() if no more positions avaialble. |      * Returns grid_.length() if no more positions available. | ||||||
|      */ |      */ | ||||||
|     auto next_pos(Pos pos) const noexcept -> Pos { |     [[nodiscard]] auto next_pos(Pos pos) const noexcept -> Pos { | ||||||
|       auto const b = grid_.begin() + pos; |       auto const b = grid_.begin() + static_cast<std::ptrdiff_t>(pos); | ||||||
|       auto const p = std::find(b, grid_.end(), empty); |       auto const p = std::find(b, grid_.end(), empty); | ||||||
|       return p - grid_.begin(); |       return p - grid_.begin(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   private: |   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(size_t x, size_t y, T c) noexcept -> void { |  | ||||||
|       assert(x < length_); |  | ||||||
|       assert(y < length_); |  | ||||||
|       assert(grid_[x + y * length_] != c); |  | ||||||
|       grid_[x + y * length_] = c; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::vector<T> grid_; ///< The grid |     std::vector<T> grid_; ///< The grid | ||||||
|     size_t length_; ///< Side length |     size_t length_; ///< Side length | ||||||
|  |  | ||||||
| @@ -231,7 +218,7 @@ namespace { | |||||||
|     static constexpr char filled = 1; ///< Character used for a filled cell, |     static constexpr char filled = 1; ///< Character used for a filled cell, | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   /** Get the n'th triangular number. */ |   /** Get the n-th triangular number. */ | ||||||
|   auto triangle_num(size_t n) noexcept -> size_t { return (n * (n + 1)) / 2; } |   auto triangle_num(size_t n) noexcept -> size_t { return (n * (n + 1)) / 2; } | ||||||
|  |  | ||||||
|   /** Vector used to identify the available squares. */ |   /** Vector used to identify the available squares. */ | ||||||
| @@ -253,7 +240,7 @@ namespace { | |||||||
|      * available squares until we find one that fits. |      * available squares until we find one that fits. | ||||||
|      */ |      */ | ||||||
|  |  | ||||||
|     // grid is our inprogress grid of square positions. |     // grid is our in-progress grid of square positions. | ||||||
|     auto const length = triangle_num(n); |     auto const length = triangle_num(n); | ||||||
|     Grid grid(length); |     Grid grid(length); | ||||||
|  |  | ||||||
| @@ -276,7 +263,7 @@ namespace { | |||||||
|     while (true) { |     while (true) { | ||||||
|       /* If the idx is 0 we've looked at all possible square lengths for this |       /* If the idx is 0 we've looked at all possible square lengths for this | ||||||
|        * position, and they've failed.  Pop the last square of the stack, remove |        * position, and they've failed.  Pop the last square of the stack, remove | ||||||
|        * it from the grid and try the next smaller one in the same position. |        * it from the grid and try the next smaller size in the same position. | ||||||
|        */ |        */ | ||||||
|       if (idx == 0) { |       if (idx == 0) { | ||||||
|         // No squares on the stack -> failed to find a solution. |         // No squares on the stack -> failed to find a solution. | ||||||
| @@ -312,13 +299,13 @@ namespace { | |||||||
|       if (pos == grid.end()) { break; } |       if (pos == grid.end()) { break; } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return Results(length, sqs); |     return {length, sqs}; | ||||||
|   } |   } | ||||||
| } // anon namespace | } // anon namespace | ||||||
|  |  | ||||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||||
|   auto n = (argc == 1) ? 8 : std::atol(argv[1]); |   auto n = (argc == 1) ? 8 : std::atol(argv[1]); | ||||||
|   auto grid = find_solution(n); |   auto const grid = find_solution(n); | ||||||
|   std::cout << "Partridge problem " << n << " side length " << grid.length() << '\n'; |   std::cout << "Partridge problem " << n << " side length " << grid.length() << '\n'; | ||||||
|   grid.output(); |   grid.output(); | ||||||
|   return 0; |   return 0; | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								results.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								results.md
									
									
									
									
									
								
							| @@ -5,9 +5,9 @@ The following show some of the results produced by running `partridge_cpp`. | |||||||
| # Partridge 8 | # Partridge 8 | ||||||
|  |  | ||||||
| Timings on Macbook Air M1: | Timings on Macbook Air M1: | ||||||
|  * 2.05s user |  * 1.76s user | ||||||
|  * 0.01s system |  * 0.00s system | ||||||
|  * 2.063 total |  * 1.765 total | ||||||
|  |  | ||||||
| ```text | ```text | ||||||
| +------++------++------++------++--+ | +------++------++------++------++--+ | ||||||
| @@ -50,9 +50,9 @@ Timings on Macbook Air M1: | |||||||
| # Partridge 9 | # Partridge 9 | ||||||
|  |  | ||||||
| Timings on Macbook Air M1: | Timings on Macbook Air M1: | ||||||
|  * 176.48s user |  * 156.99s user | ||||||
|  * 0.25s system |  * 0.18s system | ||||||
|  * 2:59.03 total |  * 2:38.69 total | ||||||
|  |  | ||||||
| ```text | ```text | ||||||
| +-------++-------++-------++-------++-------+ | +-------++-------++-------++-------++-------+ | ||||||
| @@ -105,9 +105,9 @@ Timings on Macbook Air M1: | |||||||
| # Partridge 10 | # Partridge 10 | ||||||
|  |  | ||||||
| Timings on Macbook Air M1: | Timings on Macbook Air M1: | ||||||
|  * 30578.68s user |  * 23828.35s user | ||||||
|  * 88.19s system |  * 5.62s system | ||||||
|  * 8:40:24.11 total |  * 6:38:02.83 total | ||||||
|  |  | ||||||
| ```text | ```text | ||||||
| +--------++--------++--------++--------++--------++---+ | +--------++--------++--------++--------++--------++---+ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user