<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

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

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

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

#include "amr_forestclaw.H"
#include "amr_utils.H"

void set_domain_data(fclaw2d_domain_t *domain, global_parms *parms)
{
    fclaw2d_domain_data_t *ddata = P4EST_ALLOC (fclaw2d_domain_data_t, 1);
    domain->user = (void *) ddata;

    ddata->parms = parms;
}

global_parms* get_domain_data(fclaw2d_domain_t *domain)
{
    fclaw2d_domain_data_t *ddata;
    ddata = (fclaw2d_domain_data_t *) domain->user;

    return ddata->parms;
}

void set_patch_data(fclaw2d_patch_t *patch, ClawPatch* cp)
{
    fclaw2d_patch_data_t *pdata = P4EST_ALLOC (fclaw2d_patch_data_t, 1);
    patch->user = (void *) pdata;

    pdata->cp = cp;
}

ClawPatch* get_patch_data(fclaw2d_patch_t *patch)
{
    fclaw2d_patch_data_t *pdata;
    pdata = (fclaw2d_patch_data_t *) patch->user;

    return pdata->cp;
}

void amrsetup(fclaw2d_domain_t *domain)
{
    global_parms *gparms = new global_parms();
    cout << "Global parameters " << endl;
    gparms->get_inputParams();
    gparms->print_inputParams();

    set_domain_data(domain,parms);

    for(int i = 0; i < domain->num_blocks; i++)
    {
        fclaw2d_block_t *block = &domain->blocks[i];
        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = &block->patches[j];
            ClawPatch *cp = new ClawPatch();

            // Set stuff from p4est

            cp->define(patch->xlower,
                       patch->ylower,
                       patch->xupper,
                       patch->yupper,
                       gparms);
            set_patch_data(patch,cp);
        }
    }
}

void amrinit(fclaw2d_domain_t *domain)
{
    global_parms *gparms = get_domain_data(domain);
    for(int i = 0; i < domain->num_blocks; i++)
    {
        fclaw2d_block_t *block = &domain->blocks[i];
        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = &block->patches[j];
            ClawPatch *cp = get_patch_data(patch);

            cout << "Initializing patch " << j << " on block " << i << endl;
            cp->initialize();
            cp->setAuxArray(gparms->m_maxlevel,gparms->m_refratio,patch->level);

        }
    }
}

void amrrun(fclaw2d_domain_t *domain)
{
    global_parms *parms = get_domain_data(domain);
    double tfinal = parms->m_tfinal;
    cout << "Final time : " << tfinal << endl;

    for(int i = 0; i < domain->num_blocks; i++)
    {
        fclaw2d_block_t *block = &domain->blocks[i];
        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = &block->patches[j];
            ClawPatch *cp = get_patch_data(patch);

            cout << endl;
            cout << "Clawpatch info for patch number " << j << endl;
            cout << "cp->get_mx() " << cp->get_mx() << endl;
            cout << "cp->get_my() " << cp->get_my() << endl;
            cout << "cp->get_xlower() " << cp->get_xlower() << endl;
            cout << "cp->get_ylower() " << cp->get_ylower() << endl;
            cout << "cp->get_xupper() " << cp->get_xupper() << endl;
            cout << "cp->get_yupper() " << cp->get_yupper() << endl;
        }
    }
}

void amrreset(fclaw2d_domain_t *domain)
{
    fclaw2d_domain_data_t *dd;
    dd = (fclaw2d_domain_data_t *) domain->user;

    for(int i = 0; i < domain->num_blocks; i++)
    {
        fclaw2d_block_t *block = domain->blocks + i;
        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = block->patches + j;
            fclaw2d_patch_data_t *pd = (fclaw2d_patch_data_t *) patch->user;
            ClawPatch *cp = pd->cp;

            delete cp;
            P4EST_FREE (pd);
            patch->user = NULL;
        }
    }
    P4EST_FREE (dd);
    domain->user = NULL;
}
<commit_msg>Fixed one last merge error<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

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

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

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

#include "amr_forestclaw.H"
#include "amr_utils.H"

void set_domain_data(fclaw2d_domain_t *domain, global_parms *parms)
{
    fclaw2d_domain_data_t *ddata = P4EST_ALLOC (fclaw2d_domain_data_t, 1);
    domain->user = (void *) ddata;

    ddata->parms = parms;
}

global_parms* get_domain_data(fclaw2d_domain_t *domain)
{
    fclaw2d_domain_data_t *ddata;
    ddata = (fclaw2d_domain_data_t *) domain->user;

    return ddata->parms;
}

void set_patch_data(fclaw2d_patch_t *patch, ClawPatch* cp)
{
    fclaw2d_patch_data_t *pdata = P4EST_ALLOC (fclaw2d_patch_data_t, 1);
    patch->user = (void *) pdata;

    pdata->cp = cp;
}

ClawPatch* get_patch_data(fclaw2d_patch_t *patch)
{
    fclaw2d_patch_data_t *pdata;
    pdata = (fclaw2d_patch_data_t *) patch->user;

    return pdata->cp;
}

void amrsetup(fclaw2d_domain_t *domain)
{
    global_parms *gparms = new global_parms();
    cout << "Global parameters " << endl;
    gparms->get_inputParams();
    gparms->print_inputParams();

    set_domain_data(domain,gparms);

    for(int i = 0; i < domain->num_blocks; i++)
    {
        fclaw2d_block_t *block = &domain->blocks[i];
        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = &block->patches[j];
            ClawPatch *cp = new ClawPatch();

            // Set stuff from p4est

            cp->define(patch->xlower,
                       patch->ylower,
                       patch->xupper,
                       patch->yupper,
                       gparms);
            set_patch_data(patch,cp);
        }
    }
}

void amrinit(fclaw2d_domain_t *domain)
{
    global_parms *gparms = get_domain_data(domain);
    for(int i = 0; i < domain->num_blocks; i++)
    {
        fclaw2d_block_t *block = &domain->blocks[i];
        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = &block->patches[j];
            ClawPatch *cp = get_patch_data(patch);

            cout << "Initializing patch " << j << " on block " << i << endl;
            cp->initialize();
            cp->setAuxArray(gparms->m_maxlevel,gparms->m_refratio,patch->level);

        }
    }
}

void amrrun(fclaw2d_domain_t *domain)
{
    global_parms *parms = get_domain_data(domain);
    double tfinal = parms->m_tfinal;
    cout << "Final time : " << tfinal << endl;

    for(int i = 0; i < domain->num_blocks; i++)
    {
        fclaw2d_block_t *block = &domain->blocks[i];
        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = &block->patches[j];
            ClawPatch *cp = get_patch_data(patch);

            cout << endl;
            cout << "Clawpatch info for patch number " << j << endl;
            cout << "cp->get_mx() " << cp->get_mx() << endl;
            cout << "cp->get_my() " << cp->get_my() << endl;
            cout << "cp->get_xlower() " << cp->get_xlower() << endl;
            cout << "cp->get_ylower() " << cp->get_ylower() << endl;
            cout << "cp->get_xupper() " << cp->get_xupper() << endl;
            cout << "cp->get_yupper() " << cp->get_yupper() << endl;
        }
    }
}

void amrreset(fclaw2d_domain_t *domain)
{
    fclaw2d_domain_data_t *dd;
    dd = (fclaw2d_domain_data_t *) domain->user;

    for(int i = 0; i < domain->num_blocks; i++)
    {
        fclaw2d_block_t *block = domain->blocks + i;
        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = block->patches + j;
            fclaw2d_patch_data_t *pd = (fclaw2d_patch_data_t *) patch->user;
            ClawPatch *cp = pd->cp;

            delete cp;
            P4EST_FREE (pd);
            patch->user = NULL;
        }
    }
    P4EST_FREE (dd);
    domain->user = NULL;
}
<|endoftext|>


<commit_before>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include "fnord/util/binarymessagewriter.h"
#include "tsdb/TSDBServlet.h"
#include "tsdb/RecordEnvelope.pb.h"
#include "fnord/json/json.h"
#include <fnord/wallclock.h>
#include <fnord/thread/wakeup.h>
#include "fnord/protobuf/MessageEncoder.h"
#include "fnord/protobuf/MessagePrinter.h"
#include "fnord/protobuf/msg.h"
#include <fnord/util/Base64.h>
#include <fnord/fnv.h>
#include <sstable/sstablereader.h>
#include <chartsql/runtime/ASCIITableFormat.h>

using namespace fnord;

namespace tsdb {

TSDBServlet::TSDBServlet(TSDBNode* node) : node_(node) {}

void TSDBServlet::handleHTTPRequest(
    RefPtr<http::HTTPRequestStream> req_stream,
    RefPtr<http::HTTPResponseStream> res_stream) {
  req_stream->readBody();
  const auto& req = req_stream->request();
  URI uri(req.uri());

  http::HTTPResponse res;
  res.populateFromRequest(req);
  res.addHeader("Access-Control-Allow-Origin", "*");
  res.addHeader("Access-Control-Allow-Methods", "GET, POST");
  res.addHeader("Access-Control-Allow-Headers", "X-TSDB-Namespace");

  if (req.method() == http::HTTPMessage::M_OPTIONS) {
    res.setStatus(http::kStatusOK);
    res_stream->writeResponse(res);
    return;
  }

  try {
    if (uri.path() == "/tsdb/insert") {
      insertRecords(&req, &res, &uri);
      res_stream->writeResponse(res);
      return;
    }

    if (uri.path() == "/tsdb/stream") {
      streamPartition(&req, &res, res_stream, &uri);
      return;
    }

    if (uri.path() == "/tsdb/partition_info") {
      fetchPartitionInfo(&req, &res, &uri);
      res_stream->writeResponse(res);
      return;
    }

    if (uri.path() == "/tsdb/sql") {
      executeSQL(&req, &res, &uri);
      res_stream->writeResponse(res);
      return;
    }

    if (uri.path() == "/tsdb/sql_stream") {
      executeSQLStream(&req, &res, res_stream, &uri);
      return;
    }

    res.setStatus(fnord::http::kStatusNotFound);
    res.addBody("not found");
    res_stream->writeResponse(res);
  } catch (const Exception& e) {
    fnord::logError("tsdb", e, "error while processing HTTP request");

    res.setStatus(http::kStatusInternalServerError);
    res.addBody(StringUtil::format("error: $0: $1", e.getTypeName(), e.getMessage()));
    res_stream->writeResponse(res);
  }

  res_stream->finishResponse();
}

void TSDBServlet::insertRecords(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  auto record_list = msg::decode<RecordEnvelopeList>(req->body());

  Vector<RefPtr<Partition>> partition_refs;
  HashMap<Partition*, Vector<RecordRef>> grouped;
  for (const auto& record : record_list.records()) {
    auto partition = node_->findOrCreatePartition(
        record.tsdb_namespace(),
        record.stream_key(),
        SHA1Hash::fromHexString(record.partition_key()));

    auto record_data = record.record_data().data();
    auto record_size = record.record_data().size();

    if (grouped.count(partition.get()) == 0) {
      partition_refs.emplace_back(partition);
    }

    grouped[partition.get()].emplace_back(
        SHA1Hash::fromHexString(record.record_id()),
        Buffer(record_data, record_size));
  }

  for (const auto& group : grouped) {
    group.first->insertRecords(group.second);
  }

  res->setStatus(http::kStatusCreated);
}

void TSDBServlet::streamPartition(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    RefPtr<http::HTTPResponseStream> res_stream,
    URI* uri) {
  const auto& params = uri->queryParams();

  String tsdb_namespace;
  if (!URI::getParam(params, "namespace", &tsdb_namespace)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?namespace=... parameter");
    return;
  }

  String stream_key;
  if (!URI::getParam(params, "stream", &stream_key)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?stream=... parameter");
    return;
  }

  String partition_key;
  if (!URI::getParam(params, "partition", &partition_key)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?partition=... parameter");
    return;
  }

  size_t sample_mod = 0;
  size_t sample_idx = 0;
  String sample_str;
  if (URI::getParam(params, "sample", &sample_str)) {
    auto parts = StringUtil::split(sample_str, ":");

    if (parts.size() != 2) {
      res->setStatus(fnord::http::kStatusBadRequest);
      res->addBody("invalid ?sample=... parameter, format is <mod>:<idx>");
      res_stream->writeResponse(*res);
    }

    sample_mod = std::stoull(parts[0]);
    sample_idx = std::stoull(parts[1]);
  }

  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/octet-stream");
  res->addHeader("Connection", "close");
  res_stream->startResponse(*res);

  auto partition = node_->findPartition(
      tsdb_namespace,
      stream_key,
      SHA1Hash::fromHexString(partition_key));

  if (!partition.isEmpty()) {
    FNV<uint64_t> fnv;
    auto files = partition.get()->listFiles();

    for (const auto& f : files) {
      auto fpath = FileUtil::joinPaths(node_->dbPath(), f);
      sstable::SSTableReader reader(fpath);
      auto cursor = reader.getCursor();

      while (cursor->valid()) {
        uint64_t* key;
        size_t key_size;
        cursor->getKey((void**) &key, &key_size);
        if (key_size != SHA1Hash::kSize) {
          RAISE(kRuntimeError, "invalid row");
        }

        if (sample_mod == 0 ||
            (fnv.hash(key, key_size) % sample_mod == sample_idx)) {
          void* data;
          size_t data_size;
          cursor->getData(&data, &data_size);

          util::BinaryMessageWriter buf;
          if (data_size > 0) {
            buf.appendUInt64(data_size);
            buf.append(data, data_size);
            res_stream->writeBodyChunk(Buffer(buf.data(), buf.size()));
          }
          res_stream->waitForReader();
        }

        if (!cursor->next()) {
          break;
        }
      }
    }
  }

  util::BinaryMessageWriter buf;
  buf.appendUInt64(0);
  res_stream->writeBodyChunk(Buffer(buf.data(), buf.size()));

  res_stream->finishResponse();
}

void TSDBServlet::fetchPartitionInfo(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  const auto& params = uri->queryParams();

  String tsdb_namespace;
  if (!URI::getParam(params, "namespace", &tsdb_namespace)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?namespace=... parameter");
    return;
  }

  String stream_key;
  if (!URI::getParam(params, "stream", &stream_key)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?stream=... parameter");
    return;
  }

  String partition_key;
  if (!URI::getParam(params, "partition", &partition_key)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?partition=... parameter");
    return;
  }

  auto partition = node_->findPartition(
      tsdb_namespace,
      stream_key,
      SHA1Hash::fromHexString(partition_key));

  PartitionInfo pinfo;
  pinfo.set_partition_key(partition_key);
  if (!partition.isEmpty()) {
    pinfo = partition.get()->partitionInfo();
  }

  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/x-protobuf");
  res->addBody(*msg::encode(pinfo));
}

void TSDBServlet::executeSQL(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  if (!req->hasHeader("X-TSDB-Namespace")) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing X-TSDB-Namespace header");
    return;
  }

  auto tsdb_ns = req->getHeader("X-TSDB-Namespace");

  auto query = req->body().toString();
  auto qplan = node_->sqlEngine()->parseAndBuildQueryPlan(
      tsdb_ns,
      query);

  csql::ExecutionContext context;

  Buffer result;
  csql::ASCIITableFormat format;
  format.formatResults(
      qplan,
      &context,
      BufferOutputStream::fromBuffer(&result));

  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "text/plain");
  res->addHeader("Connection", "close");
  res->addBody(result);
}

void TSDBServlet::executeSQLStream(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    RefPtr<http::HTTPResponseStream> res_stream,
    URI* uri) {
  auto tsdb_ns = req->getHeader("X-TSDB-Namespace");

  auto query = req->body().toString();
  auto qplan = node_->sqlEngine()->parseAndBuildQueryPlan(
      tsdb_ns,
      query);

  http::HTTPSSEStream sse_stream(res, res_stream);
  sse_stream.start();

  csql::ExecutionContext context;
  context.onStatusChange([&sse_stream] (const csql::ExecutionStatus& status) {
    auto progress = status.progress();

    Buffer buf;
    json::JSONOutputStream json(BufferOutputStream::fromBuffer(&buf));
    json.beginObject();
    json.addObjectEntry("status");
    json.addString("running");
    json.addComma();
    json.addObjectEntry("progress");
    json.addFloat(progress);
    json.addComma();
    json.addObjectEntry("message");
    if (progress == 0.0f) {
      json.addString("Waiting...");
    } else if (progress == 1.0f) {
      json.addString("Downloading...");
    } else {
      json.addString("Running...");
    }
    json.endObject();

    sse_stream.sendEvent(buf, Some(String("status")));
  });

  Buffer result;
  csql::ASCIITableFormat format;
  format.formatResults(
      qplan,
      &context,
      BufferOutputStream::fromBuffer(&result));

  sse_stream.sendEvent(result, Some(String("result")));
  sse_stream.finish();
}

}

<commit_msg>/sql_stream<commit_after>/**
 * This file is part of the "libfnord" project
 *   Copyright (c) 2015 Paul Asmuth
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include "fnord/util/binarymessagewriter.h"
#include "tsdb/TSDBServlet.h"
#include "tsdb/RecordEnvelope.pb.h"
#include "fnord/json/json.h"
#include <fnord/wallclock.h>
#include <fnord/thread/wakeup.h>
#include "fnord/protobuf/MessageEncoder.h"
#include "fnord/protobuf/MessagePrinter.h"
#include "fnord/protobuf/msg.h"
#include <fnord/util/Base64.h>
#include <fnord/fnv.h>
#include <sstable/sstablereader.h>
#include <chartsql/runtime/ASCIITableFormat.h>

using namespace fnord;

namespace tsdb {

TSDBServlet::TSDBServlet(TSDBNode* node) : node_(node) {}

void TSDBServlet::handleHTTPRequest(
    RefPtr<http::HTTPRequestStream> req_stream,
    RefPtr<http::HTTPResponseStream> res_stream) {
  req_stream->readBody();
  const auto& req = req_stream->request();
  URI uri(req.uri());

  http::HTTPResponse res;
  res.populateFromRequest(req);
  res.addHeader("Access-Control-Allow-Origin", "*");
  res.addHeader("Access-Control-Allow-Methods", "GET, POST");
  res.addHeader("Access-Control-Allow-Headers", "X-TSDB-Namespace");

  if (req.method() == http::HTTPMessage::M_OPTIONS) {
    res.setStatus(http::kStatusOK);
    res_stream->writeResponse(res);
    return;
  }

  try {
    if (uri.path() == "/tsdb/insert") {
      insertRecords(&req, &res, &uri);
      res_stream->writeResponse(res);
      return;
    }

    if (uri.path() == "/tsdb/stream") {
      streamPartition(&req, &res, res_stream, &uri);
      return;
    }

    if (uri.path() == "/tsdb/partition_info") {
      fetchPartitionInfo(&req, &res, &uri);
      res_stream->writeResponse(res);
      return;
    }

    if (uri.path() == "/tsdb/sql") {
      executeSQL(&req, &res, &uri);
      res_stream->writeResponse(res);
      return;
    }

    if (uri.path() == "/tsdb/sql_stream") {
      fnord::iputs("match", 1);
      executeSQLStream(&req, &res, res_stream, &uri);
      return;
    }

    res.setStatus(fnord::http::kStatusNotFound);
    res.addBody("not found");
    res_stream->writeResponse(res);
  } catch (const Exception& e) {
    fnord::logError("tsdb", e, "error while processing HTTP request");

    res.setStatus(http::kStatusInternalServerError);
    res.addBody(StringUtil::format("error: $0: $1", e.getTypeName(), e.getMessage()));
    res_stream->writeResponse(res);
  }

  res_stream->finishResponse();
}

void TSDBServlet::insertRecords(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  auto record_list = msg::decode<RecordEnvelopeList>(req->body());

  Vector<RefPtr<Partition>> partition_refs;
  HashMap<Partition*, Vector<RecordRef>> grouped;
  for (const auto& record : record_list.records()) {
    auto partition = node_->findOrCreatePartition(
        record.tsdb_namespace(),
        record.stream_key(),
        SHA1Hash::fromHexString(record.partition_key()));

    auto record_data = record.record_data().data();
    auto record_size = record.record_data().size();

    if (grouped.count(partition.get()) == 0) {
      partition_refs.emplace_back(partition);
    }

    grouped[partition.get()].emplace_back(
        SHA1Hash::fromHexString(record.record_id()),
        Buffer(record_data, record_size));
  }

  for (const auto& group : grouped) {
    group.first->insertRecords(group.second);
  }

  res->setStatus(http::kStatusCreated);
}

void TSDBServlet::streamPartition(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    RefPtr<http::HTTPResponseStream> res_stream,
    URI* uri) {
  const auto& params = uri->queryParams();

  String tsdb_namespace;
  if (!URI::getParam(params, "namespace", &tsdb_namespace)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?namespace=... parameter");
    res_stream->writeResponse(*res);
    return;
  }

  String stream_key;
  if (!URI::getParam(params, "stream", &stream_key)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?stream=... parameter");
    res_stream->writeResponse(*res);
    return;
  }

  String partition_key;
  if (!URI::getParam(params, "partition", &partition_key)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?partition=... parameter");
    res_stream->writeResponse(*res);
    return;
  }

  size_t sample_mod = 0;
  size_t sample_idx = 0;
  String sample_str;
  if (URI::getParam(params, "sample", &sample_str)) {
    auto parts = StringUtil::split(sample_str, ":");

    if (parts.size() != 2) {
      res->setStatus(fnord::http::kStatusBadRequest);
      res->addBody("invalid ?sample=... parameter, format is <mod>:<idx>");
      res_stream->writeResponse(*res);
    }

    sample_mod = std::stoull(parts[0]);
    sample_idx = std::stoull(parts[1]);
  }

  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/octet-stream");
  res->addHeader("Connection", "close");
  res_stream->startResponse(*res);

  auto partition = node_->findPartition(
      tsdb_namespace,
      stream_key,
      SHA1Hash::fromHexString(partition_key));

  if (!partition.isEmpty()) {
    FNV<uint64_t> fnv;
    auto files = partition.get()->listFiles();

    for (const auto& f : files) {
      auto fpath = FileUtil::joinPaths(node_->dbPath(), f);
      sstable::SSTableReader reader(fpath);
      auto cursor = reader.getCursor();

      while (cursor->valid()) {
        uint64_t* key;
        size_t key_size;
        cursor->getKey((void**) &key, &key_size);
        if (key_size != SHA1Hash::kSize) {
          RAISE(kRuntimeError, "invalid row");
        }

        if (sample_mod == 0 ||
            (fnv.hash(key, key_size) % sample_mod == sample_idx)) {
          void* data;
          size_t data_size;
          cursor->getData(&data, &data_size);

          util::BinaryMessageWriter buf;
          if (data_size > 0) {
            buf.appendUInt64(data_size);
            buf.append(data, data_size);
            res_stream->writeBodyChunk(Buffer(buf.data(), buf.size()));
          }
          res_stream->waitForReader();
        }

        if (!cursor->next()) {
          break;
        }
      }
    }
  }

  util::BinaryMessageWriter buf;
  buf.appendUInt64(0);
  res_stream->writeBodyChunk(Buffer(buf.data(), buf.size()));

  res_stream->finishResponse();
}

void TSDBServlet::fetchPartitionInfo(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  const auto& params = uri->queryParams();

  String tsdb_namespace;
  if (!URI::getParam(params, "namespace", &tsdb_namespace)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?namespace=... parameter");
    return;
  }

  String stream_key;
  if (!URI::getParam(params, "stream", &stream_key)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?stream=... parameter");
    return;
  }

  String partition_key;
  if (!URI::getParam(params, "partition", &partition_key)) {
    res->setStatus(fnord::http::kStatusBadRequest);
    res->addBody("missing ?partition=... parameter");
    return;
  }

  auto partition = node_->findPartition(
      tsdb_namespace,
      stream_key,
      SHA1Hash::fromHexString(partition_key));

  PartitionInfo pinfo;
  pinfo.set_partition_key(partition_key);
  if (!partition.isEmpty()) {
    pinfo = partition.get()->partitionInfo();
  }

  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/x-protobuf");
  res->addBody(*msg::encode(pinfo));
}

void TSDBServlet::executeSQL(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  auto tsdb_ns = req->getHeader("X-TSDB-Namespace");

  auto query = req->body().toString();
  auto qplan = node_->sqlEngine()->parseAndBuildQueryPlan(
      tsdb_ns,
      query);

  csql::ExecutionContext context;

  Buffer result;
  csql::ASCIITableFormat format;
  format.formatResults(
      qplan,
      &context,
      BufferOutputStream::fromBuffer(&result));

  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "text/plain");
  res->addHeader("Connection", "close");
  res->addBody(result);
}

void TSDBServlet::executeSQLStream(
    const http::HTTPRequest* req,
    http::HTTPResponse* res,
    RefPtr<http::HTTPResponseStream> res_stream,
    URI* uri) {
  http::HTTPSSEStream sse_stream(res, res_stream);
  sse_stream.start();

  const auto& params = uri->queryParams();

  String tsdb_namespace;
  if (!URI::getParam(params, "namespace", &tsdb_namespace)) {
    sse_stream.sendEvent(
        "missing ?namespace=... parameter",
        Some(String("error")));

    sse_stream.finish();
    return;
  }

  String query;
  if (!URI::getParam(params, "query", &query)) {
    sse_stream.sendEvent(
        "missing ?query=... parameter",
        Some(String("error")));

    sse_stream.finish();
    return;
  }

  Buffer result;
  try {
    auto qplan = node_->sqlEngine()->parseAndBuildQueryPlan(
        tsdb_namespace,
        query);

    csql::ExecutionContext context;

    context.onStatusChange([&sse_stream] (const csql::ExecutionStatus& status) {
      auto progress = status.progress();

      Buffer buf;
      json::JSONOutputStream json(BufferOutputStream::fromBuffer(&buf));
      json.beginObject();
      json.addObjectEntry("status");
      json.addString("running");
      json.addComma();
      json.addObjectEntry("progress");
      json.addFloat(progress);
      json.addComma();
      json.addObjectEntry("message");
      if (progress == 0.0f) {
        json.addString("Waiting...");
      } else if (progress == 1.0f) {
        json.addString("Downloading...");
      } else {
        json.addString("Running...");
      }
      json.endObject();

      sse_stream.sendEvent(buf, Some(String("status")));
    });

    csql::ASCIITableFormat format;
    format.formatResults(
        qplan,
        &context,
        BufferOutputStream::fromBuffer(&result));
  } catch (const StandardException& e) {
    fnord::logError("tsdb.sql", e, "SQL execution failed");
    sse_stream.sendEvent(e.what(), Some(String("error")));
    sse_stream.finish();
  }

  sse_stream.sendEvent(result, Some(String("result")));
  sse_stream.finish();
}

}

<|endoftext|>


<commit_before>/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-5-12 20:48:31
 * 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 0 // 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;

string s;
int K;
set<string> S;

int main()
{
  cin >> s;
  cin >> K;
  int N = (int)s.size();
  for (auto i = 0; i < N; i++)
  {
    for (auto j = 0; i + j < N && j < 5; j++)
    {
      S.insert(s.substr(i, j));
    }
  }
  auto it = S.begin();
  for (auto k = 0; k < K - 1; k++)
  {
    it++;
  }
  cout << *it << endl;
}<commit_msg>tried C.cpp to 'C'<commit_after>/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-5-12 20:48:31
 * 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 0 // 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;

string s;
int K;
set<string> S;

int main()
{
  cin >> s;
  cin >> K;
  int N = (int)s.size();
  for (auto i = 0; i < N; i++)
  {
    for (auto j = 1; i + j <= N && j < 5; j++)
    {
      S.insert(s.substr(i, j));
    }
  }
  auto it = S.begin();
  for (auto k = 0; k < K - 1; k++)
  {
    it++;
  }
  cout << *it << endl;
}<|endoftext|>


<commit_before>/* OpenSceneGraph example, osgshape.
*
*  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 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.
*/

#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/Texture2D>

#include <osgViewer/Viewer>

#include <osgDB/ReadFile>

#include <osg/Math>

// for the grid data..
#include "../osghangglide/terrain_coords.h"

osg::Geode* createShapes()
{
    osg::Geode* geode = new osg::Geode();

    // ---------------------------------------
    // Set up a StateSet to texture the objects
    // ---------------------------------------
    osg::StateSet* stateset = new osg::StateSet();

    osg::Image* image = osgDB::readImageFile( "Images/lz.rgb" );

    if (image)
    {
        osg::Texture2D* texture = new osg::Texture2D;
        texture->setImage(image);
        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
    }

    geode->setStateSet( stateset );

    float radius = 0.8f;
    float height = 1.0f;

    osg::TessellationHints* hints = new osg::TessellationHints;
    hints->setDetailRatio(0.5f);

    geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius),hints));
    geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(2.0f,0.0f,0.0f),2*radius),hints));
    geode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3(4.0f,0.0f,0.0f),radius,height),hints));
    geode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(6.0f,0.0f,0.0f),radius,height),hints));
    geode->addDrawable(new osg::ShapeDrawable(new osg::Capsule(osg::Vec3(8.0f,0.0f,0.0f),radius,height),hints));

    osg::HeightField* grid = new osg::HeightField;
    grid->allocate(38,39);
    grid->setXInterval(0.28f);
    grid->setYInterval(0.28f);

    for(unsigned int r=0;r<39;++r)
    {
        for(unsigned int c=0;c<38;++c)
        {
            grid->setHeight(c,r,vertex[r+c*39][2]);
        }
    }
    geode->addDrawable(new osg::ShapeDrawable(grid));

    osg::ConvexHull* mesh = new osg::ConvexHull;
    osg::Vec3Array* vertices = new osg::Vec3Array(4);
    (*vertices)[0].set(9.0+0.0f,-1.0f+2.0f,-1.0f+0.0f);
    (*vertices)[1].set(9.0+1.0f,-1.0f+0.0f,-1.0f+0.0f);
    (*vertices)[2].set(9.0+2.0f,-1.0f+2.0f,-1.0f+0.0f);
    (*vertices)[3].set(9.0+1.0f,-1.0f+1.0f,-1.0f+2.0f);
    osg::UByteArray* indices = new osg::UByteArray(12);
    (*indices)[0]=0;
    (*indices)[1]=2;
    (*indices)[2]=1;
    (*indices)[3]=0;
    (*indices)[4]=1;
    (*indices)[5]=3;
    (*indices)[6]=1;
    (*indices)[7]=2;
    (*indices)[8]=3;
    (*indices)[9]=2;
    (*indices)[10]=0;
    (*indices)[11]=3;
    mesh->setVertices(vertices);
    mesh->setIndices(indices);
    geode->addDrawable(new osg::ShapeDrawable(mesh));

    return geode;
}

int main(int, char **)
{
    // construct the viewer.
    osgViewer::Viewer viewer;

    // add model to viewer.
    viewer.setSceneData( createShapes() );

    return viewer.run();
}
<commit_msg>Added enabling of lighting, and disabling of mipmapping to help out testing of GLES2 target<commit_after>/* OpenSceneGraph example, osgshape.
*
*  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 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.
*/

#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/Texture2D>
#include <osgUtil/ShaderGen>

#include <osgViewer/Viewer>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osg/Math>

// for the grid data..
#include "../osghangglide/terrain_coords.h"

osg::Geode* createShapes()
{
    osg::Geode* geode = new osg::Geode();

    // ---------------------------------------
    // Set up a StateSet to texture the objects
    // ---------------------------------------
    osg::StateSet* stateset = new osg::StateSet();

    osg::Image* image = osgDB::readImageFile( "Images/lz.rgb" );
    if (image)
    {
        osg::Texture2D* texture = new osg::Texture2D;
        texture->setImage(image);
        texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
        stateset->setTextureAttributeAndModes(0,texture, osg::StateAttribute::ON);
    }

    stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);

    geode->setStateSet( stateset );

    float radius = 0.8f;
    float height = 1.0f;

    osg::TessellationHints* hints = new osg::TessellationHints;
    hints->setDetailRatio(0.5f);

    geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius),hints));
    geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(2.0f,0.0f,0.0f),2*radius),hints));
    geode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3(4.0f,0.0f,0.0f),radius,height),hints));
    geode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(6.0f,0.0f,0.0f),radius,height),hints));
    geode->addDrawable(new osg::ShapeDrawable(new osg::Capsule(osg::Vec3(8.0f,0.0f,0.0f),radius,height),hints));

    osg::HeightField* grid = new osg::HeightField;
    grid->allocate(38,39);
    grid->setXInterval(0.28f);
    grid->setYInterval(0.28f);

    for(unsigned int r=0;r<39;++r)
    {
        for(unsigned int c=0;c<38;++c)
        {
            grid->setHeight(c,r,vertex[r+c*39][2]);
        }
    }
    geode->addDrawable(new osg::ShapeDrawable(grid));

    osg::ConvexHull* mesh = new osg::ConvexHull;
    osg::Vec3Array* vertices = new osg::Vec3Array(4);
    (*vertices)[0].set(9.0+0.0f,-1.0f+2.0f,-1.0f+0.0f);
    (*vertices)[1].set(9.0+1.0f,-1.0f+0.0f,-1.0f+0.0f);
    (*vertices)[2].set(9.0+2.0f,-1.0f+2.0f,-1.0f+0.0f);
    (*vertices)[3].set(9.0+1.0f,-1.0f+1.0f,-1.0f+2.0f);
    osg::UByteArray* indices = new osg::UByteArray(12);
    (*indices)[0]=0;
    (*indices)[1]=2;
    (*indices)[2]=1;
    (*indices)[3]=0;
    (*indices)[4]=1;
    (*indices)[5]=3;
    (*indices)[6]=1;
    (*indices)[7]=2;
    (*indices)[8]=3;
    (*indices)[9]=2;
    (*indices)[10]=0;
    (*indices)[11]=3;
    mesh->setVertices(vertices);
    mesh->setIndices(indices);
    geode->addDrawable(new osg::ShapeDrawable(mesh));

    return geode;
}

int main(int, char **)
{
    // construct the viewer.
    osgViewer::Viewer viewer;

    // add model to viewer.
    viewer.setSceneData( createShapes() );

    return viewer.run();
}
<|endoftext|>


<commit_before>/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-7-2 20:45:55
 * 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 <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // 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 MOD = 1000000007;
const ll M = 250010;
random_device rd;
mt19937 mt(rd());
typedef tuple<ll, ll> D;

int N;
string S;
map<ll, int> ans;
ll X;
ll X_inv;
ll C;
ll a[500100];
D g[250010];
map<ll, ll> G;

ll power2(int i)
{
  if (i == 0)
  {
    return 1;
  }
  else if (i % 2 == 0)
  {
    ll half = power2(i / 2);
    return (half * half) % MOD;
  }
  else
  {
    return (power2(i - 1) * X) % MOD;
  }
}

ll power(int i)
{
  if (i == 0)
  {
    return 1;
  }
  else if (i < 0)
  {
    return power2(MOD + i - 1);
  }
  return power2(i);
}

ll calc_hash()
{
  fill(a, a + 500100, 0);
  int P = M;
  for (auto e : S)
  {
    if (e == '+')
    {
      a[P]++;
    }
    else if (e == '-')
    {
      a[P]--;
    }
    else if (e == '>')
    {
      P++;
    }
    else
    {
      P--;
    }
  }
  ll res = 0;
  for (auto i = 0; i < 500100; i++)
  {
    res += (((MOD + a[i]) % MOD) * power(i - M)) % MOD;
    res %= MOD;
  }
  return res;
}

void calc_g()
{
  g[N] = D(1, 0);
  for (auto i = N - 1; i >= 0; i--)
  {
    ll A_prime = get<0>(g[i + 1]);
    ll B_prime = get<1>(g[i + 1]);
    ll A, B;
    if (S[i] == '+')
    {
      A = 1, B = MOD - 1;
    }
    else if (S[i] == '-')
    {
      A = 1, B = 1;
    }
    else if (S[i] == '>')
    {
      A = X_inv, B = 0;
    }
    else
    {
      A = X, B = 0;
    }
    g[i] = D((A_prime * A) % MOD,
             ((A_prime * B) % MOD + B_prime) % MOD);
  }
}

ll count_ans()
{
  ll res = 0;
  G.clear();
  for (int i = N; i >= 1; i--)
  {
    ll J = get<1>(g[i]);
    if (G.find(J) == G.end())
    {
      G[J] = 1;
    }
    else
    {
      G[J]++;
    }
    ll I = ((get<0>(g[i - 1]) * C) % MOD + get<1>(g[i - 1])) % MOD;

    if (G.find(I) != G.end())
    {
      // cerr << "i = " << i - 1 << ", cnt of j = " << G[I] << endl;
      res += G[I];
    }
  }
  return res;
}

void solve()
{
  X = abs((ll)mt());
  X_inv = power(-1);
  C = calc_hash();
  calc_g();
  ll res = count_ans();
  if (ans.find(res) == ans.end())
  {
    ans[res] = 1;
  }
  else
  {
    ans[res]++;
  }
}

int main()
{
  cin >> N >> S;
  for (auto i = 0; i < 3; i++)
  {
    solve();
  }
  ll res = 0;
  int maxi = 0;
  for (auto e : ans)
  {
    ll a = e.first;
    int cnt = e.second;
    if (cnt > maxi)
    {
      cnt = maxi;
      res = a;
    }
  }
  cout << res << endl;
}<commit_msg>submit F.cpp to 'F - Eating Symbols Hard' (arc099) [C++14 (GCC 5.4.1)]<commit_after>/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-7-2 20:45:55
 * 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()); uniform_int_distribution<int> ra(0, 99); ra(mt);
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // 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 MOD = 1000000007;
const ll M = 250010;
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<ll> ra(1, MOD - 1);
typedef tuple<ll, ll> D;

int N;
string S;
map<ll, int> ans;
ll X;
ll X_inv;
ll C;
ll a[500100];
D g[250010];
map<ll, ll> G;

ll power2(int i)
{
  if (i == 0)
  {
    return 1;
  }
  else if (i % 2 == 0)
  {
    ll half = power2(i / 2);
    return (half * half) % MOD;
  }
  else
  {
    return (power2(i - 1) * X) % MOD;
  }
}

ll power(int i)
{
  if (i == 0)
  {
    return 1;
  }
  else if (i < 0)
  {
    return power2(MOD + i - 1);
  }
  return power2(i);
}

ll calc_hash()
{
  fill(a, a + 500100, 0);
  int P = M;
  for (auto e : S)
  {
    if (e == '+')
    {
      a[P]++;
    }
    else if (e == '-')
    {
      a[P]--;
    }
    else if (e == '>')
    {
      P++;
    }
    else
    {
      P--;
    }
  }
  ll res = 0;
  for (auto i = 0; i < 500100; i++)
  {
    res += (((MOD + a[i]) % MOD) * power(i - M)) % MOD;
    res %= MOD;
  }
  return res;
}

void calc_g()
{
  g[N] = D(1, 0);
  for (auto i = N - 1; i >= 0; i--)
  {
    ll A_prime = get<0>(g[i + 1]);
    ll B_prime = get<1>(g[i + 1]);
    ll A, B;
    if (S[i] == '+')
    {
      A = 1, B = MOD - 1;
    }
    else if (S[i] == '-')
    {
      A = 1, B = 1;
    }
    else if (S[i] == '>')
    {
      A = X_inv, B = 0;
    }
    else
    {
      A = X, B = 0;
    }
    g[i] = D((A_prime * A) % MOD,
             ((A_prime * B) % MOD + B_prime) % MOD);
  }
}

ll count_ans()
{
  ll res = 0;
  G.clear();
  for (int i = N; i >= 1; i--)
  {
    ll J = get<1>(g[i]);
    if (G.find(J) == G.end())
    {
      G[J] = 1;
    }
    else
    {
      G[J]++;
    }
    ll I = ((get<0>(g[i - 1]) * C) % MOD + get<1>(g[i - 1])) % MOD;

    if (G.find(I) != G.end())
    {
      // cerr << "i = " << i - 1 << ", cnt of j = " << G[I] << endl;
      res += G[I];
    }
  }
  return res;
}

void solve()
{
  X = ra(mt);
  X_inv = power(-1);
  C = calc_hash();
  calc_g();
  ll res = count_ans();
  if (ans.find(res) == ans.end())
  {
    ans[res] = 1;
  }
  else
  {
    ans[res]++;
  }
}

int main()
{
  cin >> N >> S;
  for (auto i = 0; i < 4; i++)
  {
    solve();
  }
  ll res = 0;
  int maxi = 0;
  for (auto e : ans)
  {
    ll a = e.first;
    int cnt = e.second;
    if (cnt > maxi)
    {
      cnt = maxi;
      res = a;
    }
  }
  cout << res << endl;
}<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 1/15/2020, 8:11:07 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll lcm(ll x, ll y) { return x / gcd(x, y) * y; }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

using I = int16_t;

enum class Color : I
{
  None = 0,
  Black = 1,
  White = 2,
  Mixed = 3,
  Invalid
};
ostream &operator<<(ostream &os, Color C)
{
  return os << static_cast<I>(C);
}
Color operator|(Color L, Color R)
{
  return static_cast<Color>(static_cast<I>(L) | static_cast<I>(R));
}

constexpr I C{186};
constexpr I X{16};

// The memory limit is strict.
I dp1[X][C][C][C];
I dp2[X][C][C][C];

I H, W;
Color A[C][C];

vector<Color> press_X(int X0, int X1)
{
  assert(X0 < X1);
  vector<Color> V(W, Color::None);
  for (auto j = 0; j < W; j++)
  {
    for (auto i = X0; i < X1; i++)
    {
      V[j] = V[j] | A[i][j];
    }
  }
  return V;
}

vector<Color> press_Y(int Y0, int Y1)
{
  assert(Y0 < Y1);
  vector<Color> V(H, Color::None);
  for (auto i = 0; i < H; i++)
  {
    for (auto j = Y0; j < Y1; j++)
    {
      V[i] = V[i] | A[i][j];
    }
  }
  return V;
}

void zero_setup()
{
  // dp1
  for (auto X0 = 0; X0 <= H; X0++)
  {
    for (auto X1 = X0; X1 <= H; X1++)
    {
      if (X0 == X1)
      {
        for (auto Y0 = 0; Y0 <= W; Y0++)
        {
          dp1[0][X0][X1][Y0] = W;
        }
      }
      else
      {
        auto V{press_X(X0, X1)};
        auto Y1{W};
        auto now{Color::None};
        dp1[0][X0][X1][W] = W;
        for (auto Y0 = W - 1; Y0 >= 0; --Y0)
        {
          auto next{now | V[Y0]};
          if (next != Color::Mixed)
          {
            now = next;
          }
          else if (V[Y0] == Color::Black || V[Y0] == Color::White)
          {
            Y1 = Y0 + 1;
            now = V[Y0];
          }
          else
          {
            Y1 = Y0;
            now = Color::None;
          }
          dp1[0][X0][X1][Y0] = Y1;
        }
      }
    }
  }
  // dp2
  for (auto Y0 = 0; Y0 <= W; Y0++)
  {
    for (auto Y1 = Y0; Y1 <= W; Y1++)
    {
      if (Y0 == Y1)
      {
        for (auto X0 = 0; X0 <= H; X0++)
        {
          dp2[0][Y0][Y1][X0] = H;
        }
      }
      else
      {
        auto V{press_Y(Y0, Y1)};
        auto X1{H};
        auto now{Color::None};
        dp2[0][Y0][Y1][H] = H;
        for (auto X0 = H - 1; X0 >= 0; --X0)
        {
          auto next{now | V[X0]};
          if (next != Color::Mixed)
          {
            now = next;
          }
          else if (V[X0] == Color::Black || V[X0] == Color::White)
          {
            X1 = X0 + 1;
            now = V[X0];
          }
          else
          {
            X1 = X0;
            now = Color::None;
          }
          dp2[0][Y0][Y1][X0] = X1;
        }
      }
    }
  }
}

void fill_dp1(int k)
{
  for (auto X0 = 0; X0 <= H; ++X0)
  {
    for (auto X1 = X0; X1 <= H; ++X1)
    {
      I Y0{W}, Y1{W};
      while (Y0 >= 0)
      {
        assert(Y0 <= Y1);
        if (dp1[k - 1][X0][X1][dp1[k - 1][X0][X1][Y0]] >= Y1 || dp2[k - 1][Y0][Y1][dp2[k - 1][Y0][Y1][X0]] >= X1)
        {
          dp1[k][X0][X1][Y0] = Y1;
#if DEBUG == 1
          cerr << "dp1[" << k << "][" << X0 << "][" << X1 << "][" << Y0 << "] = " << Y1 << endl;
#endif
          Y0--;
        }
        else
        {
          Y1--;
        }
      }
    }
  }
}

void fill_dp2(int k)
{
  for (auto Y0 = 0; Y0 <= W; ++Y0)
  {
    for (auto Y1 = Y0; Y1 <= W; ++Y1)
    {
      I X0{H}, X1{H};
      while (X0 >= 0)
      {
        assert(X0 <= X1);
        if (dp2[k - 1][Y0][Y1][dp2[k - 1][Y0][Y1][X0]] >= X1 || dp1[k - 1][X0][X1][dp1[k - 1][X0][X1][Y0]] >= Y1)
        {
          dp2[k][Y0][Y1][X0] = X1;
          X0--;
        }
        else
        {
          X1--;
        }
      }
    }
  }
}

int main()
{
  cin >> H >> W;
  for (auto i = 0; i < H; i++)
  {
    string S;
    cin >> S;
    for (auto j = 0; j < W; j++)
    {
      if (S[j] == '.')
      {
        A[i][j] = Color::White;
      }
      else
      {
        A[i][j] = Color::Black;
      }
    }
  }
  zero_setup();
  for (auto k = 1; k <= 16; ++k)
  {
    fill_dp1(k);
    fill_dp2(k);
  }
  I ans_X{-1}, ans_Y{-1};
  for (I k = 16; k >= 0; --k)
  {
    if (dp1[k][0][H][0] >= W)
    {
      ch_max(ans_X, k);
    }
    if (dp2[k][0][W][0] >= H)
    {
      ch_max(ans_Y, k);
    }
  }
  assert(ans_X >= 0);
  assert(ans_Y >= 0);
  assert(ans_X == ans_Y);
  cout << ans_X << endl;
}
<commit_msg>tried D.cpp to 'D'<commit_after>#define DEBUG 1
/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 1/15/2020, 8:11:07 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll lcm(ll x, ll y) { return x / gcd(x, y) * y; }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

using I = int16_t;

enum class Color : I
{
  None = 0,
  Black = 1,
  White = 2,
  Mixed = 3,
  Invalid
};
ostream &operator<<(ostream &os, Color C)
{
  return os << static_cast<I>(C);
}
Color operator|(Color L, Color R)
{
  return static_cast<Color>(static_cast<I>(L) | static_cast<I>(R));
}

constexpr I C{186};
constexpr I X{17};

// The memory limit is strict.
I dp1[X][C][C][C];
I dp2[X][C][C][C];

I H, W;
Color A[C][C];

vector<Color> press_X(int X0, int X1)
{
  assert(X0 < X1);
  vector<Color> V(W, Color::None);
  for (auto j = 0; j < W; j++)
  {
    for (auto i = X0; i < X1; i++)
    {
      V[j] = V[j] | A[i][j];
    }
  }
  return V;
}

vector<Color> press_Y(int Y0, int Y1)
{
  assert(Y0 < Y1);
  vector<Color> V(H, Color::None);
  for (auto i = 0; i < H; i++)
  {
    for (auto j = Y0; j < Y1; j++)
    {
      V[i] = V[i] | A[i][j];
    }
  }
  return V;
}

void zero_setup()
{
  // dp1
  for (auto X0 = 0; X0 <= H; X0++)
  {
    for (auto X1 = X0; X1 <= H; X1++)
    {
      if (X0 == X1)
      {
        for (auto Y0 = 0; Y0 <= W; Y0++)
        {
          dp1[0][X0][X1][Y0] = W;
        }
      }
      else
      {
        auto V{press_X(X0, X1)};
        auto Y1{W};
        auto now{Color::None};
        dp1[0][X0][X1][W] = W;
        for (auto Y0 = W - 1; Y0 >= 0; --Y0)
        {
          auto next{now | V[Y0]};
          if (next != Color::Mixed)
          {
            now = next;
          }
          else if (V[Y0] == Color::Black || V[Y0] == Color::White)
          {
            Y1 = Y0 + 1;
            now = V[Y0];
          }
          else
          {
            Y1 = Y0;
            now = Color::None;
          }
          dp1[0][X0][X1][Y0] = Y1;
        }
      }
    }
  }
  // dp2
  for (auto Y0 = 0; Y0 <= W; Y0++)
  {
    for (auto Y1 = Y0; Y1 <= W; Y1++)
    {
      if (Y0 == Y1)
      {
        for (auto X0 = 0; X0 <= H; X0++)
        {
          dp2[0][Y0][Y1][X0] = H;
        }
      }
      else
      {
        auto V{press_Y(Y0, Y1)};
        auto X1{H};
        auto now{Color::None};
        dp2[0][Y0][Y1][H] = H;
        for (auto X0 = H - 1; X0 >= 0; --X0)
        {
          auto next{now | V[X0]};
          if (next != Color::Mixed)
          {
            now = next;
          }
          else if (V[X0] == Color::Black || V[X0] == Color::White)
          {
            X1 = X0 + 1;
            now = V[X0];
          }
          else
          {
            X1 = X0;
            now = Color::None;
          }
          dp2[0][Y0][Y1][X0] = X1;
        }
      }
    }
  }
}

void fill_dp1(int k)
{
  for (auto X0 = 0; X0 <= H; ++X0)
  {
    for (auto X1 = X0; X1 <= H; ++X1)
    {
      I Y0{W}, Y1{W};
      while (Y0 >= 0)
      {
        assert(Y0 <= Y1);
        if (dp1[k - 1][X0][X1][dp1[k - 1][X0][X1][Y0]] >= Y1 || dp2[k - 1][Y0][Y1][dp2[k - 1][Y0][Y1][X0]] >= X1)
        {
          dp1[k][X0][X1][Y0] = Y1;
#if DEBUG == 1
          cerr << "dp1[" << k << "][" << X0 << "][" << X1 << "][" << Y0 << "] = " << Y1 << endl;
#endif
          Y0--;
        }
        else
        {
          Y1--;
        }
      }
    }
  }
}

void fill_dp2(int k)
{
  for (auto Y0 = 0; Y0 <= W; ++Y0)
  {
    for (auto Y1 = Y0; Y1 <= W; ++Y1)
    {
      I X0{H}, X1{H};
      while (X0 >= 0)
      {
        assert(X0 <= X1);
        if (dp2[k - 1][Y0][Y1][dp2[k - 1][Y0][Y1][X0]] >= X1 || dp1[k - 1][X0][X1][dp1[k - 1][X0][X1][Y0]] >= Y1)
        {
          dp2[k][Y0][Y1][X0] = X1;
          X0--;
        }
        else
        {
          X1--;
        }
      }
    }
  }
}

int main()
{
  cin >> H >> W;
  for (auto i = 0; i < H; i++)
  {
    string S;
    cin >> S;
    for (auto j = 0; j < W; j++)
    {
      if (S[j] == '.')
      {
        A[i][j] = Color::White;
      }
      else
      {
        A[i][j] = Color::Black;
      }
    }
  }
  zero_setup();
  for (auto k = 1; k <= 16; ++k)
  {
    fill_dp1(k);
    fill_dp2(k);
  }
  I ans_X{-1}, ans_Y{-1};
  for (I k = 16; k >= 0; --k)
  {
    if (dp1[k][0][H][0] >= W)
    {
      ch_max(ans_X, k);
    }
    if (dp2[k][0][W][0] >= H)
    {
      ch_max(ans_Y, k);
    }
  }
  assert(ans_X >= 0);
  assert(ans_Y >= 0);
  assert(ans_X == ans_Y);
  cout << ans_X << endl;
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, Vinitha Ranganeni
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     1. Redistributions of source code must retain the above copyright notice
//        this list of conditions and the following disclaimer.
//     2. Redistributions in binary form must reproduce the above copyright
//        notice, this list of conditions and the following disclaimer in the
//        documentation and/or other materials provided with the distribution.
//     3. Neither the name of the copyright holder nor the names of its
//        contributors may be used to endorse or promote products derived from
//        this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////////

#ifndef LIBCOZMO_DISTANCE_SE2_HPP_
#define LIBCOZMO_DISTANCE_SE2_HPP_

#include "distance/distance.hpp"

namespace libcozmo {
namespace distance {

/// Distance Metric class
///
/// This class implements a distace metric of a continuous two-dimensional
/// Special Euclidean group SE(2), i.e. the space of planar rigid body
/// transformations.
class SE2 : public virtual Distance {
 public:

 	/// Constructs metric with given statespace
 	///
 	/// \param statespace The statespace that states to calculate the distance
 	/// 				  belongs to
 	SE2(libcozmo::statespace::StateSpace* statespace) : \
 		m_statespace(statespace) {}
 	~SE2() {}

 	/// Document inherited
    double get_distance(
    	const libcozmo::statespace::StateSpace::State& _state_1,
    	const libcozmo::statespace::StateSpace::State& _state_2) const override;

 private:
 	const libcozmo::statespace::StateSpace* m_statespace;
};

}  // namespace distance
}  // namespace libcozmo

#endif<commit_msg>in middle of PR edit<commit_after>//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, Vinitha Ranganeni
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     1. Redistributions of source code must retain the above copyright notice
//        this list of conditions and the following disclaimer.
//     2. Redistributions in binary form must reproduce the above copyright
//        notice, this list of conditions and the following disclaimer in the
//        documentation and/or other materials provided with the distribution.
//     3. Neither the name of the copyright holder nor the names of its
//        contributors may be used to endorse or promote products derived from
//        this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////////

#ifndef LIBCOZMO_DISTANCE_SE2_HPP_
#define LIBCOZMO_DISTANCE_SE2_HPP_

#include "distance/distance.hpp"

namespace libcozmo {
namespace distance {

/// SE2 Distance Metric
///
/// This class implements a distace metric between SE2 transformations.
class SE2 : public virtual Distance {
 public:

 	/// Constructs metric with given statespace
 	///
 	/// \param statespace The statespace the metric operates in
 	SE2(std::shared_ptr<libcozmo::statespace::StateSpace> statespace) : \
 		m_statespace(statespace) {}
 	~SE2() {}

 	/// Documentation inherited
    double get_distance(
    	const libcozmo::statespace::StateSpace::State& _state_1,
    	const libcozmo::statespace::StateSpace::State& _state_2) const override;

 private:
 	const std::shared_ptr<libcozmo::statespace::StateSpace> m_statespace;
};

}  // namespace distance
}  // namespace libcozmo

#endif<|endoftext|>


<commit_before>#define DEBUG 1

/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 6/9/2019, 9:16:59 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

/*
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}

void No()
{
  cout << "No" << endl;
  exit(0);
}
*/

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

const ll MOD = 1000000007;

string L;
ll dp[100010][2];

int main()
{
  cin >> L;
  reverse(L.begin(), L.end());
  int N = L.size();
  dp[0][0] = 1;
  for (auto i = 0; i < N; i++)
  {
    dp[i + 1][1] += (3 * dp[i][1]) % MOD;
    dp[i + 1][1] %= MOD;
    if (L[i] == '0')
    {
      dp[i + 1][0] += dp[i][0];
      dp[i + 1][0] %= MOD;
    }
    else
    {
      dp[i + 1][1] += dp[i][0];
      dp[i + 1][1] %= MOD;
      dp[i + 1][0] += (2 * dp[i][0]) % MOD;
      dp[i + 1][0] %= MOD;
    }
    cerr << "dp[" << i + 1 << "][" << 0 << "] = " << dp[i + 1][0] << endl;
    cerr << "dp[" << i + 1 << "][" << 1 << "] = " << dp[i + 1][1] << endl;
  }
  cout << (dp[N][0] + dp[N][1]) % MOD << endl;
}<commit_msg>tried E.cpp to 'E'<commit_after>#define DEBUG 1

/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 6/9/2019, 9:16:59 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

/*
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}

void No()
{
  cout << "No" << endl;
  exit(0);
}
*/

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

const ll MOD = 1000000007;

string L;
ll dp[100010][2];

int main()
{
  cin >> L;
  reverse(L.begin(), L.end());
  int N = L.size();
  dp[0][0] = 1;
  for (auto i = 0; i < N; i++)
  {
    dp[i + 1][1] += (3 * (dp[i][1] + dp[i][0])) % MOD;
    dp[i + 1][1] %= MOD;
    if (L[i] == '0')
    {
      dp[i + 1][0] += dp[i][0];
      dp[i + 1][0] %= MOD;
    }
    else
    {
      dp[i + 1][1] += dp[i][0];
      dp[i + 1][1] %= MOD;
      dp[i + 1][0] += (2 * dp[i][0]) % MOD;
      dp[i + 1][0] %= MOD;
    }
#if DEBUG == 1
    cerr << "dp[" << i + 1 << "][" << 0 << "] = " << dp[i + 1][0] << endl;
    cerr << "dp[" << i + 1 << "][" << 1 << "] = " << dp[i + 1][1] << endl;
#endif
  }
  cout << (dp[N][0] + dp[N][1]) % MOD << endl;
}<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file dot.hpp
 * \brief Selector for the dot product
 *
 * Implementations of the dot product:
 *    1. Simple implementation using expressions
 *    2. Implementations using BLAS SDOT and DDOT
 */

#pragma once

//Include the implementations
#include "etl/impl/std/dot.hpp"
#include "etl/impl/blas/dot.hpp"

namespace etl {

namespace detail {

/*!
 * \brief Enumeration describing the different implementations of dot
 */
enum class dot_imple {
    STD,  ///< Standard implementation
    BLAS, ///< BLAS implementation
};

/*!
 * \brief Select the dot implementation for an expression of type A and B
 * \tparam A The type of lhs expression
 * \tparam B The type of rhs expression
 * \return The implementation to use
 */
template <typename A, typename B>
cpp14_constexpr dot_imple select_dot_impl() {
    if(all_dma<A, B>::value){
        if (is_cblas_enabled) {
            return dot_imple::BLAS;
        } else {
            return dot_imple::STD;
        }
    }

    return dot_imple::STD;
}

/*!
 * \brief Functor for dot product
 */
struct dot_impl {
    /*!
     * \brief Apply the functor to a and b
     * \param a the left hand side
     * \param b the left hand side
     * \return the dot product of a and b
     */
    template <typename A, typename B>
    static value_t<A> apply(const A& a, const B& b) {
        cpp14_constexpr auto impl = select_dot_impl<A, B>();

        if (impl == dot_imple::BLAS) {
            return etl::impl::blas::dot(a, b);
        } else {
            return etl::impl::standard::dot(a, b);
        }
    }
};

} //end of namespace detail

} //end of namespace etl
<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file dot.hpp
 * \brief Selector for the dot product
 */

#pragma once

//Include the implementations
#include "etl/impl/std/dot.hpp"
#include "etl/impl/blas/dot.hpp"

namespace etl {

namespace detail {

/*!
 * \brief Enumeration describing the different implementations of dot
 */
enum class dot_imple {
    STD,  ///< Standard implementation
    BLAS, ///< BLAS implementation
};

/*!
 * \brief Select the dot implementation for an expression of type A and B
 * \tparam A The type of lhs expression
 * \tparam B The type of rhs expression
 * \return The implementation to use
 */
template <typename A, typename B>
cpp14_constexpr dot_imple select_dot_impl() {
    if(all_dma<A, B>::value){
        if (is_cblas_enabled) {
            return dot_imple::BLAS;
        } else {
            return dot_imple::STD;
        }
    }

    return dot_imple::STD;
}

/*!
 * \brief Functor for dot product
 */
struct dot_impl {
    /*!
     * \brief Apply the functor to a and b
     * \param a the left hand side
     * \param b the left hand side
     * \return the dot product of a and b
     */
    template <typename A, typename B>
    static value_t<A> apply(const A& a, const B& b) {
        cpp14_constexpr auto impl = select_dot_impl<A, B>();

        if (impl == dot_imple::BLAS) {
            return etl::impl::blas::dot(a, b);
        } else {
            return etl::impl::standard::dot(a, b);
        }
    }
};

} //end of namespace detail

} //end of namespace etl
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 5/18/2020, 2:23:37 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

int main()
{
  ll W, H, x, y;
  cin >> W >> H >> x >> y;
  double A{static_cast<double>(W) * H / 2};
  cout << fixed << setprecision(6) << A << " " << setprecision(0);
  if (W % 2 == 0 && x == W / 2 && H % 2 == 0 && y == H / 2)
  {
    cout << 0 << endl;
  }
  else
  {
    cout << 1 << endl;
  }
}
<commit_msg>submit C.cpp to 'C - Rectangle Cutting' (abc130) [C++14 (GCC 5.4.1)]<commit_after>#define DEBUG 1
/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 5/18/2020, 2:23:37 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

int main()
{
  ll W, H, x, y;
  cin >> W >> H >> x >> y;
  double A{static_cast<double>(W) * H / 2};
  cout << fixed << setprecision(6) << A << " " << setprecision(0);
  if (W % 2 == 0 && x == W / 2 && H % 2 == 0 && y == H / 2)
  {
    cout << 1 << endl;
  }
  else
  {
    cout << 0 << endl;
  }
}
<|endoftext|>