Skip to content

Latest commit

 

History

History
141 lines (114 loc) · 3.46 KB

205.md

File metadata and controls

141 lines (114 loc) · 3.46 KB
Info

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]);

https://godbolt.org/z/5bnPrj

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(
    "    #    "
    "   ###   "
    "  #####  "
    " ####### "
    "#########"
    "    #    "
  )
);

https://godbolt.org/z/z93hhf

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>());

https://godbolt.org/z/oKMTqY

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) >{});

https://godbolt.org/z/5evv39

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>();

https://godbolt.org/z/fEa9v5

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>();

https://godbolt.org/z/fjs58z