import logging.config
import asyncio
import asyncio.subprocess
import datetime
import logging
from collections import OrderedDict, defaultdict
from typing import Any, Awaitable, Dict, List, Optional, Union  # noqa
from urllib.parse import urlparse
from aiohttp import web
import yacron.version
from yacron.config import (
    JobConfig,
    parse_config,
    ConfigError,
    parse_config_string,
    WebConfig,
    YacronConfig,
    JobDefaults,
)
from yacron.job import RunningJob, JobRetryState
from crontab import CronTab  # noqa

logger = logging.getLogger("yacron")
WAKEUP_INTERVAL = datetime.timedelta(minutes=1)

def naturaltime(seconds: float, future=False) -> str:
    assert future
    if seconds < 120:
        return "in {} second{}".format(
            int(seconds), "s" if seconds >= 2 else ""
        )
    minutes = seconds / 60
    if minutes < 120:
        return "in {} minute{}".format(
            int(minutes), "s" if minutes >= 2 else ""
        )
    hours = minutes / 60
    if hours < 48:
        return "in {} hour{}".format(int(hours), "s" if hours >= 2 else "")
    days = hours / 24
    return "in {} day{}".format(int(days), "s" if days >= 2 else "")

def get_now(timezone: Optional[datetime.tzinfo]) -> datetime.datetime:
    return datetime.datetime.now(timezone)

def next_sleep_interval() -> float:
    now = get_now(datetime.timezone.utc)
    target = now.replace(second=0) + WAKEUP_INTERVAL
    return (target - now).total_seconds()

def web_site_from_url(runner: web.AppRunner, url: str) -> web.BaseSite:
    parsed = urlparse(url)
    if parsed.scheme == "http":
        assert parsed.hostname is not None
        assert parsed.port is not None
        return web.TCPSite(runner, parsed.hostname, parsed.port)
    elif parsed.scheme == "unix":
        return web.UnixSite(runner, parsed.path)
    else:
        logger.warning(
            "Ignoring web listen url %s: scheme %r not supported",
            url,
            parsed.scheme,
        )
        raise ValueError(url)

class Cron:
    def __init__(
        self, config_arg: Optional[str], *, config_yaml: Optional[str] = None
    ) -> None:
        # list of cron jobs we /want/ to run
        self.cron_jobs = OrderedDict()  # type: Dict[str, JobConfig]
        # list of cron jobs already running
        # name -> list of RunningJob
        self.running_jobs = defaultdict(
            list
        )  # type: Dict[str, List[RunningJob]]
        self.config_arg = config_arg
        if config_arg is not None:
            self.update_config()
        if config_yaml is not None:
            # config_yaml is for unit testing
            config = parse_config_string(config_yaml, "")
            self.cron_jobs = OrderedDict(
                (job.name, job) for job in config.jobs
            )

        self._wait_for_running_jobs_task = None  # type: Optional[asyncio.Task]
        self._stop_event = asyncio.Event()
        self._jobs_running = asyncio.Event()
        self.retry_state = {}  # type: Dict[str, JobRetryState]
        self.web_runner = None  # type: Optional[web.AppRunner]
        self.web_config = None  # type: Optional[WebConfig]

    async def run(self) -> None:
        self._wait_for_running_jobs_task = asyncio.create_task(
            self._wait_for_running_jobs()
        )

        startup = True
        logging_configured = False
        while not self._stop_event.is_set():
            try:
                config = self.update_config()
                await self.start_stop_web_app(config.web_config)
            except ConfigError as err:
                logger.error(
                    "Error in configuration file(s), so not updating "
                    "any of the config.:\n%s",
                    str(err),
                )
            except Exception:  # pragma: nocover
                logger.exception("please report this as a bug (1)")
            if config.logging_config is not None and not logging_configured:
                logging_configured = True
                try:
                    logging.config.dictConfig(config.logging_config)
                except Exception as ex:
                    logger.error(
                        "Error while configuring logging: %s\n"
                        "Check for correct format at "
                        "https://docs.python.org/3/library/logging.config.html"
                        "#dictionary-schema-details\n%s",
                        ex,
                        config.logging_config,
                    )
            await self.spawn_jobs(startup)
            startup = False
            sleep_interval = next_sleep_interval()
            logger.debug("Will sleep for %.1f seconds", sleep_interval)
            try:
                await asyncio.wait_for(self._stop_event.wait(), sleep_interval)
            except asyncio.TimeoutError:
                pass

        logger.info("Shutting down (after currently running jobs finish)...")
        while self.retry_state:
            cancel_all = [
                self.cancel_job_retries(name) for name in self.retry_state
            ]
            await asyncio.gather(*cancel_all)
        await self._wait_for_running_jobs_task

        if self.web_runner is not None:
            logger.info("Stopping http server")
            await self.web_runner.cleanup()

    def signal_shutdown(self) -> None:
        logger.debug("Signalling shutdown")
        self._stop_event.set()

    def update_config(self) -> YacronConfig:
        if self.config_arg is None:
            return YacronConfig(
                jobs=[],
                web_config=None,
                job_defaults=JobDefaults({}),
                logging_config=None,
            )
        config = parse_config(self.config_arg)
        self.cron_jobs = OrderedDict((job.name, job) for job in config.jobs)
        return config

    async def _web_get_version(self, request: web.Request) -> web.Response:
        return web.Response(text=yacron.version.version)

    async def _web_get_status(self, request: web.Request) -> web.Response:
        out = []
        for name, job in self.cron_jobs.items():
            running = self.running_jobs.get(name, None)
            if running:
                out.append(
                    {
                        "job": name,
                        "status": "running",
                        "pid": [
                            runjob.proc.pid
                            for runjob in running
                            if runjob.proc is not None
                        ],
                    }
                )
            else:
                crontab = job.schedule  # type: Union[CronTab, str]
                now = get_now(job.timezone)
                out.append(
                    {
                        "job": name,
                        "status": "scheduled",
                        "scheduled_in": (
                            crontab.next(now=now, default_utc=job.utc)
                            if isinstance(crontab, CronTab)
                            else str(crontab)
                        ),
                    }
                )
        if request.headers.get("Accept") == "application/json":
            return web.json_response(out)
        else:
            lines = []
            for jobstat in out:  # type: Dict[str, Any]
                if jobstat["status"] == "running":
                    status = "running (pid: {pid})".format(
                        pid=", ".join(str(pid) for pid in jobstat["pid"])
                    )
                else:
                    status = "scheduled ({})".format(
                        (
                            jobstat["scheduled_in"]
                            if type(jobstat["scheduled_in"]) is str
                            else naturaltime(
                                jobstat["scheduled_in"], future=True
                            )
                        )
                    )
                lines.append(
                    "{name}: {status}".format(
                        name=jobstat["job"], status=status
                    )
                )
            return web.Response(text="\n".join(lines))

    async def _web_start_job(self, request: web.Request) -> web.Response:
        name = request.match_info["name"]
        try:
            job = self.cron_jobs[name]
        except KeyError:
            raise web.HTTPNotFound()
        await self.maybe_launch_job(job)
        return web.Response()

    async def start_stop_web_app(self, web_config: Optional[WebConfig]):
        if self.web_runner is not None and (
            web_config is None or web_config != self.web_config
        ):
            # assert self.web_runner is not None
            logger.info("Stopping http server")
            await self.web_runner.cleanup()
            self.web_runner = None

        if (
            web_config is not None
            and web_config["listen"]
            and self.web_runner is None
        ):
            app = web.Application()
            app.add_routes(
                [
                    web.get("/version", self._web_get_version),
                    web.get("/status", self._web_get_status),
                    web.post("/jobs/{name}/start", self._web_start_job),
                ]
            )
            self.web_runner = web.AppRunner(app)
            await self.web_runner.setup()
            for addr in web_config["listen"]:
                site = web_site_from_url(self.web_runner, addr)
                logger.info("web: started listening on %s", addr)
                try:
                    await site.start()
                except ValueError:
                    pass
            self.web_config = web_config

    async def spawn_jobs(self, startup: bool) -> None:
        for job in self.cron_jobs.values():
            if self.job_should_run(startup, job):
                await self.launch_scheduled_job(job)

    @staticmethod
    def job_should_run(startup: bool, job: JobConfig) -> bool:
        if not job.enabled:
            logger.debug(
                "Job %s (%s) is disabled in the config",
                job.name,
                job.schedule_unparsed,
            )
            return False
        if startup:
            if isinstance(job.schedule, str) and job.schedule == "@reboot":
                logger.debug(
                    "Job %s (%s) is scheduled for startup (@reboot)",
                    job.name,
                    job.schedule_unparsed,
                )
                return True
            else:
                return False
        if isinstance(job.schedule, CronTab):
            crontab = job.schedule  # type: CronTab
            if crontab.test(get_now(job.timezone).replace(second=0)):
                logger.debug(
                    "Job %s (%s) is scheduled for now",
                    job.name,
                    job.schedule_unparsed,
                )
                return True
            else:
                logger.debug(
                    "Job %s (%s) not scheduled for now",
                    job.name,
                    job.schedule_unparsed,
                )
                return False
        else:
            return False

    async def launch_scheduled_job(self, job: JobConfig) -> None:
        await self.cancel_job_retries(job.name)
        assert job.name not in self.retry_state

        retry = job.onFailure["retry"]
        logger.debug("Job %s retry config: %s", job.name, retry)
        if retry["maximumRetries"]:
            retry_state = JobRetryState(
                retry["initialDelay"],
                retry["backoffMultiplier"],
                retry["maximumDelay"],
            )
            self.retry_state[job.name] = retry_state

        await self.maybe_launch_job(job)

    async def maybe_launch_job(self, job: JobConfig) -> None:
        if self.running_jobs[job.name]:
            logger.warning(
                "Job %s: still running and concurrencyPolicy is %s",
                job.name,
                job.concurrencyPolicy,
            )
            if job.concurrencyPolicy == "Allow":
                pass
            elif job.concurrencyPolicy == "Forbid":
                return
            elif job.concurrencyPolicy == "Replace":
                for running_job in self.running_jobs[job.name]:
                    await running_job.cancel()
            else:
                raise AssertionError  # pragma: no cover
        logger.info("Starting job %s", job.name)
        running_job = RunningJob(job, self.retry_state.get(job.name))
        await running_job.start()
        self.running_jobs[job.name].append(running_job)
        logger.info("Job %s spawned", job.name)
        self._jobs_running.set()

    # continually watches for the running jobs, clean them up when they exit
    async def _wait_for_running_jobs(self) -> None:
        # job -> wait task
        wait_tasks = {}  # type: Dict[RunningJob, asyncio.Task]
        while self.running_jobs or not self._stop_event.is_set():
            try:
                for jobs in self.running_jobs.values():
                    for job in jobs:
                        if job not in wait_tasks:
                            wait_tasks[job] = asyncio.create_task(job.wait())
                if not wait_tasks:
                    try:
                        await asyncio.wait_for(self._jobs_running.wait(), 1)
                    except asyncio.TimeoutError:
                        pass
                    continue
                self._jobs_running.clear()
                # wait for at least one task with timeout
                done_tasks, _ = await asyncio.wait(
                    wait_tasks.values(),
                    timeout=1.0,
                    return_when=asyncio.FIRST_COMPLETED,
                )
                done_jobs = set()
                for job, task in list(wait_tasks.items()):
                    if task in done_tasks:
                        done_jobs.add(job)
                for job in done_jobs:
                    task = wait_tasks.pop(job)
                    try:
                        task.result()
                    except Exception:  # pragma: no cover
                        logger.exception("please report this as a bug (2)")

                    jobs_list = self.running_jobs[job.config.name]
                    jobs_list.remove(job)
                    if not jobs_list:
                        del self.running_jobs[job.config.name]

                    fail_reason = job.fail_reason
                    logger.info(
                        "Job %s exit code %s; has stdout: %s, "
                        "has stderr: %s; fail_reason: %r",
                        job.config.name,
                        job.retcode,
                        str(bool(job.stdout)).lower(),
                        str(bool(job.stderr)).lower(),
                        fail_reason,
                    )
                    if fail_reason is not None:
                        await self.handle_job_failure(job)
                    else:
                        await self.handle_job_success(job)
            except asyncio.CancelledError:
                raise
            except Exception:  # pragma: no cover
                logger.exception("please report this as a bug (3)")
                await asyncio.sleep(1)

    async def handle_job_failure(self, job: RunningJob) -> None:
        if self._stop_event.is_set():
            return
        if job.stdout:
            logger.info(
                "Job %s STDOUT:\n%s", job.config.name, job.stdout.rstrip()
            )
        if job.stderr:
            logger.info(
                "Job %s STDERR:\n%s", job.config.name, job.stderr.rstrip()
            )
        await job.report_failure()

        # Handle retries...
        state = job.retry_state
        if state is None or state.cancelled:
            await job.report_permanent_failure()
            return

        logger.debug(
            "Job %s has been retried %i times", job.config.name, state.count
        )
        if state.task is not None:
            if state.task.done():
                await state.task
            else:
                state.task.cancel()
        retry = job.config.onFailure["retry"]
        if (
            state.count >= retry["maximumRetries"]
            and retry["maximumRetries"] != -1
        ):
            await self.cancel_job_retries(job.config.name)
            await job.report_permanent_failure()
        else:
            retry_delay = state.next_delay()
            state.task = asyncio.create_task(
                self.schedule_retry_job(
                    job.config.name, retry_delay, state.count
                )
            )

    async def schedule_retry_job(
        self, job_name: str, delay: float, retry_num: int
    ) -> None:
        logger.info(
            "Cron job %s scheduled to be retried (#%i) " "in %.1f seconds",
            job_name,
            retry_num,
            delay,
        )
        await asyncio.sleep(delay)
        try:
            job = self.cron_jobs[job_name]
        except KeyError:
            logger.warning(
                "Cron job %s was scheduled for retry, but "
                "disappeared from the configuration",
                job_name,
            )
        await self.maybe_launch_job(job)

    async def handle_job_success(self, job: RunningJob) -> None:
        await self.cancel_job_retries(job.config.name)
        await job.report_success()

    async def cancel_job_retries(self, name: str) -> None:
        try:
            state = self.retry_state.pop(name)
        except KeyError:
            return
        state.cancelled = True
        if state.task is not None:
            if state.task.done():
                await state.task
            else:
                state.task.cancel()


import math, random

import gym
import numpy as np

import torch
import torch.nn as nn
import torch.optim as optim
import torch.autograd as autograd
import torch.nn.functional as F

import matplotlib.pyplot as plt

#from common.layers import NoisyLinear
from common.replay_buffer import ReplayBuffer

from torch.utils.tensorboard import SummaryWriter

env_id = "LunarLander-v2"
env = gym.make(env_id)
writer = SummaryWriter()

class QRDQN(nn.Module):
    def __init__(self, num_inputs, num_actions, num_quants):
        super(QRDQN, self).__init__()

        self.num_inputs  = num_inputs
        self.num_actions = num_actions
        self.num_quants  = num_quants

        self.features = nn.Sequential(
            nn.Linear(num_inputs, 32),
            nn.ReLU(),
            nn.Linear(32, 64),
            nn.ReLU(),
            nn.Linear(64, 128),
            nn.ReLU(),
            nn.Linear(128, self.num_actions * self.num_quants)
        )

        #self.noisy_value1 = NoisyLinear(64, 128, use_cuda=USE_CUDA)
        #self.noisy_value2 = NoisyLinear(128, self.num_actions * self.num_quants, use_cuda=USE_CUDA)

    def forward(self, x):
        batch_size = x.size(0)

        x = self.features(x)

        #x = self.noisy_value1(x)
        #x = F.relu(x)
        #x = self.noisy_value2(x)
        x = x.view(batch_size, self.num_actions, self.num_quants)

        return x

    def q_values(self, x):
        x = self.forward(x)
        return x.mean(2)

    def reset_noise(self):
        self.noisy_value1.reset_noise()
        self.noisy_value2.reset_noise()

    def act(self, state, epsilon):
        if random.random() > epsilon:
            state = autograd.Variable(torch.FloatTensor(np.array(state, dtype=np.float32)).unsqueeze(0), volatile=True)
            qvalues = self.forward(state).mean(2)
            action  = qvalues.max(1)[1]
            action  = action.data.cpu().numpy()[0]
        else:
            action = random.randrange(self.num_actions)
        return action

def projection_distribution(dist, next_state, reward, done):
    next_dist = target_model(next_state)
    next_action = next_dist.mean(2).max(1)[1]
    next_action = next_action.unsqueeze(1).unsqueeze(1).expand(batch_size, 1, num_quant)
    next_dist = next_dist.gather(1, next_action).squeeze(1).cpu().data

    expected_quant = reward.unsqueeze(1) + 0.99 * next_dist * (1 - done.unsqueeze(1))
    expected_quant = autograd.Variable(expected_quant)

    quant_idx = torch.sort(dist, 1, descending=False)[1]

    tau_hat = torch.linspace(0.0, 1.0 - 1./num_quant, num_quant) + 0.5 / num_quant
    tau_hat = tau_hat.unsqueeze(0).repeat(batch_size, 1)
    quant_idx = quant_idx.cpu().data
    batch_idx = np.arange(batch_size)
    tau = tau_hat[:, quant_idx][batch_idx, batch_idx]

    return tau, expected_quant

num_quant = 51
Vmin = -10
Vmax = 10

current_model = QRDQN(env.observation_space.shape[0], env.action_space.n, num_quant)
target_model  = QRDQN(env.observation_space.shape[0], env.action_space.n, num_quant)

optimizer = optim.Adam(current_model.parameters())

replay_buffer = ReplayBuffer(10000)

def update_target(current_model, target_model):
    target_model.load_state_dict(current_model.state_dict())

update_target(current_model, target_model)

def compute_td_loss(batch_size):
    state, action, reward, next_state, done = replay_buffer.sample(batch_size)

    state      = autograd.Variable(torch.FloatTensor(np.float32(state)))
    next_state = autograd.Variable(torch.FloatTensor(np.float32(next_state)), volatile=True)
    action     = autograd.Variable(torch.LongTensor(action))
    reward     = torch.FloatTensor(reward)
    done       = torch.FloatTensor(np.float32(done))

    dist = current_model(state)
    action = action.unsqueeze(1).unsqueeze(1).expand(batch_size, 1, num_quant)
    dist = dist.gather(1, action).squeeze(1)

    tau, expected_quant = projection_distribution(dist, next_state, reward, done)
    k = 1

    huber_loss = 0.5 * tau.abs().clamp(min=0.0, max=k).pow(2)
    huber_loss += k * (tau.abs() -  tau.abs().clamp(min=0.0, max=k))
    quantile_loss = (tau - (tau < 0).float()).abs() * huber_loss
    loss = torch.tensor(quantile_loss.sum() / num_quant, requires_grad=True)

    optimizer.zero_grad()
    loss.backward()
    nn.utils.clip_grad_norm(current_model.parameters(), 0.5)
    optimizer.step()

    return loss

epsilon_start = 1.0
epsilon_final = 0.01
epsilon_decay = 50000

epsilon_by_frame = lambda iteration: epsilon_final + (epsilon_start - epsilon_final) * math.exp(-1. * iteration / epsilon_decay)

def plot(iteration, rewards, losses, ep_reward):
    print("Outputing Iteration " + str(iteration))
    writer.add_scalar('Train/Rewards', rewards[-1], iteration)
    writer.add_scalar('Train/Losses', losses[-1], iteration)
    writer.add_scalar('Train/Exploration', epsilon_by_frame(iteration), iteration)
    writer.add_scalar('Train/Episode', ep_reward, iteration)
    writer.flush()

iterations = 1000000
batch_size = 32
gamma      = 0.98

losses = []
all_rewards = []
episode_reward = 0

state = env.reset()
for iteration in range(1, iterations + 1):
    action = current_model.act(state, epsilon_by_frame(iteration))

    next_state, reward, done, _ = env.step(action)
    replay_buffer.push(state, action, reward, next_state, done)

    state = next_state
    episode_reward += reward

    if done:
        state = env.reset()
        all_rewards.append(episode_reward)
        episode_reward = 0

    if len(replay_buffer) > batch_size:
        loss = compute_td_loss(batch_size)
        losses.append(loss.item())

    if iteration % 200 == 0:
        plot(iteration, all_rewards, losses, episode_reward)

    if iteration % 1000 == 0:
        update_target(current_model, target_model)


"""Day 8"""

from typing import Set
from aoc.shared import read_file_lines
from aoc.shared.input import read_file_lines

segment_count_map = {
    0: [],
    1: [],
    2: [1],
    3: [7],
    4: [4],
    5: [2, 3, 5],
    6: [0, 6, 9],
    7: [8],
}

def part1() -> int:
    """Part 1."""

    raw_notes = read_file_lines("year_2021/input_08.txt")
    notes = []

    for note in raw_notes:
        signal_patterns_string, output_value_string = note.split(" | ")
        signal_patterns = [set(s) for s in signal_patterns_string.split(" ")]
        output_values = [set(s) for s in output_value_string.split(" ")]
        notes.append((signal_patterns, output_values))

    results = {1: 0, 4: 0, 7: 0, 8: 0}

    for _, output_patterns in notes:
        for pattern in output_patterns:
            if len(pattern) == 2:
                results[1] += 1
            elif len(pattern) == 3:
                results[7] += 1
            elif len(pattern) == 4:
                results[4] += 1
            elif len(pattern) == 7:
                results[8] += 1

    return results[1] + results[4] + results[7] + results[8]

def solve(signal_patterns: Set[int], output_patterns: Set[int]) -> int:
    a = None
    b = None
    c = None
    d = None
    e = None
    f = None
    g = None

    results = {}

    for pattern in signal_patterns:
        if len(pattern) == 2:
            results[1] = pattern
        elif len(pattern) == 3:
            results[7] = pattern
        elif len(pattern) == 4:
            results[4] = pattern
        elif len(pattern) == 7:
            results[8] = pattern

    a = results[7] - results[1]

    changes = True
    while changes:
        changes = False

        for pattern in signal_patterns:

            if len(pattern) not in [5, 6]:
                continue

            if len(pattern) == 5:

                if 2 not in results and len(pattern - results[4]) == 3:
                    changes = True
                    results[2] = pattern
                    break

                if 3 not in results and len(pattern - results[1]) == 3:
                    changes = True
                    results[3] = pattern
                    break

                if (
                    5 not in results
                    and len(pattern - results[1]) == 4
                    and len(results[4] - pattern) == 1
                ):
                    changes = True
                    results[5] = pattern
                    break

            if len(pattern) == 6:

                if 9 not in results and len(pattern - results[4]) == 2:
                    changes = True
                    results[9] = pattern
                    break

                if 6 not in results and len(pattern - results[1]) == 5:
                    changes = True
                    results[6] = pattern
                    break

                if (
                    0 not in results
                    and len(pattern - results[4]) == 3
                    and len(pattern - results[7]) == 3
                ):
                    changes = True
                    results[0] = pattern
                    break

        if b is None:
            if 0 in results and 2 in results:
                changes = True
                b = results[0] - results[2] - results[1]
            elif 3 in results:
                changes = True
                b = results[4] - results[3]

        if c is None and 6 in results:
            changes = True
            c = results[8] - results[6]

        if d is None and 0 in results:
            changes = True
            d = results[8] - results[0]

        if e is None and 9 in results:
            changes = True
            e = results[8] - results[9]

        if f is None and c:
            changes = True
            f = results[1] - c

        if g is None and 9 in results and a:
            changes = True
            g = results[9] - results[4] - a

    a = list(a)[0]
    b = list(b)[0]
    c = list(c)[0]
    d = list(d)[0]
    e = list(e)[0]
    f = list(f)[0]
    g = list(g)[0]

    if {a, b, c, d, e, f, g} != {"a", "b", "c", "d", "e", "f", "g"}:
        return 0

    corrections = {
        a: "a",
        b: "b",
        c: "c",
        d: "d",
        e: "e",
        f: "f",
        g: "g",
    }

    output = ""
    for pattern in output_patterns:
        corrected_pattern = {corrections[l] for l in pattern}
        if corrected_pattern == {"a", "b", "c", "e", "f", "g"}:
            output += "0"
        elif corrected_pattern == {"c", "f"}:
            output += "1"
        elif corrected_pattern == {"a", "c", "d", "e", "g"}:
            output += "2"
        elif corrected_pattern == {"a", "c", "d", "f", "g"}:
            output += "3"
        elif corrected_pattern == {"b", "c", "d", "f"}:
            output += "4"
        elif corrected_pattern == {"a", "b", "d", "f", "g"}:
            output += "5"
        elif corrected_pattern == {"a", "b", "d", "e", "f", "g"}:
            output += "6"
        elif corrected_pattern == {"a", "c", "f"}:
            output += "7"
        elif corrected_pattern == {"a", "b", "c", "d", "e", "f", "g"}:
            output += "8"
        elif corrected_pattern == {"a", "b", "c", "d", "f", "g"}:
            output += "9"
        else:
            return -1

    return int(output)

def part2() -> int:
    """Part 2."""

    raw_notes = read_file_lines("year_2021/input_08.txt")
    notes = []

    for note in raw_notes:
        signal_patterns_string, output_value_string = note.split(" | ")
        signal_patterns = [set(s) for s in signal_patterns_string.split(" ")]
        output_values = [set(s) for s in output_value_string.split(" ")]
        notes.append((signal_patterns, output_values))

    total = 0
    for signal_patterns, output_patterns in notes:
        total += solve(signal_patterns, output_patterns)

    return total

if __name__ == "__main__":
    print("Part 1:", part1())
    print("Part 2:", part2())


from django.conf.urls import url, include, patterns
from freight.views import *
from freight.models import *

app_name = 'freight'
urlpatterns = [
    # ex: /freight/
    url(r'^$', index, name='index'),
    # ex: /freight/5
    url(r'^(?P<carrier_id>[0-9]+)/$', carrier_detail, name='carrier_detail'),
    # ex: /freight/locations
    url(r'^locations/$', location_all, name='location_all'),
    #ex: /freight/fuel
    url(r'^fuel/$', fuel_surcharge, name='fuel_surcharge'),
    #ex: /freight/history
    url(r'^history/$', rate_history, name='rate_history')
]


 # -*- coding: UTF-8 -*-

from dnslib import *
import gevent
from gevent.server import DatagramServer
from gevent import socket
from random import randint
from time import sleep

always_respond_ip = '1.2.3.4'

class DNSServer(DatagramServer):

    def handle_dns_request(self, data, address):

        req = DNSRecord.parse(data)
        qname = str(req.q.qname)
        qid = req.header.id

        response = DNSRecord(DNSHeader(qr=1, aa=1, ra=1),
                                     q=DNSQuestion(qname),
                                     a=RR(qname, rdata=A(always_respond_ip)))

        response.header.id = qid
        sleep(1.5)
        self.socket.sendto(response.pack(), address)

    def handle(self, data, address):

        self.handle_dns_request(data, address)

def main():
    DNSServer(':53').serve_forever()

if __name__ == '__main__':
    main()


# http://codeforces.com/contest/677/problem/A

fenceHeight = int(input().split(' ')[1])
friendsHeightList = input().split(' ')

widthOfRoad = 0

for ele in friendsHeightList:
    if int(ele) <= fenceHeight:
        widthOfRoad += 1
    else:
        widthOfRoad += 2

print(widthOfRoad)


#!/usr/bin/env python

import os

def configuration(parent_package='',top_path=None):
    from numpy.distutils.misc_util import Configuration
    config = Configuration('classic', parent_package, top_path)

    config.add_extension('classic1',
                         ['limiter.f90','philim.f90','step1.f90'],f2py_options=['--quiet'])

    config.add_extension('classic2',
                         ['limiter.f90','philim.f90','flux2.f90','step2ds.f90','step2.f90'],f2py_options=['--quiet'])

    config.add_extension('classic3',
                         ['limiter.f90','philim.f90','flux3.f90','step3ds.f90','step3.f90'],f2py_options=['--quiet'])

    return config

if __name__ == '__main__':
    from numpy.distutils.core import setup
    setup(**configuration(top_path='').todict())


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def getAllElements(self, root1: TreeNode, root2: TreeNode) -> List[int]:

        def getElements(root,arr):
            if not root:
                return []
            getElements(root.left,arr)
            arr.append(root.val)
            getElements(root.right,arr)
            return arr

        arr1=getElements(root1,[])
        arr2=getElements(root2,[])
        if len(arr1)==0:
            return arr2
        if len(arr2)==0:
            return arr1

        # 1 2 3 0 0 0
        # 4 5 6
        ptr1=len(arr1)-1
        ptr2=len(arr2)-1
        for i in range(len(arr2)):
            arr1.append(0)
        while ptr1>=0 and ptr2>=0:
            if arr1[ptr1]>=arr2[ptr2]:
                arr1[ptr1+ptr2+1]=arr1[ptr1]
                ptr1-=1
            else:
                arr1[ptr1+ptr2+1]=arr2[ptr2]
                ptr2-=1
        while ptr2>=0:
            arr1[ptr2]=arr2[ptr2]
            ptr2-=1
        return arr1


#!/usr/bin/python
# -*- coding: UTF-8 -*-
import StringIO
import sqlite3
import urllib
import pycurl
import re
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

# 读tocken文件获取用户Tocken
token_file = open('tocken')
try:
	my_token = token_file.read().strip()
finally:
	token_file.close()
# 组合 API URL
pinurl = 'https://api.pinterest.com/v1/pins/?access_token=' + my_token

# 指定发布Pin的 Board ID
board_id = '195765983741497086'

# 定义Pin发布函数
def Pin(pinurl,board_id,note,url,image):
	b=StringIO.StringIO()
	c=pycurl.Curl()
	c.setopt(pycurl.URL, pinurl)
	c.setopt(pycurl.WRITEFUNCTION, b.write)
	c.setopt(pycurl.FOLLOWLOCATION, 1)
	c.setopt(pycurl.MAXREDIRS, 5)
	c.setopt(pycurl.CUSTOMREQUEST,'POST')
	post_data_dic = {"board":board_id,"note":note,"link":url,"image_url":image}
	c.setopt(c.POSTFIELDS, urllib.urlencode(post_data_dic))
	c.perform()
	return c.getinfo(c.HTTP_CODE)
	#print b.getvalue()

# 连接SQLite数据库
conn = sqlite3.connect('products.sqlite')
cursor = conn.cursor()

# 从数据库中取出产品信息（默认1条；可以是多条，修改limit）
cursor.execute('select * from products where status=0 limit 0,1')
values = cursor.fetchall()

# 发送Pin
for value in values:
	pid = value[0]
	note = value[3]
	url = value[1]
	image = value[2]
	status = value[4]
	# 更新status为1，标识为已发布
	cursor.execute('update products set status=? where id=?', ('1',pid))
	conn.commit()
	# 执行发布
	pinreturn = Pin(pinurl,board_id,note,url,image)
	# 写日志，如果成功写入到succes.log
	if pinreturn == 201:
		logfile = open('succes.log','a')
		logfile.write(str(pid) + ',' + url + '\n')
		logfile.close()
	# 如果失败，写入到error.log
	else:
		logfile = open('error.log','a')
		logfile.write(str(pid) + ',' + str(pinreturn) + ',' + url + '\n')
		logfile.close()

# 关闭数据库连接
cursor.close()
conn.close()


# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QPushButton, QMessageBox
from PyPDF2 import PdfFileWriter, PdfFileReader, PdfFileMerger, PageObject
import os
import platform
import subprocess

class Ui_CuadPy(object):
    def setupUi(self, CuadPy):
        CuadPy.setObjectName("CuadPy")
        CuadPy.resize(355, 240)
        self.label = QtWidgets.QLabel(CuadPy)
        self.label.setGeometry(QtCore.QRect(30, 30, 121, 31))
        self.label.setObjectName("label")
        self.btn1 = QtWidgets.QPushButton(CuadPy)
        self.btn1.setGeometry(QtCore.QRect(30, 190, 93, 28))
        self.btn1.setStyleSheet("QPushButton:pressed {\n"
"        dlg = QDialog(self)\n"
"        dlg.setWindowTitle(\"HELLO!\")\n"
"        dlg.exec()\n"
"}")
        self.btn1.setObjectName("btn1")
        self.btn_split = QtWidgets.QPushButton(CuadPy)
        self.btn_split.setGeometry(QtCore.QRect(130, 190, 93, 28))
        self.btn_split.setObjectName("btn_split")
        self.btn_carpeta = QtWidgets.QPushButton(CuadPy)
        self.btn_carpeta.setGeometry(QtCore.QRect(230, 190, 93, 28))
        self.btn_carpeta.setObjectName("btn_carpeta")
        self.caja = QtWidgets.QTextEdit(CuadPy)
        self.caja.setGeometry(QtCore.QRect(30, 60, 291, 121))
        self.caja.setObjectName("caja")
        self.info = QtWidgets.QToolButton(CuadPy)
        self.info.setGeometry(QtCore.QRect(310, 10, 31, 22))
        self.info.setObjectName("info")

        self.retranslateUi(CuadPy)
        QtCore.QMetaObject.connectSlotsByName(CuadPy)

# AÑADO CONEXION A LAS FUNCIONES
        self.btn1.clicked.connect(self.booklet)
        self.btn_split.clicked.connect(self.dividir)
        self.btn_carpeta.clicked.connect(self.carpeta)
        self.info.clicked.connect(self.info_autor)

    def retranslateUi(self, CuadPy):
        _translate = QtCore.QCoreApplication.translate
        CuadPy.setWindowTitle(_translate("CuadPy", "CuadPy"))
        self.caja.setText(_translate("CuadPy", "C:/Users/rromero/PycharmProjects/pdf_manager/ejemplo/pdfs/20p.pdf")) #Documento cargado
        self.label.setText(_translate("CuadPy", "Arrastra el pdf aquí"))
        self.btn1.setText(_translate("CuadPy", "Reordenar"))
        self.btn_split.setText(_translate("CuadPy", "Dividir PDF"))
        self.btn_carpeta.setText(_translate("CuadPy", "Abrir carpeta"))
        self.info.setText(_translate("CuadPy", "..."))

# FUNCIONES DE LOS BOTONES

    #Funcion que invoca la funcion de reorganizar pdf, poner dos hojas en una cara y borrar los pdfs que surgen del proceso
    def booklet(self):
        self.reorganiza()
        self.dobles()
        self.borrar_residuos()

    #Organizar las paginas del pdf segun el orden surgido del algoritmo en una tupla
    def reorganiza(self):

        #Cargar pdf
        doc = self.caja.toPlainText()
        ruta_PDF = os.path.join(os.getcwd(), doc)  # ALternativa --> ruta_PDF = "ejemplo/sample.pdf"
        PDF = PdfFileReader(ruta_PDF)
        numPages = int(PDF.getNumPages())

        ########################################
        """RECUENTO DE PAGINAS y AJUSTE A MULTIPLOS DE 4"""
        ########################################

        # PASO 1 Introducimos el numero y Transformamos el numero de paginas a un multiplo de 4 (porque sino nos dará error, porque debemos poner 4 paginas en cada hoja del folio al final)
        num_hojas = numPages

        # Defino la funcion que trnaforma el numero a en un multiplo de b
        def multiplo(a, b):
            return int((a / b + 1)) * b

        # Verifico si el numero de paginas del pdf es multiplo de 4
        if num_hojas % 4 == 0:  # Si el residuo es 0, es múltiplo 4, por lo tanto nos quedamos el numero
            num = num_hojas

        # Si no es múltiplo 4, usamos la funcion "multiplo" para transformar el numero
        else:
            num = multiplo(num_hojas, 4)

        diferencia = num - num_hojas

        #############################
        """AÑADIENDO PAGINAS BLANCAS"""
        #############################

        # PASO 1 Añadimos el PDF original y creamos las paginas blancas a añadir
        input_pdf = PDF
        output = PdfFileWriter()
        medida_hoja = input_pdf.getPage(0)  # Tomo la primera hoja del pdf para crear paginas blancas de la misma medida

        # PASO 2 Obtenemos el numero de hojas blancas que queremos añadir y creamos hojas blancas segun se necesitan
        for blancas in range(diferencia):
            largo = medida_hoja.mediaBox.getHeight()
            ancho = medida_hoja.mediaBox.getWidth()
            blanc_pdf = PageObject.createBlankPage(None, ancho, largo)  # Creamos pagina en blanco con las medidas del pdf original
            output.addPage(blanc_pdf)

        with open(os.path.join("PDF_EDITADO", "residuo.pdf"), 'wb') as f:
            output.write(f)

        # PASO 3 Juntamos le PDF con las paginas en blanco
        union = PdfFileMerger()
        union.append(input_pdf)
        union.append("PDF_EDITADO/residuo.pdf")

        with open(os.path.join("PDF_EDITADO", "residuo2.pdf"), 'wb') as f:
            union.write(f)

        #######################
        """ALGORITMO DE ORDENACION"""
        #######################

        # PASO 1 Creamos la primera tupla con los numeros en orden de pares mayor-menor
        tupla = []
        for i in range(num):
            tupla.append((num - i, i + 1))

        # PASO 2 Hago otra tupla a partir de la generada en el paso anterior pero en orden inverso
        idx = len(tupla) - 1
        tupla_inversa = []
        while (idx >= 0):
            tupla_inversa.append(tupla[idx])
            idx = idx - 1

        # resultado paso 2 --> print(tupla_inversa)

        # PASO 3 Combinamos las dos tuplas en orden normal y en orden inverso para alternar una tupla de cada
        t_combinadas = []
        numI = int(num - 1)  # resto 1 al numero input para no tener mas tuplas de las que puede haber
        for p in range(numI):
            t_combinadas.append((tupla[p], tupla_inversa[p + 1]))

        # PASO 4 Ahora hacemos una nueva tupla que combine una normal y una inversa

        if num >= 8:
            div = int(
                num / 4)  # Dividimos por 4 el numero introducido para recortar los cuadruplicados al unir 2 pares de tuplas en pasos anteriores
        else:
            div = int(num / 3)  # Dividimos por 2 cuando los numeros son mas pequeños que 8 ()

        resultados = []
        for r in range(div):
            resultados.append(t_combinadas[r * 2])

        for item in resultados:
            print(item[0][0], ',', item[0][1], '/', item[1][0], ',', item[1][1])

        # PASO 5 Aplanamos la tupla obtenida (que estaba comprimida) y mostramos resultados

        ordenacion = [i for x in resultados for j in x for i in j]
        print("El orden de las hojas será ", ordenacion)

        # Imprimimos el numero de hojas añadidas, si las hay
        if num_hojas % 4 == 0:
            self.caja.setText("OK")
        else:
            self.caja.setText("El numero de paginas que tenia el pdf eran "+ str(num_hojas)+ " Pero se han añadido "+ str(diferencia)+" hojas para que sea multiplo de 4 y cuadre con el documento final")

        ########################################
        """CREANDO EL PDF"""
        ########################################

        # Cargo el pdf con las paginas blancas y creo un doc para crear
        fusion = PdfFileReader("PDF_EDITADO/residuo2.pdf")
        creacion = PdfFileWriter()

        # Hago un bucle for que escriba siguiendo el orden de las tuplas obtenidas
        for numero_pagina in ordenacion:
            temp = fusion.getPage(numero_pagina - 1)
            creacion.addPage(temp)

        with open(os.path.join("PDF_EDITADO", "creado.pdf"), 'wb') as f:
            creacion.write(f)

    def dobles(self): #CREAR UN BOOKLET CON LAS PAGINAS YA ORDENADAS

        # Carga pdf y variables
        doc= "PDF_EDITADO/creado.pdf"
        pdf_elegido = os.path.join(os.getcwd(), doc)
        reader = PdfFileReader(pdf_elegido)#(open(pdf_elegido, 'rb'))  # el primer pdf
        sup_reader = reader  # el segundo pdf
        numPags = int(reader.getNumPages()/2)
        writer = PdfFileWriter()

        # Bucle para crear paginas
        for i in range(numPags):
            invoice_page = reader.getPage(i * 2)  # Hoja que ira a la izquierda del folio
            sup_page = sup_reader.getPage(int(i * 2) + 1)  # Hoja que ira a la derecha del folio

            # Creamos pagina en blanco con las medidas del pdf original pero multiplico ancho x2 para que quede apaisada
            largo = sup_page.mediaBox.getHeight()
            ancho = sup_page.mediaBox.getWidth()
            translated_page = PageObject.createBlankPage(None, ancho * 2, largo)

            # Localizacion de las copias en cada lado
            escala = 1  # Escala original
            desp_horizonal = int(ancho)  # pongo el ancho porque asi es justo la mitad de la hoja creada
            desp_vertical = 0
            e, x, y = [escala, desp_horizonal,
                       desp_vertical]  # Escala de la copia, colocacion en eje horizontal, colocacion eje vertical

            translated_page.mergeScaledTranslatedPage(sup_page, e, x, y)
            translated_page.mergePage(invoice_page)

            # Escribiendo el pdf
            writer.addPage(translated_page)

        with open(os.path.join("PDF_EDITADO", "IMPRIMIBLE.pdf"), 'wb') as f:
            writer.write(f)

    def carpeta(self):
        # Abrir carpeta en funcion al sistema operatico que estemos usando
        def open_file(path):
            if platform.system() == "Windows":
                os.startfile(path)
            elif platform.system() == "Darwin":
                subprocess.Popen(["open", path])
            else:
                subprocess.Popen(["xdg-open", path])

        open_file("PDF_EDITADO")

    def dividir(self):
        self.caja.setText("Dividido en pares e impares para imprimir por caras")

        # Cargo el pdf con las paginas blancas y creo un doc para crear
        xdividir = PdfFileReader("PDF_EDITADO/IMPRIMIBLE.pdf")
        hojas_pares = PdfFileWriter()
        hojas_impares = PdfFileWriter()
        numPages = int(xdividir.getNumPages()/2)

        #Creo un pdf con paginas pares
        for i in range(numPages):
            pares = xdividir.getPage(int(i*2)+1)
            hojas_pares.addPage(pares)
        with open(os.path.join("PDF_EDITADO", "1_Pares_carasB.pdf"), 'wb') as f:
            hojas_pares.write(f)

        # Creo un pdf con paginas impares
        for i in range(numPages):
            impares = xdividir.getPage(i*2)
            hojas_impares.addPage(impares)
        with open(os.path.join("PDF_EDITADO", "2_Impares_carasA.pdf"), 'wb') as f:
            hojas_impares.write(f)

    def borrar_residuos(self):
        from os import remove
        remove("PDF_EDITADO/residuo2.pdf")
        remove("PDF_EDITADO/creado.pdf")

    def info_autor(self):
        msgBox = QMessageBox()
        msgBox.setIcon(QMessageBox.Information)
        msgBox.setText("Creado por R.Romero")
        msgBox.setWindowTitle("Info")
        msgBox.setStandardButtons(QMessageBox.Ok)

        #msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        #msgBox.buttonClicked.connect(msgButtonClick)

        returnValue = msgBox.exec()
        if returnValue == QMessageBox.Ok:
            print('OK clicked')

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    CuadPy = QtWidgets.QDialog()
    ui = Ui_CuadPy()
    ui.setupUi(CuadPy)
    CuadPy.show()
    sys.exit(app.exec_())


import bracketology.brackets as bracketology
import re
import random
from collections import defaultdict

# Patch
bracketology.brackets_dict.clear()
bracketology.brackets_dict.update({
    "2023": {
        "Finals": {
            "game1": {
                "team1": "south",
                "team2": "east",
            },
            "game2": {
                "team1": "midwest",
                "team2": "west",
            },
        }
    }
})

MAX_UPSET_CHANCE = .5

upset_chances = []

with open('data/cups.txt', 'r') as f:
    order = f.read().splitlines()
    for i in order:
        upset_chances.append(MAX_UPSET_CHANCE * int(i)/len(order))

regions = []
all_teams = []

def sim_func(game):
    team1 = game.top_team
    team2 = game.bottom_team
    seed_diff = team1.seed - team2.seed

    if seed_diff == 0:
        worse, better = (team2, team1) if random.random() < .5 else (team1, team2)
    else:
        worse, better = (team2, team1) if seed_diff < 0 else (team1, team2)

    upset_chance = upset_chances[all_teams.index(better)]
    return worse if random.random() < upset_chance else better

for region_name in ["east", "west", "south", "midwest"]:
    with open(f'data/{region_name}.txt', 'r') as f:
        lines = f.read().splitlines()

    teams = []

    for line in lines:
        match = re.match(r'^No\. (\d+) (.*) vs. No. (\d+) (.*)$', line)
        team1 = bracketology.Team(seed = int(match.group(1)), name=match.group(2))
        team2 = bracketology.Team(seed = int(match.group(3)), name=match.group(4))
        teams.append(team1)
        teams.append(team2)

    teams.sort(key=lambda x: x.seed)

    all_teams.extend(teams)

    region = bracketology.SubBracket16(region_name).initialize_first_round(teams)
    regions.append(region)

teams_and_chances = [(upset_chances[i], team) for i, team in enumerate(all_teams)]
teams_and_chances.sort(key = lambda x: x[0], reverse=True)

print("Upset chances:")
for weight, team in teams_and_chances:
    print(f"{team}: {weight}")

winners_by_region = {
    region.region: defaultdict(list)
    for region in regions
}

def run_full_sim():
    for region in regions:
        region.run_bracket(sim_func)
        print(region)

    final_four = bracketology.FinalFour(2023)
    final_four.set_matches({
        region.region: region.winner for region in regions
    })
    final_four.run_final_four(sim_func)
    final_four.run_championship(sim_func)
    print(final_four)

run_full_sim()


import logging

import torch

from nni.nas.pytorch.base_mutator import BaseMutator

logger = logging.getLogger(__name__)

class Mutator(BaseMutator):

    def __init__(self, model):
        super().__init__(model)
        self._cache = dict()

    def sample_search(self):
        """
        Override to implement this method to iterate over mutables and make decisions.

        Returns
        -------
        dict
            A mapping from key of mutables to decisions.
        """
        raise NotImplementedError

    def sample_final(self):
        """
        Override to implement this method to iterate over mutables and make decisions that is final
        for export and retraining.

        Returns
        -------
        dict
            A mapping from key of mutables to decisions.
        """
        raise NotImplementedError

    def reset(self):
        """
        Reset the mutator by call the `sample_search` to resample (for search). Stores the result in a local
        variable so that `on_forward_layer_choice` and `on_forward_input_choice` can use the decision directly.
        """
        self._cache = self.sample_search()

    def export(self):
        """
        Resample (for final) and return results.

        Returns
        -------
        dict
            A mapping from key of mutables to decisions.
        """
        return self.sample_final()

    def on_forward_layer_choice(self, mutable, *inputs):
        """
        On default, this method retrieves the decision obtained previously, and select certain operations.
        Only operations with non-zero weight will be executed. The results will be added to a list.
        Then it will reduce the list of all tensor outputs with the policy specified in `mutable.reduction`.

        Parameters
        ----------
        mutable : LayerChoice
            Layer choice module.
        inputs : list of torch.Tensor
            Inputs

        Returns
        -------
        tuple of torch.Tensor and torch.Tensor
            Output and mask.
        """
        def _map_fn(op, *inputs):
            return op(*inputs)

        mask = self._get_decision(mutable)
        assert len(mask) == len(mutable.choices), \
            "Invalid mask, expected {} to be of length {}.".format(mask, len(mutable.choices))
        out = self._select_with_mask(_map_fn, [(choice, *inputs) for choice in mutable.choices], mask)
        return self._tensor_reduction(mutable.reduction, out), mask

    def on_forward_input_choice(self, mutable, tensor_list):
        """
        On default, this method retrieves the decision obtained previously, and select certain tensors.
        Then it will reduce the list of all tensor outputs with the policy specified in `mutable.reduction`.

        Parameters
        ----------
        mutable : InputChoice
            Input choice module.
        tensor_list : list of torch.Tensor
            Tensor list to apply the decision on.

        Returns
        -------
        tuple of torch.Tensor and torch.Tensor
            Output and mask.
        """
        mask = self._get_decision(mutable)
        assert len(mask) == mutable.n_candidates, \
            "Invalid mask, expected {} to be of length {}.".format(mask, mutable.n_candidates)
        out = self._select_with_mask(lambda x: x, [(t,) for t in tensor_list], mask)
        return self._tensor_reduction(mutable.reduction, out), mask

    def _select_with_mask(self, map_fn, candidates, mask):
        if "BoolTensor" in mask.type():
            out = [map_fn(*cand) for cand, m in zip(candidates, mask) if m]
        elif "FloatTensor" in mask.type():
            out = [map_fn(*cand) * m for cand, m in zip(candidates, mask) if m]
        else:
            raise ValueError("Unrecognized mask")
        return out

    def _tensor_reduction(self, reduction_type, tensor_list):
        if reduction_type == "none":
            return tensor_list
        if not tensor_list:
            return None  # empty. return None for now
        if len(tensor_list) == 1:
            return tensor_list[0]
        if reduction_type == "sum":
            return sum(tensor_list)
        if reduction_type == "mean":
            return sum(tensor_list) / len(tensor_list)
        if reduction_type == "concat":
            return torch.cat(tensor_list, dim=1)
        raise ValueError("Unrecognized reduction policy: \"{}\"".format(reduction_type))

    def _get_decision(self, mutable):
        """
        By default, this method checks whether `mutable.key` is already in the decision cache,
        and returns the result without double-check.

        Parameters
        ----------
        mutable : Mutable

        Returns
        -------
        object
        """
        if mutable.key not in self._cache:
            raise ValueError("\"{}\" not found in decision cache.".format(mutable.key))
        result = self._cache[mutable.key]
        logger.debug("Decision %s: %s", mutable.key, result)
        return result


#!/usr/bin/env python

from __future__ import print_function

import os
import cgi
from subprocess import Popen, PIPE, STDOUT

# # Haskell
SCRIPTDIR = 'haskell'

# To run NON compiled code
# SCRIPT = ['/usr/bin/runhaskell', 'Shrdlite.hs']

# Run compiled code with garbage collection off
# compile with this command: ghc -O2 -rtsopts Shrdlite.hs
SCRIPT = ['./Shrdlite',' +RTS -A2G']

################################################################################

print('Content-type:text/plain')
print()

try:
    while not os.path.isdir(SCRIPTDIR):
        SCRIPTDIR = os.path.join("..", SCRIPTDIR)

    form = cgi.FieldStorage()
    data = form.getfirst('data')
    script = Popen(SCRIPT, cwd=SCRIPTDIR, stdin=PIPE, stdout=PIPE, stderr=PIPE)
    out, err = script.communicate(data)

    print(out)
    if err:
        raise Exception(err)

except:
    import sys, traceback
    print(traceback.format_exc())
    sys.exit(1)


m=int(input("Enter number of elements "))
arr=[]
print("Enter elements :")
for i in range(0,m):
        z=int(input())
        arr.append(z)

arr.sort()
i=0
while(i<m-1) :
    flag=0
    while((i+1)<m and arr[i]==arr[i+1]):
        i=i+1
        flag=1
    if flag:
        print(arr[i],end=" ")
    else:
        i=i+1


from slide import Slide

def make_slideshow_sorted(slides):

        slideshow = bucketSort(slides)

        return slideshow

# sort slides on amount of tags
def qsort(inlist):
    if inlist == []:
        return []
    else:
        pivot = len(inlist[0].tags)
        lesser = qsort([x for x in inlist[1:] if len(x.tags) < pivot])
        greater = qsort([x for x in inlist[1:] if len(x.tags) >= pivot])
        return lesser + [pivot] + greater

def bucketSort(slides):
    arr = []

    # find max amount of tags
    slot_num = 0
    for s in slides:
        n_tags = len(s.tags)
        if slot_num < n_tags:
            slot_num = n_tags

    for i in range(slot_num):
        arr.append([])

    # Put array elements in different buckets
    for s in slides:
        arr[len(s.tags)-1].append(s)

    x = []
    # concatenate the result
    #k = 0
    for i in range(slot_num):
        if len(arr[i]) > 1:
            arr[i] = Slide.make_slideshow(arr[i])

        for j in range(len(arr[i])):
            x.append(arr[i][j])
            #k += 1

    slideshow = x
    return slideshow


import sys
sys.stdin = open('수열 편집.txt')

class Node:
    def __init__(self, data=0, nex=None):
        self.data = data
        self.next = nex
    def __str__(self):
        return f"{self.data}"

class LinkedList:
    def __init__(self, node=None):
        self.head = node
        self.count = 0

    def __del__(self):
        self.count -= 1

    def append(self, node):
        self.count += 1
        if self.head == None:
            self.head = node
        else:
            cur = self.head
            while cur.next != None:
                cur = cur.next
            cur.next = node

    def delete(self, index):
        if index == 0:
            cur = self.head
            self.head = cur.next
            cur.next = None
        else:
            cur = self.head
            for _ in range(index-1):
                cur = cur.next
            temp = cur.next
            cur.next = cur.next.next
            temp.next = None
        self.count -= 1

    def insert(self, node, index):
        if index == 0:
            node.next = self.head
            self.head = node
        else:
            cur = self.head
            for _ in range(index-1):
                cur = cur.next
            node.next = cur.next
            cur.next = node
        self.count += 1

    def print(self):
        result = []
        cur = self.head
        while cur.next != None:
            result.append(cur.data)
            cur = cur.next
        result.append(cur.data)
        print(result)

    def get(self, index):
        cur = self.head
        for _ in range(index):
            cur = cur.next
        return cur

    def len(self):
        return self.count

    def change(self, index, data):
        node = self.head

        for _ in range(index):
            node.data = data

T = int(input())

for test_case in range(1, T + 1):
    N, M, L = map(int, input().split())
    number = list(map(int, input().split()))
    my_list = LinkedList()

    for i in range(N):
        my_list.append(number[i])

    for i in range(M):
        temp = list(input().split())
        if temp[0] == 'I':
            my_list.insert(int(temp[1]), int(temp[2]))
        elif temp[0] == 'D':
            my_list.delete(int(temp[1]))
        elif temp[0] == 'C':
            my_list.change(int(temp[1]), int(temp[2]))
    my_list.print()
    # print("#{} {}".format(test_case, result))

수열 편집ver종우.py


import os

def folderIn(folder_nm, inside_folder):
    try:
        x = os.getcwd()
        parent = x
        child1 = folder_nm
        child2 = inside_folder
        path = os.path.join(parent, child1, child2)
        if not os.path.exists(path):
            os.makedirs(path)
            print(path)
            print("foldercreated succesfully")

    except Exception as e:
        print("error due to ___",e)

"""folder_nm = "manish"
inside_folder = '5negi'
folderIn(folder_nm, inside_foldernm)"""


#!/usr/bin/env python

import numpy as np
import krpc

import ephem_templates

import os

real_planet_names=["MERCURY","VENUS","EARTH","MARS","JUPITER","SATURN","URANUS","NEPTUNE","PLUTO"]
real_planet_NAIF_codes=[199,299,399,499,599,699,799,899,999]

base_output_dir="./ephemeris"

from collections import defaultdict

conn = krpc.connect(address="192.168.0.101",name="ephemeris")

ksp_bodies = conn.space_center.bodies

ksp_sun = ksp_bodies['Sun']

#get all the planets, both into a dictionary and a sorted list
ksp_planets = dict([i for i in ksp_bodies.iteritems() if i[1].orbit != None and i[1].orbit.body.name == "Sun"])
ksp_planet_list = list(ksp_planets.itervalues())
ksp_planet_list.sort(key=lambda x:x.orbit.semi_major_axis)

#Get all the moons, and put them into dictionaries by planet.
ksp_moons = dict([i for i in ksp_bodies.iteritems() if i[1].orbit != None and i[1].orbit.body.name != "Sun"])
ksp_moons_by_planet = defaultdict(list)
for one_moon in ksp_moons.itervalues():
	ksp_moons_by_planet[one_moon.orbit.body.name].append(one_moon)

#sort the moon lists
for one_list_of_moons in ksp_moons_by_planet.itervalues():
	one_list_of_moons.sort(key=lambda x:x.orbit.semi_major_axis)

ten_to_min_nine=0.000000001
solar_gm=1172332800.0

#generate the templates
for i in range(len(ksp_planet_list)):
	one_planet = ksp_planet_list[i]
	its_orbit = one_planet.orbit

	setup_file_string = ephem_templates.setup_template.format(object_id=real_planet_NAIF_codes[i],
			object_name=real_planet_names[i],
			center_id=0,
			center_gm=solar_gm)
	ephemeris_data = ephem_templates.ephemeris_template.format(object_id=real_planet_NAIF_codes[i],
			center_id=0,
			center_gm=solar_gm,
			rad_periapsis_km=its_orbit.periapsis*0.001,
			eccentricity=its_orbit.eccentricity,
			inclination=np.rad2deg(its_orbit.inclination),
			longitude_of_ascending_node=np.rad2deg(its_orbit.longitude_of_ascending_node),
			argument_of_periapsis=np.rad2deg(its_orbit.argument_of_periapsis),
			mean_anomaly_at_epoch=np.rad2deg(its_orbit.mean_anomaly_at_epoch)
			)

	ephem_data = ""
	ephem_data += ephem_templates.ephemeris_template_header.format(object_id=real_planet_NAIF_codes[i],
			center_id=0,
			center_gm=solar_gm)
	for j in range(20):
		ephem_data += ephem_templates.ephemeris_data_line.format(time_in_seconds=j*its_orbit.period,
			rad_periapsis_km=its_orbit.periapsis*0.001,
			eccentricity=its_orbit.eccentricity,
			inclination=np.rad2deg(its_orbit.inclination),
			longitude_of_ascending_node=np.rad2deg(its_orbit.longitude_of_ascending_node),
			argument_of_periapsis=np.rad2deg(its_orbit.argument_of_periapsis),
			mean_anomaly_at_epoch=np.rad2deg(its_orbit.mean_anomaly_at_epoch)
			)

	with open(os.path.join(base_output_dir,"{}_{}.setup".format(i+1,one_planet.name)),"w") as setupfile:
		setupfile.write(setup_file_string)
	with open(os.path.join(base_output_dir,"{}_{}.data".format(i+1,one_planet.name)),"w") as datafile:
		datafile.write(ephem_data)

#conn.close()


import time
import threading

gal_nam = [100, 22]

def test1(temp):
    temp.append(33)
    print("---test1=%s---" % str(temp))

def test2(temp):
    print("---test2=%s---" % str(temp))

def main():
    t1 = threading.Thread(target=test1, args=(gal_nam,))
    t2 = threading.Thread(target=test2, args=(gal_nam,))
    t1.start()
    time.sleep(1)
    t2.start()
if __name__ == "__main__":
    main()

8.多线程共享全局变量带参数.py


import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage,signal
from operator import itemgetter
import cv2

#Computes the C matrix - [[Eex,Eexy],[Eexy],[Eey]]
#Takes in the gradient matrices ex (x gradient squared), ey (y gradient squared), exey (product of x and y gradients),
#								location to build neighborhood, size of neighborhood and returns the c matrix

def compute_c(ex,ey,exey,i,j,offset):
	ex_window = ex[i-offset:i+offset+1,j-offset:j+offset+1]
	ey_window = ey[i-offset:i+offset+1,j-offset:j+offset+1]
	exey_window = exey[i-offset:i+offset+1,j-offset:j+offset+1]
	sum_ex = ex_window.sum()
	sum_ey = ey_window.sum()
	sum_exey = exey_window.sum()
	c_matrix = [[sum_ex,sum_exey],[sum_exey,sum_ey]]
	return c_matrix

#Filters corners based on threshold from possible corner points.
#Type linear gives accurate representation of corners. Type grid is 30% faster than linear but has overlapping grids
#Threshold is calculated based on a percentage of the maximum delta value in the list
#Takes in the possible corner points, threshold ratio and offset of neighborhood
def filter_points(points,threshold,offset,filter_type):
	new_points = []
	#Compute threshold eigenvalue
	maxVal = max(points,key=itemgetter(2))[2]
	threshold = maxVal * threshold
	points = [x for x in points if x[2] > threshold]

	#Sort in decreasing order of eigenvalue delta
	points = sorted(points,key = lambda x : x[2],reverse=True)

	#Remove all lower eigenvalue points in the neighbourhood
	if filter_type == "linear":
		while points:
			new_points.append(points[0])
			points = [point for point in points[1:] if point[0] > new_points[-1][0] + offset or point[1] > new_points[-1][1] + offset or point[0] < new_points[-1][0] - offset or point[1] < new_points[-1][1] - offset]

		return new_points
	elif filter_type == "grid":
		detected = {}
		for row,col,del2,grid in points:
			if grid not in detected:
				detected[grid] = (row,col,del2)
		return detected.values()
	else:
		print("Type not identified")
		return []

#Constructs a rectangle around the corner point. Size of the rectangle is the size of the neighbourhood
#Takes in the image, corner point co-ordinates and the offset for neighbourhood
def draw_rectangle(img,x,y,offset):
	for i in range(-offset,offset+1):
		img[x+i][y-offset] = 255
		img[x+i][y+offset] = 255

	for j in range(-offset,offset+1):
		img[x-offset][y+j] = 255
		img[x+offset][y+j] = 255

#Represents corners on the image and displays it on a plot
#Takes in the image, corner points and offset of neighbourhood
def display_corners(img,corners,offset):
	for row,col,delta,grid in corners:
		draw_rectangle(img,row,col,offset)

	plt.gray()
	plt.axis("off")
	plt.imshow(img)

	plt.show()

#Performs corner detection
#Takes in the input image, standard deviation value for gaussian smoothing, threshold value for corners and size of neighbourhood
def detect_corners(img,sigma=1,threshold=0.1,n=4,filter_type="linear"):
	possible_corners = []
	#Determine number of pixels and offset for neighbourhood
	size = 2*n +1
	offset=size//2

	#Gaussian smoothing
	smooth_img = ndimage.gaussian_filter(img,sigma)

	#Obtain values necessary to calculate c matrix
	jx,jy = np.gradient(smooth_img)
	ex = jx**2
	ey = jy**2
	exey = jx*jy

	#Detect corners for each point
	for i in range(offset,len(img)-offset):
		for j in range(offset,len(img[0])-offset):
			c_matrix = compute_c(ex,ey,exey,i,j,offset)
			eigenVals = np.linalg.eig(c_matrix)
			#Smaller eigenvalue delta 2
			del2 = min(eigenVals[0])
			possible_corners.append([i,j,del2,(i//size, j//size)]) #i//size,j//size gives grid co-ordinates
	corners = filter_points(possible_corners,threshold,size,filter_type)
	display_corners(smooth_img,corners,offset)
	#print(corners)

#Test cases
if __name__ == "__main__":
	img = cv2.imread("CheckerBoard.jpg",0)
	detect_corners(img)
	# detect_corners(img,sigma=2)
	# detect_corners(img,sigma=3)
	# detect_corners(img,threshold=0.4)
	# detect_corners(img,threshold=0.6)
	# detect_corners(img,n=1)
	# detect_corners(img,n=9)
	img1 = cv2.imread("Building1.jpg",0)
	detect_corners(img1)


# Standard packages
import logging
from enum import Enum
import time
from datetime import datetime, timedelta
import asyncio
import os
import tqdm

# External packages
from django.core.management.base import BaseCommand, CommandError
from twilio.rest import Client

# Internal Packages
from flint.db.models import KhojUser, Conversation
from flint.constants import KHOJ_WHATSAPP_PROD, KHOJ_WHATSAPP_DEBUG
from flint.configure import save_conversation

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)

# Initialize Twilio Client
account_sid = os.getenv("TWILIO_ACCOUNT_SID")
auth_token = os.getenv("TWILIO_AUTH_TOKEN")
twillio_client = Client(account_sid, auth_token)

class UserFilterTypes(Enum):
    ALL = "all"
    ACTIVE_LAST_DAY = "active_last_day"

class MessageType(Enum):
    DEBUG = "debug"
    PROD = "prod"

class Command(BaseCommand):
    help = "test management commands"

    def add_arguments(self, parser):
        parser.add_argument("--user_filter_type", type=str, help="user filter type: all, active_last_day", default=UserFilterTypes.ACTIVE_LAST_DAY.value, required=False, choices=[e.value for e in UserFilterTypes])
        parser.add_argument("bot_message", type=str, help="bot message to send")
        parser.add_argument("--message_type", type=str, help="message type: debug, prod", default=MessageType.DEBUG.value, choices=[e.value for e in MessageType])

    def handle(self, *args, **options):
        user_filter_type = options["user_filter_type"]
        bot_message = options["bot_message"]
        message_type = options["message_type"]

        from_number = KHOJ_WHATSAPP_DEBUG if message_type == MessageType.DEBUG.value else KHOJ_WHATSAPP_PROD

        if user_filter_type == UserFilterTypes.ALL.value:
            logger.warn(f"Sending message '{bot_message}' to all users. This must match a template in the WhatsApp template manager")
            khoj_users = KhojUser.objects.all()

        elif user_filter_type == UserFilterTypes.ACTIVE_LAST_DAY.value:
            logger.warn(f"Sending message '{bot_message}' to all users active in the last 24 hours. This must match a template in the WhatsApp template manager")
            curr_time = datetime.now()
            conversations = Conversation.objects.filter(created_at__gte=curr_time - timedelta(days=1))
            khoj_users = conversations.values_list("user", flat=True).distinct()
            khoj_users = KhojUser.objects.filter(id__in=khoj_users)

        else:
            raise CommandError(f"Invalid user filter type: {user_filter_type}")

        logger.info(f"Sending message '{bot_message}' to {len(khoj_users)} users")

        bar = tqdm.tqdm(total=len(khoj_users))

        for khoj_user in khoj_users:
            user = khoj_user.user
            logger.info(f"Sending message '{bot_message}' to user {user.id}")
            try:
                message = twillio_client.messages.create(
                    body=bot_message,
                    from_=from_number,
                    to=f'whatsapp:{khoj_user.phone_number}'
                )
                logger.info(f"Sent message '{bot_message}' to user {khoj_user.id}, {khoj_user.phone_number}, from number {from_number} with Twilio message id {message.sid}")
                asyncio.run(save_conversation(user, '', bot_message, user_message_type='system'))
                time.sleep(0.5)
            except Exception as e:
                logger.error(f"Failed to send message '{bot_message}' to user {khoj_user.id}, {khoj_user.phone_number} with error {e}")
            bar.update(1)

        bar.close()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@author: zparteka
"""
import numpy as np
# from chiapet_operations.chiapet_given_region import read_region
from math import ceil
from os import path
from glob import glob
from scripts.config import hg19_chromosomes_dict  as chromosomes_hg19
from scripts.config import hg38_chromosomes_dict as chromosomes_hg38
from scripts.config import mm10_chromosomes_dict as chromosomes_mm10

# --------------------------------------------MATRICES------------------------------------------------------------------

def choose_genome_version(genome_version):
    """Check if chosen genome version is supported."""
    if genome_version == 'hg19':
        chromosomes_dict = chromosomes_hg19
    elif genome_version == 'hg38':
        chromosomes_dict = chromosomes_hg38
    elif genome_version == "mm10":
        chromosomes_dict = chromosomes_mm10
    else:
        print("Genome version not included.")
        raise Exception("Not supported genome version.")
    return chromosomes_dict

def bead_ranges_in_chromosome(chromosome, genome_version, resolution):
    """Return list with bead ranges for given chromosome."""
    chromosomes_dict = choose_genome_version(genome_version=genome_version)
    bead_ranges = []
    for i in range(0, chromosomes_dict[chromosome], resolution):
        bead_ranges.append((i, i + resolution))
    return bead_ranges

def bead_ranges_in_region(region, genome_version, resolution):
    """Return list with bead ranges for given region"""
    bead_ranges_chr = bead_ranges_in_chromosome(chromosome=region[0], genome_version=genome_version,
                                                resolution=resolution)
    if int(region[2]) <= bead_ranges_chr[-1][-1]:
        for i in range(len(bead_ranges_chr)):
            if int(region[1]) in range(bead_ranges_chr[i][0], bead_ranges_chr[i][1]):
                start = i
            if int(region[2]) in range(bead_ranges_chr[i][0], bead_ranges_chr[i][1]):
                end = i

        bead_ranges = bead_ranges_chr[start:end + 1]
    else:
        raise ValueError("Domain boundries exceed chromosome length")
    return bead_ranges

def create_chromosome_empty_matrix(chromosome, resolution, genome):
    """Create empty array based on chromosome length and given resolution"""
    chromosomes_dict = choose_genome_version(genome_version=genome)
    length = chromosomes_dict[chromosome]
    number_of_beads = ceil(length / resolution)
    matr = np.zeros((number_of_beads, number_of_beads))
    return matr

def create_matrix_from_bed(interactions):
    """Create matrix using only interactions"""
    n = len(interactions)
    matr = np.zeros((n, n))
    return matr

def create_empty_region_matrix(region, resolution, genome):
    """Create empty matrix of a region by cutting the empty matrix for whole chromosome"""
    check_region(region=region, genome=genome)
    chrom_beads = bead_ranges_in_chromosome(chromosome=region[0], genome_version=genome, resolution=resolution)
    start_bead, end_bead = 0, 0
    for i in range(len(chrom_beads)):
        if int(region[1]) in range(chrom_beads[i][0], chrom_beads[i][1]):
            start_bead = i
        if int(region[2]) in range(chrom_beads[i][0], chrom_beads[i][1]):
            end_bead = i + 1
    region_len = end_bead - start_bead
    region_matr = np.zeros((region_len, region_len))
    return region_matr

def create_empty_domain_matrix(region, resolution):
    """Create empty matrix of domain region with given resolution"""
    start = region[0]
    end = region[1]
    beads = 0
    while start < end:
        start += resolution
        beads += 1
    return np.zeros((beads, beads))

# todo check if this works
def check_region(region, genome):
    """Check if given error is in requested chromosome"""
    chromosomes_dict = choose_genome_version(genome_version=genome)
    if int(region[2]) > chromosomes_dict[region[0]]:
        raise ValueError("End of region exceeds length od chromosome.")

def save_matr(matr, filename, fileformat="txt"):
    """Save matrix in numpy or txt format."""
    if fileformat == "txt":
        np.savetxt(filename, matr)
    elif fileformat == "npy":
        np.save(filename, matr)

# todo - tests for juicer
# ---------------------------------------------JUICER-------------------------------------------------------------------

# TODO read to pandas
def read_juicer_dump(dumpfile, resolution):
    """read file dumped from juicer straw and return nonzero positions of beads"""
    dumped = open(dumpfile, 'r')
    print("Processing " + dumpfile)
    nonzero_beads = []
    for i in dumped:
        line = i.strip().split()
        nonzero_beads.append(
            ((int(ceil(int(line[0]) / resolution))) - 1, int(ceil((int(line[1]) / resolution))) - 1, float(line[2])))
    nonzero_beads = sorted(nonzero_beads, key=lambda tup: tup[1])
    return nonzero_beads

# todo przetestować!!!!
def beads_to_matr(nonzero_beads, chromosome, resolution, genome):
    """Create a matrix from nonzero beads read from dumped file"""
    matr = create_chromosome_empty_matrix(chromosome=chromosome, resolution=resolution, genome=genome)
    for i in range(len(nonzero_beads)):
        matr[nonzero_beads[i][0]][nonzero_beads[i][1]] = nonzero_beads[i][2]
        matr[nonzero_beads[i][1]][nonzero_beads[i][0]] = nonzero_beads[i][2]
    return matr

def multiple_juicer_matrices(matrices_dir, resolution):
    file_list = glob(path.join(matrices_dir, "*KB.txt"))
    for i in file_list:
        print("Parsing " + i)
        filename = path.join(matrices_dir, i.split(".")[0] + "_matrix.txt")
        fi = path.join(matrices_dir, i)
        bead = read_juicer_dump(dumpfile=fi, resolution=resolution)
        matr = beads_to_matr(nonzero_beads=bead)
        save_matr(matr=matr, filename=filename, fileformat="txt")
    print("All matrices have been saved.")