Info
-
Did you know that C++20
std::to_array
supports creating from string literals?
Example
static_assert(1 == std::size(std::to_array("")));
static_assert(0 == std::to_array("")[0]);
static_assert(4 == std::size(std::to_array("foo")));
static_assert(0 == std::to_array("foo")[3]);
Puzzle
- Can you implement a
xmas_tree
variable template which creates a Xmas-tree array with a given size?
template<auto Size, class T = char>
constexpr const auto xmas_tree = /*TODO*/std::array<T, (Size+1) * ((Size*2) - 1) + 1>{};
static_assert(
xmas_tree<3>
==
std::to_array(
" # "
" ### "
"#####"
" # "
)
);
static_assert(
xmas_tree<5>
==
std::to_array(
" # "
" ### "
" ##### "
" ####### "
"#########"
" # "
)
);
Solutions
template<auto Size, class T = char>
constexpr const auto xmas_tree = []<auto... Is>(std::index_sequence<Is...>) {
std::array<T, (Size+1) * ((Size*2) - 1) + 1> arr{};
auto row = [it = arr.begin()](size_t i) mutable {
it = std::fill_n(it, Size - i, ' ');
it = std::fill_n(it, i * 2 - 1, '#');
it = std::fill_n(it, Size - i, ' ');
};
(row(Is + 1), ..., row(1));
return arr;
}(std::make_index_sequence<Size>());
template<auto Size, class T = char>
constexpr const auto xmas_tree = []<auto ... Is>(std::index_sequence<Is...>)
{
static_assert( Size > 0 );
auto constexpr M = Size * 2 - 1 ;
auto constexpr Center = Size - 1 ;
return std::array<T, (Size+1) * (Size * 2 - 1) + 1> {
[]<auto I >(std::index_sequence<I>) {
auto constexpr R = I/ M ;
auto constexpr C = I - R * M;
auto constexpr CL = (R != Size? Size-R-1:Size-1);
auto constexpr CH = (R != Size? Size+R-1:Size-1);
if constexpr( C >= CL && C <= CH )
return '#';
else
return ' ';
}(std::index_sequence<Is>{}) ...
};
}(std::make_index_sequence<(Size+1) * (Size * 2 - 1) >{});
template <auto Size, class T>
consteval auto make_xmas_tree() {
constexpr const auto rows = Size + 1;
constexpr const auto cols = (Size * 2) - 1;
std::array<T, rows * cols + 1> tree{};
tree.fill(' ');
for (auto mid = cols/2, width = 0;
mid < rows * cols;
mid += cols, ++width, width %= Size) {
std::fill_n(&tree[mid - width], width * 2 + 1, '#');
}
tree.back() = 0;
return tree;
}
template<auto Size, class T = char>
constexpr const auto xmas_tree = make_xmas_tree<Size, T>();
template<auto Size, class T= char>
constexpr const auto tree()
{
std::array<T, (Size+1)*((Size*2)-1)+1> tree{};
for(uint32_t r=0; r<Size+1; r++)
for(int32_t c=0; c<2*Size-1; c++)
if(r < Size)
tree[r*(2*Size-1)+c] = std::abs(c-(Size-1)) >r ? ' ' : '#';
else
tree[r*(2*Size-1)+c] = std::abs(c-(Size-1)) != 0 ? ' ' : '#';
return tree;
}
template<auto Size, class T = char>
constexpr const auto xmas_tree = tree<Size, T>();