<commit_before>#include <glib.h>
#include <nan.h>

#include "closure.h"
#include "macros.h"
#include "loop.h"
#include "type.h"
#include "value.h"

using v8::Context;
using v8::Function;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::Value;
using Nan::Persistent;

namespace GNodeJS {

GClosure *Closure::New(Local<Function> function) {
    Closure *closure = (Closure *) g_closure_new_simple (sizeof (*closure), NULL);
    closure->persistent.Reset(function);
    GClosure *gclosure = &closure->base;
    g_closure_set_marshal (gclosure, Closure::Marshal);
    g_closure_add_invalidate_notifier (gclosure, NULL, Closure::Invalidated);
    return gclosure;
}

void Closure::Execute(const Nan::Persistent<v8::Function>& persFn, GValue *g_return_value, uint n_param_values, const GValue *param_values) {
    Nan::HandleScope scope;
    auto fn = Nan::New<Function>(persFn);

    uint n_js_args = n_param_values - 1;
    #ifndef __linux__
        Local<Value>* js_args = new Local<Value>[n_js_args];
    #else
        Local<Value> js_args[n_js_args];
    #endif

    for (uint i = 1; i < n_js_args; i++) {
        bool mustCopy = true; // TODO: get information about mustCopy
        js_args[i] = GValueToV8(&param_values[i], mustCopy);
    }

    Local<Object> self = fn;
    Local<Value> return_value;

    Nan::TryCatch try_catch;

    auto result = Nan::Call(fn, self, n_js_args, js_args);

    if (!try_catch.HasCaught()
            && result.ToLocal(&return_value)) {
        if (g_return_value) {
            if (G_VALUE_TYPE(g_return_value) == G_TYPE_INVALID)
                WARN ("Marshal: return value has invalid g_type");
            else if (!V8ToGValue (g_return_value, return_value, true))
                WARN ("Marshal: could not convert return value");
        }
        CallMicrotaskHandlers();
    }
    else {
        GNodeJS::QuitLoopStack();
        Nan::FatalException(try_catch);
    }

    #ifndef __linux__
        delete[] js_args;
    #endif
}

void Closure::Marshal(GClosure     *base,
                      GValue       *g_return_value,
                      uint          n_param_values,
                      const GValue *param_values,
                      gpointer      invocation_hint,
                      gpointer      marshal_data) {

    auto closure = (Closure *) base;

    AsyncCallEnvironment* env = reinterpret_cast<AsyncCallEnvironment *>(Closure::asyncHandle.data);
    uv_thread_t thread = uv_thread_self();

    /* Case 1: same thread */
    if (uv_thread_equal(&thread, &env->mainThread)) {
        Closure::Execute(closure->persistent, g_return_value, n_param_values, param_values);
        return;
    }

    /* Case 2: different thread */
    CallbackWrapper cb = CallbackWrapper();
    cb.Prepare(&closure->persistent, g_return_value, n_param_values, param_values);

    uv_mutex_lock(&env->mutex);
    env->queue.push(&cb);
    uv_mutex_unlock(&env->mutex);
    uv_async_send(&Closure::asyncHandle);

    cb.Wait();
}

void Closure::Invalidated (gpointer data, GClosure *base) {
    Closure *closure = (Closure *) base;
    closure->~Closure();
}

// locking and signalling adapted from https://github.com/node-ffi-napi/node-ffi-napi
uv_async_t Closure::asyncHandle;

void Closure::QueueHandler(uv_async_t* handle) {
    AsyncCallEnvironment* data = reinterpret_cast<AsyncCallEnvironment *>(handle->data);
    uv_mutex_lock(&data->mutex);

    while (!data->queue.empty()) {
        CallbackWrapper* cb = data->queue.front();
        cb->Execute();
        data->queue.pop();
    }

    uv_mutex_unlock(&data->mutex);
}

void Closure::Initialize() {
    auto& handle = Closure::asyncHandle;
    AsyncCallEnvironment* env = new AsyncCallEnvironment();
    handle.data = env;
    env->mainThread = uv_thread_self();
    uv_loop_t* loop = uv_default_loop();
    uv_async_init(loop, &handle, Closure::QueueHandler);
    uv_mutex_init(&env->mutex);
    uv_unref(reinterpret_cast<uv_handle_t *>(&handle));
    uv_async_send(&handle);
}

CallbackWrapper::CallbackWrapper() {
    uv_mutex_init(&mutex);
    uv_mutex_lock(&mutex);
    uv_cond_init(&cond);
}

CallbackWrapper::~CallbackWrapper() {
    uv_mutex_unlock(&mutex);
    uv_cond_destroy(&cond);
    uv_mutex_destroy(&mutex);
}

void CallbackWrapper::Execute() {
    Closure::Execute(*persistent, returnValue, nValues, values);
    Done();
}
void CallbackWrapper::Prepare(const Nan::Persistent<v8::Function>* persistentIn, GValue* returnValueIn, uint nValuesIn, const GValue* valuesIn) {
    // copy values
    persistent = persistentIn;
    returnValue = returnValueIn;
    nValues = nValuesIn;
    values = new GValue[nValues];
    for (uint i = 0; i < nValues; ++i) {
        values[i] = G_VALUE_INIT;
        g_value_init(&values[i], G_VALUE_TYPE(&valuesIn[i]));
        g_value_copy(&valuesIn[i], &values[i]);
    }
}

void CallbackWrapper::Done() {
    uv_mutex_lock(&mutex);
    uv_cond_signal(&cond);
    uv_mutex_unlock(&mutex);
}
void CallbackWrapper::Wait() {
    uv_cond_wait(&cond, &mutex);
}

};
<commit_msg>Fix counter when stripping first argument<commit_after>#include <glib.h>
#include <nan.h>

#include "closure.h"
#include "macros.h"
#include "loop.h"
#include "type.h"
#include "value.h"

using v8::Context;
using v8::Function;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::Value;
using Nan::Persistent;

namespace GNodeJS {

GClosure *Closure::New(Local<Function> function) {
    Closure *closure = (Closure *) g_closure_new_simple (sizeof (*closure), NULL);
    closure->persistent.Reset(function);
    GClosure *gclosure = &closure->base;
    g_closure_set_marshal (gclosure, Closure::Marshal);
    g_closure_add_invalidate_notifier (gclosure, NULL, Closure::Invalidated);
    return gclosure;
}

void Closure::Execute(const Nan::Persistent<v8::Function>& persFn, GValue *g_return_value, uint n_param_values, const GValue *param_values) {
    Nan::HandleScope scope;
    auto fn = Nan::New<Function>(persFn);

    uint n_js_args = n_param_values - 1;
    #ifndef __linux__
        Local<Value>* js_args = new Local<Value>[n_js_args];
    #else
        Local<Value> js_args[n_js_args];
    #endif

    for (uint i = 0; i < n_js_args; i++) {
        bool mustCopy = true; // TODO: get information about mustCopy
        js_args[i] = GValueToV8(&param_values[i + 1], mustCopy);
    }

    Local<Object> self = fn;
    Local<Value> return_value;

    Nan::TryCatch try_catch;

    auto result = Nan::Call(fn, self, n_js_args, js_args);

    if (!try_catch.HasCaught()
            && result.ToLocal(&return_value)) {
        if (g_return_value) {
            if (G_VALUE_TYPE(g_return_value) == G_TYPE_INVALID)
                WARN ("Marshal: return value has invalid g_type");
            else if (!V8ToGValue (g_return_value, return_value, true))
                WARN ("Marshal: could not convert return value");
        }
        CallMicrotaskHandlers();
    }
    else {
        GNodeJS::QuitLoopStack();
        Nan::FatalException(try_catch);
    }

    #ifndef __linux__
        delete[] js_args;
    #endif
}

void Closure::Marshal(GClosure     *base,
                      GValue       *g_return_value,
                      uint          n_param_values,
                      const GValue *param_values,
                      gpointer      invocation_hint,
                      gpointer      marshal_data) {

    auto closure = (Closure *) base;

    AsyncCallEnvironment* env = reinterpret_cast<AsyncCallEnvironment *>(Closure::asyncHandle.data);
    uv_thread_t thread = uv_thread_self();

    /* Case 1: same thread */
    if (uv_thread_equal(&thread, &env->mainThread)) {
        Closure::Execute(closure->persistent, g_return_value, n_param_values, param_values);
        return;
    }

    /* Case 2: different thread */
    CallbackWrapper cb = CallbackWrapper();
    cb.Prepare(&closure->persistent, g_return_value, n_param_values, param_values);

    uv_mutex_lock(&env->mutex);
    env->queue.push(&cb);
    uv_mutex_unlock(&env->mutex);
    uv_async_send(&Closure::asyncHandle);

    cb.Wait();
}

void Closure::Invalidated (gpointer data, GClosure *base) {
    Closure *closure = (Closure *) base;
    closure->~Closure();
}

// locking and signalling adapted from https://github.com/node-ffi-napi/node-ffi-napi
uv_async_t Closure::asyncHandle;

void Closure::QueueHandler(uv_async_t* handle) {
    AsyncCallEnvironment* data = reinterpret_cast<AsyncCallEnvironment *>(handle->data);
    uv_mutex_lock(&data->mutex);

    while (!data->queue.empty()) {
        CallbackWrapper* cb = data->queue.front();
        cb->Execute();
        data->queue.pop();
    }

    uv_mutex_unlock(&data->mutex);
}

void Closure::Initialize() {
    auto& handle = Closure::asyncHandle;
    AsyncCallEnvironment* env = new AsyncCallEnvironment();
    handle.data = env;
    env->mainThread = uv_thread_self();
    uv_loop_t* loop = uv_default_loop();
    uv_async_init(loop, &handle, Closure::QueueHandler);
    uv_mutex_init(&env->mutex);
    uv_unref(reinterpret_cast<uv_handle_t *>(&handle));
    uv_async_send(&handle);
}

CallbackWrapper::CallbackWrapper() {
    uv_mutex_init(&mutex);
    uv_mutex_lock(&mutex);
    uv_cond_init(&cond);
}

CallbackWrapper::~CallbackWrapper() {
    uv_mutex_unlock(&mutex);
    uv_cond_destroy(&cond);
    uv_mutex_destroy(&mutex);
}

void CallbackWrapper::Execute() {
    Closure::Execute(*persistent, returnValue, nValues, values);
    Done();
}
void CallbackWrapper::Prepare(const Nan::Persistent<v8::Function>* persistentIn, GValue* returnValueIn, uint nValuesIn, const GValue* valuesIn) {
    // copy values
    persistent = persistentIn;
    returnValue = returnValueIn;
    nValues = nValuesIn;
    values = new GValue[nValues];
    for (uint i = 0; i < nValues; ++i) {
        values[i] = G_VALUE_INIT;
        g_value_init(&values[i], G_VALUE_TYPE(&valuesIn[i]));
        g_value_copy(&valuesIn[i], &values[i]);
    }
}

void CallbackWrapper::Done() {
    uv_mutex_lock(&mutex);
    uv_cond_signal(&cond);
    uv_mutex_unlock(&mutex);
}
void CallbackWrapper::Wait() {
    uv_cond_wait(&cond, &mutex);
}

};
<|endoftext|>


<commit_before>/*
 * The MIT License
 *
 * Copyright 2017-2018 Norwegian University of Technology
 *
 * 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 FMI4CPP_ODEINTSOLVER_HPP
#define FMI4CPP_ODEINTSOLVER_HPP

#if FMI4CPP_WITH_ODEINT

#include <boost/numeric/odeint.hpp>

#include "ModelExchangeSolver.hpp"

using namespace boost::numeric::odeint;

namespace fmi4cpp::solver {

    template <class T>
    class OdeintModelExchangeSolver: public ModelExchangeSolver {

    protected:

        T solver_;

    };

    template <class T>
    class ConstantStepSizeOdeintSolver: public OdeintModelExchangeSolver<T> {

    protected:

        double stepSize_;

    public:

        explicit ConstantStepSizeOdeintSolver(double stepSize): stepSize_(stepSize) {}

        double integrate(FmuWrapper &wrapper, state_type &x, double tStart, double tStop) override {
            size_t n = integrate_const(this->solver_, wrapper, x, tStart, tStop, stepSize_);
            return tStart + n*stepSize_;
        }

    };

    typedef ConstantStepSizeOdeintSolver<euler<state_type>> EulerSolver;
    typedef ConstantStepSizeOdeintSolver<implicit_euler<state_type>> ImplicitEulerSolver;

    typedef ConstantStepSizeOdeintSolver<runge_kutta4<state_type>> RK4Solver;
    typedef ConstantStepSizeOdeintSolver<runge_kutta4_classic<state_type>> RK4ClassicSolver;

}

#endif

#endif //FMI4CPP_ODEINTSOLVER_HPP
<commit_msg>include only what we need from boost-odeint<commit_after>/*
 * The MIT License
 *
 * Copyright 2017-2018 Norwegian University of Technology
 *
 * 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 FMI4CPP_ODEINTSOLVER_HPP
#define FMI4CPP_ODEINTSOLVER_HPP

#include <boost/numeric/odeint/stepper/euler.hpp>
#include <boost/numeric/odeint/stepper/implicit_euler.hpp>

#include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
#include <boost/numeric/odeint/stepper/runge_kutta4_classic.hpp>

#include <boost/numeric/odeint/integrate/integrate_const.hpp>

#include "ModelExchangeSolver.hpp"

using namespace boost::numeric::odeint;

namespace fmi4cpp::solver {

    template <class T>
    class OdeintModelExchangeSolver: public ModelExchangeSolver {

    protected:

        T solver_;

    };

    template <class T>
    class ConstantStepSizeOdeintSolver: public OdeintModelExchangeSolver<T> {

    protected:

        double stepSize_;

    public:

        explicit ConstantStepSizeOdeintSolver(double stepSize): stepSize_(stepSize) {}

        double integrate(FmuWrapper &wrapper, state_type &x, double tStart, double tStop) override {
            size_t n = integrate_const(this->solver_, wrapper, x, tStart, tStop, stepSize_);
            return tStart + n*stepSize_;
        }

    };

    typedef ConstantStepSizeOdeintSolver<euler<state_type>> EulerSolver;
    typedef ConstantStepSizeOdeintSolver<implicit_euler<state_type>> ImplicitEulerSolver;

    typedef ConstantStepSizeOdeintSolver<runge_kutta4<state_type>> RK4Solver;
    typedef ConstantStepSizeOdeintSolver<runge_kutta4_classic<state_type>> RK4ClassicSolver;

}

#endif //FMI4CPP_ODEINTSOLVER_HPP
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: CurrentMasterPagesSelector.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 06:38:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "CurrentMasterPagesSelector.hxx"
#include "MasterPagesSelectorListener.hxx"
#include "PreviewValueSet.hxx"
#include "drawdoc.hxx"
#include "sdpage.hxx"
#include "MasterPageContainer.hxx"
#include "app.hrc"

#include <vcl/image.hxx>
#include <svx/svdmodel.hxx>

#include <set>

using namespace ::com::sun::star;

namespace sd { namespace toolpanel { namespace controls {

CurrentMasterPagesSelector::CurrentMasterPagesSelector (
    TreeNode* pParent,
    SdDrawDocument& rDocument,
    ViewShellBase& rBase,
    DrawViewShell& rViewShell)
    : MasterPagesSelector (pParent, rDocument, rBase),
      mxListener(NULL)
{
    SetName(String(RTL_CONSTASCII_USTRINGPARAM("CurrentMasterPagesSelector")));

    // For this master page selector only we change the default action for
    // left clicks.
    mnDefaultClickAction = SID_TP_APPLY_TO_SELECTED_SLIDES;
}

CurrentMasterPagesSelector::~CurrentMasterPagesSelector (void)
{
    if (mxListener.is())
    {
        mxListener->dispose();
        mxListener = NULL;
    }
}

void CurrentMasterPagesSelector::LateInit (void)
{
    MasterPagesSelector::LateInit ();
    Fill ();
    // The selection listener is reference counted and thus takes care
    // of its own lifetime.
    mxListener = uno::Reference<lang::XComponent>(
        static_cast<uno::XWeak*>(
            new MasterPagesSelectorListener (mrBase, *this)),
        uno::UNO_QUERY);
}

void CurrentMasterPagesSelector::Fill (void)
{
    Clear();

    USHORT nPageCount = mrDocument.GetMasterSdPageCount(PK_STANDARD);
    SdPage* pMasterPage;
    // Remember the names of the master pages that have been inserted to
    // avoid double insertion.
    ::std::set<String> aMasterPageNames;
    for (USHORT nIndex=0; nIndex<nPageCount; nIndex++)
    {
        pMasterPage = mrDocument.GetMasterSdPage (nIndex, PK_STANDARD);
        if (pMasterPage != NULL)
        {
            String sName (pMasterPage->GetName());
            if (aMasterPageNames.find(sName)==aMasterPageNames.end())
            {
                aMasterPageNames.insert (sName);

                int nIndex = mpPageSet->GetItemCount() + 1;

                Image aPreview = MasterPageContainer::Instance().GetPreviewForPage (
                    pMasterPage,
                    mnPreviewWidth);
                mpPageSet->InsertItem (
                    nIndex,
                    aPreview,
                    pMasterPage->GetName());
                mpPageSet->SetItemData (
                    nIndex,
                    pMasterPage);
            }
        }
    }
    GetParentNode()->RequestResize();
}

void CurrentMasterPagesSelector::Clear (void)
{
    mpPageSet->Clear ();
}

void CurrentMasterPagesSelector::UpdateAllPreviews (void)
{
    SdPage* pMasterPage;
    for (USHORT nIndex=1; nIndex<=mpPageSet->GetItemCount(); nIndex++)
    {
        pMasterPage = reinterpret_cast<SdPage*>(mpPageSet->GetItemData(nIndex));
        if (pMasterPage != NULL)
            mpPageSet->SetItemImage (nIndex,
                MasterPageContainer::Instance().GetPreviewForPage (
                    pMasterPage,
                    mnPreviewWidth));
    }
    GetParentNode()->RequestResize();
}

void CurrentMasterPagesSelector::UpdatePreview (USHORT nIndex)
{
    SdPage* pMasterPage = reinterpret_cast<SdPage*>(mpPageSet->GetItemData(nIndex));
    if (pMasterPage != NULL)
        mpPageSet->SetItemImage (nIndex,
            MasterPageContainer::Instance().GetPreviewForPage (
                pMasterPage,
                mnPreviewWidth));
    GetParentNode()->RequestResize();
}

void CurrentMasterPagesSelector::InvalidatePreview (const SdPage* pPage)
{
    for (USHORT nIndex=1; nIndex<=mpPageSet->GetItemCount(); nIndex++)
    {
        if (pPage == reinterpret_cast<SdPage*>(mpPageSet->GetItemData(nIndex)))
        {
            MasterPagesSelector::InvalidatePreview(nIndex);
            break;
        }
    }
}

SdPage* CurrentMasterPagesSelector::GetSelectedMasterPage (void)
{
    USHORT nIndex = mpPageSet->GetSelectItemId();
    SdPage* pMasterPage = reinterpret_cast<SdPage*>(mpPageSet->GetItemData (nIndex));
    return pMasterPage;
}

void CurrentMasterPagesSelector::UpdateSelection (void)
{
    // Iterate over all pages and for the selected ones put the name of
    // their master page into a set.
    USHORT nPageCount = mrDocument.GetSdPageCount(PK_STANDARD);
    SdPage* pPage;
    ::std::set<String> aNames;
    USHORT nIndex;
    for (nIndex=0; nIndex<nPageCount; nIndex++)
    {
        pPage = mrDocument.GetSdPage (nIndex, PK_STANDARD);
        if (pPage != NULL && pPage->IsSelected())
        {
            SdrPage& rMasterPage (pPage->TRG_GetMasterPage());
            SdPage* pMasterPage = static_cast<SdPage*>(&rMasterPage);
            if (pMasterPage != NULL)
                aNames.insert (pMasterPage->GetName());
        }
    }

    // Find the items for the master pages in the set.
    USHORT nItemCount (mpPageSet->GetItemCount());
    for (nIndex=1; nIndex<=nItemCount; nIndex++)
    {
        String sName (mpPageSet->GetItemText (nIndex));
        if (aNames.find(sName) != aNames.end())
        {
            mpPageSet->SelectItem (nIndex);
        }
    }
}

} } } // end of namespace ::sd::toolpanel::controls
<commit_msg>INTEGRATION: CWS taskpane (1.5.116); FILE MERGED 2006/04/21 11:11:36 af 1.5.116.6: #i61115# Adaption to modified PutMasterPage() signature. 2006/04/18 15:28:05 af 1.5.116.5: #i61115# Fixed a typo. 2006/04/12 15:18:18 af 1.5.116.4: #i61359# Fixed some compiler problems. 2006/03/24 12:09:50 af 1.5.116.3: #i61115# Reorganization of accessing the valueset. 2006/02/22 09:43:37 af 1.5.116.2: #i61359# Using EventMultiplexer instead of MasterPagesSelectorListener. 2006/02/17 13:13:13 af 1.5.116.1: #i61359# Major restructuring of MasterPageContainer and MasterPagesSelector.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: CurrentMasterPagesSelector.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2006-04-26 20:47:25 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "CurrentMasterPagesSelector.hxx"
#include "PreviewValueSet.hxx"
#include "ViewShellBase.hxx"
#include "drawdoc.hxx"
#include "sdpage.hxx"
#include "MasterPageContainer.hxx"
#include "MasterPageDescriptor.hxx"
#include "EventMultiplexer.hxx"
#include "app.hrc"

#include <vcl/image.hxx>
#include <svx/svdmodel.hxx>

#include <set>

using namespace ::com::sun::star;

namespace sd { namespace toolpanel { namespace controls {

CurrentMasterPagesSelector::CurrentMasterPagesSelector (
    TreeNode* pParent,
    SdDrawDocument& rDocument,
    ViewShellBase& rBase,
    DrawViewShell& rViewShell,
    const ::boost::shared_ptr<MasterPageContainer>& rpContainer)
    : MasterPagesSelector (pParent, rDocument, rBase, rpContainer)
{
    SetName(String(RTL_CONSTASCII_USTRINGPARAM("CurrentMasterPagesSelector")));

    // For this master page selector only we change the default action for
    // left clicks.
    mnDefaultClickAction = SID_TP_APPLY_TO_SELECTED_SLIDES;

    Link aLink (LINK(this,CurrentMasterPagesSelector,EventMultiplexerListener));
    rBase.GetEventMultiplexer().AddEventListener(aLink,
        sd::tools::EventMultiplexerEvent::EID_CURRENT_PAGE
        | sd::tools::EventMultiplexerEvent::EID_EDIT_MODE
        | sd::tools::EventMultiplexerEvent::EID_PAGE_ORDER
        | sd::tools::EventMultiplexerEvent::EID_SHAPE_CHANGED
        | sd::tools::EventMultiplexerEvent::EID_SHAPE_INSERTED
        | sd::tools::EventMultiplexerEvent::EID_SHAPE_REMOVED);

}

CurrentMasterPagesSelector::~CurrentMasterPagesSelector (void)
{
    Link aLink (LINK(this,CurrentMasterPagesSelector,EventMultiplexerListener));
    mrBase.GetEventMultiplexer().RemoveEventListener(aLink);
}

void CurrentMasterPagesSelector::LateInit (void)
{
    MasterPagesSelector::LateInit();
    MasterPagesSelector::Fill();
}

void CurrentMasterPagesSelector::Fill (ItemList& rItemList)
{
    USHORT nPageCount = mrDocument.GetMasterSdPageCount(PK_STANDARD);
    SdPage* pMasterPage;
    // Remember the names of the master pages that have been inserted to
    // avoid double insertion.
    ::std::set<String> aMasterPageNames;
    for (USHORT nIndex=0; nIndex<nPageCount; nIndex++)
    {
        pMasterPage = mrDocument.GetMasterSdPage (nIndex, PK_STANDARD);
        if (pMasterPage == NULL)
            continue;

        // Use the name of the master page to avoid duplicate entries.
        String sName (pMasterPage->GetName());
        if (aMasterPageNames.find(sName)!=aMasterPageNames.end())
            continue;
        aMasterPageNames.insert (sName);

        // Look up the master page in the container and, when it is not yet
        // in it, insert it.
        MasterPageContainer::Token aToken = mpContainer->GetTokenForPageObject(pMasterPage);
        if (aToken == MasterPageContainer::NIL_TOKEN)
        {
            SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor(
                MasterPageContainer::MASTERPAGE,
                nIndex,
                String(),
                pMasterPage->GetName(),
                String(),
                ::boost::shared_ptr<PageObjectProvider>(new ExistingPageProvider(pMasterPage)),
                ::boost::shared_ptr<PreviewProvider>(new PagePreviewProvider())));
            aToken = mpContainer->PutMasterPage(pDescriptor);
        }

        rItemList.push_back(aToken);
    }
}

SdPage* CurrentMasterPagesSelector::GetSelectedMasterPage (void)
{
    USHORT nIndex = mpPageSet->GetSelectItemId();
    UserData* pData = GetUserData(nIndex);
    if (pData != NULL)
        return mpContainer->GetPageObjectForToken(pData->second);
    else
        return NULL;
}

void CurrentMasterPagesSelector::UpdateSelection (void)
{
    // Iterate over all pages and for the selected ones put the name of
    // their master page into a set.
    USHORT nPageCount = mrDocument.GetSdPageCount(PK_STANDARD);
    SdPage* pPage;
    ::std::set<String> aNames;
    USHORT nIndex;
    for (nIndex=0; nIndex<nPageCount; nIndex++)
    {
        pPage = mrDocument.GetSdPage (nIndex, PK_STANDARD);
        if (pPage != NULL && pPage->IsSelected())
        {
            SdrPage& rMasterPage (pPage->TRG_GetMasterPage());
            SdPage* pMasterPage = static_cast<SdPage*>(&rMasterPage);
            if (pMasterPage != NULL)
                aNames.insert (pMasterPage->GetName());
        }
    }

    // Find the items for the master pages in the set.
    USHORT nItemCount (mpPageSet->GetItemCount());
    for (nIndex=1; nIndex<=nItemCount; nIndex++)
    {
        String sName (mpPageSet->GetItemText (nIndex));
        if (aNames.find(sName) != aNames.end())
        {
            mpPageSet->SelectItem (nIndex);
        }
    }
}

IMPL_LINK(CurrentMasterPagesSelector,EventMultiplexerListener,
    sd::tools::EventMultiplexerEvent*,pEvent)
{
    if (pEvent != NULL)
    {
        switch (pEvent->meEventId)
        {
            case sd::tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
            case sd::tools::EventMultiplexerEvent::EID_EDIT_MODE:
            case sd::tools::EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION:
                UpdateSelection();
                break;

            case sd::tools::EventMultiplexerEvent::EID_PAGE_ORDER:
                // This is tricky.  If a master page is removed, moved, or
                // added we have to wait until both the notes master page
                // and the standard master page have been removed, moved,
                // or added.  We do this by looking at the number of master
                // pages which has to be odd in the consistent state (the
                // handout master page is always present).  If the number is
                // even we ignore the hint.
                if (mrBase.GetDocument()->GetMasterPageCount()%2 == 1)
                    MasterPagesSelector::Fill();
                break;

            case sd::tools::EventMultiplexerEvent::EID_SHAPE_CHANGED:
            case sd::tools::EventMultiplexerEvent::EID_SHAPE_INSERTED:
            case sd::tools::EventMultiplexerEvent::EID_SHAPE_REMOVED:
                InvalidatePreview((const SdPage*)pEvent->mpUserData);
                break;
        }
    }

    return 0;
}

} } } // end of namespace ::sd::toolpanel::controls
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N;
int p[200010];
vector<int> V[200010];
bool visited[200010];
bool isloop[200010];
int memo[200010];

int calc(int v) {
  cerr << "v = " << v << endl;
  if (memo[v] != -1) return memo[v];
  set<int> S;
  for (auto x : V[v]) {
    S.insert(calc(x));
  }
  for (auto i = 0; ; ++i) {
    if (S.find(i) == S.end()) {
      return (memo[v] = i);
    }
  }
}

int main () {
  cin >> N;
  for (auto i = 0; i < N; ++i) {
    cin >> p[i];
    p[i]--;
  }
  for (auto i = 0; i < N; ++i) {
    V[p[i]].push_back(i);
  }
  fill(visited, visited+200010, false);
  int now = 0;
  while (!visited[now]) {
    visited[now] = true;
    now = p[now];
  }
  fill(isloop, isloop+200010, false);
  while (!isloop[now]) {
    isloop[now] = true;
    now = p[now];
  }
  cerr << "now = " << now << endl;
  fill(memo, memo+200010, -1);
  for (auto i = 0; i < N; ++i) {
    if (!isloop[i]) calc(i);
    cerr << "calc(" << i << ") = " << calc(i) << endl;
  }
  vector<int> kouho;
  set<int> S;
  for (auto x : V[now]) {
    if (!isloop[x]) {
      S.insert(calc(x));
    }
  }
  for (auto i = 0; ; ++i) {
    if (S.find(i) == S.end()) {
      kouho.push_back(i);
      if (kouho.size() == 2) break;
    }
  }
  cerr << "kouho: ";
  for (auto x : kouho) {
    cerr << x << " ";
  }
  cerr << endl;
  for (auto z : kouho) {
    for (auto i = 0; i < N; ++i) {
      if (isloop[i]) memo[now] = -1;
    }
    memo[now] = z;
    for (auto i = 0; i < N; ++i) {
      if (isloop[i] && i != now) calc(i);
    }
    memo[now] = -1;
    if (calc(now) == z) {
      cout << "POSSIBLE" << endl;
      return 0;
    }
  }
  cout << "IMPOSSIBLE" << endl;
}
<commit_msg>tried F.cpp to 'F'<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N;
int p[200010];
vector<int> V[200010];
bool visited[200010];
bool isloop[200010];
int memo[200010];

int calc(int v) {
  if (memo[v] != -1) return memo[v];
  set<int> S;
  for (auto x : V[v]) {
    S.insert(calc(x));
  }
  for (auto i = 0; ; ++i) {
    if (S.find(i) == S.end()) {
      return (memo[v] = i);
    }
  }
}

int main () {
  cin >> N;
  for (auto i = 0; i < N; ++i) {
    cin >> p[i];
    p[i]--;
  }
  for (auto i = 0; i < N; ++i) {
    V[p[i]].push_back(i);
  }
  fill(visited, visited+200010, false);
  int now = 0;
  while (!visited[now]) {
    visited[now] = true;
    now = p[now];
  }
  fill(isloop, isloop+200010, false);
  while (!isloop[now]) {
    isloop[now] = true;
    now = p[now];
  }
  cerr << "now = " << now << endl;
  fill(memo, memo+200010, -1);
  for (auto i = 0; i < N; ++i) {
    if (!isloop[i]) calc(i);
    cerr << "calc(" << i << ") = " << calc(i) << endl;
  }
  vector<int> kouho;
  set<int> S;
  for (auto x : V[now]) {
    if (!isloop[x]) {
      S.insert(calc(x));
    }
  }
  for (auto i = 0; ; ++i) {
    if (S.find(i) == S.end()) {
      kouho.push_back(i);
      if (kouho.size() == 2) break;
    }
  }
  cerr << "kouho: ";
  for (auto x : kouho) {
    cerr << x << " ";
  }
  cerr << endl;
  for (auto z : kouho) {
    for (auto i = 0; i < N; ++i) {
      if (isloop[i]) memo[now] = -1;
    }
    memo[now] = z;
    for (auto i = 0; i < N; ++i) {
      if (isloop[i] && i != now) calc(i);
    }
    memo[now] = -1;
    if (calc(now) == z) {
      cout << "POSSIBLE" << endl;
      return 0;
    }
  }
  cout << "IMPOSSIBLE" << endl;
}
<|endoftext|>


<commit_before>#include "ShardCatchupWriter.h"
#include "Application/Common/ContextTransport.h"
#include "ShardQuorumProcessor.h"
#include "ShardServer.h"

ShardCatchupWriter::ShardCatchupWriter()
{
    Reset();
}

ShardCatchupWriter::~ShardCatchupWriter()
{
    if (cursor != NULL)
        delete cursor;
}

void ShardCatchupWriter::Init(ShardQuorumProcessor* quorumProcessor_)
{
    quorumProcessor = quorumProcessor_;

    environment = quorumProcessor->GetShardServer()->GetDatabaseManager()->GetEnvironment();

    Reset();
}

void ShardCatchupWriter::Reset()
{
    cursor = NULL;
    isActive = false;
}

bool ShardCatchupWriter::IsActive()
{
    return isActive;
}

void ShardCatchupWriter::Begin(CatchupMessage& request)
{
    assert(!isActive);
    assert(quorumProcessor != NULL);
    assert(cursor == NULL);

    isActive = true;
    nodeID = request.nodeID;
    quorumID = request.quorumID;
    paxosID = quorumProcessor->GetPaxosID() - 1;

    if (quorumProcessor->GetConfigQuorum()->shards.GetLength() == 0)
        SendCommit();
    else
        SendFirst();
    CONTEXT_TRANSPORT->RegisterWriteReadyness(nodeID, MFUNC(ShardCatchupWriter, OnWriteReadyness));
}

void ShardCatchupWriter::Abort()
{
    CatchupMessage msg;

    msg.Abort();
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);

    if (cursor != NULL)
    {
        delete cursor;
        cursor = NULL;
    }

    CONTEXT_TRANSPORT->UnregisterWriteReadyness(nodeID, MFUNC(ShardCatchupWriter, OnWriteReadyness));

    Reset();
}

void ShardCatchupWriter::SendFirst()
{
    CatchupMessage      msg;
    ReadBuffer          key;
    ReadBuffer          value;

    assert(quorumProcessor->GetConfigQuorum()->shards.GetLength() > 0);
    shardID = *(quorumProcessor->GetConfigQuorum()->shards.First());

    assert(cursor == NULL);
    cursor = environment->GetBulkCursor(QUORUM_DATABASE_DATA_CONTEXT, shardID);
    assert(cursor != NULL);

    msg.BeginShard(shardID);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);

    // send first KV
    kv = cursor->First();
    if (kv == NULL)
    {
        SendNext();
        return;
    }

    TransformKeyValue(kv, msg);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
    Log_Debug("Sending BEGIN SHARD %U", shardID);
}

void ShardCatchupWriter::SendNext()
{
    uint64_t*           itShardID;
    CatchupMessage      msg;

    assert(cursor != NULL);
    if (kv != NULL)
    {
        kv = cursor->Next(kv);
        if (kv)
        {
            TransformKeyValue(kv, msg);
            CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
            return;
        }
    }

    // kv is NULL, at end of current shard
    delete cursor;
    cursor = NULL;

    itShardID = NextShard();

    if (!itShardID)
    {
        SendCommit(); // there is no next shard, send commit
        return;
    }

    shardID = *itShardID;

    delete cursor;
    cursor = quorumProcessor->GetShardServer()->GetDatabaseManager()->GetEnvironment()->GetBulkCursor(
     QUORUM_DATABASE_DATA_CONTEXT, shardID);

    msg.BeginShard(shardID);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
    Log_Debug("Sending BEGIN SHARD %U", shardID);

    // send first KV
    kv = cursor->First();
    if (!kv)
    {
        SendNext();
        return;
    }

    TransformKeyValue(kv, msg);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
}

void ShardCatchupWriter::SendCommit()
{
    CatchupMessage msg;

    msg.Commit(paxosID);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
    Log_Debug("Sending COMMIT with paxosID = %U", paxosID);

    if (cursor != NULL)
    {
        delete cursor;
        cursor = NULL;
    }

    CONTEXT_TRANSPORT->UnregisterWriteReadyness(nodeID, MFUNC(ShardCatchupWriter, OnWriteReadyness));

    Reset();
}

void ShardCatchupWriter::OnWriteReadyness()
{
    SendNext();
}

uint64_t* ShardCatchupWriter::NextShard()
{
    uint64_t* it;

    ShardQuorumProcessor::ShardList& shards = quorumProcessor->GetConfigQuorum()->shards;

    FOREACH(it, shards)
    {
        if (*it == shardID)
            break;
    }
    assert(it != NULL);

    it = shards.Next(it);

    return it;
}

void ShardCatchupWriter::TransformKeyValue(StorageKeyValue* kv, CatchupMessage& msg)
{
    if (kv->GetType() == STORAGE_KEYVALUE_TYPE_SET)
        msg.Set(kv->GetKey(), kv->GetValue());
    else
        msg.Delete(kv->GetKey());
}
<commit_msg>Fixed bugs in Catchup.<commit_after>#include "ShardCatchupWriter.h"
#include "Application/Common/ContextTransport.h"
#include "ShardQuorumProcessor.h"
#include "ShardServer.h"

ShardCatchupWriter::ShardCatchupWriter()
{
    Reset();
}

ShardCatchupWriter::~ShardCatchupWriter()
{
    if (cursor != NULL)
        delete cursor;
}

void ShardCatchupWriter::Init(ShardQuorumProcessor* quorumProcessor_)
{
    quorumProcessor = quorumProcessor_;

    environment = quorumProcessor->GetShardServer()->GetDatabaseManager()->GetEnvironment();

    Reset();
}

void ShardCatchupWriter::Reset()
{
    cursor = NULL;
    isActive = false;
}

bool ShardCatchupWriter::IsActive()
{
    return isActive;
}

void ShardCatchupWriter::Begin(CatchupMessage& request)
{
    assert(!isActive);
    assert(quorumProcessor != NULL);
    assert(cursor == NULL);

    isActive = true;
    nodeID = request.nodeID;
    quorumID = request.quorumID;
    paxosID = quorumProcessor->GetPaxosID() - 1;

    if (quorumProcessor->GetConfigQuorum()->shards.GetLength() == 0)
        SendCommit();
    else
        SendFirst();

    if (isActive)
        CONTEXT_TRANSPORT->RegisterWriteReadyness(nodeID, MFUNC(ShardCatchupWriter, OnWriteReadyness));
}

void ShardCatchupWriter::Abort()
{
    CatchupMessage msg;

    msg.Abort();
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);

    if (cursor != NULL)
    {
        delete cursor;
        cursor = NULL;
    }

    CONTEXT_TRANSPORT->UnregisterWriteReadyness(nodeID, MFUNC(ShardCatchupWriter, OnWriteReadyness));

    Reset();
}

void ShardCatchupWriter::SendFirst()
{
    CatchupMessage      msg;
    ReadBuffer          key;
    ReadBuffer          value;

    assert(quorumProcessor->GetConfigQuorum()->shards.GetLength() > 0);
    shardID = *(quorumProcessor->GetConfigQuorum()->shards.First());

    assert(cursor == NULL);
    cursor = environment->GetBulkCursor(QUORUM_DATABASE_DATA_CONTEXT, shardID);
    assert(cursor != NULL);

    msg.BeginShard(shardID);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);

    // send first KV
    kv = cursor->First();
    if (kv == NULL)
    {
        SendNext();
        return;
    }

    TransformKeyValue(kv, msg);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
    Log_Debug("Sending BEGIN SHARD %U", shardID);
}

void ShardCatchupWriter::SendNext()
{
    uint64_t*           itShardID;
    CatchupMessage      msg;

    assert(cursor != NULL);
    if (kv != NULL)
    {
        kv = cursor->Next(kv);
        if (kv)
        {
            TransformKeyValue(kv, msg);
            CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
            return;
        }
    }

    // kv is NULL, at end of current shard
    delete cursor;
    cursor = NULL;

    itShardID = NextShard();

    if (!itShardID)
    {
        SendCommit(); // there is no next shard, send commit
        return;
    }

    shardID = *itShardID;

    delete cursor;
    cursor = quorumProcessor->GetShardServer()->GetDatabaseManager()->GetEnvironment()->GetBulkCursor(
     QUORUM_DATABASE_DATA_CONTEXT, shardID);

    msg.BeginShard(shardID);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
    Log_Debug("Sending BEGIN SHARD %U", shardID);

    // send first KV
    kv = cursor->First();
    if (!kv)
    {
        SendNext();
        return;
    }

    TransformKeyValue(kv, msg);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
}

void ShardCatchupWriter::SendCommit()
{
    CatchupMessage msg;

    msg.Commit(paxosID);
    CONTEXT_TRANSPORT->SendQuorumMessage(nodeID, quorumID, msg);
    Log_Debug("Sending COMMIT with paxosID = %U", paxosID);

    if (cursor != NULL)
    {
        delete cursor;
        cursor = NULL;
    }

    CONTEXT_TRANSPORT->UnregisterWriteReadyness(nodeID, MFUNC(ShardCatchupWriter, OnWriteReadyness));

    Reset();
}

void ShardCatchupWriter::OnWriteReadyness()
{
    SendNext();
}

uint64_t* ShardCatchupWriter::NextShard()
{
    uint64_t* it;

    ShardQuorumProcessor::ShardList& shards = quorumProcessor->GetConfigQuorum()->shards;

    FOREACH(it, shards)
    {
        if (*it == shardID)
            break;
    }
    assert(it != NULL);

    it = shards.Next(it);

    return it;
}

void ShardCatchupWriter::TransformKeyValue(StorageKeyValue* kv, CatchupMessage& msg)
{
    if (kv->GetType() == STORAGE_KEYVALUE_TYPE_SET)
        msg.Set(kv->GetKey(), kv->GetValue());
    else
        msg.Delete(kv->GetKey());
}
<|endoftext|>


<commit_before>#include "config.h"

Config* Config::getHandle() {
	static Config instance;
	return &instance;
}

void Config::setMainConfigFile(const std::string& configFileName) {
	if (confname.empty())
		confname = configFileName;
}

void Config::readConfig() {
	config = readConfig(confname, std::ifstream(confname));
	for (auto callback : notifyList)
		callback();
}

enum ConfigState { CONFIG_BLOCK, CONFIG_KEY, CONFIG_VALUE, CONFIG_VALUE_NEXT, CONFIG_VALUE_VAR, CONFIG_VALUE_STR, CONFIG_VALUE_STR_ESCAPED };
// This enum is simply an implementation detail for the configuration parser; hence it is placed here instead of the header file.

std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> Config::readConfig(const std::string& filename, std::istream&& configData) {
	ConfigState state = CONFIG_BLOCK;
	unsigned int lineNum = 1;
	LogManager* logger = LogManager::getHandle();
	std::string blockName, key, value, valueVar;
	std::unordered_map<std::string, std::string> blockValues;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> localConfig;
	while (configData.good()) {
		char nextChar = configData.get();
		if (nextChar == std::istream::traits_type::eof())
			break;
		if (nextChar == '\n')
			lineNum++;
		if (state == CONFIG_BLOCK) {
			if (nextChar == '{') {
				if (blockName.empty())
					throw ConfigError (filename, lineNum, "A block without a name was opened.");
				state = CONFIG_KEY;
			} else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A closing brace could not be mached to an open block.");
			else if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				blockName += nextChar;
		} else if (state == CONFIG_KEY) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}') {
				if (blockValues.empty())
					throw ConfigError (filename, lineNum, "An empty block was defined.  What was the point of that?");
				if (!key.empty() || !value.empty())
					throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
				localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (blockName, blockValues));
				blockName.clear();
				blockValues.clear();
				logger->log(LOG_ALL, "config", "Block " + blockName + " read.");
				state = CONFIG_BLOCK;
			} else if (nextChar == ';')
				throw ConfigError (filename, lineNum, "A key was specified without a value.");
			else if (nextChar == '=')
				state = CONFIG_VALUE_NEXT;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				key += nextChar;
		} else if (state == CONFIG_VALUE) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == ';') {
				blockValues.insert(std::pair<std::string, std::string> (key, value));
				key.clear();
				value.clear();
				state = CONFIG_KEY;
			} else if (nextChar == '+')
				state = CONFIG_VALUE_NEXT;
			else
				throw ConfigError (filename, lineNum, "An unexpected character was encountered; expected ';' or '+' (perhaps you forgot to end or properly concatenate your value?).");
		} else if (state == CONFIG_VALUE_NEXT) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '"')
				state = CONFIG_VALUE_STR;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n') {
				valueVar += nextChar;
				state = CONFIG_VALUE_VAR;
			}
		} else if (state == CONFIG_VALUE_VAR) {
			if (nextChar == '"')
				throw ConfigError (filename, lineNum, "A string value was specified in the middle of a variable (perhaps you forgot to properly concatenate with '+'?).");
			else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
			else if (nextChar == ' ' || nextChar == '\t' || nextChar == '\r' || nextChar == '\n' || nextChar == '+' || nextChar == ';') {
				auto keyIter = blockValues.find(valueVar);
				if (keyIter == blockValues.end())
					throw ConfigError (filename, lineNum, "The variable " + valueVar + " was specified, but did not match a variable already specified in the block.");
				value += keyIter->second;
				valueVar.clear();
				if (nextChar == ';') {
					state = CONFIG_KEY;
					blockValues.insert(std::pair<std::string, std::string> (key, value));
					key.clear();
					value.clear();
				} else if (nextChar == '+')
					state = CONFIG_VALUE_NEXT;
				else
					state = CONFIG_VALUE;
			} else
				valueVar += nextChar;
		} else if (state == CONFIG_VALUE_STR) {
			if (nextChar == '\\')
				state = CONFIG_VALUE_STR_ESCAPED;
			else if (nextChar == '"')
				state = CONFIG_VALUE;
			else
				value += nextChar;
		} else if (state == CONFIG_VALUE_STR_ESCAPED) {
			if (nextChar == '\\')
				value += '\\';
			else if (nextChar == 'n')
				value += '\n';
			else if (nextChar == 't')
				value += '\t';
			else if (nextChar == 'r')
				value += '\r';
			else
				value += nextChar;
			state = CONFIG_VALUE_STR;
		}
	}
	if (!blockValues.empty())
		throw ConfigError (filename, lineNum, "A block remained unterminated at the end of the file.");
	std::list<std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>> includedConfigs;
	for (auto block : localConfig) {
		if (block.first == "include") {
			auto inclfIter = block.second.find("file");
			if (inclfIter != block.second.end()) {
				std::string name = inclfIter->second;
				logger->log(LOG_ALL, "config", "Reading included file " + inclfIter->second);
				includedConfigs.push_back(readConfig(inclfIter->second, std::ifstream(name)));
			} else {
				auto incleIter = block.second.find("executable");
				if (incleIter != block.second.end()) {
					std::string cmd = incleIter->second;
					logger->log(LOG_ALL, "config", "Getting configuration data from `" + incleIter->second + "`");
					FILE* pipe = popen(cmd.c_str(), "r");
					if (!pipe)
						throw ConfigError (cmd, 0, "Could not open pipe to read output.");
					char buffer[256];
					std::stringstream output;
					while (!feof(pipe)) {
						if (fgets(buffer, 256, pipe) != NULL)
							output << buffer;
					}
					pclose(pipe);
					includedConfigs.push_back(readConfig(cmd, std::move(output)));
				} else
					throw ConfigError (filename, lineNum, "An include block was present that contained neither a file nor an executable.");
			}
		}
	}
	for (auto includes : includedConfigs) {
		for (auto conf : includes) {
			for (auto block : conf.second)
				localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (block.first, block.second));
		}
	}
	return localConfig;
}

void Config::addRehashNotify(std::function<void()> notifyCallback) {
	notifyList.push_back(notifyCallback);
}

size_t Config::blockCount(const std::string& block) const {
	return config.count(block);
}

std::list<std::unordered_map<std::string, std::string>> Config::getBlock(const std::string& block) const {
	std::list<std::unordered_map<std::string, std::string>> blockList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter)
		blockList.push_back(startIter->second);
	return blockList;
}

std::unordered_map<std::string, std::string> Config::getSingleBlock(const std::string& block, const std::unordered_map<std::string, std::string>& conditions) const {
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		for (auto check : conditions) {
			auto blockIter = startIter->second.find(check.first);
			if (blockIter == startIter->second.end())
				continue;
			if (check.second == blockIter->second)
				return startIter->second;
		}
	}
	return std::unordered_map<std::string, std::string> ();
}

std::string Config::getValue(const std::string& block, const std::string& key) const {
	auto blockIter = config.find(block);
	if (blockIter == config.end())
		return "";
	auto dataIter = blockIter->second.find(key);
	if (dataIter == blockIter->second.end())
		return "";
	return dataIter->second;
}

bool Config::getBoolValue(const std::string& block, const std::string& key) const {
	const std::string& value = getValue(block, key);
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

std::list<std::string> Config::getAllValues(const std::string& block, const std::string& key) const {
	std::list<std::string> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back("");
		else
			valueList.push_back(dataIter->second);
	}
	return valueList;
}

std::list<bool> Config::getAllBoolValues(const std::string& block, const std::string& key) const {
	std::list<bool> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (std::string lowerValue; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back(false);
		else {
			lowerValue.clear();
			std::transform(dataIter->second.begin(), dataIter->second.end(), std::back_inserter(lowerValue), ::tolower);
			if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
				valueList.push_back(true);
			else
				valueList.push_back(false);
		}
	}
	return valueList;
}

bool Config::makeBool(const std::string& value) {
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

Config::Config() {}

ConfigError::ConfigError(const std::string& filename, unsigned int lineNum, const std::string& description) {
	std::ostringstream descStr;
	descStr << "An error occurred reading the configuration from '" << filename << "' on line " << lineNum << ": " << description;
	desc = descStr.str();
}<commit_msg>Properly fix the merging of included config files<commit_after>#include "config.h"

Config* Config::getHandle() {
	static Config instance;
	return &instance;
}

void Config::setMainConfigFile(const std::string& configFileName) {
	if (confname.empty())
		confname = configFileName;
}

void Config::readConfig() {
	config = readConfig(confname, std::ifstream(confname));
	for (auto callback : notifyList)
		callback();
}

enum ConfigState { CONFIG_BLOCK, CONFIG_KEY, CONFIG_VALUE, CONFIG_VALUE_NEXT, CONFIG_VALUE_VAR, CONFIG_VALUE_STR, CONFIG_VALUE_STR_ESCAPED };
// This enum is simply an implementation detail for the configuration parser; hence it is placed here instead of the header file.

std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> Config::readConfig(const std::string& filename, std::istream&& configData) {
	ConfigState state = CONFIG_BLOCK;
	unsigned int lineNum = 1;
	LogManager* logger = LogManager::getHandle();
	std::string blockName, key, value, valueVar;
	std::unordered_map<std::string, std::string> blockValues;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> localConfig;
	while (configData.good()) {
		char nextChar = configData.get();
		if (nextChar == std::istream::traits_type::eof())
			break;
		if (nextChar == '\n')
			lineNum++;
		if (state == CONFIG_BLOCK) {
			if (nextChar == '{') {
				if (blockName.empty())
					throw ConfigError (filename, lineNum, "A block without a name was opened.");
				state = CONFIG_KEY;
			} else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A closing brace could not be mached to an open block.");
			else if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				blockName += nextChar;
		} else if (state == CONFIG_KEY) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}') {
				if (blockValues.empty())
					throw ConfigError (filename, lineNum, "An empty block was defined.  What was the point of that?");
				if (!key.empty() || !value.empty())
					throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
				localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (blockName, blockValues));
				blockName.clear();
				blockValues.clear();
				logger->log(LOG_ALL, "config", "Block " + blockName + " read.");
				state = CONFIG_BLOCK;
			} else if (nextChar == ';')
				throw ConfigError (filename, lineNum, "A key was specified without a value.");
			else if (nextChar == '=')
				state = CONFIG_VALUE_NEXT;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				key += nextChar;
		} else if (state == CONFIG_VALUE) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == ';') {
				blockValues.insert(std::pair<std::string, std::string> (key, value));
				key.clear();
				value.clear();
				state = CONFIG_KEY;
			} else if (nextChar == '+')
				state = CONFIG_VALUE_NEXT;
			else
				throw ConfigError (filename, lineNum, "An unexpected character was encountered; expected ';' or '+' (perhaps you forgot to end or properly concatenate your value?).");
		} else if (state == CONFIG_VALUE_NEXT) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '"')
				state = CONFIG_VALUE_STR;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n') {
				valueVar += nextChar;
				state = CONFIG_VALUE_VAR;
			}
		} else if (state == CONFIG_VALUE_VAR) {
			if (nextChar == '"')
				throw ConfigError (filename, lineNum, "A string value was specified in the middle of a variable (perhaps you forgot to properly concatenate with '+'?).");
			else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
			else if (nextChar == ' ' || nextChar == '\t' || nextChar == '\r' || nextChar == '\n' || nextChar == '+' || nextChar == ';') {
				auto keyIter = blockValues.find(valueVar);
				if (keyIter == blockValues.end())
					throw ConfigError (filename, lineNum, "The variable " + valueVar + " was specified, but did not match a variable already specified in the block.");
				value += keyIter->second;
				valueVar.clear();
				if (nextChar == ';') {
					state = CONFIG_KEY;
					blockValues.insert(std::pair<std::string, std::string> (key, value));
					key.clear();
					value.clear();
				} else if (nextChar == '+')
					state = CONFIG_VALUE_NEXT;
				else
					state = CONFIG_VALUE;
			} else
				valueVar += nextChar;
		} else if (state == CONFIG_VALUE_STR) {
			if (nextChar == '\\')
				state = CONFIG_VALUE_STR_ESCAPED;
			else if (nextChar == '"')
				state = CONFIG_VALUE;
			else
				value += nextChar;
		} else if (state == CONFIG_VALUE_STR_ESCAPED) {
			if (nextChar == '\\')
				value += '\\';
			else if (nextChar == 'n')
				value += '\n';
			else if (nextChar == 't')
				value += '\t';
			else if (nextChar == 'r')
				value += '\r';
			else
				value += nextChar;
			state = CONFIG_VALUE_STR;
		}
	}
	if (!blockValues.empty())
		throw ConfigError (filename, lineNum, "A block remained unterminated at the end of the file.");
	std::list<std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>> includedConfigs;
	for (auto block : localConfig) {
		if (block.first == "include") {
			auto inclfIter = block.second.find("file");
			if (inclfIter != block.second.end()) {
				std::string name = inclfIter->second;
				logger->log(LOG_ALL, "config", "Reading included file " + inclfIter->second);
				includedConfigs.push_back(readConfig(inclfIter->second, std::ifstream(name)));
			} else {
				auto incleIter = block.second.find("executable");
				if (incleIter != block.second.end()) {
					std::string cmd = incleIter->second;
					logger->log(LOG_ALL, "config", "Getting configuration data from `" + incleIter->second + "`");
					FILE* pipe = popen(cmd.c_str(), "r");
					if (!pipe)
						throw ConfigError (cmd, 0, "Could not open pipe to read output.");
					char buffer[256];
					std::stringstream output;
					while (!feof(pipe)) {
						if (fgets(buffer, 256, pipe) != NULL)
							output << buffer;
					}
					pclose(pipe);
					includedConfigs.push_back(readConfig(cmd, std::move(output)));
				} else
					throw ConfigError (filename, lineNum, "An include block was present that contained neither a file nor an executable.");
			}
		}
	}
	for (auto includes : includedConfigs) {
		for (auto conf : includes)
			localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (conf.first, conf.second));
	}
	return localConfig;
}

void Config::addRehashNotify(std::function<void()> notifyCallback) {
	notifyList.push_back(notifyCallback);
}

size_t Config::blockCount(const std::string& block) const {
	return config.count(block);
}

std::list<std::unordered_map<std::string, std::string>> Config::getBlock(const std::string& block) const {
	std::list<std::unordered_map<std::string, std::string>> blockList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter)
		blockList.push_back(startIter->second);
	return blockList;
}

std::unordered_map<std::string, std::string> Config::getSingleBlock(const std::string& block, const std::unordered_map<std::string, std::string>& conditions) const {
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		for (auto check : conditions) {
			auto blockIter = startIter->second.find(check.first);
			if (blockIter == startIter->second.end())
				continue;
			if (check.second == blockIter->second)
				return startIter->second;
		}
	}
	return std::unordered_map<std::string, std::string> ();
}

std::string Config::getValue(const std::string& block, const std::string& key) const {
	auto blockIter = config.find(block);
	if (blockIter == config.end())
		return "";
	auto dataIter = blockIter->second.find(key);
	if (dataIter == blockIter->second.end())
		return "";
	return dataIter->second;
}

bool Config::getBoolValue(const std::string& block, const std::string& key) const {
	const std::string& value = getValue(block, key);
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

std::list<std::string> Config::getAllValues(const std::string& block, const std::string& key) const {
	std::list<std::string> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back("");
		else
			valueList.push_back(dataIter->second);
	}
	return valueList;
}

std::list<bool> Config::getAllBoolValues(const std::string& block, const std::string& key) const {
	std::list<bool> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (std::string lowerValue; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back(false);
		else {
			lowerValue.clear();
			std::transform(dataIter->second.begin(), dataIter->second.end(), std::back_inserter(lowerValue), ::tolower);
			if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
				valueList.push_back(true);
			else
				valueList.push_back(false);
		}
	}
	return valueList;
}

bool Config::makeBool(const std::string& value) {
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

Config::Config() {}

ConfigError::ConfigError(const std::string& filename, unsigned int lineNum, const std::string& description) {
	std::ostringstream descStr;
	descStr << "An error occurred reading the configuration from '" << filename << "' on line " << lineNum << ": " << description;
	desc = descStr.str();
}<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, K;
int cnt[2000][2000][2];
int sum[2000][2000][2];

int main () {
  fill(&cnt[0][0][0], &cnt[0][0][0]+2000*2000*2, 0);
  cin >> N >> K;
  int white = 0;
  for (auto i = 0; i < N; ++i) {
    int x, y;
    char c;
    cin >> x >> y >> c;
    bool color = (c == 'W');
    int area = ((x/K) + (y/K))%2;
    x %= K;
    y %= K;
    if (color) {
      white++;
      cnt[x + K * area][y][0]++;
      cnt[x + K * area][y + K][0]++;
    } else {
      cnt[x + K * area][y][1]++;
      cnt[x + K * area][y + K][1]++;
    }
  }
  for (auto k = 0; k < 2; ++k) {
    cerr << "k = " << k << endl;
    for (auto i = 0; i < 2 * K; ++i) {
      for (auto j = 0; j < 2 * K; ++j) {
        cerr << cnt[i][j][k] << " ";
      }
      cerr << endl;
    }
  }
  for (auto k = 0; k < 2; ++k) {
    for (auto i = 0; i < 2 * K; ++i) {
      for (auto j = 0; j < 2 * K; ++j) {
        sum[i][j][k] = cnt[i][j][k];
      }
    }
    for (auto i = 0; i < 2 * K; ++i) {
      for (auto j = 0; j < 2 * K-1; ++j) {
        sum[i][j+1][k] += sum[i][j][k];
      }
    }
    for (auto j = 0; j < 2 * K; ++j) {
      for (auto i = 0; i < 2 * K-1; ++i) {
        sum[i+1][j][k] += sum[i][j][k];
      }
    }
  }
  for (auto k = 0; k < 2; ++k) {
    cerr << "k = " << k << endl;
    for (auto i = 0; i < 2 * K; ++i) {
      for (auto j = 0; j < 2 * K; ++j) {
        cerr << sum[i][j][k] << " ";
      }
      cerr << endl;
    }
  }
  int ans = 0;
  for (auto i = 0; i < K; ++i) {
    for (auto j = 0; j < K; ++j) {
      int x = i + K;
      int y = j + K;
      int w = sum[x][y][0] - sum[i][y][0] - sum[x][j][0] + sum[i][j][0];
      int b = sum[x][y][1] - sum[i][y][1] - sum[x][j][1] + sum[i][j][1];
      int c = white - w + b;
      ans = max(ans, c);
    }
  }
  cout << ans << endl;
}
<commit_msg>tried D.cpp to 'D'<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, K;
int cnt[2000][2000][2];
int sum[2000][2000][2];

int main () {
  fill(&cnt[0][0][0], &cnt[0][0][0]+2000*2000*2, 0);
  cin >> N >> K;
  int white = 0;
  for (auto i = 0; i < N; ++i) {
    int x, y;
    char c;
    cin >> x >> y >> c;
    bool color = (c == 'W');
    int area = ((x/K) + (y/K))%2;
    x %= K;
    y %= K;
    if (color) {
      white++;
      cnt[x + K * area][y][0]++;
      cnt[x + K * area][y + K][0]++;
    } else {
      cnt[x + K * area][y][1]++;
      cnt[x + K * area][y + K][1]++;
    }
  }
  for (auto k = 0; k < 2; ++k) {
    cerr << "k = " << k << endl;
    for (auto i = 0; i < 2 * K; ++i) {
      for (auto j = 0; j < 2 * K; ++j) {
        cerr << cnt[i][j][k] << " ";
      }
      cerr << endl;
    }
  }
  for (auto k = 0; k < 2; ++k) {
    for (auto i = 0; i < 2 * K; ++i) {
      for (auto j = 0; j < 2 * K; ++j) {
        sum[i][j][k] = cnt[i][j][k];
      }
    }
    for (auto i = 0; i < 2 * K; ++i) {
      for (auto j = 0; j < 2 * K-1; ++j) {
        sum[i][j+1][k] += sum[i][j][k];
      }
    }
    for (auto j = 0; j < 2 * K; ++j) {
      for (auto i = 0; i < 2 * K-1; ++i) {
        sum[i+1][j][k] += sum[i][j][k];
      }
    }
  }
  for (auto k = 0; k < 2; ++k) {
    cerr << "k = " << k << endl;
    for (auto i = 0; i < 2 * K; ++i) {
      for (auto j = 0; j < 2 * K; ++j) {
        cerr << sum[i][j][k] << " ";
      }
      cerr << endl;
    }
  }
  int ans = 0;
  for (auto i = 0; i < K; ++i) {
    for (auto j = 0; j < K; ++j) {
      int x = i + K;
      int y = j + K;
      int w = sum[x][y][0] - sum[i][y][0] - sum[x][j][0] + sum[i][j][0];
      int b = sum[x][y][1] - sum[i][y][1] - sum[x][j][1] + sum[i][j][1];
      cerr << "(" << x << ", " << y << ") = ("
           << w << ", " << b << ")" << endl;
      int c = white - w + b;
      ans = max(ans, c);
    }
  }
  cout << ans << endl;
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexGAP.cxx
 ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra)
 ** http://www.gap-system.org
 **/
// Copyright 2007 by Istvan Szollosi ( szteven <at> gmail <dot> com )
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsGAPOperator(char ch) {
	if (isalnum(ch)) return false;
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
		ch == '^' || ch == ',' || ch == '!' || ch == '.' ||
		ch == '=' || ch == '<' || ch == '>' || ch == '(' ||
		ch == ')' || ch == ';' || ch == '[' || ch == ']' ||
		ch == '{' || ch == '}' || ch == ':' )
		return true;
	return false;
}

static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) {
	unsigned int i = 0;
	while ((i < end - start + 1) && (i < len-1)) {
		s[i] = static_cast<char>(styler[start + i]);
		i++;
	}
	s[i] = '\0';
}

static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {

	WordList &keywords1 = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	// Do not leak onto next line
	if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		// Prevent SCE_GAP_STRINGEOL from leaking back to previous line
		if ( sc.atLineStart ) {
			if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING);
			if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR);
		}

		// Handle line continuation generically
		if (sc.ch == '\\' ) {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate
		switch (sc.state) {
			case SCE_GAP_OPERATOR :
				sc.SetState(SCE_GAP_DEFAULT);
				break;

			case SCE_GAP_NUMBER :
				if (!IsADigit(sc.ch)) {
					if (sc.ch == '\\') {
						if (!sc.atLineEnd) {
							if (!IsADigit(sc.chNext)) {
								sc.Forward();
								sc.ChangeState(SCE_GAP_IDENTIFIER);
							}
						}
					} else if (isalpha(sc.ch) || sc.ch == '_') {
						sc.ChangeState(SCE_GAP_IDENTIFIER);
					}
					else sc.SetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_IDENTIFIER :
				if (!(iswordstart(static_cast<char>(sc.ch)) || sc.ch == '$')) {
					if (sc.ch == '\\') sc.Forward();
					else {
						char s[1000];
						sc.GetCurrent(s, sizeof(s));
						if (keywords1.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD);
						} else if (keywords2.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD2);
						} else if (keywords3.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD3);
						} else if (keywords4.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD4);
						}
						sc.SetState(SCE_GAP_DEFAULT);
					}
				}
				break;

			case SCE_GAP_COMMENT :
				if (sc.atLineEnd) {
					sc.SetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_STRING:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_GAP_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"') {
						sc.Forward();
					}
				} else if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_CHAR:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_GAP_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\'') {
						sc.Forward();
					}
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_STRINGEOL:
				if (sc.atLineStart) {
					sc.SetState(SCE_GAP_DEFAULT);
				}
				break;
		}

		// Determine if a new state should be entered
		if (sc.state == SCE_GAP_DEFAULT) {
			if (IsGAPOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_GAP_OPERATOR);
			}
			else if (IsADigit(sc.ch)) {
				sc.SetState(SCE_GAP_NUMBER);
			} else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') {
				sc.SetState(SCE_GAP_IDENTIFIER);
				if (sc.ch == '\\') sc.Forward();
			} else if (sc.ch == '#') {
				sc.SetState(SCE_GAP_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_GAP_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_GAP_CHAR);
			}
		}

	}
	sc.Complete();
}

static int ClassifyFoldPointGAP(const char* s) {
	int level = 0;
	if (strcmp(s, "function") == 0 ||
		strcmp(s, "do") == 0 ||
		strcmp(s, "if") == 0 ||
		strcmp(s, "repeat") == 0 ) {
		level = 1;
	} else if (strcmp(s, "end") == 0 ||
			strcmp(s, "od") == 0 ||
			strcmp(s, "fi") == 0 ||
			strcmp(s, "until") == 0 ) {
		level = -1;
	}
	return level;
}

static void FoldGAPDoc( unsigned int startPos, int length, int initStyle,   WordList** , Accessor &styler) {
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;

	int lastStart = 0;

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (stylePrev == SCE_GAP_DEFAULT && style == SCE_GAP_KEYWORD) {
			// Store last word start point.
			lastStart = i;
		}

		if (stylePrev == SCE_GAP_KEYWORD) {
			if(iswordchar(ch) && !iswordchar(chNext)) {
				char s[100];
				GetRange(lastStart, i, styler, s, sizeof(s));
				levelCurrent += ClassifyFoldPointGAP(s);
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const GAPWordListDesc[] = {
	"Keywords 1",
	"Keywords 2",
	"Keywords 3 (unused)",
	"Keywords 4 (unused)",
	0
};

LexerModule lmGAP(
   SCLEX_GAP,
   ColouriseGAPDoc,
   "gap",
   FoldGAPDoc,
   GAPWordListDesc);
<commit_msg>Bug 1704800 fixed dealing with strings and chars like "something\\".<commit_after>// Scintilla source code edit control
/** @file LexGAP.cxx
 ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra)
 ** http://www.gap-system.org
 **/
// Copyright 2007 by Istvan Szollosi ( szteven <at> gmail <dot> com )
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsGAPOperator(char ch) {
	if (isalnum(ch)) return false;
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
		ch == '^' || ch == ',' || ch == '!' || ch == '.' ||
		ch == '=' || ch == '<' || ch == '>' || ch == '(' ||
		ch == ')' || ch == ';' || ch == '[' || ch == ']' ||
		ch == '{' || ch == '}' || ch == ':' )
		return true;
	return false;
}

static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) {
	unsigned int i = 0;
	while ((i < end - start + 1) && (i < len-1)) {
		s[i] = static_cast<char>(styler[start + i]);
		i++;
	}
	s[i] = '\0';
}

static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {

	WordList &keywords1 = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	// Do not leak onto next line
	if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		// Prevent SCE_GAP_STRINGEOL from leaking back to previous line
		if ( sc.atLineStart ) {
			if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING);
			if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR);
		}

		// Handle line continuation generically
		if (sc.ch == '\\' ) {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate
		switch (sc.state) {
			case SCE_GAP_OPERATOR :
				sc.SetState(SCE_GAP_DEFAULT);
				break;

			case SCE_GAP_NUMBER :
				if (!IsADigit(sc.ch)) {
					if (sc.ch == '\\') {
						if (!sc.atLineEnd) {
							if (!IsADigit(sc.chNext)) {
								sc.Forward();
								sc.ChangeState(SCE_GAP_IDENTIFIER);
							}
						}
					} else if (isalpha(sc.ch) || sc.ch == '_') {
						sc.ChangeState(SCE_GAP_IDENTIFIER);
					}
					else sc.SetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_IDENTIFIER :
				if (!(iswordstart(static_cast<char>(sc.ch)) || sc.ch == '$')) {
					if (sc.ch == '\\') sc.Forward();
					else {
						char s[1000];
						sc.GetCurrent(s, sizeof(s));
						if (keywords1.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD);
						} else if (keywords2.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD2);
						} else if (keywords3.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD3);
						} else if (keywords4.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD4);
						}
						sc.SetState(SCE_GAP_DEFAULT);
					}
				}
				break;

			case SCE_GAP_COMMENT :
				if (sc.atLineEnd) {
					sc.SetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_STRING:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_GAP_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_CHAR:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_GAP_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_STRINGEOL:
				if (sc.atLineStart) {
					sc.SetState(SCE_GAP_DEFAULT);
				}
				break;
		}

		// Determine if a new state should be entered
		if (sc.state == SCE_GAP_DEFAULT) {
			if (IsGAPOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_GAP_OPERATOR);
			}
			else if (IsADigit(sc.ch)) {
				sc.SetState(SCE_GAP_NUMBER);
			} else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') {
				sc.SetState(SCE_GAP_IDENTIFIER);
				if (sc.ch == '\\') sc.Forward();
			} else if (sc.ch == '#') {
				sc.SetState(SCE_GAP_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_GAP_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_GAP_CHAR);
			}
		}

	}
	sc.Complete();
}

static int ClassifyFoldPointGAP(const char* s) {
	int level = 0;
	if (strcmp(s, "function") == 0 ||
		strcmp(s, "do") == 0 ||
		strcmp(s, "if") == 0 ||
		strcmp(s, "repeat") == 0 ) {
		level = 1;
	} else if (strcmp(s, "end") == 0 ||
			strcmp(s, "od") == 0 ||
			strcmp(s, "fi") == 0 ||
			strcmp(s, "until") == 0 ) {
		level = -1;
	}
	return level;
}

static void FoldGAPDoc( unsigned int startPos, int length, int initStyle,   WordList** , Accessor &styler) {
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;

	int lastStart = 0;

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (stylePrev == SCE_GAP_DEFAULT && style == SCE_GAP_KEYWORD) {
			// Store last word start point.
			lastStart = i;
		}

		if (stylePrev == SCE_GAP_KEYWORD) {
			if(iswordchar(ch) && !iswordchar(chNext)) {
				char s[100];
				GetRange(lastStart, i, styler, s, sizeof(s));
				levelCurrent += ClassifyFoldPointGAP(s);
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const GAPWordListDesc[] = {
	"Keywords 1",
	"Keywords 2",
	"Keywords 3 (unused)",
	"Keywords 4 (unused)",
	0
};

LexerModule lmGAP(
   SCLEX_GAP,
   ColouriseGAPDoc,
   "gap",
   FoldGAPDoc,
   GAPWordListDesc);
<|endoftext|>


<commit_before>/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-14 21:58:19
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 1 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int H, W;
string S[20];
typedef tuple<int, int> P;
vector<vector<P>> pairs;

void dfs(vector<P> temp, vector<bool> used, int R)
{
  if (R == 0)
  {
    pairs.push_back(temp);
    return;
  }
  if (R == 1)
  {
    for (auto i = 0; i < H; i++)
    {
      if (!used[i])
      {
        temp.push_back(P(i, i));
        dfs(temp, used, 0);
        return;
      }
    }
  }
  assert(R >= 2);
  int first = -1;
  for (auto i = 0; i < H; i++)
  {
    if (!used[i])
    {
      first = i;
      used[i] = true;
      break;
    }
  }
  assert(first >= 0);
  for (auto i = 0; i < H; i++)
  {
    if (!used[i])
    {
      vector<bool> n_used = used;
      n_used[i] = true;
      vector<P> n_temp = temp;
      n_temp.push_back(P(first, i));
      dfs(n_temp, n_used, R - 2);
    }
  }
}

vector<string> make_strings(vector<P>& V)
{
  vector<int> X;
  int N = V.size();
  for (auto i = 0; i < N; i++)
  {
    X.push_back(get<0>(V[i]));
  }
  for (auto i = N-1; i >= 0; i--)
  {
    X.push_back(get<1>(V[i]));
  }
  vector<string> res;
  for (auto j = 0; j < W; j++)
  {
    string str = "";
    for (auto i : X)
    {
      string t = {S[i][j]};
      str += t;
    }
    res.push_back(str);
  }
  return res;
}

vector<string> reverse_strings(const vector<string>& V)
{
  vector<string> res;
  for (auto x : V)
  {
    reverse(x.begin(), x.end());
    res.push_back(x);
  }
  return res;
}

int main()
{
  cin >> H >> W;
  for (auto i = 0; i < H; i++)
  {
    cin >> S[i];
  }
  vector<P> emp_P;
  vector<bool> emp_used = vector<bool>(H, false);
  dfs(emp_P, emp_used, H);
  #if DEBUG == 1
  cerr << "pairs.size() = " << pairs.size() << endl;
  for (auto V : pairs)
  {
    for (auto e : V)
    {
      cerr << "[" << get<0>(e) << ", " << get<1>(e) << "] ";
    }
    cerr << endl;
  }
  #endif
  for (auto e : pairs)
  {
    vector<string> V1 = make_strings(e);
    vector<string> V2 = reverse_strings(V1);
    vector<bool> used = vector<bool>(false, W);
    int R = W;
    while (R > 0)
    {
      bool ok = true;
      for (auto i = 0; i < W; i++)
      {
        if (!used[i])
        {
          bool found = false;
          used[i] = true;
          for (auto j = 0; j < W; j++)
          {
            if (!used[j] && V1[i] == V2[j])
            {
              used[j] = true;
              R -= 2;
              found = true;
              break;
            }
          }
          if (!found && V1[i] == V2[i])
          {
            R -= 1;
            found = true;
          }
          if (!found)
          {
            ok = false;
            break;
          }
        }
      }
      if (!ok)
      {
        break;
      }
    }
    if (R == 0)
    {
      cout << "YES" << endl;
      return 0;
    }
  }
  cerr << "NO" << endl;
}<commit_msg>tried E.cpp to 'E'<commit_after>/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-14 21:58:19
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 1 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int H, W;
string S[20];
typedef tuple<int, int> P;
vector<vector<P>> pairs;

void dfs(vector<P> temp, vector<bool> used, int R)
{
  if (R == 0)
  {
    pairs.push_back(temp);
    return;
  }
  if (R == 1)
  {
    for (auto i = 0; i < H; i++)
    {
      if (!used[i])
      {
        temp.push_back(P(i, i));
        dfs(temp, used, 0);
        return;
      }
    }
  }
  assert(R >= 2);
  int first = -1;
  for (auto i = 0; i < H; i++)
  {
    if (!used[i])
    {
      first = i;
      used[i] = true;
      break;
    }
  }
  assert(first >= 0);
  for (auto i = 0; i < H; i++)
  {
    if (!used[i])
    {
      vector<bool> n_used = used;
      n_used[i] = true;
      vector<P> n_temp = temp;
      n_temp.push_back(P(first, i));
      dfs(n_temp, n_used, R - 2);
    }
  }
}

vector<string> make_strings(vector<P>& V)
{
  vector<int> X;
  int N = V.size();
  for (auto i = 0; i < N; i++)
  {
    X.push_back(get<0>(V[i]));
  }
  for (auto i = N-1; i >= 0; i--)
  {
    X.push_back(get<1>(V[i]));
  }
  vector<string> res;
  for (auto j = 0; j < W; j++)
  {
    string str = "";
    for (auto i : X)
    {
      string t = {S[i][j]};
      str += t;
    }
    res.push_back(str);
  }
  return res;
}

vector<string> reverse_strings(const vector<string>& V)
{
  vector<string> res;
  for (auto x : V)
  {
    reverse(x.begin(), x.end());
    res.push_back(x);
  }
  return res;
}

int main()
{
  cin >> H >> W;
  for (auto i = 0; i < H; i++)
  {
    cin >> S[i];
  }
  vector<P> emp_P;
  vector<bool> emp_used = vector<bool>(H, false);
  dfs(emp_P, emp_used, H);
  #if DEBUG == 1
  cerr << "pairs.size() = " << pairs.size() << endl;
  if (pairs.size() < 5)
  {
    for (auto V : pairs)
    {
      for (auto e : V)
      {
        cerr << "[" << get<0>(e) << ", " << get<1>(e) << "] ";
      }
      cerr << endl;
    }
  }
  #endif
  for (auto e : pairs)
  {
    vector<string> V1 = make_strings(e);
    vector<string> V2 = reverse_strings(V1);
    vector<bool> used = vector<bool>(false, W);
    int R = W;
    while (R > 0)
    {
      bool ok = true;
      for (auto i = 0; i < W; i++)
      {
        if (!used[i])
        {
          bool found = false;
          used[i] = true;
          for (auto j = 0; j < W; j++)
          {
            if (!used[j] && V1[i] == V2[j])
            {
              used[j] = true;
              R -= 2;
              found = true;
              break;
            }
          }
          if (!found && V1[i] == V2[i])
          {
            R -= 1;
            found = true;
          }
          if (!found)
          {
            ok = false;
            break;
          }
        }
      }
      if (!ok)
      {
        break;
      }
    }
    if (R == 0)
    {
      cout << "YES" << endl;
      return 0;
    }
  }
  cerr << "NO" << endl;
}<|endoftext|>