import math

import numpy as np
import matplotlib.pyplot as plt

from data.data_set import OurSet
from env.environment import ConflictEnv
from parameters import *

def draw(env, expert_set):
    train_num_list = [int(info['id']) for info in env.train_set]
    test_num_list = [int(info['id']) for info in env.test_set]
    _, train_action_list = expert_set.get_next_batch(train_num_list)
    _, test_action_list = expert_set.get_next_batch(test_num_list)
    total_action_list = list(train_action_list) + list(test_action_list)

    fig, axes = plt.subplots(3, 1, sharex=True, figsize=(6, 6))
    axes[0].hist(train_action_list, bins=bins)
    axes[0].xaxis.set_visible(False)
    ax_twin = axes[0].twinx()
    ax_twin.plot(*stat(train_action_list), 'red', label='train')
    ax_twin.ticklabel_format(style='sci', scilimits=(0, 1), axis='y')
    ax_twin.xaxis.set_visible(False)
    ax_twin.legend(fontsize=14)

    axes[1].hist(test_action_list, bins=bins)
    axes[1].xaxis.set_visible(False)
    ax_twin = axes[1].twinx()
    ax_twin.plot(*stat(test_action_list), 'green', label='test')
    ax_twin.ticklabel_format(style='sci', scilimits=(0, 1), axis='y')
    ax_twin.xaxis.set_visible(False)
    ax_twin.legend(fontsize=14)

    axes[2].hist(total_action_list, bins=bins)
    axes[2].xaxis.set_visible(False)
    ax_twin = axes[2].twinx()
    ax_twin.plot(*stat(total_action_list), 'blue', label='total')
    ax_twin.ticklabel_format(style='sci', scilimits=(0, 1), axis='y')
    ax_twin.xaxis.set_visible(False)
    ax_twin.legend(fontsize=14)

    fig.text(0.5, 0.05, 'Action Index', ha='center', fontsize=16)
    fig.text(0.05, 0.5, 'Count', va='center', rotation='vertical', fontsize=16)
    fig.text(0.95, 0.5, 'Frequency', va='center', rotation='vertical', fontsize=16)
    plt.show()

def stat(lst):
    length = len(lst)

    result = {i: 0 for i in range(bins)}
    for v in lst:
        assert v in result.keys()
        result[v] += 1

    x, y = [], []
    for key, value in result.items():
        x.append(key)
        y.append(value / length)
    return x, y

def kl_divergence(p, q):
    p = np.array(stat(p))
    q = np.array(stat(q))
    return np.sum(np.where(p != 0, p * np.log(p / (q+1e-8)), 0))

def get_acr_mse(int_num_list, int_act, exp_num_list, exp_act):
    acr_list = []
    mse_list = []
    for num, act in zip(int_num_list, int_act):
        e_act = exp_act[exp_num_list.index(num)]
        delta = act - e_act
        acr_list.append(int(delta == 0))
        mse_list.append(delta * delta)
    return np.mean(acr_list), math.sqrt(np.mean(mse_list))

def _analysis(path, prefix, start=0, end=10001, delta=1000):
    traj_data = np.load(expert_path)
    print(list(traj_data.keys()))
    expert_num = list(traj_data['name'])
    expert_act = traj_data['action']

    train_idx, test_idx = None, None
    expert_train_act, expert_test_act = None, None
    train_acr_list, test_acr_list, total_acr_list = [], [], []
    train_mse_list, test_mse_list, total_mse_list = [], [], []
    kl_train_lst, kl_test_lst = [], []
    sr_train_lst, sr_test_lst = [], []
    steps = list(range(start, end, delta))
    ad_lst = []
    for step in steps:
        print(path + prefix + '_train_{}.npz'.format(step))
        train_data = np.load(path + prefix + '_train_{}.npz'.format(step))
        test_data = np.load(path + prefix + '_test_{}.npz'.format(step))
        train_num, test_num = train_data['name'], test_data['name']
        train_act, test_act = train_data['action'], test_data['action']

        if train_idx is None:
            train_idx = [expert_num.index(num) for num in train_num]
            test_idx = [expert_num.index(num) for num in test_num]
            expert_train_act = expert_act[train_idx]
            expert_test_act = expert_act[test_idx]

        # AD
        kl_train = kl_divergence(expert_train_act, train_act)
        kl_train_lst.append(kl_train)
        kl_test = kl_divergence(expert_test_act, test_act)
        kl_test_lst.append(kl_test)
        ad_lst.append([stat(train_act), stat(test_act)])
        # SR
        sr_train_lst.append(np.mean(train_data['result']))
        sr_test_lst.append(np.mean(test_data['result']))
        # ACR, MSE
        acr, mse = get_acr_mse(train_num, train_act, expert_num, expert_act)
        train_acr_list.append(acr)
        train_mse_list.append(mse)
        print(step, acr, mse, end=' ')
        acr, mse = get_acr_mse(test_num, test_act, expert_num, expert_act)
        test_acr_list.append(acr)
        test_mse_list.append(mse)
        print(acr, mse)

    fig, axes = plt.subplots(2, 3)

    ax00 = axes[0, 0]
    ax10 = axes[1, 0]
    ax00.plot(*stat(expert_train_act), label='expert_train')
    ax10.plot(*stat(expert_test_act), label='expert_test')

    for i, [train_ad, test_ad] in enumerate(ad_lst):
        step = steps[i]
        if step not in [1000, 10000, end-1, ]:
            continue
        ax00.plot(*train_ad, label='train_{}'.format(step))
        ax10.plot(*test_ad, label='test_{}'.format(step))

    ax01 = axes[0, 1]
    ax11 = axes[1, 1]
    ax01.plot(steps, kl_train_lst, label='train_kl')
    ax01.plot(steps, kl_test_lst, label='test_kl')
    ax11.plot(steps, sr_train_lst, label='train_sr')
    ax11.plot(steps, sr_test_lst, label='test_sr')

    ax02 = axes[0, 2]
    ax12 = axes[1, 2]
    ax02.plot(steps, train_acr_list, label='train_acr')
    ax02.plot(steps, test_acr_list, label='test_acr')
    ax12.plot(steps, train_mse_list, label='train_mse')
    ax12.plot(steps, test_mse_list, label='test_mse')

    [ax.legend() for ax in [ax00, ax10, ax01, ax11, ax02, ax12]]
    plt.show()

if __name__ == '__main__':
    kwargs = {
        "start": 0,
        "end": 100001,
        "delta": 5000
    }

    # draw(
    #     env=ConflictEnv(limit_path=limit_path, size=size, ratio=ratio),
    #     expert_set=OurSet(expert_path=expert_path)
    # )

    # _analysis(path=bc_actions_path, prefix='bc_actions', **kwargs)
    # _analysis(path=dqn_no_exp_path, prefix='dqn_no_exp', **kwargs)
    _analysis(path=gail_actions_path, prefix='dqn_actions', **kwargs)
    # _analysis(path=gail_tracks_path, prefix='dqn_tracks', **kwargs)


from django.shortcuts import render,redirect, get_object_or_404
from .models import Contato
from .forms import ContatoForm

def listar_contatos(request):
    busca = request.GET.get('pesquisa', None)

    if busca:
        contatos = Contato.objects.all()
        contatos = contatos.filter(nome__icontains=busca)

    else:
        contatos = Contato.objects.all()

    return render(request, 'lista.html',{'contatos': contatos})

def criar_contato(request):
    form = ContatoForm(request.POST or None, request.FILES or None)

    if form.is_valid():
        form.save()
        return redirect('listar_contatos')

    else:
        return render(request, "novo_contato.html", {'form': form})

def alterar_contato(request, id):
    contato = get_object_or_404(Contato, pk=id)
    form = ContatoForm(request.POST or None, request.FILES or None, instance=contato)

    if form.is_valid():
        form.save()
        return redirect('listar_contatos')

    return render(request, 'novo_contato.html', {'form': form})

def deletar_contato(request, id):
    contato = get_object_or_404(Contato, pk=id)

    if request.method == 'POST':
        contato.delete()
        return redirect('listar_contatos')

    return render(request, 'deletar_contato.html', {'contato': contato})


import re
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox

from .Action import Action

class TextTriggerAction(Action):
	def __init__(self, root):
		Action.__init__(self, root)

		self.listbox = None
		self.list_var = tk.StringVar()
		self.list_items = None
		self.text_area = None
		self.triggers = []
		self.edit_index = -1
		self.current_trigger = None

		self.font_frame = None
		self.font_box = None
		self.font_size_box = None
		self.font_var = tk.StringVar()
		self.font_size_var = tk.StringVar()

		self.import_separator = '\n-------------------------------------------------------- !! DO NOT EDIT THIS LINE !!\n'

		self.default_text = 'Select an item to edit its contents.'

		self.preview_pattern = re.compile(r'[\s\n\r]+')

		self.fonts = {
			'envy_bold': [20],
			'sans_bold': [20, 26, 36],
			'Caracteres': [26, 36, 40, 52, 64, 72, 92, 140],
			'ProximaNovaReg': [20, 26, 36, 42, 58, 72, 100],
			'ProximaNovaThin': [20, 26, 36, 42]
		}
	# END __init__

	def init(self):
		Action.init(self)
	# END init

	def create_gui(self):
		PADDING = 4
		HPADDING = PADDING / 2

		dlg = self.create_modal_window('Text Triggers')

		self.edit_index = -1
		list_items = self.list_items = []
		self.triggers = []
		for (id, (x, y, entity)) in list(self.map.entities.items()):
			if entity.type == 'text_trigger' or entity.type == 'z_text_prop_trigger':
				text = self.text(entity)
				list_items.append(self.text_preview(text))
				self.triggers.append(entity)

		top_frame = ttk.Frame(dlg, padding=PADDING)
		top_frame.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.W, tk.E), padx=0, pady=0)

		self.list_var.set(list_items)
		lbox = self.listbox =tk.Listbox(top_frame, listvariable=self.list_var, width=30, height=25, exportselection=False)
		lbox.grid(column=0, row=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(PADDING, 0), pady=PADDING)
		lbox.config(font='Helvetica 11')
		lbox.bind('<<ListboxSelect>>', self.on_select)

		lbox_scrollbar = ttk.Scrollbar(top_frame, orient=tk.VERTICAL, command=lbox.yview)
		lbox_scrollbar.grid(column=1, row=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, PADDING), pady=PADDING)
		lbox.configure(yscrollcommand=lbox_scrollbar.set)

		text_frame = ttk.Frame(top_frame, padding=PADDING)
		text_frame.grid(column=2, row=0, sticky=(tk.N, tk.S, tk.W, tk.E), padx=0, pady=0)

		text_area = self.text_area = tk.Text(text_frame, width=60, height=25, wrap='none')
		text_area.grid(column=0, row=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, PADDING), pady=PADDING)
		text_area.insert('1.0', self.default_text)

		text_area_vscrollbar = ttk.Scrollbar(text_frame, orient=tk.VERTICAL, command=text_area.yview)
		text_area_vscrollbar.grid(column=1, row=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, PADDING), pady=PADDING)
		text_area.configure(yscrollcommand=text_area_vscrollbar.set)

		text_area_hscrollbar = ttk.Scrollbar(text_frame, orient=tk.HORIZONTAL, command=text_area.xview)
		text_area_hscrollbar.grid(column=0, row=1, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, PADDING), pady=PADDING)
		text_area.configure(xscrollcommand=text_area_hscrollbar.set)
		text_area.bind('<KeyRelease>', self.on_text_changed)

		font_frame = self.font_frame = ttk.Frame(text_frame, padding=PADDING)
		font_frame.grid(column=0, row=2, columnspan=2, sticky=(tk.N, tk.S, tk.W, tk.E), padx=0, pady=0)

		font_box = self.font_box = ttk.Combobox(font_frame, textvariable=self.font_var, state='readonly')
		font_box['values'] = ['envy_bold', 'sans_bold', 'Caracteres', 'ProximaNovaReg', 'ProximaNovaThin']
		font_box.grid(column=0, row=0,  sticky=tk.W)
		font_box.bind('<<ComboboxSelected>>', self.on_font_select)

		font_size_box = self.font_size_box = ttk.Combobox(font_frame, textvariable=self.font_size_var, state='readonly')
		font_size_box['values'] = []
		font_size_box.grid(column=1, row=0, sticky=tk.W, padx=(PADDING, 0))
		font_size_box.bind('<<ComboboxSelected>>', self.on_font_size_select)

		buttons_frame = ttk.Frame(top_frame, padding=PADDING)
		buttons_frame.grid(column=0, row=2, columnspan=3, sticky=(tk.N, tk.S, tk.W, tk.E), padx=0, pady=0)

		ttk.Button(buttons_frame, text='Import', command=self.import_text).grid(column=0, row=0, sticky=(tk.N), padx=(0, PADDING))
		ttk.Button(buttons_frame, text='Export', command=self.export_text).grid(column=1, row=0, sticky=(tk.N), padx=(0, PADDING))

		Action.enable_frame(self.font_frame, False)

		self.centre_window(dlg)
	# END createGui

	def run(self, map):
		Action.run(self, map)

		self.create_gui()
	# END run

	def import_text(self):
		text = self.app.root.clipboard_get().split(self.import_separator)

		if len(text) != len(self.triggers):
			messagebox.showinfo(message='Number of items in clipboard do not match number of text triggers', icon='warning')
			return

		index = 0
		for trigger in self.triggers:
			new_text = text[index]
			self.text(trigger, new_text)
			self.list_items[index] = self.text_preview(new_text)
			index += 1

		self.list_var.set(self.list_items)

		messagebox.showinfo(message='Text successfully imported', icon='info')

	def export_text(self):
		text = ''
		index = 0
		for trigger in self.triggers:
			if index > 0:
				text += self.import_separator
			text += self.text(trigger)
			index += 1

		self.app.root.clipboard_clear()
		self.app.root.clipboard_append(text)

		messagebox.showinfo(message='All text copied to clipboard', icon='info')

	def set_text(self, value):
		self.text_area.delete(1.0, 'end')
		self.text_area.insert('end', value)

	def get_text(self):
		return self.text_area.get(1.0, 'end-1c')

	def text_preview(self, text, preview_length=30):
		text = re.sub(self.preview_pattern, ' ', text).strip()
		return (text[:preview_length] + '..') if len(text) > preview_length else text

	def trigger_text(self, index, value=None):
		return self.text(self.triggers[index], value)

	@staticmethod
	def text(trigger, value=None):
		var_name = 'text' if trigger.type == 'z_text_prop_trigger' else 'text_string'
		# print(trigger.vars)

		if value is None:
			return trigger.vars[var_name].value
		else:
			trigger.vars[var_name].value = value
			return value

	def on_text_changed(self, event=None):
		if self.current_trigger is not None:
			new_text = self.get_text()
			self.text(self.current_trigger, new_text)

	def on_select(self, event = None):
		previous_trigger = self.current_trigger
		previous_index = self.edit_index

		selection = self.listbox.curselection()
		if len(selection) == 1:
			selection_index = self.edit_index = int(selection[0])
			self.listbox.see(selection_index)
			self.current_trigger = self.triggers[self.edit_index]
		else:
			selection_index = self.edit_index = -1
			self.current_trigger = None
			return

		if previous_trigger is not None and previous_trigger != self.current_trigger:
			self.list_items[previous_index] = self.text_preview(self.text(previous_trigger))
			self.list_var.set(self.list_items)

		self.set_text(self.default_text if selection_index == -1 else self.trigger_text(selection_index))

		trigger = self.current_trigger
		z_text = trigger.type == 'z_text_prop_trigger'
		Action.enable_frame(self.font_frame, z_text)

		if z_text:
			font_name = trigger.vars['font'].value
			self.font_box.set(font_name)
			self.font_size_box.set(trigger.vars['font_size'].value)
			self.font_size_box['values'] = self.fonts[font_name]
		else:
			self.font_box.set('')
			self.font_size_box.set('')

	def on_font_select(self, event=None):
		self.font_size_box['values'] = self.fonts[self.font_box.get()]

		if self.current_trigger is not None:
			self.current_trigger.vars['font'].value = self.font_box.get()

	def on_font_size_select(self, event=None):
		if self.current_trigger is not None:
			self.current_trigger.vars['font_size'].value = int(self.font_size_box.get())

# END Action


from django.test import TestCase
from .models import Locker
from django.core.exceptions import ValidationError

class school_tests(TestCase):
    def test_01_create_locker_wrong_combo(self):

        new_locker = Locker(locker_number=150, combination='213-435')
        try:
            new_locker.full_clean() # runs your validators
        except ValidationError as e:
            self.assertTrue("Invalid combination" in e.message_dict['combination'])


#https://leetcode.com/problems/odd-even-linked-list/
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def oddEvenList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """

        evenNodes = []
        oddNodes = []
        pointer = head
        i = 1
        while(pointer):
            if(i%2 == 0):
                evenNodes.append(pointer)
            else:
                oddNodes.append(pointer)
            i += 1
            pointer = pointer.next

        newList = ListNode()
        newPointer = newList
        for i in range(len(oddNodes)):
            newPointer.next = ListNode(oddNodes[i].val)
            newPointer = newPointer.next

        for i in range(len(evenNodes)):
            newPointer.next = ListNode(evenNodes[i].val)
            newPointer = newPointer.next

        return newList.next


# Writing to CSV files using DictWriter
# Creates a writer object for writing to CSV files using dictionaries
# fieldnames = kwarg for DictWriter specifying the header row
# writeheader = method to write a line of headers
# writerow = method to write a row based on a dictionary

from csv import DictWriter

with open("example.csv", "w") as data:
    headers = ["Character", "Finishing Move"]       # Setup row headers
    content = DictWriter(data, fieldnames=headers)
    content.writeheader()                           # Write row headers
    content.writerow({                              # Write content per row in dictionary form
        "Character": "Ryu",
        "Finishing Move": "Hadouken"
    })
    content.writerow({
        "Character": "Ken",
        "Finishing Move": "Shoryuken"
    })
    content.writerow({
        "Character": "Chun-Li",
        "Finishing Move": "Kaitenteki Kakukyakushu"
    })

with open("cats.csv", "w") as data:
    headers = ["Name", "Breed", "Age"]
    content = DictWriter(data, fieldnames=headers)
    content.writeheader()
    content.writerow({
        "Name": "Blue",
        "Breed": "Scottish Fold",
        "Age": 3
    })
    content.writerow({
        "Name": "Kitty",
        "Breed": "Russian Blue",
        "Age": 1
    })
    content.writerow({
        "Name": "Garfield",
        "Breed": "Orange Tabby",
        "Age": 10
    })


def powerset(k, arr, target):
    global n,cnt
    if sum(arr) == target:
        # au가 1인게 있으면 괜찮은거임
        for au in alreadyUsed:
            flag = False
            for x in range(n):
                if au[x] and not arr[x]:
                    flag = True
            if not flag:
                return
        if len(relation) == len({tuple(x[i] for i in range(len(arr)) if arr[i]) for x in relation}):
            alreadyUsed.append([i for i in arr])
            cnt += 1
        return
    if k == n:
        return
    arr[k] = 0
    powerset(k+1, arr, target)
    arr[k] = 1
    powerset(k+1, arr, target)

relation = [
    ["100","ryan","music","2"],
    ["200","apeach","math","2"],
    ["300","tube","computer","3"],
    ["400","con","computer","4"],
    ["500","muzi","music","3"],
    ["600","apeach","music","2"]
]

cnt = 0
n = len(relation[0])
alreadyUsed = []
for i in range(1, n+1):
    arr = [0]*n
    powerset(0, arr, i)
print(cnt)


import numpy as np
import scipy.cluster.vq as cluster
from operations import gen_blobs, measure_time

if __name__ == '__main__':
    t_time = measure_time()
    print("Type,Obs,Feats,Clusters,Time")
    for obs_power in range(4, 11):
        num_obs = 2**obs_power
        for feats_power in range(1, 11):
            for clust_power in range(1, obs_power):
                features = 2**feats_power
                k = 2**clust_power
                observations, labels = gen_blobs(num_obs, features, k)
                for _ in range(50):
                    try:
                        time = measure_time()
                        centroids, labels = cluster.kmeans2(observations, k)
                        time = measure_time() - time
                    except:
                        continue

                    print("scipy,%d,%d,%d,%.9f" %(num_obs, features, k, time))

    total_time = measure_time() - t_time
    print(total_time)


import os
import sys

from sqlalchemy import engine_from_config

from pyramid.paster import (
    get_appsettings,
    setup_logging,
    )

from pyramid.scripts.common import parse_vars
from itertools import takewhile

def usage(argv):
    cmd = os.path.basename(argv[0])
    print('usage: %s <config_uri> [var=value, [var2=value] django management commands\n'
          '(example: "%s development.ini check")' % (cmd, cmd))
    sys.exit(1)

def main(argv=sys.argv):
    if len(argv) < 2:
        usage(argv)

    config_uri = argv[1]
    setup_logging(config_uri)

    var_strings = list(takewhile(lambda x: '=' in x, argv[2:]))
    options = parse_vars(var_strings)
    settings = get_appsettings(config_uri, options=options)

    del argv[1:2 + len(var_strings)]

    os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings['django.settings'])
    sys.path.insert(0, settings['django.project'])
    sys.argv[0] = os.path.join(settings['django.project'], 'manage.py')

    from django.core.management import execute_from_command_line
    execute_from_command_line(sys.argv)


"""
Tests reading in the standard test files.
"""
import os.path
import unittest

import numpy as np

import kastore as kas

class StandardFilesMixin:
    """
    Read in the standard files.
    """

    @classmethod
    def setUpClass(cls):
        # Figure out where this is being run from and set the test data
        # path accordingly.
        cwd = os.getcwd()
        cls.test_data_path = "test-data"
        if cwd.endswith("python"):
            cls.test_data_path = "../test-data"

    def read_file(self, filename):
        full_path = os.path.join(self.test_data_path, filename)
        return kas.load(full_path, engine=self.engine, read_all=False)

    def test_empty_file(self):
        self.assertRaises(EOFError, self.read_file, "malformed/empty_file.kas")

    def test_bad_type(self):
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_type_11.kas"
        )
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_type_20.kas"
        )

    def test_bad_filesizes(self):
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_filesize_0_-1.kas"
        )
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_filesize_0_1.kas"
        )
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_filesize_0_1024.kas"
        )
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_filesize_10_-1.kas"
        )
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_filesize_10_1.kas"
        )
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_filesize_10_1024.kas"
        )

    def test_bad_magic_number(self):
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_magic_number.kas"
        )

    def test_version_0(self):
        self.assertRaises(
            kas.VersionTooOldError, self.read_file, "malformed/version_0.kas"
        )

    def test_version_100(self):
        self.assertRaises(
            kas.VersionTooNewError, self.read_file, "malformed/version_100.kas"
        )

    def test_truncated_file(self):
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/truncated_file.kas"
        )

    def test_key_offset_outside_file(self):
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/key_offset_outside_file.kas"
        )

    def test_array_offset_outside_file(self):
        self.assertRaises(
            kas.FileFormatError,
            self.read_file,
            "malformed/array_offset_outside_file.kas",
        )

    def test_key_len_outside_file(self):
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/key_len_outside_file.kas"
        )

    def test_array_len_outside_file(self):
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/array_len_outside_file.kas"
        )

    def test_bad_array_start(self):
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_array_start_-8.kas"
        )
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_array_start_-1.kas"
        )
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_array_start_1.kas"
        )
        self.assertRaises(
            kas.FileFormatError, self.read_file, "malformed/bad_array_start_8.kas"
        )

    def test_truncated_file_correct_size(self):
        self.assertRaises(
            kas.FileFormatError,
            self.read_file,
            "malformed/truncated_file_correct_size_100.kas",
        )
        self.assertRaises(
            kas.FileFormatError,
            self.read_file,
            "malformed/truncated_file_correct_size_128.kas",
        )
        self.assertRaises(
            kas.FileFormatError,
            self.read_file,
            "malformed/truncated_file_correct_size_129.kas",
        )
        self.assertRaises(
            kas.FileFormatError,
            self.read_file,
            "malformed/truncated_file_correct_size_200.kas",
        )

    def test_all_types(self):
        dtypes = [
            "int8",
            "uint8",
            "uint32",
            "int32",
            "uint64",
            "int64",
            "float32",
            "float64",
        ]
        for n in range(10):
            filename = f"v1/all_types_{n}_elements.kas"
            data = self.read_file(filename)
            for dtype in dtypes:
                self.assertTrue(np.array_equal(data[dtype], np.arange(n, dtype=dtype)))

class TestStandardFilesPyEngine(StandardFilesMixin, unittest.TestCase):
    engine = kas.PY_ENGINE
    read_all = False

class TestStandardFilesCEngine(StandardFilesMixin, unittest.TestCase):
    engine = kas.C_ENGINE
    read_all = False

class TestStandardFilesPyEngineReadAll(StandardFilesMixin, unittest.TestCase):
    engine = kas.PY_ENGINE
    read_all = True

class TestStandardFilesCEngineReadAll(StandardFilesMixin, unittest.TestCase):
    engine = kas.C_ENGINE
    read_all = True

class TestStandardFilesLoads(StandardFilesMixin, unittest.TestCase):
    def read_file(self, filename):
        full_path = os.path.join(self.test_data_path, filename)
        with open(full_path, "rb") as f:
            encoded = f.read()
        return kas.loads(encoded)


# -*- coding: utf-8 -*-
'''
The epoch
The epoch is the point where the time starts.
The point is taken as the 0.0 hours of January 1st
of the current year.
For Unix,the epoch is 0.0 hours of January 1st 1970
It is possible to measure the time in seconds since
the epoch using time() function of 'time' module
'''

'''
Program 1 : A python program to measure the time in
seconds since the epoch
'''
import time
epoch = time.time()
print(epoch)

'''
Program 2 : A python program to get date and time
from the epoch time

tm_year - 4 digit year like 2019
tm_mon - range [1,12]
tm_mday - range [1,31]
tm_hour - range [0,23]
tm_min - range [0,59]
tm_sec - range [0,61] including leap seconds
tm_wday - range [0,6] Monday is 0
tm_yday - range [1,366]
tm_isdst - [0,1 or -1] 0 - no DST,1 - DST is ineffect
-1= not known
tm_zone timezone name
'''
import time
epoch = time.time()
t = time.localtime(epoch)

#Retrieve the date from the structure t
d = t.tm_mday
m = t.tm_mon
y = t.tm_year
print('Current date is: %d - %d - %d' %(d,m,y))

#Retrive the time from the strurcture t
h = t.tm_hour
m = t.tm_min
s = t.tm_sec

print('Current time is: %d : %d : %d' %(h,m,s))

'''
Program 3 : A python program to convert epoch time
into corresponding date and time

The current date and time as shown in our computer
system can be known using the following
ctime() function of 'time' module
now() method of 'datetime' class of 'datetime' module
today() method of 'datetime' class of 'datetime' module
'''
import time
epoch = time.time()
t = time.ctime(epoch)
print('Current date and time ',t)

'''
Program 4 : A python program to know the current date
and time using ctime() function
'''

import time
t = time.ctime()
print('Current date and time is ',t)

'''
Program 5 : A python program to know the local date and time.

now () methods returns the object that contains date
and time information in any timezone.
By default the local time zone in india is IST
if the timezone is not passed
'''

from datetime import *
now = datetime.now()
print('current date time ' ,now)
print('Date now : {}/{}/{}'.format(now.day,now.month,now.year))
print('Time now : {}:{}:{}'.format(now.hour,now.minute,now.second))

'''
Program 6 : A python program to know today's date and time
'''

from datetime import *
# today() of timetime class gives date and time
tdm = datetime.today()
print("Today's date and time = ",tdm)

#today() of the date class gives the date only
td = date.today()
print("Today's date = ",td)


import pandas as pd
import torch
from typing import Tuple

RAW_DATA = "data/ES_continuous_adjusted_1min.txt"

def _load_data() -> pd.DataFrame:

    return pd.read_csv(
        RAW_DATA,
        engine="pyarrow",
        header=None,
        names=["time", "open", "high", "low", "close", "volume"]
    )

def get_univariate_dataset(column, limit=None) -> pd.Series:

    data = _load_data()

    data = data[column]

    if limit is not None:
        data = data[:limit]

    return data

def get_multivariate_dataset(columns, limit=None) -> pd.Series:

    data = _load_data()

    data = data[columns]

    if limit is not None:
        data = data[:limit]

    return data

def train_test_split(
        data, train_ratio=0.8,
        val_ratio=0.1
    ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:

    num_data = data.shape[0]

    train_start_index = 0
    train_end_index = int(train_ratio * num_data)

    val_start_index = int(train_ratio * num_data)
    val_end_index = int((train_ratio + val_ratio) * num_data)

    test_start_index = int((train_ratio + val_ratio) * num_data)

    print(
        f'Dataset shape: {data.shape}\n',
        f'Train:         {train_start_index}:{train_end_index}\n',
        f'Val:           {val_start_index}:{val_end_index}\n',
        f'Test:          {test_start_index}:{num_data}\n'
    )

    train_data = data[train_start_index:train_end_index]
    val_data = data[val_start_index:val_end_index]
    test_data = data[test_start_index:num_data]

    #return (
    #    torch.tensor(train_data.values, dtype=torch.float32),
    #    torch.tensor(val_data.values, dtype=torch.float32),
    #    torch.tensor(test_data.values, dtype=torch.float32)
    #)

    return (
        train_data,
        val_data,
        test_data
    )


import datetime as dt
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.email_operator import EmailOperator
from airflow.models.baseoperator import chain

with DAG('dummy_dag',
    description='An Airflow DAG running dbt and Great Expectations tasks',
    schedule_interval=None,
    start_date=dt.datetime(2022, 7, 21),
    catchup=False,
    render_template_as_native_obj=True
    ) as dag:

    send_email_1 = EmailOperator(
        task_id='send_email_1',
        to='user1@gmail.com',
        subject='Airflow Alert',
        html_content=f"""
Hi user1, \nData Validated and Transformed Successfully!
 """,
        dag=dag
        )

    send_email_2 = EmailOperator(
        task_id='send_email_2',
        to='user2@gmail.com',
        subject='Airflow Alert',
        html_content=f"""
Hi user2, \nData Validated and Transformed Successfully!
 """,
        dag=dag
        )

    send_email_3 = EmailOperator(
        task_id='send_email_3',
        to='user3@gmail.com',
        subject='Airflow Alert',
        html_content=f"""
Hi user3, \nData Validated and Transformed Successfully!
 """,
        dag=dag
        )

    begin = DummyOperator(task_id="begin")
    end = DummyOperator(task_id="end")

    chain(
        begin,
        send_email_1,
        send_email_2,
        send_email_3,
        end,
    )


# Crie um programa para contar as vogais ou consoantes de uma frase, caso não passe o segundo parâmetro contará automaticamente as vogais
def conta_letras(frase, contar="vogais"):
    # Variáveis para acumular
    vogais = 0
    consoantes = 0
    # Laço para as vogais
    if contar == 'vogais':
        for i in range(len(frase)):
            if frase[i] == 'a' or frase[i] == 'e' or frase[i] == 'i' or frase[i] == 'o' or frase[i] == 'u':
                vogais += 1
        return vogais
    # Laço para as consoantes
    else:
        for i in range(len(frase)):
            if frase[i] != 'a' and frase[i] != 'e' and frase[i] != 'i' and frase[i] != 'o' and frase[i] != 'u' and frase[i] != ' ':
                consoantes += 1
        return consoantes


dados = {}
pessoas = []
mulheres = []
pessoaIdade = []
contP = mediaI = 0
while True:
    nome = str(input('Nome: ')).strip().title()
    sexo = str(input('Sexo: [M/F] ')).strip().upper()[0]
    while sexo not in 'MF':
        sexo = str(input('Sexo: [M/F] ')).strip().upper()[0]
    idade = int(input('Idade: '))
    contP += 1
    dados['nome'] = nome
    dados['sexo'] = sexo
    dados['idade'] = idade
    pessoas.append(dados.copy())
    if sexo in 'F':
        mulheres.append(dados.copy())
    dados.clear()
    continuar = ' '
    while continuar not in 'SN':
        continuar = str(input('Continuar? [S/N]')).strip().upper()[0]
    if continuar in 'N':
        break
for i, p in enumerate(pessoas):
    mediaI += p['idade']
mediaI /= contP
for p in pessoas:
    if p['idade'] > mediaI:
        pessoaIdade.append(p.copy())
print('-=' * 30)
print(f' - O grupo tem {contP} pessoas.')
print(f' - A média de idade é de {mediaI:.2f}')
print(' - A mulheres Cadastradas foram: ', end='')
for mu in range(0, len(mulheres)):
    print(f'{mulheres[mu]["nome"]} ', end='')
print()
print('Lista das pessoas que estão acima da média:')
print()
for pI in pessoaIdade:
    print(f'nome = {pI["nome"]}; sexo = {pI["sexo"]}; idade = {pI["idade"]}')
print('<<< Encerrando >>')


import sys
input = lambda: sys.stdin.readline().rstrip()
sys.setrecursionlimit(10**4)

def resolve():
    m = int(input())
    n = int(input())
    c = [list(map(int, input().split())) for _ in range(n)]

    ans = [0]
    dir = ((0, 1), (1, 0), (0, -1), (-1, 0))

    def dfs(now, step, visited):
        is_end = True
        for dy, dx in dir:
            next = (now[0]+dy, now[1]+dx)
            if 0<=next[0]<n and 0<=next[1]<m and c[next[0]][next[1]]==1 and not next in visited:
                is_end = False
                dfs(next, step+1, visited|{now})
        if is_end:
            ans[0] = max(step, ans[0])

    for i in range(n):
        for j in range(m):
            if c[i][j]==1:
                dfs((i, j), 1, set())

    print(ans[0])

if __name__ == '__main__':
    resolve()


import usb  # This is pyusb

class uDMX():
    SingleChannelModeFlag = 1
    MultiChannelModeFlag = 2

    def __init__(self):
        self.vid = 0x16c0
        self.pid = 0x05dc
        self.dev = None
        self.channel_mode = "single"  # single = 1 or multi = 2

        self.dev = usb.core.find(idVendor=self.vid, idProduct=self.pid)
        if self.dev is None:
            raise ResourceWarning("uDMX device was not found")

        self.bmRequestType = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_RECIPIENT_DEVICE | usb.util.CTRL_OUT

    def setDMX(self, channel, value):
        channel = channel - 1
        if type(value) is int:
            n = self.dev.ctrl_transfer(self.bmRequestType, self.SingleChannelModeFlag, wValue=value, wIndex=channel,
                                       data_or_wLength=1)
        elif type(value) is list:
            channel_values = bytearray(value)
            n = self.dev.ctrl_transfer(self.bmRequestType, self.MultiChannelModeFlag, wValue=len(channel_values), wIndex=channel, data_or_wLength=channel_values)
        else:
            raise ValueError("The value can be an integer or a list.")


import argparse
import sys

import matplotlib.pyplot as plt
import numpy as np
import gurobipy as gb

sys.path.append("../..")
from utils.auxiliary_energy import *
from utils.evolution import out_of_sample_test

parser = argparse.ArgumentParser()
# name of example
parser.add_argument('--name', help='example name', type=str, default='Energy')
# number of qubits
parser.add_argument('--n', help='number of qubits', type=int, default=2)
# number of edges for generating regular graph
parser.add_argument('--num_edges', help='number of edges for generating regular graph', type=int,
                    default=1)
# if generate the graph randomly
parser.add_argument('--rgraph', help='if generate the graph randomly', type=int, default=0)
# number of instances
parser.add_argument('--g_seed', help='graph seed', type=int, default=0)
# seed for uncertainties
parser.add_argument('--r_seed', help='seed for uncertainties', type=int, default=0)
# number of scenarios
parser.add_argument('--num_scenario', help='number of scenarios', type=int, default=100)
# evolution time
parser.add_argument('--evo_time', help='evolution time', type=float, default=2)
# time steps
parser.add_argument('--n_ts', help='time steps', type=int, default=40)
# initial control file
parser.add_argument('--control', help='file name of control', type=str, default=None)
# threshold of CVaR
parser.add_argument('--cvar', help='threshold of CVaR', type=float, default=0.01)
parser.add_argument('--bound', help='bound of uniform sample', type=float, default=0.3)

args = parser.parse_args()

y0 = uniform(args.n)

if args.rgraph == 0:
    Jij, edges = generate_Jij_MC(args.n, args.num_edges, 100)

    C = get_ham(args.n, True, Jij)
    B = get_ham(args.n, False, Jij)

    args.seed = 0

if args.rgraph == 1:
    Jij = generate_Jij(args.n, args.g_seed)
    C = get_ham(args.n, True, Jij)
    B = get_ham(args.n, False, Jij)

if args.num_scenario == 1:
    c_uncertainty = np.zeros((2, 1))
else:
    np.random.seed(args.r_seed)
    c_uncertainty = np.random.uniform(low=-args.bound, high=args.bound, size=(2, args.num_scenario))
prob = np.ones(args.num_scenario) * 1 / args.num_scenario

if not os.path.exists("../../output/OutSampleTest/"):
    os.makedirs("../../output/OutSampleTest/")

output_num = "../../output/OutSampleTest/" + args.control.split('/')[-1].split('.csv')[0] + "_out_test" + \
             "cvar{}_scenario{}_group{}_bound{}".format(args.cvar, args.num_scenario, args.r_seed, args.bound) + ".log"

f = open(output_num, "w+")
control = np.loadtxt(args.control, delimiter=',')
obj = out_of_sample_test(args.num_scenario, c_uncertainty, np.zeros((2 ** args.n, 2 ** args.n), dtype=complex),
                         [B, C], args.n_ts, args.evo_time, control, y0[0:2 ** args.n], None, 'energy')
print("********* Results *****************", file=f)
m = gb.Model()
zeta_var = m.addVar(lb=-np.infty)
cos = m.addVars(args.num_scenario, lb=0)
m.addConstrs(cos[l] >= obj[l] - zeta_var for l in range(args.num_scenario))
m.setObjective(zeta_var + 1 / args.cvar * gb.quicksum(prob[l] * cos[l] for l in range(args.num_scenario)))
m.optimize()
print("Final original objective value", file=f)
for l in range(args.num_scenario):
    print(obj[l], file=f)

print("********* Summary *****************", file=f)
print("zeta", zeta_var.x, file=f)
print("objective value", m.objval, file=f)
print("Final maximum energy {}".format(-min(abs(obj))), file=f)
print("Final average original objective value {}".format(sum(obj) / len(obj)), file=f)
print("Final original objective value exceeding current objective value {}".format(obj[obj > m.objval]), file=f)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2018/7/8 上午10:33
# @Author  : 杨寿国
# @mail    : 891584158@qq.com
# @File    : data_helper.py
# @intro: 读取各个优化级别的二进制文件，并且自动附加标签，从O0 - Os 依次对应 0~5
import os
import numpy as np
import re

class DataHelper(object):
    def __init__(self, class_num=4):
        self.rowbyte = 4
        self._class_num = class_num

        pass

    def get_all_data(self, directory='./dataset/ARM'):

        all_result = []
        label = 0

        print('loading data {} from {} : label {}'.format("O0", directory, label))
        all_result += self.get_certain_compile_level_with_label(os.path.join(directory, 'O0'), label=label)
        label+=1

        print('loading data {} from {} : label {}'.format("O1", directory, label))
        all_result += self.get_certain_compile_level_with_label(os.path.join(directory, 'O1'), label=label)
        label += 1
        print('loading data {} from {} : label {}'.format("O2", directory, label))
        all_result += self.get_certain_compile_level_with_label(os.path.join(directory, 'O2'), label=label)
        if self._class_num ==5 :
            label+=1

        print('loading data {} from {} : label {}'.format("O3", directory, label))
        all_result += self.get_certain_compile_level_with_label(os.path.join(directory, 'O3'), label=label)
        label+=1
        print('loading data {} from {} : label {}'.format("Os", directory, label))

        all_result += self.get_certain_compile_level_with_label(os.path.join(directory, 'Os'), label=label)

        return np.array(all_result)

    def get_certain_compile_level_with_label(self, directory, label):
        # directory: 某一优化级别的二进制文件所在目录
        # label:该类二进制文件对应标签

        result = []
        # 迭代访问目录下每个文件
        for parent, dirs, files in os.walk(directory):
            # result.append([self.read_binary_from_file(filez), label])
            for file in files:
                filedatas = self.read_binary_from_file(os.path.join(parent, file))
                for hexfiledata in filedatas:
                    if hexfiledata is not None:
                        result.append([hexfiledata, label])

        return result

    def load_data_and_labels(self, dir):
        data = self.get_all_data(dir)
        train_data = np.array(list(data[:, 0]), dtype=np.float32)
        print(data.shape)
        # 归一化
        # train_data = np.true_divide(train_data, 1)
        return train_data, data[:, 1]

    def read_binary_from_file(self, file_path, rowbyte=4, min_row=100, rows=1024):
        # file_path: 二进制文件的路径
        # rowbyte: 每一行的字节数
        # min_row : 最小字节行数 ( min_row * 4 )
        # rows : 从二进制文件中提取的字节行数 ( rows * 4 )
        # 返回一个矩阵 N*32矩阵 N = 4096/32 = 128

        allbytevalue = []

        #读取所有字节内容
        # 将所有字节内容分成多个 rows * rowbyte 的numpy数组并返回
        with open(file_path, 'rb') as f:
            allbytevalue = list(bytearray(f.read()))

        seg_length = rowbyte*rows
        segs = int(len(allbytevalue)/seg_length)

        byte_arrays = []
        for i in range(segs):
            byte_arrays.append(np.array(allbytevalue[i*seg_length:(i+1)*seg_length]).reshape(rows, rowbyte))

        byte_array = np.array(allbytevalue[segs*seg_length:])
        if byte_array.size < rowbyte * rows:
            byte_array = np.pad(byte_array, (0, rows * rowbyte - byte_array.size), 'constant')
        byte_arrays.append(byte_array.reshape(rows, rowbyte))
        return np.array(byte_arrays)

    def read_hex_from_file(self, file_path, rows=1024, min_len=100, fromMid=True):
        # file_path: 二进制文件的路径
        # rows : 最多读取文件的行数，即二进制文件的指令长度
        # min_len ： 文件包含的最少的指令长度，如果少于这个长度，丢弃该文件
        # fromMid : 从二进制文件的中间部分开始读，如果文件长度大于1024行

        data_4byte = []
        readed_lines = rows
        byte_len = 4  # 每一行4个字节
        with open(file_path, 'r') as f:
            lines = f.readlines()
            if len(lines) < min_len:
                return None

            if rows > len(lines):
                readed_lines = len(lines)

            for index in range(readed_lines):
                hexdata = lines[index].strip()

                if len(hexdata) == 0:
                    continue

                split_data = re.findall(r'.{2}', hexdata)

                split_integer = []
                for byte_hex in split_data:
                    split_integer.append(int('0x' + byte_hex, base=16))

                if len(split_integer) < byte_len:
                    n_split_integer = np.zeros(byte_len)
                    n_split_integer[0:len(split_integer)] = split_integer
                    split_integer = n_split_integer.tolist()

                data_4byte.append(split_integer)

            if rows > len(data_4byte):
                fill_data = np.zeros((rows, byte_len))
                fill_data[0:len(data_4byte)] = data_4byte
                return fill_data

        return np.array(data_4byte).reshape((-1, byte_len))

    def batch_iter(self, data, batch_size, num_epochs, shuffle=True):
        """
        Generates a batch iterator for a dataset.
        """
        data = np.array(data)
        data_size = len(data)
        num_batches_per_epoch = int((len(data) - 1) / batch_size) + 1
        for epoch in range(num_epochs):
            # Shuffle the data at each epoch
            if shuffle:
                shuffle_indices = np.random.permutation(np.arange(data_size))
                shuffled_data = data[shuffle_indices]
            else:
                shuffled_data = data
            for batch_num in range(num_batches_per_epoch):
                start_index = batch_num * batch_size
                end_index = min((batch_num + 1) * batch_size, data_size)
                yield shuffled_data[start_index:end_index]

def test():
    dh = DataHelper(5)
    data = dh.load_data_and_labels('../dataset_singlefunc/')

    print({0:[1,2,3]})

if __name__ == '__main__':
    test()


import os

import nltk
from nltk.tokenize import word_tokenize

class FileReader:
    def __init__(self, file_name):
        self.file_name = file_name
        file = None
        self.file_lines = []
        self.file_content = ''
        self.line_count = None
        self.word_count = None
        try:
            file = open(file_name, 'r', encoding='utf8')
            self.file_lines = file.readlines()
            self.file_content = ''.join(self.file_lines)
            self.line_count = len(self.file_lines)
            self.word_count = len(
                word_tokenize(self.file_content, language='russian')
            )
        except FileNotFoundError:
            print('ERROR: file does not exist')
        file.close()

    def read(self):
        return self.file_contentЫ

    def write_line(self, content):
        try:
            file = open(self.file_name)
            file.write(content)
        except FileNotFoundError:
            print('ERROR: file does not exist')

    def count_lines(self):
        return [self.line_count, self.word_count]

    def __add__(self, other):
        new_name = self.file_name[:-4] + '_add_' + other.file_name[:-4] + '.txt'
        new_content = self.file_lines + other.file_lines

        try:
            new_file = open(new_name, 'w', encoding='utf8')
            new_file.writelines(new_content)
            new_file.close()
        except FileExistsError:
            print('ERROR: file already exist')

        new_file_reader = FileReader(new_name)
        return new_file_reader

    def __str__(self):
        return os.getcwd() + self.file_name


import itertools
from collections import Counter

from core.common.SemanticSimilarityAlgorithm import SemanticSimilarityAlgorithm

import numpy as np

class SifCosineSimilarity(SemanticSimilarityAlgorithm):

    def get_label(self):
        return "Smooth Inverse Frequency + Cosine Distance"

    def __init__(self, embedding, stemmer):
        super().__init__()
        self.a = 0.001
        self.embedding = embedding
        self.stemmer = stemmer

    def _absolute_score(self, sentence_1, sentence_2):
        splitted_1 = self.stemmer.stem_sentence(sentence_1)
        splitted_2 = self.stemmer.stem_sentence(sentence_2)
        vecs = self._sif_feature_vectors(splitted_1, splitted_2, self.embedding)
        A = vecs[0]
        B = vecs[1]
        return A @ B / (np.linalg.norm(A) * np.linalg.norm(B))

    def _normalize(self, absolute):
        return absolute * 50 + 50

    # Based on
    # medium.com/@Intellica.AI/comparison-of-different-word-embeddings-on-text-similarity-a-use-case-in-nlp-e83e08469c1c
    def _sif_feature_vectors(self, splitted_1, splitted_2, embedding, a=0.001):
        s_1 = [token for token in splitted_1 if token in embedding.model.wv.vocab]
        s_2 = [token for token in splitted_2 if token in embedding.model.wv.vocab]
        word_counts = self._map_word_frequency((s_1 + s_2))
        sentence_set = []
        for sentence in [s_1, s_2]:
            vs = np.zeros(embedding.model_shape)
            sentence_length = len(sentence)
            for word in sentence:
                a_value = a / (a + word_counts[word])  # smooth inverse frequency, SIF
                vs = np.add(vs, np.multiply(a_value, embedding.model.wv[word]))  # vs += sif * word_vector
            vs = np.divide(vs, sentence_length)  # weighted average
            sentence_set.append(vs)
        return sentence_set

    def _map_word_frequency(self, document):
        return Counter(itertools.chain(*document))


cycle = 0
X = 1
takes = {"addx": 2, "noop": 1}
interesting = [20, 60, 100, 140, 180, 220]
signalStrength = 0
for instruction in [x.split() for x in open("E:/AdventOfCode/_Input/2022/2022-10.txt", "r").readlines()]:
    for _ in range(takes[instruction[0]]):
        cycle += 1
        if cycle in interesting: signalStrength += cycle * X
    if len(instruction) == 2: X += int(instruction[1])
if cycle in interesting: signalStrength += cycle * X
print(signalStrength)


#!/usr/bin/python3

import copy
import time
from abc import ABC, abstractmethod
from array import array
from typing import Tuple, List, Optional, Type

# An OptionSet is an int that has 9 bits set either to:
#  - 1 to mark a digit already used
#  - 0 to mark a digit available
class OptionSet:

    @staticmethod
    def iter_digits(bitset: int):
        b = ~bitset & 0b111111111  # For easier algorithm, flip the bits
        for d in range(1, 10):
            if b & (1 << (d - 1)):
                yield d

Coords = Tuple[int, int]

class UnresolvedCell:

    def __init__(self, idx: int, possible_digits: int):
        self.idx = idx
        self.possible_digits = possible_digits

# The sudoku class maintains several states to solve the sudoku without exploratory work
# Every time a value is inserted, the constraint is propagated to a cells one the same line, row and block
# When a cell has a single possibility, it's id is put on a list that can be used for further solving
#
# For the purpose of the algorithm, the state can be mutated. However, when exploring branches of solutions
# one is supposed to deepcopy the sudoku instead of remembering and resetting the values mutated during the exploration
class Sudoku:

    def __init__(self, is_copy=False):
        if not is_copy:
            self.grid = array('i', [0] * 81)
            self.options = array('i', [0] * 81)
            self.options_count = array('i', [9] * 81)
            self.one_option_list = []

    def copy(self):
        new = Sudoku(is_copy=True)
        new.grid = copy.deepcopy(self.grid)
        new.options = copy.deepcopy(self.options)
        new.options_count = copy.deepcopy(self.options_count)
        new.one_option_list = []

        return new

    def update_value(self, idx: int, digit: int):
        assert digit != 0
        self.grid[idx] = digit
        self.options[idx] = 0
        self.options_count[idx] = 0
        self.propagate_constraints(idx, digit)

    def propagate_constraints(self, idx: int, digit: int):
        self.propagate_line_constraints(idx, digit)
        self.propagate_row_constraints(idx, digit)
        self.propagate_block_constraints(idx, digit)

    def propagate_line_constraints(self, idx: int, digit: int):
        line_start_idx = int(idx / 9) * 9
        for idx in range(line_start_idx, line_start_idx + 9):
            self.remove_option(idx, digit)

    def propagate_row_constraints(self, idx: int, digit: int):
        row_start_idx = idx % 9
        for idx in range(row_start_idx, 81, 9):
            self.remove_option(idx, digit)

    def propagate_block_constraints(self, idx: int, digit: int):
        left_corner_idx = int(idx / 27) * 27 + int((idx % 9) / 3) * 3
        for block_line_idx in range(3):
            left_idx = left_corner_idx + (block_line_idx * 9)
            for i in range(left_idx, left_idx + 3):
                self.remove_option(i, digit)

    # Remove an option at a given cell. Check if we reach an abnormal situation.
    # If a given cell has a single possibility, keep track of it
    def remove_option(self, idx: int, digit: int):
        current_count = self.options_count[idx]
        if current_count > 0:  # do not touch already solved cells
            old_options = self.options[idx]
            new_options = old_options | (1 << (digit - 1))
            if old_options != new_options:  # Check that removing a possibility actually changed current options
                new_count = current_count - 1
                if new_count == 0:
                    raise RuntimeError('Impossible sudoku')
                if new_count == 1:
                    self.one_option_list.append(idx)  # Store this idx for further processing
                # Remember the new values
                self.options[idx] = new_options
                self.options_count[idx] = new_count

    # Find the cell that has the least possibilities for exploratory work
    def get_least_options_unresolved_cell(self) -> Optional[UnresolvedCell]:
        min_idx = -1
        min_count = 9
        for i in range(81):
            options = self.options[i]
            if options > 0:
                count = self.options_count[i]
                if count < min_count:
                    min_idx = i
                    min_count = count

        if min_idx == -1:
            return None
        else:
            return UnresolvedCell(min_idx, self.options[min_idx])

    def get_grid_idx(self, coords: Coords):
        return coords[0] * 9 + coords[1]

    def get_digit(self, coords: Coords):
        return self.grid[self.get_grid_idx(coords)]

    # Load a Sudoku from a List[List[Int]]
    def load(self, lines):
        assert len(lines) == 9
        for i in range(9):
            line = lines[i]
            assert len(line) == 9
            for j in range(9):
                digit = line[j]
                if digit != 0:
                    self.update_value(self.get_grid_idx((i, j)), digit)

    # Useful to print out a sudoku in terminal
    def __str__(self):
        s = ""
        for i in range(3):
            for j in range(3):
                for k in range(3):
                    for l in range(3):
                        s += str(self.grid[self.get_grid_idx((i * 3 + j, k * 3 + l))])
                        s += " "
                    s += " "
                s += "\n"
            s += "\n"

        return s

class Solver:
    # A special value used to initiate the solution exploration
    EXPLORATION_BOOTSTRAP = None

    class ExplorationTraversal(ABC):

        def __init__(self):
            self.exploration_tuples = [Solver.EXPLORATION_BOOTSTRAP]

        def has_more(self) -> bool:
            return len(self.exploration_tuples) > 0

        def add(self, exploration_tuple: Tuple[int, int, Sudoku]):
            self.exploration_tuples.append(exploration_tuple)

        @abstractmethod
        def next(self) -> Tuple[int, int, Sudoku]:
            pass

    # Depth-First-Search traversal kind
    class DFS(ExplorationTraversal):
        def next(self) -> Tuple[int, int, Sudoku]:
            return self.exploration_tuples.pop()

    # Breadth-First-Search traversal kind
    class BFS(ExplorationTraversal):
        def next(self) -> Tuple[int, int, Sudoku]:
            return self.exploration_tuples.pop(0)

    # Resolves cells that can be resolved by pure constraint
    # returns the unresolved cell with the least number of possible options
    # None if the sudoku is solved
    #
    # Raises if the sudoku cannot be solved
    #
    # Warning: the sudoku is mutated by this method
    @staticmethod
    def resolve_constrained_cells(sudoku: Sudoku) -> Optional[UnresolvedCell]:

        while len(sudoku.one_option_list) > 0:
            single_option_idx = sudoku.one_option_list.pop()
            sudoku.update_value(single_option_idx, next(OptionSet.iter_digits(sudoku.options[single_option_idx])))

        return sudoku.get_least_options_unresolved_cell()

    # Solves a sudoku, possibly through exploration
    #
    # Returns the sudoku solution, or None if the sudoku has no solution
    #
    # Note: the provided sudoku is mutated but the resulting mutation is not necessarily the solution
    @staticmethod
    def solve(sudoku: Sudoku, traversal_kind: Type[ExplorationTraversal] = DFS) -> Optional[Sudoku]:
        # We push Tuple[idx, digit_to_test, Sudoku] to the exploration_traversal
        # Keeping a deep copy of the sudoku is important since resolve_constrained_cells
        # mutates its state. It would be a lot harder to keep track of all values discovered through constraints
        # and reset all of them

        # Init the exploration
        exploration_traversal = traversal_kind()

        while exploration_traversal.has_more():
            exploration_tuple = exploration_traversal.next()
            if exploration_tuple != Solver.EXPLORATION_BOOTSTRAP:
                idx, digit, sudoku = exploration_tuple
                sudoku.update_value(idx, digit)

            try:
                least_options_remaining_cell = Solver.resolve_constrained_cells(sudoku)
            except RuntimeError:
                # Such sudoku has no solution, explore other branches
                continue
            if least_options_remaining_cell is None:
                # This sudoku is solved, return it
                return sudoku
            else:
                # Otherwise, we need to continue exploration
                for digit_to_test in OptionSet.iter_digits(least_options_remaining_cell.possible_digits):
                    exploration_traversal.add((least_options_remaining_cell.idx, digit_to_test, sudoku.copy()))

        # We are out of the loop, we explored everything and could not solve
        return None

def verify_solution_matches_problem(problem: List[List[int]], solution: Sudoku):
    for i in range(9):
        for j in range(9):
            problem_digit = problem[i][j]
            solution_digit = solution.get_digit((i, j))
            if problem_digit != 0 and solution_digit != problem_digit:
                raise RuntimeError(
                    f"The solution does not match the problem at cell {(i, j)}. "
                    f"Expected {problem_digit}, got {solution_digit}"
                )

def verify_sudoku_correctness(solution: Sudoku):
    import itertools
    lines = {}
    rows = {}
    blocks = {}
    for i in range(9):
        for j in range(9):
            digit = solution.get_digit((i, j))
            lines.setdefault(i, []).append(digit)
            rows.setdefault(j, []).append(digit)
            blocks.setdefault(int(i / 3) * 3 + int(j / 3), []).append(digit)
    for digit_list in itertools.chain(lines.values(), rows.values(), blocks.values()):
        if len(digit_list) != len(set(digit_list)):
            raise RuntimeError("The solution is invalid")

def run_and_verify_with_traversal(problem, traversal_kind):
    # start_time = time.time()
    sudoku = Sudoku()
    sudoku.load(problem)
    solver = Solver()
    solved_sudoku = solver.solve(sudoku, traversal_kind=traversal_kind)

    # print(solved_sudoku)
    verify_solution_matches_problem(problem, solved_sudoku)
    verify_sudoku_correctness(solved_sudoku)
    # print()
    # end_time = time.time()
    # duration = end_time - start_time
    # print(f"Tests duration using {traversal_kind}: {duration} seconds")
    # print()
    return solved_sudoku

def run_and_verify(problem):
    return run_and_verify_with_traversal(problem, Solver.DFS)
    # run_and_verify_with_traversal(problem, Solver.BFS)

if __name__ == '__main__':
    # print("Problem easy")
    # run_and_verify([
    #     [9, 4, 1, 0, 3, 0, 7, 0, 0],
    #     [0, 0, 5, 0, 0, 8, 6, 0, 0],
    #     [7, 0, 0, 2, 0, 0, 4, 3, 5],
    #     [0, 1, 0, 0, 5, 0, 0, 4, 3],
    #     [2, 9, 0, 1, 0, 0, 0, 0, 0],
    #     [8, 5, 0, 7, 4, 0, 9, 0, 0],
    #     [1, 3, 8, 9, 0, 6, 0, 0, 0],
    #     [0, 0, 0, 0, 1, 0, 0, 8, 2],
    #     [5, 0, 2, 0, 8, 0, 0, 0, 6],
    # ])
    # print("Problem medium")
    # run_and_verify([
    #     [0, 5, 3, 0, 0, 0, 0, 0, 0],
    #     [0, 0, 0, 0, 0, 0, 0, 6, 9],
    #     [0, 0, 0, 7, 2, 0, 0, 0, 0],
    #     [0, 0, 0, 0, 0, 0, 0, 9, 8],
    #     [4, 0, 0, 6, 0, 0, 0, 0, 7],
    #     [5, 0, 0, 4, 3, 0, 0, 0, 0],
    #     [0, 0, 2, 5, 0, 6, 0, 0, 0],
    #     [0, 0, 0, 0, 0, 8, 1, 0, 0],
    #     [0, 8, 9, 0, 0, 7, 0, 0, 4]
    # ])
    # print("Problem hard")
    # run_and_verify([
    #     [0, 8, 0, 0, 0, 4, 0, 5, 0],
    #     [0, 6, 0, 2, 0, 0, 0, 0, 0],
    #     [5, 0, 2, 0, 7, 0, 1, 0, 0],
    #     [0, 0, 6, 0, 0, 0, 0, 0, 0],
    #     [2, 0, 1, 9, 0, 0, 0, 4, 0],
    #     [0, 0, 0, 0, 8, 0, 0, 0, 9],
    #     [0, 0, 0, 0, 0, 3, 7, 0, 0],
    #     [4, 0, 9, 8, 0, 0, 0, 1, 0],
    #     [0, 5, 0, 0, 0, 0, 0, 0, 0]
    # ])
    # print("Problem")
    # run_and_verify([
    #     [0, 0, 4, 0, 8, 0, 0, 0, 6],
    #     [0, 0, 0, 0, 0, 0, 0, 0, 2],
    #     [0, 2, 6, 0, 0, 0, 0, 1, 0],
    #     [0, 0, 0, 6, 4, 2, 0, 0, 0],
    #     [0, 0, 0, 8, 0, 0, 1, 0, 3],
    #     [0, 0, 0, 1, 0, 0, 5, 0, 0],
    #     [0, 1, 0, 0, 7, 0, 0, 0, 0],
    #     [8, 0, 0, 0, 0, 4, 0, 0, 0],
    #     [3, 0, 0, 0, 0, 0, 9, 7, 0]
    # ])
    print("Problem")
    run_and_verify([
        [0, 0, 0, 0, 0, 0, 2, 0, 0],
        [0, 0, 6, 0, 0, 3, 0, 0, 0],
        [3, 0, 0, 0, 1, 0, 9, 4, 0],
        [0, 0, 7, 9, 0, 0, 4, 8, 0],
        [0, 0, 0, 0, 8, 0, 0, 0, 6],
        [4, 0, 0, 0, 0, 0, 0, 0, 2],
        [0, 5, 0, 7, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 8],
        [6, 0, 0, 0, 9, 0, 3, 1, 0]
    ])
    # print("Problem master class")
    # run_and_verify([
    #     [8, 0, 0, 0, 0, 0, 0, 0, 0],
    #     [0, 0, 3, 6, 0, 0, 0, 0, 0],
    #     [0, 7, 0, 0, 9, 0, 2, 0, 0],
    #     [0, 5, 0, 0, 0, 7, 0, 0, 0],
    #     [0, 0, 0, 0, 4, 5, 7, 0, 0],
    #     [0, 0, 0, 1, 0, 0, 0, 3, 0],
    #     [0, 0, 1, 0, 0, 0, 0, 6, 8],
    #     [0, 0, 8, 5, 0, 0, 0, 1, 0],
    #     [0, 9, 0, 0, 0, 0, 4, 0, 0]
    # ])


import collections
import itertools
import re

import utils

def get_data():
    matches = utils.get_input(
        cast=lambda line: re.match(
            r'Valve (?P<valve>.+) has flow rate=(?P<rate>\d+); tunnels? leads? to valves? (?P<next_valves>.+)',
            line,
        ),
        delimiter=None,
        line_delimiter='\n',
    )
    data = []

    for match in matches:
        data.append((
            match.group('valve'),
            int(match.group('rate')),
            match.group('next_valves').split(', '),
        ))

    neighbors = {}
    rates = {}
    valves_to_open = set()

    for valve, rate, valve_neighbors in data:
        neighbors[valve] = valve_neighbors
        rates[valve] = rate

        if rate:
            valves_to_open.add(valve)

    return neighbors, rates, frozenset(valves_to_open)

@utils.part
def part_1():
    neighbors, rates, _ = get_data()

    open_valves = set()
    seen = {}
    max_so_far = 0

    def search(time, me, pressure):
        nonlocal max_so_far

        if seen.get((time, me), -1) >= pressure:
            return

        seen[time, me] = pressure

        if time == 30:
            max_so_far = max(max_so_far, pressure)
            return

        net_pressure = sum(rates[valve] for valve in open_valves)

        if me not in open_valves and rates[me]:
            open_valves.add(me)
            search(time + 1, me, pressure + net_pressure + rates[me])
            open_valves.remove(me)

        for neighbor in neighbors[me]:
            search(time + 1, neighbor, pressure + net_pressure)

    search(1, 'AA', 0)
    print(max_so_far)

@utils.part
def part_2():
    neighbors, rates, valves_to_open = get_data()

    open_valves = set()
    visited = {}
    max_so_far = 0

    def search(time, me, elephant, pressure):
        nonlocal max_so_far

        if visited.get((time, me, elephant), -1) >= pressure:
            return

        visited[time, me, elephant] = pressure

        if time == 26:
            max_so_far = max(max_so_far, pressure)
            return

        pressure += sum(rates[valve] for valve in open_valves)

        # If all valves are open, just stay here
        if len(open_valves) == len(valves_to_open):
            search(time + 1, me, elephant, pressure)
            return

        # I could open the valve
        if me not in open_valves and rates[me]:
            open_valves.add(me)

            # Elephant could open the valve
            if elephant not in open_valves and rates[elephant]:
                open_valves.add(elephant)
                search(
                    time + 1,
                    me,
                    elephant,
                    pressure + rates[me] + rates[elephant]
                )
                open_valves.remove(elephant)

            # Elephant could just move
            for neighbor in neighbors[elephant]:
                search(
                    time + 1,
                    me,
                    neighbor,
                    pressure + rates[me]
                )

            open_valves.remove(me)

        # I could just move
        for me_neighbor in neighbors[me]:
            # Elephant could open the valve
            if elephant not in open_valves and rates[elephant]:
                open_valves.add(elephant)
                search(
                    time + 1,
                    me_neighbor,
                    elephant,
                    pressure + rates[elephant]
                )
                open_valves.remove(elephant)

            # Elephant could just move
            for elephant_neighbor in neighbors[elephant]:
                search(
                    time + 1,
                    me_neighbor,
                    elephant_neighbor,
                    pressure,
                )

    search(1, 'AA', 'AA', 0)
    print(max_so_far)

def bfs_search():
    neighbors, rates, valves_to_open = get_data()
    states = {}
    valves = {valve: 1 << i for i, valve in enumerate(valves_to_open)}

    def next_states(current_states):
        for me, open_valves, flow, pressure in current_states:
            candidate_states = []

            # If at a valve of interest and it's closed, open it
            if me in valves and ~open_valves & valves[me]:
                candidate_states.append((me, open_valves | valves[me], flow + rates[me]))

            # Alternatively, move to another valve
            for neighbor in neighbors[me]:
                candidate_states.append((neighbor, open_valves, flow))

            for state in candidate_states:
                if state not in states or states[state] < pressure + flow:
                    states[state] = pressure + flow
                    yield (*state, pressure + flow)

    current_states = [('AA', 0, 0, 0)]

    for _ in range(26):
        current_states = list(next_states(current_states))

    return states

@utils.part
def part_2_bfs_disjoint():
    """
    Somewhat of a more clever/simpler solution here than doing 2D DFS, where the idea is that you
    use BFS to compile a list of all possible 1-player states at the end of 26 minutes, with
    a bitset to represent open valves.

    Then you group them by the open valves at the end and select the state for maximal pressure
    for that given set of final open valves.

    Then, noting that you and the elephant operate on disjoint sets of open valves, we simply
    take all distinct pairs of final states with disjoint open valves and try to find the pair
    with maximal total pressure.
    """
    states = bfs_search()
    grouped_states = collections.defaultdict(list)

    for state, pressure in states.items():
        open_valves = state[1]
        grouped_states[open_valves].append(pressure)

    best_states = {
        open_valves: max(pressures)
        for open_valves, pressures in grouped_states.items()
    }

    print(max(
        me_pressure + elephant_pressure
        for (me_open_valves, me_pressure), (elephant_open_valves, elephant_pressure)
        in itertools.combinations(best_states.items(), 2)
        if not me_open_valves & elephant_open_valves
    ))

def all_shortest_paths(adj):
    """Floyd-Warshall implementation"""
    valves = sorted(adj.keys())
    distances = {u: {v: float('inf') for v in valves} for u in valves}

    for u in valves:
        distances[u][u] = 0

        for v in adj[u]:
            distances[u][v] = 1

    for k, i, j in itertools.product(valves, repeat=3):
        if distances[i][j] > distances[i][k] + distances[k][j]:
            distances[i][j] = distances[i][k] + distances[k][j]

    return distances

def compressed_bfs_search():
    """
    This performs a BFS search on the possible 1-player states, but on a compressed weighted graph
    that whose nodes are only those with positive flow rates, and the edge weights represent
    the amount of time it takes to travel to the next valve and open it.
    """
    neighbors, rates, valves_to_open = get_data()
    masks = {valve: 1 << i for i, valve in enumerate(valves_to_open)}
    distances = all_shortest_paths(neighbors)

    # Compress the graph to only valves with a positive flow rate
    neighbors = {
        valve_1: [valve_2 for valve_2 in valves_to_open if valve_2 != valve_1]
        for valve_1 in valves_to_open
    }

    states = {}

    # Initialize queue with 1 valve already opened
    queue = collections.deque([
        (
            valve,
            masks[valve],
            # We store the total pressure that this opened valve will contribute for the entire 26 minutes instead
            # of just simulating each individual minute
            rates[valve] * (26 - distances['AA'][valve] - 1),
            distances['AA'][valve] + 1,
        )
        for valve in valves_to_open
    ])

    while queue:
        me, open_valves, pressure, time = queue.popleft()
        state = (me, open_valves)

        if state not in states or states[state] < pressure:
            states[state] = pressure

        for neighbor in neighbors[me]:
            # New time elapsed after traveling to the valve and opening it
            new_time = time + distances[me][neighbor] + 1

            # If valve is closed, we can get to it and open it, and we can get at least 1 minute of positive flow,
            # consider it a candidate next state
            if ~open_valves & masks[neighbor] and new_time < 26:
                new_state = (neighbor, open_valves | masks[neighbor])
                new_pressure = pressure + (26 - new_time) * rates[neighbor]

                if new_state not in states or states[new_state] < new_pressure:
                    states[new_state] = new_pressure
                    queue.append((*new_state, new_pressure, new_time))

    return states

@utils.part
def part_2_compressed_bfs_disjoint():
    """
    This is a variant on the other BFS disjoint solution, but instead we "compress" the graph.

    0-valves are completely useless and only serve as connection points to the actual valves that
    add pressure, so we can remove them entirely and form a new weighted graph using Floyd-Warshall
    to calculate the minimum distances between valves of interest.
    """
    states = compressed_bfs_search()
    grouped_states = collections.defaultdict(list)

    for state, pressure in states.items():
        open_valves = state[1]
        grouped_states[open_valves].append(pressure)

    best_states = {
        open_valves: max(pressures)
        for open_valves, pressures in grouped_states.items()
    }

    print(max(
        me_pressure + elephant_pressure
        for (me_open_valves, me_pressure), (elephant_open_valves, elephant_pressure)
        in itertools.combinations(best_states.items(), 2)
        if not me_open_valves & elephant_open_valves
    ))


#!/usr/bin/env python
# node to add some noise to the laser readings

import rospy
import random
from sensor_msgs.msg import LaserScan

MAX_LASER = 5.75  # maximum range the laser can detect
SHOULD_EXTEND = 0.95  # the probability that a particular laser value should be extended
ONE_MINUS_SHOULD_EXTEND = 1.0 - SHOULD_EXTEND  # only calculate once
MAX_EXTEND = 1.5  # the maximum we should ever extend a single laser reading

def laser_callback(scan):
    '''callback function loops through each item in the range
    values provided by the laser scan. 1- SHOULD_EXTEND*100 % of the time we mess up our laser reading
    to provide a mimicked version of real life'''
    my_ranges = scan.ranges
    for i in range(len(my_ranges)):
        new_num = random.random()  # random number between 0 and 1
        if new_num >= SHOULD_EXTEND:
            # decide how much to add using random number generated
            to_add = ((new_num-SHOULD_EXTEND)/ONE_MINUS_SHOULD_EXTEND) * MAX_EXTEND
            my_ranges[i] = min(my_ranges[i] + to_add, MAX_LASER)  # cap the value at the range of our laser

    scan.ranges = my_ranges  # change the message to hold my updated ranges
    leaky_pub.publish(scan)

if __name__ == '__main__':
    rospy.init_node('leaky_laser')
    leaky_pub = rospy.Publisher('leaky_laser', LaserScan, queue_size=100)
    rospy.Subscriber('base_scan', LaserScan, laser_callback)
    rospy.spin()


import math
from collections import namedtuple, defaultdict
from email.policy import default
from queue import Queue
from typing import Dict, NamedTuple, List

Material = namedtuple('Material', 'amount kind')

class Reaction(NamedTuple):
    ins: List[Material]
    out: Material

def parse_mat(raw: str) -> Material:
    ingredient = raw.strip()
    amount, kind = ingredient.split(' ')
    return Material(int(amount), kind)

def solve(file):
    with open(file) as f:
        lines = f.readlines()

    base_products = set()

    # Build tree
    reactions: Dict[str, Reaction] = {}
    for line in lines:
        ingredients, result = line.split('=>')

        mats = []
        for ingredient in ingredients.split(','):
            mats.append(parse_mat(ingredient))

        result = parse_mat(result)
        reactions[result.kind] = Reaction(mats, result)

        if len(mats) == 1 and mats[0].kind == 'ORE':
            base_products.add(result.kind)

    # resolve
    tasks = Queue()
    tasks.put(Material(1, 'FUEL'))
    ore = 0

    left_over: Dict[str, int] = defaultdict(int)
    req_base = defaultdict(int)

    while not tasks.empty():
        # get reaction to rollback

        req_amount, req_kind = tasks.get()
        reaction = reactions[req_kind]
        times_to_execute = math.ceil(req_amount / reaction.out.amount)
        left_over[req_kind] += times_to_execute * reaction.out.amount - req_amount

        print('req:', req_amount, ' * ', req_kind)

        # Calculate required mats
        mats = defaultdict(int)
        for mat in reaction.ins:
            # TODO: check left_over
            req_source_amount = times_to_execute * mat.amount
            old_leave_over = left_over[mat.kind]

            req_amount = max(req_source_amount - left_over[mat.kind], 0)
            left_over[mat.kind] = max(left_over[mat.kind] - times_to_execute * mat.amount, 0)

            # print(f'require {req_amount} {mat.kind} of {req_source_amount} leaves {left_over[mat.kind]}/{old_leave_over} rest')

            mats[mat.kind] += req_amount

        # start new tasks
        for source_kind, source_amount in mats.items():
            if source_kind == 'ORE':
                ore += source_amount
                print('req ore!')
            elif source_kind in base_products:
                req_base[source_kind] += source_amount
            else:
                tasks.put(Material(source_amount, source_kind))

    print('base_products', base_products)
    # print(req_base)

    # process base products
    for kind, amount in req_base.items():
        reaction = reactions[kind]
        times = math.ceil(amount / reaction.out.amount)

        for mat in reaction.ins:
            ore += mat.amount * times

    print(ore)
    return ore

if __name__ == '__main__':
    # file = 'input.txt'
    file = 'input_test_1.txt'
    assert solve(file) == 31

    file = 'input_test_2.txt'
    assert solve(file) == 165

    assert solve('input_test_3.txt') == 13312
    assert solve('input_test_4.txt') == 2210736


import json
import math

skillName = ["walk",
        "run",
        "jump",
        "kick",
        "punch",
        "roll",
        "spin",
        "spinkick",
        "backflip",
        "cartwheel",
        "crawl",
        "dance_a",
        "dance_b",
        "getup_facedown",
        "getup_faceup"]
for movement in skillName:
    with open(f"Assets/Motions/humanoid3d_{movement}.txt", 'r') as f:
        skill = json.load(f)

    convertedSkill = {
        'Frames': []
    }

    for frame in skill['Frames']:
        skillFrame = {
            'deltaTime': frame[0],
            'rootPosition':     {'x': frame[1], 'y' : frame[2], 'z': frame[3]},
            'rootRotation':     {'w': frame[4], 'x' : frame[5], 'y': frame[6], 'z': frame[7]},
            'chestRotation':    {'w': frame[8], 'x' : frame[9], 'y': frame[10], 'z': frame[11]},
            'neckRotation':     {'w': frame[12], 'x': frame[13], 'y': frame[14], 'z': frame[15]},
            'rHipRotation':     {'w': frame[16], 'x': frame[17], 'y': frame[18], 'z': frame[19]},
            'lHipRotation':     {'w': frame[30], 'x': frame[31], 'y': frame[32], 'z': frame[33]},

            'rAnkleRotation':   {'w': frame[21], 'x': frame[22], 'y': frame[23], 'z': frame[24]},
            'lAnkleRotation':   {'w': frame[35], 'x': frame[36], 'y':  frame[37], 'z': frame[38]},

            'lShoulderRotation': {'w': frame[25], 'x': frame[26], 'y': frame[27], 'z': frame[28]},
            'rShoulderRotation': {'w': frame[39], 'x': frame[40], 'y': frame[41], 'z': frame[42]},

            'rKneeRotation': {'z': frame[20]*(180/math.pi), 'x': 0, 'y': 0},
            'lKneeRotation': {'z': frame[34]*(180/math.pi), 'x': 0, 'y': 0},

            'lElbowRotation': {'z': frame[29]*(180/math.pi), 'x': 0, 'y': 0},
            'rElbowRotation': {'z': frame[43]*(180/math.pi), 'x': 0, 'y': 0},
            }

        convertedSkill['Frames'].append(skillFrame)

    with open(f"Assets/Motions/{movement}.json", 'w') as f:
        json.dump(convertedSkill, f)


# 3) Multi arguments functions (non-keyworded)
# Write a function that receives several lists of 3 positive integers each (ex. [2,4,6] and [0,2,2])
# The function finds the largest integer from all the lists. (Hint, use the max function with a list,
# as in max(mylist). Try the function max() to explore how it works.
# The function should return the largest integer and the corresponding list. Print the returned
# values in the main section of your script. Notice that the function returns two values, make sure
# you assign two values when you call the function. (i.e. a, b = myfunction(…) )

def findMax(*listed):
    count = 0;
    largest = 0;
    largetCount = 0;
    for x in listed:
        count += 1;
        if max(x) > largest:
            largest = max(x);
            largetCount = count;

    return largest, largetCount;

a,b = findMax([0,1,2], [0,23,4]);
print("The largest number is: {}, which can be found in list: {}.".format(a,b));


#!/usr/bin/env python3
"""
Read in MEX format Single Cell Expression Data

author: jy, nkmtmsys
"""
import csv
import gzip
import scipy.io
import pandas as pd
from warnings import warn

class Reader(object):
	"""
	Object to read in MEX data.
	"""
	def __init__(self,
		matrix_path:str = None,
		features_path:str = None,
		barcodes_path:str = None,
		):
		"""
		:param matrix_path: <str Default = None>
			Path to the matrix file.

		:param features_path: <str Default = None>
			Path to the feature (gene) file.

		:param barcodes_path: <str Default = None>
			Path to the barcode file.
		"""
		self.matrix_path = matrix_path

		# Process features
		self.features_path = features_path
		with gzip.open(self.features_path, 'rt') as features:
			self.features = pd.DataFrame(
				data = [x for x in csv.reader(features, delimiter = '\t')]
			)
		assert self.features.shape[1] >= 2

		# Process barcodes
		self.barcodes_path = barcodes_path
		with gzip.open(self.barcodes_path, 'rt') as barcodes:
			self.barcodes = [
				rec[-1] for rec in csv.reader(barcodes, delimiter = '\t')
			]

	def read_matrix(self):
		"""
		Read in matrix at once.
		"""
		return pd.DataFrame(scipy.io.mmread(self.matrix_path).toarray())

	def read_matrix_sparse(self):
		"""
		Read in files without loading full matrix.
		Go through matrix line by line and populate dataframe if there is a read

		Developing~
		"""
		return None

	def seperate_matrices(self, sparse_read:bool = False):
		"""
		Seperate matrices in MEX by data type.
		Useful for handling multiomic data.

		:param sparse_read:bool = False
			Whether load in matrix with sparse method or not.
		"""
		matrices = dict()
		assert self.features.shape[1] >= 3
		types = list(set(self.features[2]))
		# Load data
		if sparse_read:
			data = self.read_matrix_sparse()
			print('Developing~')
		else:
			data = self.read_matrix()
			for type in types:
				matrices[type] = data[self.features[2] == type]
		return matrices

	def get_gem(self,
		save_path:str = None,
		handle_repeat:str = 'sum',
		sparse_read:bool = False
		):
		"""
		Obtain GEM data frame from processed MEX file.

		:param save_path:str = None

		:param handle_repeat:str = 'sum'

		:return: Pandas.DataFrame
		"""
		if sparse_read:
			data = self.read_matrix_sparse()
		else:
			data = self.read_matrix()
		data.index = self.features[0]
		data.columns = self.barcodes
		# sum up data sharing same gene name if any
		if len(data.columns) != len(list(set(data.columns))):
			warn('Found repeated barcodes in MEX! Merging.')
			if handle_repeat == 'first':
				data=data[~data.columns.duplicated(keep='first')]
			elif handle_repeat == 'sum':
				data = data.groupby(data.columns).sum()

		# summ up data sharing same barcode if any
		if len(data.index) != len(list(set(data.index))):
			warn('Found repeated genes in MEX! Merging.')
			if handle_repeat == 'first':
				data = data[~data.index.duplicated(keep='first')]
			elif handle_repeat == 'sum':
				data = data.groupby(data.index).sum()

		# Check for repeats
		assert len(data.columns) == len(list(set(data.columns)))
		assert len(data.index) == len(list(set(data.index)))

		# Remove Gfp counts
		if 'bGH' in data.index:
			data.drop('bGH')
		if 'eGFP' in data.index:
			data.drop('eGFP')

		# save GEM if specified path to save
		if save_path != None:
			data.to_csv(save_path)

		# Return df purned records only have 0 counts
		return data.loc[~(data==0).all(axis=1)]


import pandas as pd
import numpy as np
from functions.dataset import *
from functions.plot import plot_linear, plot, plot_multiple, plot_prediction, plot_comparison
from functions.craft_readme import write_rd2 as write_rd
from functions import scraper
from functions.plot_maker import PlotsMaker

FOLDER = "./data/"

# load datasets
ndf = load_file(FOLDER+'national_data.json')
rdf = load_file(FOLDER+'regional_data.json')
ukdf = load_file(FOLDER+'uk.json')
frdf = load_file(FOLDER+'france.json')
dark = 'dark_background'

# loads plotMaker
pltmk = PlotsMaker(ndf, rdf, ukdf, frdf)

#########################################################
# CAMPI CHIAMABILI NEL CAMPO kind
#
#  intensive --> terapia_intensiva
#  hospitalized --> totale_ospedalizzati
#  deaths --> deceduti
#  new_cases --> nuovi_positivi
#########################################################

# april vs september (natioanal & regional level)
pltmk.make_april_september(region="Veneto")
pltmk.make_april_september(region="Lombardia")
pltmk.make_april_september(region="P.A. Trento")
pltmk.make_april_september(region="Campania", kind="intensive")

pltmk.make_april_september(region="Veneto", kind="new_cases")
pltmk.make_april_september(region="Campania", kind="new_cases")

# nations comparisons
pltmk.make_states_comparison(kind='intensive')
pltmk.make_states_comparison(kind='new_cases')
pltmk.make_states_comparison(kind='hospitalized')

# prediction for the future
pltmk.make_prediction()
pltmk.make_prediction(kind='hospitalized')

# plot all history
pltmk.make_history()
pltmk.make_history(kind='hospitalized')
pltmk.make_history(kind='new_cases')
pltmk.make_history(kind='deaths')

# WRITE
# NEW
# README
write_rd(ndf.df.iloc[-1], ndf.df.iloc[-4])

print('DONE')


import cv2
import numpy as np
from statistics import mode
import sys
import matplotlib.pyplot as plt
from PDF_to_PNG import convertPDF
import os
import time
import kMean

radii = []
# Define acceptable error
radiusDelta = 1

# Define acceptable range of dimension sizes, 15-20 usually.
minCricleW = 16
minCricleH = 16
minCricleArea = ((minCricleW+minCricleH)/4)*((minCricleW+minCricleH)/4)*3.1

class _mcOption:
    ID = None
    questionID = None
    optionID = None
    centerX = None
    centerY = None
    circleContour = None
    radius = None
    isChecked = False
    centroidID = None

    def __init__(self, ID, questionID, optionID):
        self.ID = ID
        self.questionID = questionID
        self.optionID = optionID

    def initCenters(self, circleContour):
        self.circleContour = circleContour
        self.centerX, self.centerY, self.radius = extractFromCricleContour(circleContour)

def extractFromCricleContour(circleContour):
    (x, y, w, h) = cv2.boundingRect(circleContour)  # This boudingRect function in opencv takes in a "contour" datatype
    return [x+w/2, y+h/2, w/2]                      # and return 4 values that form a bouding rectangle of the contour.

def processImage(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurry = cv2.GaussianBlur(gray, (3, 3), 1)
    adapt_thresh = cv2.adaptiveThreshold(blurry, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
    input(len(adapt_thresh.shape))
    return adapt_thresh

def findCircleContours(image):
    processed_image = processImage(image)
    # cv2.fincContours return 3 values, 1st one not needed, "contours" contains all contours in the given image,
    # "hierarchy", refer https://docs.opencv.org/3.4.0/d9/d8b/tutorial_py_contours_hierarchy.html
    # for understanding, basically it describe a "level" relationship between contours and contours.
    # Opencv hierarchy structure: [Next, Previous, First_Child, Parent]
    _, contours, hierarchy = cv2.findContours(processed_image.copy(), cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
    cv2.drawContours(image, contours, -1, (0,255,0), 1)
    cv2.imshow("Contours", image)
    cv2.waitKey(0)

    hierarchy = hierarchy[0]
    circleContours = []
    i = 0
    nCirlces = 0
    # Looping over contours one by one till the end, and for each contour, check if it satisfy our rules to be
    # considered as a valid circle, if it's valid, add this contour to the list "circleContours for storage".
    for contour in contours:
        (x, y, w, h) = cv2.boundingRect(contour)
        ar = w / float(h)
        if hierarchy[i][3] == -1 and w >= minCricleW and h >= minCricleH and 0.9 <= ar and ar <= 1.2:
            epsilon = 0.01*cv2.arcLength(contour, True)
            approx = cv2.approxPolyDP(contour, epsilon, True)
            area = cv2.contourArea(contour)
            if ( (len(approx) > 8) & (len(approx) < 20) & (area >= minCricleArea) ):
                circleContours.append(contour)
                nCirlces = nCirlces + 1
        i = i + 1
    return [circleContours, nCirlces]   # Return a list containing another list, and the number of circles detected.

def isCircleChecked(mcOption, image):
    ulx = mcOption.centerX - mcOption.radius
    uly = mcOption.centerY - mcOption.radius
    lrx = mcOption.centerX + mcOption.radius
    lry = mcOption.centerY + mcOption.radius
    nPixels = (lrx-ulx)*(lry-uly)
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    circleImg = gray_image[int(uly):int(lry),int(ulx):int(lrx)]
    m = cv2.mean(circleImg)
    intensity = m[0]
    if m[0] < 160:
        mcOption.isChecked = True

def filterBadCricles(objList):
    initN = len(objList)
    objList = sorted(objList , key=lambda k: [k.centerY, k.centerX])
    for i in range(nCirlces):
        radii.append(objList[i].radius)
    radiiMode = mode(radii)
    removed = 0
    for mcOption in objList[:]:
        if not ( mcOption.radius - radiusDelta < radiiMode and mcOption.radius + radiusDelta > radiiMode ):
            objList.remove(mcOption)
            removed = removed + 1
    return [objList, initN - removed]

def makeMCs(nCirlces):
    mcOptions_ObjList = []
    for i in range(nCirlces):
        instance = None
        instance = _mcOption(nCirlces-i, None, None)
        instance.initCenters(circleContours[i])
        mcOptions_ObjList.append(instance)
    return mcOptions_ObjList

################################################################################
print("[1]Multi-page PDD")
print("[2]Single PNG")
_mode = input("[?] = ")
if _mode == "1":
    imgFolder = "./imgs"
    if not os.path.exists(imgFolder):
        os.makedirs(imgFolder)
    while( os.path.isfile(input("Please enter the filename of the PDF template: ")) == False ):
        print("FILE DOES NOT EXIST! Please Try Again!")
    imgPath = imgFolder + "/" + time.strftime("%Y%m%d-%H%M%S") + "-" + pdfName[:-4]
    os.makedirs(imgPath)
    nPage, pngNames = convertPDF(pdfName, imgPath)
    images = []
    for name in pngNames:
        print(imgPath + name)
        images.append(cv2.imread(imgPath + "/" + name))
if _mode == "2":
    images = []
    images.append(cv2.imread("imgs/Test1.png"))
################################################################################

currentPage = 0
for image in images:
    currentPage = currentPage + 1
    input("Press <ENTER> to begin processing the current page [" + str(currentPage) + "]: ")

    circleContours, nCirlces = findCircleContours(image)
    mcOptions_ObjList = makeMCs(nCirlces)
    mcOptions_ObjList, nCirlces = filterBadCricles(mcOptions_ObjList)

    # Check to see if cricle is checked
    for i in range(nCirlces):
        isCircleChecked(mcOptions_ObjList[i], image)

    # Show results
    del circleContours[:]
    for mcOption in mcOptions_ObjList[:]:
        circleContours.append(mcOption.circleContour)
    cv2.drawContours(image, circleContours,  -1, (0,0,255), 1)
    print(nCirlces, "Circles Detected")
    cv2.imshow('Circles Detected',image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    x  = [mcOption.centerX for mcOption in mcOptions_ObjList]
    y  = [mcOption.centerY for mcOption in mcOptions_ObjList]
    cx = [mcOption.centerX for mcOption in mcOptions_ObjList if mcOption.isChecked == True] #checked
    cy = [mcOption.centerY for mcOption in mcOptions_ObjList if mcOption.isChecked == True] #checked
    plt.scatter(x, y, label='MC options dected')
    plt.scatter(cx, cy, c='r', label='Checked MC options')
    plt.gca().invert_yaxis()
    plt.show()

    groupedList, K, height, width = kMean.kMeanClustering(image, mcOptions_ObjList, 5)
    for i in range(0, K):
        plotx = [mcOption.centerX for mcOption in groupedList if mcOption.centroidID == i]
        ploty = [mcOption.centerY for mcOption in groupedList if mcOption.centroidID == i]
        plt.scatter(plotx,ploty,label=i)
        plt.xlim(0, width)
        plt.ylim(0, height)
        plt.gca().invert_yaxis()
        plt.show()