<commit_before>#include <iostream>
#include <daedalus/DATFile.h>
#include <daedalus/DaedalusVM.h>
#include <daedalus/DaedalusStdlib.h>
#include <daedalus/DaedalusDialogManager.h>
#include <utils/logger.h>
#include <utils/split.h>
#include <inttypes.h>
#include <stdlib.h>
#include <algorithm>

using namespace Daedalus;

bool listFunctions = false;
bool listStrings = false;
bool cmdLine = false;
bool listSymbols = false;
bool verbose = false;
std::string ou_file;

void printDebugOutput(const std::vector< std::pair<std::string, size_t>>& dbg)
{
    for(auto& l : dbg)
    {
        if(l.second > 1)
            LogInfo() << "DBG: " << l.first << " (" << l.second << "x)";
        else
            LogInfo() << "DBG: " << l.first;
    }
}

void listNPCs(Daedalus::DaedalusVM& vm)
{
    GameState::DaedalusGameState& s = vm.getGameState();
    auto& npcs = s.getRegisteredObjects().NPCs;

    LogInfo() << "Found " << npcs.getNumObtainedElements() << " NPCs";

    for(size_t i=0;i<npcs.getNumObtainedElements(); i++)
    {
        Daedalus::GEngineClasses::C_Npc& n = npcs.getElements()[i];
        LogInfo() << "NPC: " << n.name[0];
        LogInfo() << " - Level: " << n.level;
        LogInfo() << " - WP: " << n.wp;
    }
}

size_t npcInstanceFromName(Daedalus::DaedalusVM& vm, const std::string& n)
{
    auto& npcs = vm.getGameState().getRegisteredObjects().NPCs;
    for(size_t i=0;i<npcs.getNumObtainedElements();i++)
    {
        if(npcs.getElements()[i].name[0] == n)
        {
            return npcs.getElements()[i].instanceSymbol;
        }
    }

    return static_cast<size_t>(-1);
}

std::string join(const std::vector<std::string>& v, const std::string& delim)
{
    std::string s;

    for(size_t i=0;i<v.size();i++)
    {
        if(!s.empty())
        {
            s += delim;
        }

        s += v[i];
    }

    return s;
}

void createPlayer(Daedalus::DaedalusVM& vm)
{
    GameState::NpcHandle hero = vm.getGameState().createNPC();
    vm.initializeInstance(ZMemory::toBigHandle(hero), vm.getDATFile().getSymbolIndexByName("PC_Hero"), Daedalus::IC_Npc);
    vm.setInstance("hero", ZMemory::toBigHandle(hero), Daedalus::IC_Npc);
}

void runVM(Daedalus::DaedalusVM& vm, bool print = true)
{
    if(print) LogInfo() << " -------------------------- RUNNING -------------------------- ";

    std::vector<Daedalus::PARSymbol> storedSymbols = vm.getDATFile().getSymTable().symbols;

    while (vm.doStack(verbose));

    if(print) LogInfo() << " -------------------------- FINISHED -------------------------- ";

    if(verbose)
    {
        for (size_t i = 0; i < vm.getDATFile().getSymTable().symbols.size(); i++)
        {
            if (i >= storedSymbols.size())
                continue;

            auto& s = vm.getDATFile().getSymTable().symbols[i];
            auto& o = storedSymbols[i];

            if (s.isDataSame(o))
                continue;

            LogInfo() << "Changed Symbol: " << s.name << " (" << i << "):";

            if (!s.intData.empty())
            {
                for (size_t j = 0; j < s.intData.size(); j++)
                {
                    if (j >= o.intData.size())
                        LogInfo() << " - Int[" << j << "]: (new) " << s.intData[j];
                    else if (o.intData[j] != s.intData[j])
                        LogInfo() << " - Int[" << j << "]: " << o.intData[j] << " -> " << s.intData[j];
                }
            }

            if (!s.strData.empty())
            {
                for (size_t j = 0; j < s.strData.size(); j++)
                {
                    if (j >= o.strData.size())
                        LogInfo() << " - String[" << j << "]: (new) " << s.strData[j];
                    else if (o.strData[j] != s.strData[j])
                        LogInfo() << " - String[" << j << "]: " << o.strData[j] << " -> " << s.strData[j];
                }
            }

            if (!s.floatData.empty())
            {
                for (size_t j = 0; j < s.floatData.size(); j++)
                {
                    if (j >= o.floatData.size())
                        LogInfo() << " - Float[" << j << "]: (new) " << s.floatData[j];
                    else if (o.floatData[j] != s.floatData[j])
                        LogInfo() << " - Float[" << j << "]: " << o.floatData[j] << " -> " << s.floatData[j];
                }
            }
        }
    }
}

/**
 * ----------------------------- main ------------------------------
 */
int main(int argc, char** argv)
{
    setlocale(LC_CTYPE, "");

    /*if (argc != 2) {
        std::cout << "Usage: dat_load <dat-file>" << std::endl
                  << "(No spaces in path or filename)" << std::endl;
        return 0;
    }*/

    std::vector<std::string> parts;
    for(size_t i=1;i<argc;i++)
        parts.push_back(argv[i]);

    std::string file;
    std::string main;

    for(size_t i=0;i<parts.size();i+=2)
    {
        LogInfo() << "Arg: " << parts[i];

        // Single flag args
        if(parts[i] == "-lf")
        {
            listFunctions = true;
            i--; // No arg here
            continue;
        }else if(parts[i] == "-ls")
        {
            listStrings = true;
            i--; // No arg here
            continue;
        }else if(parts[i] == "-c")
        {
            cmdLine = true;

            i--; // No arg here
            continue;
        }else if(parts[i] == "-ly")
        {
            listSymbols = true;
            i--; // No arg here
            continue;
        }
        else if(parts[i] == "-v")
        {
            verbose = true;
            i--; // No arg here
            continue;
        }

        if(i+1 == parts.size())
        {
            LogError() << "Missing argument for: " << parts[i];
            return 0;
        }

        if(parts[i] == "-m")
            main = parts[i+1];
        else if(parts[i] == "-f")
            file = parts[i+1];
        else if(parts[i] == "-ou")
        {
            ou_file = parts[i+1];
            continue;
        }
    }

    if(file.empty())
    {
        LogError() << "No file specified. Please use -f <file>.";
        return 0;
    }

    Daedalus::DATFile f(file);

    if(listFunctions)
    {
        LogInfo() << "Listing functions:";
        size_t i=0;
        for(const auto& s : f.getSymTable().symbols)
        {
            if(s.properties.elemProps.type == Daedalus::EParType_Func)
            {
                LogInfo() << "[" << i << "] - '" << s.name << "', at: " << s.address;
            }

            i++;
        }
    }

    if(listStrings)
    {
        LogInfo() << "Listing strings:";
        size_t i=0;
        for(const auto& s : f.getSymTable().symbols)
        {
            if(s.properties.elemProps.type == Daedalus::EParType_String)
            {
                if(s.strData.size() == 1 && !s.strData[0].empty())
                {
                    LogInfo() << "[" << i << "] - " << s.name << ": " << s.strData[0];
                }else
                {
                    LogInfo() << "[" << i << "]  - " << s.name;
                    for (size_t i = 0; i < s.strData.size(); i++)
                        if (!s.strData[i].empty())
                            LogInfo() << "[" << i << "]  -- String[" << i << "]: " << s.strData[i];
                }
            }

            i++;
        }
    }

    if(listSymbols)
    {
        int i=0;
        for(const auto& s : f.getSymTable().symbols)
        {
            LogInfo() << "[" << i << "] -- Symbol: " << s.name << ", Offset: " << s.classOffset;

            i++;
        }
    }

    if(!main.empty() || cmdLine)
    {
        Daedalus::DaedalusVM vm(file, main);

#include "lambdas.cpp"

        std::vector<std::pair<std::string, size_t>> debugOutput;
        vm.registerExternalFunction("printdebug", [&](Daedalus::DaedalusVM& vm){
            std::string s = vm.popString(); if(verbose) LogInfo() << "s: " << s;

            if(!debugOutput.empty() && debugOutput.back().first == s)
                debugOutput.back().second++;
            else
                debugOutput.push_back(std::make_pair(s, 0));
        });

        vm.registerExternalFunction("printdebuginst", [&](Daedalus::DaedalusVM& vm){
            std::string text = vm.popString(); if(verbose) LogInfo() << "text: " << text;

            if(!debugOutput.empty() && debugOutput.back().first == text)
                debugOutput.back().second++;
            else
                debugOutput.push_back(std::make_pair(text, 0));
        });

        vm.registerExternalFunction("printdebuginstch", [&](Daedalus::DaedalusVM& vm){
            std::string text = vm.popString(); if(verbose) LogInfo() << "text: " << text;

            if(!debugOutput.empty() && debugOutput.back().first == text)
                debugOutput.back().second++;
            else
                debugOutput.push_back(std::make_pair(text, 0));
        });

        vm.registerExternalFunction("printdebugch", [&](Daedalus::DaedalusVM& vm){
            std::string text = vm.popString(); if(verbose) LogInfo() << "text: " << text;

            if(!debugOutput.empty() && debugOutput.back().first == text)
                debugOutput.back().second++;
            else
                debugOutput.push_back(std::make_pair(text, 0));
        });

        registerDaedalusStdLib(vm, verbose);
        registerGothicEngineClasses(vm);
        vm.getGameState().registerExternals();

        // Create hero
        createPlayer(vm);

        if(!ou_file.empty())
        {
            GameState::DaedalusDialogManager* dm = new GameState::DaedalusDialogManager(vm, ou_file);

            auto onAIOutput = [&](GameState::NpcHandle self, GameState::NpcHandle target, const ZenLoad::oCMsgConversationData& msg)
            {
                LogInfo() << vm.getGameState().getNpc(self).name[0] << ": " << msg.text;
            };

            auto onAIProcessInfos = [&](GameState::NpcHandle self, std::vector<GameState::InfoHandle> infos)
            {
                GameState::NpcHandle target = ZMemory::handleCast<GameState::NpcHandle>(
                        vm.getDATFile().getSymbolByName("other").instanceDataHandle);

                LogInfo() << "Started talking with: " << vm.getGameState().getNpc(self).name[0];
                LogInfo() << "Options: ";

                std::map<size_t, size_t> optionsMap;
                std::vector<std::pair<size_t, size_t>> optionsSorted;
                for(size_t i=0;i<infos.size();i++)
                {
                    auto& info = vm.getGameState().getInfo(infos[i]);

                    //LogInfo() << " ---------- Checking: " << info.description << " ------------ ";

                    // Check condition
                    std::string vstr;
                    int32_t valid = 0;
                    if(info.condition)
                    {
                        // Most functions don't do a return
                        vm.pushState();

                        vm.pushInt(0);
                        vm.doCallOperation(info.condition);
                        runVM(vm, false);

                        valid = vm.popDataValue();
                        //LogInfo() << "#### Valid: " << valid;

                        vm.popState();
                    }

                    if(valid && !info.description.empty())
                    {
                        //LogInfo() << info.nr << ": value, '" << info.description << "'";
                        optionsMap[info.nr] = i;
                        optionsSorted.push_back(std::make_pair(info.nr, i));
                    }
                    //if(info.description.empty())
                    //    LogInfo() << " - [" << i+1 << "]: [other]";
                    //else
                    //    LogInfo() << " - [" << i+1 << "]" << vstr <<": " << info.description;
                }

                std::sort(optionsSorted.begin(), optionsSorted.end(),
                          [](const std::pair<size_t, size_t>& l, const std::pair<size_t, size_t>& r)
                          {return l.first < r.first;});

                LogInfo() << "";
                for(size_t i=0;i<optionsSorted.size();i++) {
                    auto& info = vm.getGameState().getInfo(infos[optionsSorted[i].second]);
                    LogInfo() << " - [" << i + 1 << "]" << ": " << info.description;
                }
                LogInfo() << "";

                size_t choice;
                std::cout << "Choice: " << std::flush;
                std::cin >> choice;

                LogInfo() << "";

                if(choice-1 < optionsSorted.size())
                {
                    Daedalus::GEngineClasses::C_Info& info = vm.getGameState().getInfo(infos[optionsSorted[choice-1].second]);

                    vm.pushState();
                    vm.doCallOperation(info.information);
                    runVM(vm, false);
                    vm.popState();

                    // Register information
                    dm->setNpcInfoKnown(vm.getGameState().getNpc(target).instanceSymbol, info.instanceSymbol);

                    // End dialog
                    vm.pushState();
                    vm.doCallOperation(vm.getDATFile().getSymbolByName("ZS_Talk_Loop").address);
                    runVM(vm, false);
                    vm.popState();

                    if(info.nr != 999)
                    {
                        // END wasn't selected, bring up dialog again
                        vm.pushState();
                        vm.doCallOperation(vm.getDATFile().getSymbolByName("ZS_Talk").address);
                        runVM(vm);
                        vm.popState();
                    }
                } else {
                    LogInfo() << "Invalid choice!";
                }

            };

            dm->registerExternals(onAIOutput, onAIProcessInfos);
        }

        //size_t self = vm.getDATFile().addSymbol();
        //vm.pushVar(self);

        if(!main.empty()) {
            runVM(vm);

            //listNPCs(vm);

            printDebugOutput(debugOutput);
            debugOutput.clear();
        } else
        {
            while (true)
            {
                if (cmdLine)
                {
                    // Read commandline
                    std::cout << "> " << std::flush;
                    std::string cmd;
                    std::getline(std::cin, cmd);

                    if(cmd.empty())
                        continue;

                    // Split into arguments
                    parts = Utils::split(cmd, ' ');

                    LogInfo() << cmd;

                    // First part is expected to be one of the following: "exec", [todo]
                    if (parts[0] == "exec")
                    {
                        // Arguments for exec are to be given like this:
                        // fname <vtype>:value1 <vtype2>:value2 ...
                        // Example: exec myFunction i:3 s:hello! v:SELF
                        // TODO: Support spaces in strings
                        if (parts.size() < 2)
                        {
                            std::cout << "Missing argument for exec!" << std::endl;
                            continue;
                        }

                        std::string fn = parts[1];
                        std::vector<std::string> args(parts.begin() + 2, parts.end());

                        if (!vm.getDATFile().hasSymbolName(fn))
                        {
                            std::cout << "Failed to find function: " << fn << std::endl;
                            continue;
                        }

                        vm.pushState();

                        uint32_t fnAddress = vm.getDATFile().getSymbolByName(fn).address;
                        int32_t i;
                        float flt;
                        std::string s;
                        size_t vidx;
                        for (std::string& a : args)
                        {
                            switch (a.front())
                            {
                                case 'i':
                                    i = atoi(a.c_str() + 2);
                                    vm.pushInt(i);
                                    break;

                                case 'f':
                                    flt = atof(a.c_str() + 2);
                                    vm.pushInt(*reinterpret_cast<uint32_t*>(&flt));
                                    break;

                                case 's':
                                    s = a.c_str() + 2;
                                    vm.pushString(s);
                                    LogInfo() << "s:" << s;
                                    break;

                                case 'v':
                                    s = a.c_str() + 2;
                                    vidx = vm.getDATFile().getSymbolIndexByName(s);
                                    vm.pushVar(vidx);
                                    break;

                            }
                        }

                        vm.doCallOperation(fnAddress);
                        runVM(vm);
                        vm.popState();

                        //listNPCs(vm);

                        if(verbose)
                        {
                            printDebugOutput(debugOutput);
                            debugOutput.clear();
                        }
                    } else if (parts[0] == "self")
                    {
                        if(parts.size() != 2)
                        {
                            LogInfo() << "Usage: self <symName>";
                            continue;
                        }

                        ZMemory::BigHandle h = vm.getDATFile().getSymbolByName(parts[1]).instanceDataHandle;
                        vm.setInstance("self", h, Daedalus::IC_Npc);
                    } else if (parts[0] == "other")
                    {
                        if(parts.size() != 2)
                        {
                            LogInfo() << "Usage: other <symName>";
                            continue;
                        }

                        ZMemory::BigHandle h = vm.getDATFile().getSymbolByName(parts[1]).instanceDataHandle;
                        vm.setInstance("other", h, Daedalus::IC_Npc);
                    } else if (parts[0] == "exit")
                    {
                        if(parts.size() != 2)
                        {
                            LogInfo() << "Usage: talk <npc>";
                            continue;
                        }

                        ZMemory::BigHandle h = vm.getDATFile().getSymbolByName(parts[1]).instanceDataHandle;
                        vm.setInstance("other", h, Daedalus::IC_Npc);

                    }
                    else if (parts[0] == "verbose")
                    {
                        if(parts.size() != 2)
                        {
                            LogInfo() << "Usage: verbose <0|1>";
                            continue;
                        }

                        if(parts[1] == "0")
                            verbose = false;
                        else
                            verbose = true;
                    }else if (parts[0] == "talk")
                    {
                        auto& npcs = vm.getGameState().getRegisteredObjects().NPCs;

                        parts.erase(parts.begin());

                        std::string cname = join(parts, " ");

                        size_t inst = npcInstanceFromName(vm, cname);

                        if(inst != static_cast<uint32_t>(-1))
                        {
                            vm.pushState();
                            // Set up self and other
                            ZMemory::BigHandle s = vm.getDATFile().getSymbolByIndex(inst).instanceDataHandle;
                            vm.setInstance("self", s, Daedalus::IC_Npc);

                            ZMemory::BigHandle o = vm.getDATFile().getSymbolByName("hero").instanceDataHandle;
                            vm.setInstance("other", o, Daedalus::IC_Npc);

                            vm.doCallOperation(vm.getDATFile().getSymbolByName("ZS_Talk").address);
                            runVM(vm);
                            vm.popState();
                        }
                        else
                            LogInfo() << "Failed to find npc with name: " << cname;
                    }else if (parts[0] == "log")
                    {

                        for(auto& t : vm.getGameState().getPlayerLog())
                        {
                            LogInfo() << " --- " << t.second.topic << " --- ";
                            std::string ents;
                            for(const std::string& s : t.second.entries)
                                if(s.empty())
                                        ents += s + "\n";
                                    else
                                        ents += "        \n        ---------\n        "
                                            + s + "\n";

                            LogInfo() << ents;
                        }
                    }
                    else if (parts[0] == "inv")
                    {
                        auto& npcs = vm.getGameState().getRegisteredObjects().NPCs;

                        parts.erase(parts.begin());

                        std::string cname = join(parts, " ");

                        size_t inst = npcInstanceFromName(vm, cname);

                        if(inst != static_cast<uint32_t>(-1))
                        {
                            GameState::NpcHandle h = ZMemory::handleCast<GameState::NpcHandle>(vm.getDATFile().getSymbolByIndex(inst).instanceDataHandle);

                            //vm.getGameState().getInventory(h)

                        }
                        else
                            LogInfo() << "Failed to find npc with name: " << cname;
                    }else if (parts[0] == "exit")
                    {
                        break;
                    }
                }
            }
        }
    }

    return 0;
}
<commit_msg>Samples: Reduce size of dat_load example (amd made it compile again)<commit_after>#include <iostream>
#include <daedalus/DATFile.h>
#include <daedalus/DaedalusVM.h>
#include <daedalus/DaedalusStdlib.h>
#include <daedalus/DaedalusDialogManager.h>
#include <utils/logger.h>
#include <utils/split.h>
#include <inttypes.h>
#include <stdlib.h>
#include <algorithm>

using namespace Daedalus;

bool listFunctions = false;
bool listStrings = false;
bool cmdLine = false;
bool listSymbols = false;
bool verbose = false;
std::string ou_file;

void printDebugOutput(const std::vector< std::pair<std::string, size_t>>& dbg)
{
    for(auto& l : dbg)
    {
        if(l.second > 1)
            LogInfo() << "DBG: " << l.first << " (" << l.second << "x)";
        else
            LogInfo() << "DBG: " << l.first;
    }
}

void listNPCs(Daedalus::DaedalusVM& vm)
{
    GameState::DaedalusGameState& s = vm.getGameState();
    auto& npcs = s.getRegisteredObjects().NPCs;

    LogInfo() << "Found " << npcs.getNumObtainedElements() << " NPCs";

    for(size_t i=0;i<npcs.getNumObtainedElements(); i++)
    {
        Daedalus::GEngineClasses::C_Npc& n = npcs.getElements()[i];
        LogInfo() << "NPC: " << n.name[0];
        LogInfo() << " - Level: " << n.level;
        LogInfo() << " - WP: " << n.wp;
    }
}

size_t npcInstanceFromName(Daedalus::DaedalusVM& vm, const std::string& n)
{
    auto& npcs = vm.getGameState().getRegisteredObjects().NPCs;
    for(size_t i=0;i<npcs.getNumObtainedElements();i++)
    {
        if(npcs.getElements()[i].name[0] == n)
        {
            return npcs.getElements()[i].instanceSymbol;
        }
    }

    return static_cast<size_t>(-1);
}

std::string join(const std::vector<std::string>& v, const std::string& delim)
{
    std::string s;

    for(size_t i=0;i<v.size();i++)
    {
        if(!s.empty())
        {
            s += delim;
        }

        s += v[i];
    }

    return s;
}

void createPlayer(Daedalus::DaedalusVM& vm)
{
    GameState::NpcHandle hero = vm.getGameState().createNPC();
    vm.initializeInstance(ZMemory::toBigHandle(hero), vm.getDATFile().getSymbolIndexByName("PC_Hero"), Daedalus::IC_Npc);
    vm.setInstance("hero", ZMemory::toBigHandle(hero), Daedalus::IC_Npc);
}

void runVM(Daedalus::DaedalusVM& vm, bool print = true)
{
    if(print) LogInfo() << " -------------------------- RUNNING -------------------------- ";

    std::vector<Daedalus::PARSymbol> storedSymbols = vm.getDATFile().getSymTable().symbols;

    while (vm.doStack(verbose));

    if(print) LogInfo() << " -------------------------- FINISHED -------------------------- ";

    if(verbose)
    {
        for (size_t i = 0; i < vm.getDATFile().getSymTable().symbols.size(); i++)
        {
            if (i >= storedSymbols.size())
                continue;

            auto& s = vm.getDATFile().getSymTable().symbols[i];
            auto& o = storedSymbols[i];

            if (s.isDataSame(o))
                continue;

            LogInfo() << "Changed Symbol: " << s.name << " (" << i << "):";

            if (!s.intData.empty())
            {
                for (size_t j = 0; j < s.intData.size(); j++)
                {
                    if (j >= o.intData.size())
                        LogInfo() << " - Int[" << j << "]: (new) " << s.intData[j];
                    else if (o.intData[j] != s.intData[j])
                        LogInfo() << " - Int[" << j << "]: " << o.intData[j] << " -> " << s.intData[j];
                }
            }

            if (!s.strData.empty())
            {
                for (size_t j = 0; j < s.strData.size(); j++)
                {
                    if (j >= o.strData.size())
                        LogInfo() << " - String[" << j << "]: (new) " << s.strData[j];
                    else if (o.strData[j] != s.strData[j])
                        LogInfo() << " - String[" << j << "]: " << o.strData[j] << " -> " << s.strData[j];
                }
            }

            if (!s.floatData.empty())
            {
                for (size_t j = 0; j < s.floatData.size(); j++)
                {
                    if (j >= o.floatData.size())
                        LogInfo() << " - Float[" << j << "]: (new) " << s.floatData[j];
                    else if (o.floatData[j] != s.floatData[j])
                        LogInfo() << " - Float[" << j << "]: " << o.floatData[j] << " -> " << s.floatData[j];
                }
            }
        }
    }
}

/**
 * ----------------------------- main ------------------------------
 */
int main(int argc, char** argv)
{
    setlocale(LC_CTYPE, "");

    /*if (argc != 2) {
        std::cout << "Usage: dat_load <dat-file>" << std::endl
                  << "(No spaces in path or filename)" << std::endl;
        return 0;
    }*/

    std::vector<std::string> parts;
    for(size_t i=1;i<argc;i++)
        parts.push_back(argv[i]);

    std::string file;
    std::string main;

    for(size_t i=0;i<parts.size();i+=2)
    {
        // Single flag args
        if(parts[i] == "-lf")
        {
            listFunctions = true;
            i--; // No arg here
            continue;
        }else if(parts[i] == "-ls")
        {
            listStrings = true;
            i--; // No arg here
            continue;
        }else if(parts[i] == "-c")
        {
            cmdLine = true;

            i--; // No arg here
            continue;
        }else if(parts[i] == "-ly")
        {
            listSymbols = true;
            i--; // No arg here
            continue;
        }
        else if(parts[i] == "-v")
        {
            verbose = true;
            i--; // No arg here
            continue;
        }

        if(i+1 == parts.size())
        {
            LogError() << "Missing argument for: " << parts[i];
            return 0;
        }

        if(parts[i] == "-m")
            main = parts[i+1];
        else if(parts[i] == "-f")
            file = parts[i+1];
        else if(parts[i] == "-ou")
        {
            ou_file = parts[i+1];
            continue;
        }
    }

    if(file.empty())
    {
        LogError() << "No file specified. Please use -f <file>.";
        return 0;
    }

    Daedalus::DATFile f(file);

    if(listFunctions)
    {
        LogInfo() << "Listing functions:";
        size_t i=0;
        for(const auto& s : f.getSymTable().symbols)
        {
            if(s.properties.elemProps.type == Daedalus::EParType_Func)
            {
                LogInfo() << "[" << i << "] - '" << s.name << "', at: " << s.address;
            }

            i++;
        }
    }

    if(listStrings)
    {
        LogInfo() << "Listing strings:";
        size_t i=0;
        for(const auto& s : f.getSymTable().symbols)
        {
            if(s.properties.elemProps.type == Daedalus::EParType_String)
            {
                if(s.strData.size() == 1 && !s.strData[0].empty())
                {
                    LogInfo() << "[" << i << "] - " << s.name << ": " << s.strData[0];
                }else
                {
                    LogInfo() << "[" << i << "]  - " << s.name;
                    for (size_t i = 0; i < s.strData.size(); i++)
                        if (!s.strData[i].empty())
                            LogInfo() << "[" << i << "]  -- String[" << i << "]: " << s.strData[i];
                }
            }

            i++;
        }
    }

    if(listSymbols)
    {
        int i=0;
        for(const auto& s : f.getSymTable().symbols)
        {
            LogInfo() << "[" << i << "] -- Symbol: " << s.name << ", Offset: " << s.classOffset;

            i++;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : B.cpp
 * Author  : Kazune Takahashi
 * Created : 6/17/2020, 5:57:02 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "APPROVED" << endl;
  exit(0);
}
void No()
{
  cout << "DENIED" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{

public:
  Solve()
  {
  }

  void flush()
  {
  }

private:
};

// ----- main() -----

/*
int main()
{
  Solve solve;
  solve.flush();
}
*/

int main()
{
  int N;
  vector<int> A(N);
  for (auto i{0}; i < N; ++i)
  {
    cin >> A[i];
  }
  for (auto i{0}; i < N; ++i)
  {
    if (A[i] % 2 == 0 && A[i] % 3 != 0 && A[i] % 5 != 0)
    {
      No();
    }
  }
  Yes();
}
<commit_msg>submit B.cpp to 'B - Papers, Please' (abc155) [C++14 (GCC 5.4.1)]<commit_after>#define DEBUG 1
/**
 * File    : B.cpp
 * Author  : Kazune Takahashi
 * Created : 6/17/2020, 5:57:02 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "APPROVED" << endl;
  exit(0);
}
void No()
{
  cout << "DENIED" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{

public:
  Solve()
  {
  }

  void flush()
  {
  }

private:
};

// ----- main() -----

/*
int main()
{
  Solve solve;
  solve.flush();
}
*/

int main()
{
  int N;
  cin >> N;
  vector<int> A(N);
  for (auto i{0}; i < N; ++i)
  {
    cin >> A[i];
  }
  for (auto i{0}; i < N; ++i)
  {
    if (A[i] % 2 == 0 && A[i] % 3 != 0 && A[i] % 5 != 0)
    {
      No();
    }
  }
  Yes();
}
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/23 1:01:45
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

int main()
{
  ll N;
  cin >> N;
  vector<ll> A(N);
  for (auto i{0}; i < N; ++i)
  {
    cin >> A[i];
  }
  vector<vector<ll>> dp(N, vector<ll>(3, mInfty<ll>()));
  dp[0][0] = A[0];
  dp[1][1] = A[1];
  if (N >= 3)
  {
    dp[2][2] = A[3];
  }
  for (auto i{0}; i < N; ++i)
  {
    for (auto j{0}; j < 3; ++j)
    {
      if (dp[i][j] == mInfty<ll>())
      {
        continue;
      }
      for (auto k{0}; k < 3; ++k)
      {
        int ni{i + 2 + k};
        int nj{j + k};
        if (ni < N && nj < 3)
        {
          ch_max(dp[ni][nj], dp[i][j] + A[ni]);
        }
      }
    }
  }
#if DEBUG == 1
  for (auto i{0}; i < N; ++i)
  {
    for (auto j{0}; j < 3; ++j)
    {
      cerr << "dp[" << i << "][" << j << "] = " << dp[i][j] << endl;
    }
  }
#endif
  ll ans{mInfty<ll>()};
  if (N % 2 == 1)
  {
    ans = max({dp[N - 1][2], dp[N - 2][1], dp[N - 3][0]});
  }
  else
  {
    ans = max({dp[N - 1][1], dp[N - 2][0]});
  }
  cout << ans << endl;
}
<commit_msg>submit F.cpp to 'F - Select Half' (abc162) [C++ (GCC 9.2.1)]<commit_after>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/23 1:01:45
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

int main()
{
  ll N;
  cin >> N;
  vector<ll> A(N);
  for (auto i{0}; i < N; ++i)
  {
    cin >> A[i];
  }
  vector<vector<ll>> dp(N, vector<ll>(3, mInfty<ll>()));
  dp[0][0] = A[0];
  dp[1][1] = A[1];
  if (N >= 3)
  {
    dp[2][2] = A[2];
  }
  for (auto i{0}; i < N; ++i)
  {
    for (auto j{0}; j < 3; ++j)
    {
      if (dp[i][j] == mInfty<ll>())
      {
        continue;
      }
      for (auto k{0}; k < 3; ++k)
      {
        int ni{i + 2 + k};
        int nj{j + k};
        if (ni < N && nj < 3)
        {
          ch_max(dp[ni][nj], dp[i][j] + A[ni]);
        }
      }
    }
  }
#if DEBUG == 1
  for (auto i{0}; i < N; ++i)
  {
    for (auto j{0}; j < 3; ++j)
    {
      cerr << "dp[" << i << "][" << j << "] = " << dp[i][j] << endl;
    }
  }
#endif
  ll ans{mInfty<ll>()};
  if (N % 2 == 1)
  {
    ans = max({dp[N - 1][2], dp[N - 2][1], dp[N - 3][0]});
  }
  else
  {
    ans = max({dp[N - 1][1], dp[N - 2][0]});
  }
  cout << ans << endl;
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_INTRUSIVE_PTR_BASE
#define TORRENT_INTRUSIVE_PTR_BASE

#include <boost/detail/atomic_count.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	template<class T>
	struct intrusive_ptr_base
	{
		intrusive_ptr_base(const intrusive_ptr_base<T>& b)
			: m_refs(0) {}

		friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s)
		{
			assert(s->m_refs >= 0);
			assert(s != 0);
			++s->m_refs;
		}

		friend void intrusive_ptr_release(intrusive_ptr_base<T> const* s)
		{
			assert(s->m_refs > 0);
			assert(s != 0);
			if (--s->m_refs == 0)
				delete static_cast<T const*>(s);
		}

		int refcount() const { return m_refs; }

		intrusive_ptr_base(): m_refs(0) {}
	private:
		// reference counter for intrusive_ptr
		mutable boost::detail::atomic_count m_refs;
	};

}

#endif

<commit_msg>fixed compile warning<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_INTRUSIVE_PTR_BASE
#define TORRENT_INTRUSIVE_PTR_BASE

#include <boost/detail/atomic_count.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	template<class T>
	struct intrusive_ptr_base
	{
		intrusive_ptr_base(intrusive_ptr_base<T> const&)
			: m_refs(0) {}

		friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s)
		{
			assert(s->m_refs >= 0);
			assert(s != 0);
			++s->m_refs;
		}

		friend void intrusive_ptr_release(intrusive_ptr_base<T> const* s)
		{
			assert(s->m_refs > 0);
			assert(s != 0);
			if (--s->m_refs == 0)
				delete static_cast<T const*>(s);
		}

		int refcount() const { return m_refs; }

		intrusive_ptr_base(): m_refs(0) {}
	private:
		// reference counter for intrusive_ptr
		mutable boost::detail::atomic_count m_refs;
	};

}

#endif

<|endoftext|>


<commit_before>/*
 * integer_sequence.hpp
 *
 *  Created on: Mar 9, 2017
 *      Author: zmij
 */

#ifndef PUSHKIN_META_INTEGER_SEQUENCE_HPP_
#define PUSHKIN_META_INTEGER_SEQUENCE_HPP_

#include <type_traits>
#include <utility>

#include <pushkin/meta/algorithm.hpp>

namespace psst {
namespace meta {

/**
 * Metafunction to join sequences
 */
template < typename ... T >
struct join;

template < typename T >
struct join < T > {
    using type = T;
};

template < typename T, typename U, typename ... V >
struct join< T, U, V... >
    : join< typename join< T, U >::type, V... > {};

#if __cplusplus >= 201402L

template < typename T, T ... A, T... B >
struct join< ::std::integer_sequence<T, A...>, ::std::integer_sequence<T, B...> > {
    using type = ::std::integer_sequence<T, A..., B...>;
};

template <typename T>
struct is_empty<::std::integer_sequence<T>> : ::std::true_type {};
template <typename T, T ... Values>
struct is_empty<::std::integer_sequence<T, Values...>> : ::std::false_type {};

namespace detail {

template < typename T, T Min, T Max, T ... Values >
struct unwrap_range_impl {
    static_assert(Min < Max, "Start of range must be less than ending");
    using type = typename unwrap_range_impl<T, Min, Max - 1, Max, Values ... >::type;
};

template < typename T, T V, T ... Values >
struct unwrap_range_impl<T, V, V, Values...> {
    using type = ::std::integer_sequence< T, V, Values... >;
};

template < typename T, T Min, T Max, T ... Values >
struct reverse_unwrap_range_impl {
    static_assert(Min < Max, "Start of range must be less than ending");
    using type = typename reverse_unwrap_range_impl<T, Min + 1, Max, Min, Values ... >::type;
};

template < typename T, T V, T ... Values >
struct reverse_unwrap_range_impl<T, V, V, Values...> {
    using type = ::std::integer_sequence< T, V, Values... >;
};

const ::std::size_t template_depth = 128;

template < typename T, T Min, T Max >
struct unwrap_range;
template < typename T, T Min, T Max >
struct reverse_unwrap_range;

template < typename T, T Min, T Max >
struct split_range_helper {
    using type = typename join<
            typename unwrap_range_impl<T, Min, Min + template_depth - 1>::type,
            typename unwrap_range<T, Min + template_depth, Max>::type
    >::type;
};

template < typename T, T Min, T Max >
struct unwrap_range :
    ::std::conditional< (Max - Min < template_depth),
         unwrap_range_impl<T, Min, Max>,
         split_range_helper<T, Min, Max>
    >::type {};

template < typename T, T Min, T Max >
struct reverse_split_range_helper {
    using type = typename join<
            typename reverse_unwrap_range<T, Min + template_depth, Max>::type,
            typename reverse_unwrap_range_impl<T, Min, Min + template_depth - 1>::type
    >::type;
};
template < typename T, T Min, T Max >
struct reverse_unwrap_range :
    ::std::conditional< (Max - Min < template_depth),
         reverse_unwrap_range_impl<T, Min, Max>,
         reverse_split_range_helper<T, Min, Max>
    >::type {};

template < typename T, T Min, T Max, bool Reverse >
struct make_integer_sequence_impl : unwrap_range<T, Min, Max> {};

template < typename T, T Min, T Max >
struct make_integer_sequence_impl<T, Min, Max, true> : reverse_unwrap_range<T, Max, Min> {};

} /* namespace detail */

/**
 * Metafunction to make integer sequences in range [Min, Max]
 * If Min > Max, the sequence will be reversed.
 */
template < typename T, T Min, T Max >
struct make_integer_sequence :
    detail::make_integer_sequence_impl<T, Min, Max, (Min > Max )> {};

#endif /* __cplusplus >= 201402L */

} /* namespace meta */
} /* namespace psst */

#endif /* PUSHKIN_META_INTEGER_SEQUENCE_HPP_ */
<commit_msg>Find index if metafunction<commit_after>/*
 * integer_sequence.hpp
 *
 *  Created on: Mar 9, 2017
 *      Author: zmij
 */

#ifndef PUSHKIN_META_INTEGER_SEQUENCE_HPP_
#define PUSHKIN_META_INTEGER_SEQUENCE_HPP_

#include <type_traits>
#include <utility>

#include <pushkin/meta/algorithm.hpp>

namespace psst {
namespace meta {

/**
 * Metafunction to join sequences
 */
template < typename ... T >
struct join;

template < typename T >
struct join < T > {
    using type = T;
};

template < typename T, typename U, typename ... V >
struct join< T, U, V... >
    : join< typename join< T, U >::type, V... > {};

#if __cplusplus >= 201402L

template < typename T, T ... A, T... B >
struct join< ::std::integer_sequence<T, A...>, ::std::integer_sequence<T, B...> > {
    using type = ::std::integer_sequence<T, A..., B...>;
};

template < typename T, T ... A, T B >
struct join< ::std::integer_sequence<T, A...>, ::std::integral_constant<T, B > > {
    using type = ::std::integer_sequence<T, A..., B>;
};

template < typename T, T A, T ...B >
struct join< ::std::integral_constant<T, A>, ::std::integer_sequence<T, B...> > {
    using type = ::std::integer_sequence<T, A, B...>;
};

template <typename T>
struct is_empty<::std::integer_sequence<T>> : ::std::true_type {};
template <typename T, T ... Values>
struct is_empty<::std::integer_sequence<T, Values...>> : ::std::false_type {};

namespace detail {

template < typename T, T Min, T Max, T ... Values >
struct unwrap_range_impl {
    static_assert(Min < Max, "Start of range must be less than ending");
    using type = typename unwrap_range_impl<T, Min, Max - 1, Max, Values ... >::type;
};

template < typename T, T V, T ... Values >
struct unwrap_range_impl<T, V, V, Values...> {
    using type = ::std::integer_sequence< T, V, Values... >;
};

template < typename T, T Min, T Max, T ... Values >
struct reverse_unwrap_range_impl {
    static_assert(Min < Max, "Start of range must be less than ending");
    using type = typename reverse_unwrap_range_impl<T, Min + 1, Max, Min, Values ... >::type;
};

template < typename T, T V, T ... Values >
struct reverse_unwrap_range_impl<T, V, V, Values...> {
    using type = ::std::integer_sequence< T, V, Values... >;
};

const ::std::size_t template_depth = 128;

template < typename T, T Min, T Max >
struct unwrap_range;
template < typename T, T Min, T Max >
struct reverse_unwrap_range;

template < typename T, T Min, T Max >
struct split_range_helper {
    using type = typename join<
            typename unwrap_range_impl<T, Min, Min + template_depth - 1>::type,
            typename unwrap_range<T, Min + template_depth, Max>::type
    >::type;
};

template < typename T, T Min, T Max >
struct unwrap_range :
    ::std::conditional< (Max - Min < template_depth),
         unwrap_range_impl<T, Min, Max>,
         split_range_helper<T, Min, Max>
    >::type {};

template < typename T, T Min, T Max >
struct reverse_split_range_helper {
    using type = typename join<
            typename reverse_unwrap_range<T, Min + template_depth, Max>::type,
            typename reverse_unwrap_range_impl<T, Min, Min + template_depth - 1>::type
    >::type;
};
template < typename T, T Min, T Max >
struct reverse_unwrap_range :
    ::std::conditional< (Max - Min < template_depth),
         reverse_unwrap_range_impl<T, Min, Max>,
         reverse_split_range_helper<T, Min, Max>
    >::type {};

template < typename T, T Min, T Max, bool Reverse >
struct make_integer_sequence_impl : unwrap_range<T, Min, Max> {};

template < typename T, T Min, T Max >
struct make_integer_sequence_impl<T, Min, Max, true> : reverse_unwrap_range<T, Max, Min> {};

} /* namespace detail */

/**
 * Metafunction to make integer sequences in range [Min, Max]
 * If Min > Max, the sequence will be reversed.
 */
template < typename T, T Min, T Max >
struct make_integer_sequence :
    detail::make_integer_sequence_impl<T, Min, Max, (Min > Max )> {};

namespace detail {

template < ::std::size_t Head, template <typename> class Predicate, typename ... T >
struct find_index_if_impl;

template < ::std::size_t Head, template <typename> class Predicate, typename T, typename ...Y >
struct find_index_if_impl<Head, Predicate, T, Y...> :
    ::std::conditional<
            Predicate<T>::value,
            typename join< ::std::integral_constant<::std::size_t, Head>,
                    typename find_index_if_impl<Head + 1, Predicate, Y... >::type >::type,
            typename find_index_if_impl<Head + 1, Predicate, Y...>::type
        > {};

template < ::std::size_t Head, template <typename> class Predicate, typename T >
struct find_index_if_impl<Head, Predicate, T > :
    ::std::conditional<
            Predicate<T>::value,
            ::std::index_sequence<Head>,
            ::std::index_sequence<>
        > {};

} /* namespace detail */

/**
 * Metafunction to build index sequence of types matching predicate
 */
template < template <typename> class Predicate, typename ... T >
struct find_index_if : detail::find_index_if_impl<0, Predicate, T...> {};

template <template <typename> class Predicate>
struct find_index_if<Predicate> {
    using type = ::std::index_sequence<>;
};

#endif /* __cplusplus >= 201402L */

} /* namespace meta */
} /* namespace psst */

#endif /* PUSHKIN_META_INTEGER_SEQUENCE_HPP_ */
<|endoftext|>


<commit_before><commit_msg>EL (orig): general improvments.<commit_after><|endoftext|>


<commit_before>/************************************************************************/
/*                                                                      */
/*        Copyright 2008-2009 by  Ullrich Koethe and Rahul Nair         */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/
#ifndef VIGRA_RANDOM_FOREST_REGION_HXX
#define VIGRA_RANDOM_FOREST_REGION_HXX
#include <algorithm>
#include <map>
#include <numeric>
#include "vigra/mathutil.hxx"
#include "vigra/array_vector.hxx"
#include "vigra/sized_int.hxx"
#include "vigra/matrix.hxx"
#include "vigra/random.hxx"
#include "vigra/functorexpression.hxx"

namespace vigra
{

/** Standard Stackentry used to Build a Tree. Contains Information
 * About the current region being split
 */
template <class Iter>
class DT_StackEntry
{
  public:
    typedef Iter IndexIterator;
    // tree specific stuff
    enum  ParentTag
    {
        DecisionTreeNoParent = -1
    };

    /** Address of left and Right parent in the topology container
     */
    Int32                                   leftParent;
    Int32                                   rightParent;
    /** rule associated with current node
     */
    ArrayVector<std::pair<Int32, double> >  rule;

    // RegionSpecificStuff
    ArrayVector<Int32>                      classCounts_;
    ArrayVector<double>                     weightedClassCounts_;
    bool                                    classCountsIsValid;
    bool                                    weightedClassCountsIsValid;
    IndexIterator                           begin_,  end_;
    int                                     size_;
    IndexIterator                           oob_begin_, oob_end_;
    int                                     oob_size_;

    Int32 depth()
    {
        return rule.size();
    }

    void setRange(IndexIterator s, IndexIterator e)
    {
        begin_      = s;
        end_        = e;
        size_       = e-s;
    }
    void set_oob_range(IndexIterator s, IndexIterator e)
    {
        oob_begin_   = s;
        oob_end_     = e;
        oob_size_       = e-s;
    }

    void reset()
    {
        classCountsIsValid = false;
    }

    bool  isPure()
    {
        int num = 0;

        for(int ii = 0; ii < (int)classCounts().size(); ++ii)
        {
            num += classCounts()[ii] > 0;
        }
        return num <= 1;
    }

    int&  operator[](int i)
    {
        return *(begin_+i);
    }

    IndexIterator & begin()
    {
        return begin_;
    }

    IndexIterator & end()
    {
        return end_;
    }
    IndexIterator & oob_begin()
    {
        return oob_begin_;
    }

    IndexIterator & oob_end()
    {
        return oob_end_;
    }
    ArrayVector<Int32> & classCounts()
    {
        return classCounts_;
    }
    ArrayVector<Int32> & weightedClassCounts()
    {
        return classCounts_;
    }
    bool  classCountsValid(bool u)
    {
        classCountsIsValid = u;
        return classCountsIsValid;

    }

    void classCounts(ArrayVector<Int32> in);

    DT_StackEntry( IndexIterator i, IndexIterator e,
                        int classCount,
                        Int32 lp = DecisionTreeNoParent,
                        Int32 rp = DecisionTreeNoParent)
    :
        leftParent(lp),
        rightParent(rp),
        classCounts_(classCount, 0u),
        classCountsIsValid(false),
        begin_(i),
        end_(e),
        size_(e-i)
    {}

    Int32 size()const
    {
        return size_;
    }

    Int32 oob_size()const
    {
        return oob_size_;
    }

};

}
//namespace vigra

#endif // VIGRA_RANDOM_FOREST_REGION_HXX
<commit_msg>stackentry reset() working<commit_after>/************************************************************************/
/*                                                                      */
/*        Copyright 2008-2009 by  Ullrich Koethe and Rahul Nair         */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/
#ifndef VIGRA_RANDOM_FOREST_REGION_HXX
#define VIGRA_RANDOM_FOREST_REGION_HXX
#include <algorithm>
#include <map>
#include <numeric>
#include "vigra/mathutil.hxx"
#include "vigra/array_vector.hxx"
#include "vigra/sized_int.hxx"
#include "vigra/matrix.hxx"
#include "vigra/random.hxx"
#include "vigra/functorexpression.hxx"

namespace vigra
{

/** Standard Stackentry used to Build a Tree. Contains Information
 * About the current region being split
 */
template <class Iter>
class DT_StackEntry
{
  public:
    typedef Iter IndexIterator;
    // tree specific stuff
    enum  ParentTag
    {
        DecisionTreeNoParent = -1
    };

    /** Address of left and Right parent in the topology container
     */
    Int32                                   leftParent;
    Int32                                   rightParent;
    /** rule associated with current node
     */
    ArrayVector<std::pair<Int32, double> >  rule;

    // RegionSpecificStuff
    ArrayVector<Int32>                      classCounts_;
    ArrayVector<double>                     weightedClassCounts_;
    bool                                    classCountsIsValid;
    bool                                    weightedClassCountsIsValid;
    IndexIterator                           begin_,  end_;
    int                                     size_;
    IndexIterator                           oob_begin_, oob_end_;
    int                                     oob_size_;

    Int32 depth()
    {
        return rule.size();
    }

    void setRange(IndexIterator s, IndexIterator e)
    {
        begin_      = s;
        end_        = e;
        size_       = e-s;
    }
    void set_oob_range(IndexIterator s, IndexIterator e)
    {
        oob_begin_   = s;
        oob_end_     = e;
        oob_size_       = e-s;
    }

    void reset()
    {
        begin_      = end_      = IndexIterator();
        oob_begin_  = oob_end_  = IndexIterator();
        size_       = oob_size_ = 0;
        leftParent  = DecisionTreeNoParent;
        rightParent = DecisionTreeNoParent;
        classCountsIsValid = false;
    }

    bool  isPure()
    {
        int num = 0;

        for(int ii = 0; ii < (int)classCounts().size(); ++ii)
        {
            num += classCounts()[ii] > 0;
        }
        return num <= 1;
    }

    int&  operator[](int i)
    {
        return *(begin_+i);
    }

    IndexIterator & begin()
    {
        return begin_;
    }

    IndexIterator & end()
    {
        return end_;
    }
    IndexIterator & oob_begin()
    {
        return oob_begin_;
    }

    IndexIterator & oob_end()
    {
        return oob_end_;
    }
    ArrayVector<Int32> & classCounts()
    {
        return classCounts_;
    }
    ArrayVector<Int32> & weightedClassCounts()
    {
        return classCounts_;
    }
    bool  classCountsValid(bool u)
    {
        classCountsIsValid = u;
        return classCountsIsValid;

    }

    void classCounts(ArrayVector<Int32> in);

    DT_StackEntry( IndexIterator i, IndexIterator e,
                        int classCount,
                        Int32 lp = DecisionTreeNoParent,
                        Int32 rp = DecisionTreeNoParent)
    :
        leftParent(lp),
        rightParent(rp),
        classCounts_(classCount, 0u),
        classCountsIsValid(false),
        begin_(i),
        end_(e),
        size_(e-i)
    {}

    Int32 size()const
    {
        return size_;
    }

    Int32 oob_size()const
    {
        return oob_size_;
    }

};

}
//namespace vigra

#endif // VIGRA_RANDOM_FOREST_REGION_HXX
<|endoftext|>


<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#pragma once

#ifndef VSNRAY_DETAIL_PATHTRACING_INL
#define VSNRAY_DETAIL_PATHTRACING_INL 1

#ifndef NDEBUG
#include <iostream>
#include <ostream>
#endif

#include <visionaray/get_surface.h>
#include <visionaray/result_record.h>
#include <visionaray/traverse.h>

namespace visionaray
{
namespace pathtracing
{

template <typename Params>
struct kernel
{

    Params params;

    template <typename Intersector, typename R, typename Generator>
    VSNRAY_FUNC result_record<typename R::scalar_type> operator()(
            Intersector& isect,
            R ray,
            Generator& gen
            ) const
    {
        using S = typename R::scalar_type;
        using I = simd::int_type_t<S>;
        using V = typename result_record<S>::vec_type;
        using C = spectrum<S>;

        simd::mask_type_t<S> active_rays = true;

        C dst(1.0);

        result_record<S> result;
        result.color = params.bg_color;

        for (unsigned bounce = 0; bounce < params.num_bounces; ++bounce)
        {
            auto hit_rec = closest_hit(ray, params.prims.begin, params.prims.end, isect);

            // Handle rays that just exited
            auto exited = active_rays & !hit_rec.hit;
            dst = mul( dst, C(from_rgba(params.ambient_color)), exited, dst );

            // Exit if no ray is active anymore
            active_rays &= hit_rec.hit;

            if (!any(active_rays))
            {
                break;
            }

            // Special handling for first bounce
            if (bounce == 0)
            {
                result.hit = hit_rec.hit;
                result.isect_pos = ray.ori + ray.dir * hit_rec.t;
            }

            // Process the current bounce

            V refl_dir;
            V view_dir = -ray.dir;

            hit_rec.isect_pos = ray.ori + ray.dir * hit_rec.t;

            auto surf = get_surface(hit_rec, params);

            S pdf(0.0);
            I inter = 0;

            auto src = surf.sample(view_dir, refl_dir, pdf, inter, gen);

            auto zero_pdf = pdf <= S(0.0);
            auto emissive = has_emissive_material(surf);

            dst = mul( dst, src, active_rays && !zero_pdf, dst );
            dst = select( zero_pdf && active_rays, C(0.0), dst );

            active_rays &= !emissive;
            active_rays &= !zero_pdf;

            if (!any(active_rays))
            {
                break;
            }

            ray.ori = hit_rec.isect_pos + refl_dir * S(params.epsilon);
            ray.dir = refl_dir;
        }

        // Terminate paths that are still active
        dst = select(active_rays, C(0.0), dst);

        result.color = select( result.hit, to_rgba(dst), result.color );

        return result;
    }

    template <typename R, typename Generator>
    VSNRAY_FUNC result_record<typename R::scalar_type> operator()(
            R ray,
            Generator& gen
            ) const
    {
        default_intersector ignore;
        return (*this)(ignore, ray, gen);
    }
};

} // pathtracing
} // visionaray

#endif // VSNRAY_DETAIL_PATHTRACING_INL
<commit_msg>Use surface_interaction flag to check for emission<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#pragma once

#ifndef VSNRAY_DETAIL_PATHTRACING_INL
#define VSNRAY_DETAIL_PATHTRACING_INL 1

#ifndef NDEBUG
#include <iostream>
#include <ostream>
#endif

#include <visionaray/get_surface.h>
#include <visionaray/result_record.h>
#include <visionaray/surface_interaction.h>
#include <visionaray/traverse.h>

namespace visionaray
{
namespace pathtracing
{

template <typename Params>
struct kernel
{

    Params params;

    template <typename Intersector, typename R, typename Generator>
    VSNRAY_FUNC result_record<typename R::scalar_type> operator()(
            Intersector& isect,
            R ray,
            Generator& gen
            ) const
    {
        using S = typename R::scalar_type;
        using I = simd::int_type_t<S>;
        using V = typename result_record<S>::vec_type;
        using C = spectrum<S>;

        simd::mask_type_t<S> active_rays = true;

        C dst(1.0);

        result_record<S> result;
        result.color = params.bg_color;

        for (unsigned bounce = 0; bounce < params.num_bounces; ++bounce)
        {
            auto hit_rec = closest_hit(ray, params.prims.begin, params.prims.end, isect);

            // Handle rays that just exited
            auto exited = active_rays & !hit_rec.hit;
            dst = mul( dst, C(from_rgba(params.ambient_color)), exited, dst );

            // Exit if no ray is active anymore
            active_rays &= hit_rec.hit;

            if (!any(active_rays))
            {
                break;
            }

            // Special handling for first bounce
            if (bounce == 0)
            {
                result.hit = hit_rec.hit;
                result.isect_pos = ray.ori + ray.dir * hit_rec.t;
            }

            // Process the current bounce

            V refl_dir;
            V view_dir = -ray.dir;

            hit_rec.isect_pos = ray.ori + ray.dir * hit_rec.t;

            auto surf = get_surface(hit_rec, params);

            S pdf(0.0);
            I inter = 0;

            auto src = surf.sample(view_dir, refl_dir, pdf, inter, gen);

            auto zero_pdf = pdf <= S(0.0);
            auto emissive = inter == I(surface_interaction::Emission);

            dst = mul( dst, src, active_rays && !zero_pdf, dst );
            dst = select( zero_pdf && active_rays, C(0.0), dst );

            active_rays &= !emissive;
            active_rays &= !zero_pdf;

            if (!any(active_rays))
            {
                break;
            }

            ray.ori = hit_rec.isect_pos + refl_dir * S(params.epsilon);
            ray.dir = refl_dir;
        }

        // Terminate paths that are still active
        dst = select(active_rays, C(0.0), dst);

        result.color = select( result.hit, to_rgba(dst), result.color );

        return result;
    }

    template <typename R, typename Generator>
    VSNRAY_FUNC result_record<typename R::scalar_type> operator()(
            R ray,
            Generator& gen
            ) const
    {
        default_intersector ignore;
        return (*this)(ignore, ray, gen);
    }
};

} // pathtracing
} // visionaray

#endif // VSNRAY_DETAIL_PATHTRACING_INL
<|endoftext|>


<commit_before>/**
 * ValueBase.hpp -
 * @author: Jonathan Beard
 * @version: Tue Dec 10 08:34:09 2013
 */
#ifndef _VALUEBASE_HPP_
#define _VALUEBASE_HPP_  1

#include "NodeAbstract.hpp"
namespace Node{
class ValueBase : public NodeAbstract {
public:
   ValueBase() = default;
   virtual ~ValueBase() = default;

   virtual bool get_value( const char *typeName, void *ptr ) = 0;
};
} /* end namespace Node */
#endif /* END _VALUEBASE_HPP_ */
<commit_msg>updates<commit_after>/**
 * ValueBase.hpp -
 * @author: Jonathan Beard
 * @version: Tue Dec 10 08:34:09 2013
 */
#ifndef _VALUEBASE_HPP_
#define _VALUEBASE_HPP_  1

#include "NodeAbstract.hpp"
namespace Node{
class ValueBase : public NodeAbstract {
public:
   ValueBase() = default;
   virtual ~ValueBase() = default;

   /**
    * get_value - To get a value that this object was constructed
    * with, pass an initialized ptr (initialized with the proper
    * length for that data type)
    */
   virtual bool get_value( const char *typeName, void *ptr ) = 0;
};
} /* end namespace Node */
#endif /* END _VALUEBASE_HPP_ */
<|endoftext|>


<commit_before>/*
	Conrad 'Condzi' Kubacki 2017
	https://github.com/condzi
*/

#include <SFML/Graphics.hpp>

sf::Font font;
sf::RenderWindow window;
sf::Event event;

sf::Text sampleText;
sf::RectangleShape testRectangle;

void init();
void workInit();
void pollEvent();
void workUpdate();
void workDraw();
void draw();

int main()
{
	init();
	workInit();

	while ( window.isOpen() )
	{
		pollEvent();
		workUpdate();
		draw();
	}
}

void init()
{
	window.create( { 800,600 }, "" );

	font.loadFromFile( "consolas.ttf" );
}

void workInit()
{
	sampleText.setFont( font );
	sampleText.setString( "abc_ABC-321\nhello!\nWARNING?\nError?" );
	sampleText.setPosition( 100, 100 );
	sampleText.setFillColor( sf::Color::Red );
	sampleText.setCharacterSize( 100 );

	// magic offset ??
	testRectangle.setPosition( sampleText.getPosition().x, sampleText.getPosition().y + ( sampleText.getCharacterSize() * 15.3f ) / 50.0f );
	//testRectangle.setSize( GetLocalSize( sampleText ) );
	testRectangle.setSize( { sampleText.getGlobalBounds().width, sampleText.getGlobalBounds().height } );
}

void pollEvent()
{
	while ( window.pollEvent( event ) )
		if ( event.type == sf::Event::Closed )
			window.close();
}

void workUpdate()
{

}

void workDraw()
{
	window.draw( testRectangle );
	window.draw( sampleText );
}

void draw()
{
	window.clear();
	workDraw();
	window.display();
}
<commit_msg>add offset for x axis<commit_after>/*
	Conrad 'Condzi' Kubacki 2017
	https://github.com/condzi
*/

#include <SFML/Graphics.hpp>

sf::Font font;
sf::RenderWindow window;
sf::Event event;

sf::Text sampleText;
sf::RectangleShape testRectangle;

void init();
void workInit();
void pollEvent();
void workUpdate();
void workDraw();
void draw();

int main()
{
	init();
	workInit();

	while ( window.isOpen() )
	{
		pollEvent();
		workUpdate();
		draw();
	}
}

void init()
{
	window.create( { 800,600 }, "" );

	font.loadFromFile( "consolas.ttf" );
}

void workInit()
{
	sampleText.setFont( font );
	sampleText.setString( "abc_ABC-321" );
	sampleText.setPosition( 100, 100 );
	sampleText.setFillColor( sf::Color::Red );
	sampleText.setCharacterSize( 50 );

	// magic offset ??
	testRectangle.setPosition( sampleText.getPosition().x + ( sampleText.getCharacterSize() * 3 ) / 50.0f, sampleText.getPosition().y + ( sampleText.getCharacterSize() * 15.3f ) / 50.0f );
	//testRectangle.setSize( GetLocalSize( sampleText ) );
	testRectangle.setSize( { sampleText.getGlobalBounds().width, sampleText.getGlobalBounds().height } );
}

void pollEvent()
{
	while ( window.pollEvent( event ) )
		if ( event.type == sf::Event::Closed )
			window.close();
}

void workUpdate()
{

}

void workDraw()
{
	window.draw( testRectangle );
	window.draw( sampleText );
}

void draw()
{
	window.clear();
	workDraw();
	window.display();
}
<|endoftext|>