#include <iostream>
#include <string>
#include <type_traits>
namespace mu {
namespace index_list {
template<size_t... Indices> struct IndexList
{
template<size_t N> using append = IndexList<Indices..., N>;
static constexpr size_t size() {
return sizeof...(Indices);
}
};
template<size_t Size> struct IndexListMaker {
typedef typename IndexListMaker<Size-1>::type::template append<Size-1> type;
};
template<> struct IndexListMaker<0u> {
typedef IndexList<> type;
};
template<typename... Ts> using toIndexList = typename IndexListMaker<sizeof...(Ts)>::type;
}
namespace il = index_list;
}
struct EmptyResult {
static const std::string value;
};
const std::string EmptyResult::value;
template<size_t Width, size_t Height> struct ResultSize {
static constexpr size_t width = Width;
static constexpr size_t height = Height;
static constexpr size_t square = Width * Height;
};
template<char Foreground, char Background> struct RenderRule {
static constexpr char background = Background;
static constexpr char foreground = Foreground;
};
template<size_t Idx, unsigned char Block> struct GetElement {
static constexpr size_t value = ((Block & ((Idx < 4u) ? 0xF0u : 0x0Fu)) >> (7u - Idx)) & 1u;
};
template<size_t Id, size_t Idx, class Size, class Rule, size_t Element> struct OneElementProcessor {
static constexpr bool inRenderZone = Idx < Size::square;
static constexpr bool needNewLine = Idx > 0 && (Idx % Size::width == 0u);
static const std::string value;
};
template<size_t Id, size_t Idx, class Size, class Rule, size_t Element>
const std::string OneElementProcessor<Id, Idx, Size, Rule, Element>::value = (inRenderZone) ? (((needNewLine) ? (std::string() + '\n') : std::string()) +
((Element != 0u) ? Rule::foreground : Rule::background)) : std::string();
template<template <size_t> class T, size_t... Indices> struct Summa;
template<template <size_t> class T, size_t Index, size_t... Indices> struct Summa<T, Index, Indices...> {
static const decltype(T<Index>::value) value;
};
template<template <size_t> class T, size_t Index, size_t... Indices>
const decltype(T<Index>::value) Summa<T, Index, Indices...>::value = T<Index>::value + Summa<T, Indices...>::value;
template<template <size_t> class T, size_t Index> struct Summa<T, Index> {
static const decltype(T<Index>::value) value;
};
template<template <size_t> class T, size_t Index>
const decltype(T<Index>::value) Summa<T, Index>::value = T<Index>::value;
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Block> struct BlockProcessor {
template<size_t N> using processOne = OneElementProcessor<Id, Idx + N, Size, Rule, GetElement<N, Block>::value>;
template<size_t... Indices> static constexpr auto run(const mu::il::IndexList<Indices...>&) {
return Summa<processOne, Indices...>::value;
}
static const std::string value;
};
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Block>
const std::string BlockProcessor<Id, Idx, Size, Rule, Block>::value = BlockProcessor<Id, Idx, Size, Rule, Block>::template run(mu::il::IndexListMaker<8>::type());
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char... Data> struct Render;
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char First, unsigned char... Data> struct Render<Id, Idx, Size, Rule, First, Data...> {
static const std::string value;
};
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char First, unsigned char... Data>
const std::string Render<Id, Idx, Size, Rule, First, Data...>::value = BlockProcessor<Id, Idx, Size, Rule, First>::value +
Render<Id, Idx + 8, Size, Rule, Data...>::value;
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Last> struct Render<Id, Idx, Size, Rule, Last> {
static const std::string value;
};
template<size_t Id, size_t Idx, class Size, class Rule, unsigned char Last>
const std::string Render<Id, Idx, Size, Rule, Last>::value = BlockProcessor<Id, Idx, Size, Rule, Last>::value;
template<size_t Id, size_t Width, class Rule, unsigned char... Data> struct SillyImage {
static constexpr size_t width = Width;
static constexpr size_t height = (Width > 0) ? (sizeof...(Data) * 8 / Width) : 0;
static constexpr bool is_valid = width > 0 && height > 0;
static const std::string data;
static void showMe() {
std::cout << "(" << Id << ") Size: " << width << " x " << height << "\n\n";
std::cout << data;
}
};
template<size_t Id, size_t Width, class Rule, unsigned char... Data>
const std::string SillyImage<Id, Width, Rule, Data...>::data = std::string() +
std::conditional< is_valid, Render<Id, 0, ResultSize<width, height>, Rule, Data...>, EmptyResult>::type::value;
int main() {
SillyImage<0, 11, RenderRule<'$', ' '>, 0x31, 0x8F, 0x7B, 0xFF, 0xFF, 0xF3, 0xF8, 0x1C, 0x01, 0x00>::showMe();
std::cout << "\n\n";
SillyImage<1, 15, RenderRule<'#', '.'>, 0x31, 0x84, 0xF7, 0x9F, 0xFF, 0x97, 0xFF, 0x03, 0xF8, 0x81, 0xC3, 0x81, 0x02, 0x00>::showMe();
std::cout << "\n\n";
SillyImage<2, 15, RenderRule<'*', ' '>, 0x3F, 0xE4, 0xFF, 0x9F, 0xC0, 0x17, 0x80, 0x0F, 0x00, 0x8F, 0xF3, 0x8F, 0xF2, 0x00>::showMe();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgpuYW1lc3BhY2UgbXUgewoKICAgIG5hbWVzcGFjZSBpbmRleF9saXN0IHsKCiAgICAgICAgdGVtcGxhdGU8c2l6ZV90Li4uIEluZGljZXM+IHN0cnVjdCBJbmRleExpc3QKICAgICAgICB7CiAgICAgICAgICAgIHRlbXBsYXRlPHNpemVfdCBOPiB1c2luZyBhcHBlbmQgPSBJbmRleExpc3Q8SW5kaWNlcy4uLiwgTj47CgogICAgICAgICAgICBzdGF0aWMgY29uc3RleHByIHNpemVfdCBzaXplKCkgewogICAgICAgICAgICAgICAgcmV0dXJuIHNpemVvZi4uLihJbmRpY2VzKTsKICAgICAgICAgICAgfQogICAgICAgIH07CgogICAgICAgIHRlbXBsYXRlPHNpemVfdCBTaXplPiBzdHJ1Y3QgSW5kZXhMaXN0TWFrZXIgewogICAgICAgICAgICB0eXBlZGVmIHR5cGVuYW1lIEluZGV4TGlzdE1ha2VyPFNpemUtMT46OnR5cGU6OnRlbXBsYXRlIGFwcGVuZDxTaXplLTE+IHR5cGU7CiAgICAgICAgfTsKCiAgICAgICAgdGVtcGxhdGU8PiBzdHJ1Y3QgSW5kZXhMaXN0TWFrZXI8MHU+IHsKICAgICAgICAgICAgdHlwZWRlZiBJbmRleExpc3Q8PiB0eXBlOwogICAgICAgIH07CgogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lLi4uIFRzPiB1c2luZyB0b0luZGV4TGlzdCA9IHR5cGVuYW1lIEluZGV4TGlzdE1ha2VyPHNpemVvZi4uLihUcyk+Ojp0eXBlOwogICAgfQoKICAgIG5hbWVzcGFjZSBpbCA9IGluZGV4X2xpc3Q7Cn0KCnN0cnVjdCBFbXB0eVJlc3VsdCB7CiAgICBzdGF0aWMgY29uc3Qgc3RkOjpzdHJpbmcgdmFsdWU7Cn07Cgpjb25zdCBzdGQ6OnN0cmluZyBFbXB0eVJlc3VsdDo6dmFsdWU7Cgp0ZW1wbGF0ZTxzaXplX3QgV2lkdGgsIHNpemVfdCBIZWlnaHQ+IHN0cnVjdCBSZXN1bHRTaXplIHsKICAgIHN0YXRpYyBjb25zdGV4cHIgc2l6ZV90IHdpZHRoID0gV2lkdGg7CiAgICBzdGF0aWMgY29uc3RleHByIHNpemVfdCBoZWlnaHQgPSBIZWlnaHQ7CiAgICBzdGF0aWMgY29uc3RleHByIHNpemVfdCBzcXVhcmUgPSBXaWR0aCAqIEhlaWdodDsKfTsKCnRlbXBsYXRlPGNoYXIgRm9yZWdyb3VuZCwgY2hhciBCYWNrZ3JvdW5kPiBzdHJ1Y3QgUmVuZGVyUnVsZSB7CiAgICBzdGF0aWMgY29uc3RleHByIGNoYXIgYmFja2dyb3VuZCA9IEJhY2tncm91bmQ7CiAgICBzdGF0aWMgY29uc3RleHByIGNoYXIgZm9yZWdyb3VuZCA9IEZvcmVncm91bmQ7Cn07Cgp0ZW1wbGF0ZTxzaXplX3QgSWR4LCB1bnNpZ25lZCBjaGFyIEJsb2NrPiBzdHJ1Y3QgR2V0RWxlbWVudCB7CiAgICBzdGF0aWMgY29uc3RleHByIHNpemVfdCB2YWx1ZSA9ICgoQmxvY2sgJiAoKElkeCA8IDR1KSA/IDB4RjB1IDogMHgwRnUpKSA+PiAoN3UgLSBJZHgpKSAmIDF1Owp9OwoKdGVtcGxhdGU8c2l6ZV90IElkLCBzaXplX3QgSWR4LCBjbGFzcyBTaXplLCBjbGFzcyBSdWxlLCBzaXplX3QgRWxlbWVudD4gc3RydWN0IE9uZUVsZW1lbnRQcm9jZXNzb3IgewogICAgc3RhdGljIGNvbnN0ZXhwciBib29sIGluUmVuZGVyWm9uZSA9IElkeCA8IFNpemU6OnNxdWFyZTsKICAgIHN0YXRpYyBjb25zdGV4cHIgYm9vbCBuZWVkTmV3TGluZSA9IElkeCA+IDAgJiYgKElkeCAlIFNpemU6OndpZHRoID09IDB1KTsKICAgIHN0YXRpYyBjb25zdCBzdGQ6OnN0cmluZyB2YWx1ZTsKfTsKCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgc2l6ZV90IEVsZW1lbnQ+CmNvbnN0IHN0ZDo6c3RyaW5nIE9uZUVsZW1lbnRQcm9jZXNzb3I8SWQsIElkeCwgU2l6ZSwgUnVsZSwgRWxlbWVudD46OnZhbHVlID0gKGluUmVuZGVyWm9uZSkgPyAoKChuZWVkTmV3TGluZSkgPyAoc3RkOjpzdHJpbmcoKSArICdcbicpIDogc3RkOjpzdHJpbmcoKSkgKwogICAgICAgICgoRWxlbWVudCAhPSAwdSkgPyBSdWxlOjpmb3JlZ3JvdW5kIDogUnVsZTo6YmFja2dyb3VuZCkpIDogc3RkOjpzdHJpbmcoKTsKCnRlbXBsYXRlPHRlbXBsYXRlIDxzaXplX3Q+IGNsYXNzIFQsIHNpemVfdC4uLiBJbmRpY2VzPiBzdHJ1Y3QgU3VtbWE7Cgp0ZW1wbGF0ZTx0ZW1wbGF0ZSA8c2l6ZV90PiBjbGFzcyBULCBzaXplX3QgSW5kZXgsIHNpemVfdC4uLiBJbmRpY2VzPiBzdHJ1Y3QgU3VtbWE8VCwgSW5kZXgsIEluZGljZXMuLi4+IHsKICAgIHN0YXRpYyBjb25zdCBkZWNsdHlwZShUPEluZGV4Pjo6dmFsdWUpIHZhbHVlOwp9OwoKdGVtcGxhdGU8dGVtcGxhdGUgPHNpemVfdD4gY2xhc3MgVCwgc2l6ZV90IEluZGV4LCBzaXplX3QuLi4gSW5kaWNlcz4KY29uc3QgZGVjbHR5cGUoVDxJbmRleD46OnZhbHVlKSBTdW1tYTxULCBJbmRleCwgSW5kaWNlcy4uLj46OnZhbHVlID0gVDxJbmRleD46OnZhbHVlICsgU3VtbWE8VCwgSW5kaWNlcy4uLj46OnZhbHVlOwoKdGVtcGxhdGU8dGVtcGxhdGUgPHNpemVfdD4gY2xhc3MgVCwgc2l6ZV90IEluZGV4PiBzdHJ1Y3QgU3VtbWE8VCwgSW5kZXg+IHsKICAgIHN0YXRpYyBjb25zdCBkZWNsdHlwZShUPEluZGV4Pjo6dmFsdWUpIHZhbHVlOwp9OwoKdGVtcGxhdGU8dGVtcGxhdGUgPHNpemVfdD4gY2xhc3MgVCwgc2l6ZV90IEluZGV4Pgpjb25zdCBkZWNsdHlwZShUPEluZGV4Pjo6dmFsdWUpIFN1bW1hPFQsIEluZGV4Pjo6dmFsdWUgPSBUPEluZGV4Pjo6dmFsdWU7Cgp0ZW1wbGF0ZTxzaXplX3QgSWQsIHNpemVfdCBJZHgsIGNsYXNzIFNpemUsIGNsYXNzIFJ1bGUsIHVuc2lnbmVkIGNoYXIgQmxvY2s+IHN0cnVjdCBCbG9ja1Byb2Nlc3NvciB7CiAgICB0ZW1wbGF0ZTxzaXplX3QgTj4gdXNpbmcgcHJvY2Vzc09uZSA9IE9uZUVsZW1lbnRQcm9jZXNzb3I8SWQsIElkeCArIE4sIFNpemUsIFJ1bGUsIEdldEVsZW1lbnQ8TiwgQmxvY2s+Ojp2YWx1ZT47CgogICAgdGVtcGxhdGU8c2l6ZV90Li4uIEluZGljZXM+IHN0YXRpYyBjb25zdGV4cHIgYXV0byBydW4oY29uc3QgbXU6OmlsOjpJbmRleExpc3Q8SW5kaWNlcy4uLj4mKSB7CiAgICAgICAgcmV0dXJuIFN1bW1hPHByb2Nlc3NPbmUsIEluZGljZXMuLi4+Ojp2YWx1ZTsKICAgIH0KCiAgICBzdGF0aWMgY29uc3Qgc3RkOjpzdHJpbmcgdmFsdWU7Cn07Cgp0ZW1wbGF0ZTxzaXplX3QgSWQsIHNpemVfdCBJZHgsIGNsYXNzIFNpemUsIGNsYXNzIFJ1bGUsIHVuc2lnbmVkIGNoYXIgQmxvY2s+CmNvbnN0IHN0ZDo6c3RyaW5nIEJsb2NrUHJvY2Vzc29yPElkLCBJZHgsIFNpemUsIFJ1bGUsIEJsb2NrPjo6dmFsdWUgPSAgQmxvY2tQcm9jZXNzb3I8SWQsIElkeCwgU2l6ZSwgUnVsZSwgQmxvY2s+Ojp0ZW1wbGF0ZSBydW4obXU6OmlsOjpJbmRleExpc3RNYWtlcjw4Pjo6dHlwZSgpKTsKCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhci4uLiBEYXRhPiBzdHJ1Y3QgUmVuZGVyOwoKdGVtcGxhdGU8c2l6ZV90IElkLCBzaXplX3QgSWR4LCBjbGFzcyBTaXplLCBjbGFzcyBSdWxlLCB1bnNpZ25lZCBjaGFyIEZpcnN0LCB1bnNpZ25lZCBjaGFyLi4uIERhdGE+IHN0cnVjdCBSZW5kZXI8SWQsIElkeCwgU2l6ZSwgUnVsZSwgRmlyc3QsIERhdGEuLi4+IHsKICAgIHN0YXRpYyBjb25zdCBzdGQ6OnN0cmluZyB2YWx1ZTsKfTsKCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhciBGaXJzdCwgdW5zaWduZWQgY2hhci4uLiBEYXRhPgpjb25zdCBzdGQ6OnN0cmluZyBSZW5kZXI8SWQsIElkeCwgU2l6ZSwgUnVsZSwgRmlyc3QsIERhdGEuLi4+Ojp2YWx1ZSA9IEJsb2NrUHJvY2Vzc29yPElkLCBJZHgsIFNpemUsIFJ1bGUsIEZpcnN0Pjo6dmFsdWUgKwogICAgICAgIFJlbmRlcjxJZCwgSWR4ICsgOCwgU2l6ZSwgUnVsZSwgRGF0YS4uLj46OnZhbHVlOwoKdGVtcGxhdGU8c2l6ZV90IElkLCAgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhciBMYXN0PiBzdHJ1Y3QgUmVuZGVyPElkLCBJZHgsIFNpemUsIFJ1bGUsIExhc3Q+IHsKICAgIHN0YXRpYyBjb25zdCBzdGQ6OnN0cmluZyB2YWx1ZTsKfTsKCnRlbXBsYXRlPHNpemVfdCBJZCwgc2l6ZV90IElkeCwgY2xhc3MgU2l6ZSwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhciBMYXN0Pgpjb25zdCBzdGQ6OnN0cmluZyBSZW5kZXI8SWQsIElkeCwgU2l6ZSwgUnVsZSwgTGFzdD46OnZhbHVlID0gQmxvY2tQcm9jZXNzb3I8SWQsIElkeCwgU2l6ZSwgUnVsZSwgTGFzdD46OnZhbHVlOwoKdGVtcGxhdGU8c2l6ZV90IElkLCBzaXplX3QgV2lkdGgsIGNsYXNzIFJ1bGUsIHVuc2lnbmVkIGNoYXIuLi4gRGF0YT4gc3RydWN0IFNpbGx5SW1hZ2UgewogICAgc3RhdGljIGNvbnN0ZXhwciBzaXplX3Qgd2lkdGggPSBXaWR0aDsKICAgIHN0YXRpYyBjb25zdGV4cHIgc2l6ZV90IGhlaWdodCA9IChXaWR0aCA+IDApID8gKHNpemVvZi4uLihEYXRhKSAqIDggLyBXaWR0aCkgOiAwOwogICAgc3RhdGljIGNvbnN0ZXhwciBib29sIGlzX3ZhbGlkID0gd2lkdGggPiAwICYmIGhlaWdodCA+IDA7CiAgICBzdGF0aWMgY29uc3Qgc3RkOjpzdHJpbmcgZGF0YTsKCiAgICBzdGF0aWMgdm9pZCBzaG93TWUoKSB7CiAgICAgICAgc3RkOjpjb3V0IDw8ICIoIiA8PCBJZCA8PCAiKSBTaXplOiAiIDw8IHdpZHRoIDw8ICIgeCAiIDw8IGhlaWdodCA8PCAiXG5cbiI7CiAgICAgICAgc3RkOjpjb3V0IDw8IGRhdGE7CiAgICB9Cn07Cgp0ZW1wbGF0ZTxzaXplX3QgSWQsIHNpemVfdCBXaWR0aCwgY2xhc3MgUnVsZSwgdW5zaWduZWQgY2hhci4uLiBEYXRhPgpjb25zdCBzdGQ6OnN0cmluZyBTaWxseUltYWdlPElkLCBXaWR0aCwgUnVsZSwgRGF0YS4uLj46OmRhdGEgPSBzdGQ6OnN0cmluZygpICsKICAgICAgICBzdGQ6OmNvbmRpdGlvbmFsPCBpc192YWxpZCwgUmVuZGVyPElkLCAwLCBSZXN1bHRTaXplPHdpZHRoLCBoZWlnaHQ+LCBSdWxlLCBEYXRhLi4uPiwgRW1wdHlSZXN1bHQ+Ojp0eXBlOjp2YWx1ZTsKCmludCBtYWluKCkgewogICAgU2lsbHlJbWFnZTwwLCAxMSwgUmVuZGVyUnVsZTwnJCcsICcgJz4sIDB4MzEsIDB4OEYsIDB4N0IsIDB4RkYsIDB4RkYsIDB4RjMsIDB4RjgsIDB4MUMsIDB4MDEsIDB4MDA+OjpzaG93TWUoKTsKICAgIHN0ZDo6Y291dCA8PCAiXG5cbiI7CiAgICBTaWxseUltYWdlPDEsIDE1LCBSZW5kZXJSdWxlPCcjJywgJy4nPiwgMHgzMSwgMHg4NCwgMHhGNywgMHg5RiwgMHhGRiwgMHg5NywgMHhGRiwgMHgwMywgMHhGOCwgMHg4MSwgMHhDMywgMHg4MSwgMHgwMiwgMHgwMD46OnNob3dNZSgpOwogICAgc3RkOjpjb3V0IDw8ICJcblxuIjsKICAgIFNpbGx5SW1hZ2U8MiwgMTUsIFJlbmRlclJ1bGU8JyonLCAnICc+LCAweDNGLCAweEU0LCAweEZGLCAweDlGLCAweEMwLCAweDE3LCAweDgwLCAweDBGLCAweDAwLCAweDhGLCAweEYzLCAweDhGLCAweEYyLCAweDAwPjo6c2hvd01lKCk7Cn0K