class Solution:
    def findMedianSortedArrays0(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        resultList = nums1 + nums2
        resultList.sort()
        numLength = len(resultList)
        if numLength % 2 == 1:
            index = int((numLength + 1) / 2) - 1
            return resultList[index]
        else:
            index = int(numLength / 2) - 1
            return (resultList[index] + resultList[index + 1]) / 2

    def findMedianSortedArrays(self, nums1, nums2):
        nums3 = [0] * (len(nums1) + len(nums2))

        r_i, l_i, i = 0, 0, 0
        while (l_i < len(nums1)) and (r_i < len(nums2)):
            if nums1[l_i] < nums2[r_i]:
                nums3[i] = nums1[l_i]
                l_i = l_i + 1
            else:
                nums3[i] = nums2[r_i]
                r_i = r_i + 1

            i += 1

        if l_i != len(nums1):
            nums3[i:] = nums1[l_i:]
        else:
            nums3[i:] = nums2[r_i:]

        len_3 = len(nums3)
        if len_3 % 2 != 0:
            return float(nums3[(len_3 - 1) // 2])

        return (nums3[(len_3 - 1) // 2] + nums3[len_3 // 2]) / 2

if __name__ == '__main__':
    nums1 = [1,3]
    nums2 = [2]
    su = Solution()
    result = su.findMedianSortedArrays(nums1, nums2)
    print(result)

004.Median of Two Sorted Arrays/Median of Two Sorted Arrays.py


"""
Program for optimization. Python 4, Lesson 5.

Calculates the groffle speed of a knurl widget
of average density given by user input.
"""

from math import log
from timeit import Timer
try:
    import cProfile as profile
except ImportError:
    import profile

def groffle_slow(mass, density):
    total = 0.0
    for i in range(10000):
        masslog = log(mass * density)
        total += masslog/(i+1)
    return total

def groffle_fast(mass, density):
    def groffle_fast_inner(mass, density):
        masslog = log(mass * density)
        for i in range(10000):
            yield masslog/(i+1)
    return sum(groffle_fast_inner(mass, density))

def groffle_also_fast(mass, density):
        masslog = log(mass * density)
        return sum(masslog/(i+1) for i in range(10000))

mass = 2.5
density = 12.0

slow = groffle_slow(mass, density)
fast = groffle_fast(mass, density)
also_fast = groffle_also_fast(mass, density)

if slow == fast == also_fast:
    print("Restults are identical")
else:
    print("Results differ")

slow_timer = Timer("total = groffle_slow(mass, density)",
 "from __main__ import groffle_slow, mass, density")
slow_time = slow_timer.timeit(number=1000)
print("slow_time:", slow_time)

fast_timer = Timer("total = groffle_fast(mass, density)",
 "from __main__ import groffle_fast, mass, density")
fast_time = fast_timer.timeit(number=1000)
print("fast_time:", fast_time)

also_fast_timer = Timer("total = groffle_also_fast(mass, density)",
 "from __main__ import groffle_also_fast, mass, density")
also_fast_time = also_fast_timer.timeit(number=1000)
print("also_fast_time:", also_fast_time)

profile.run("groffle_slow(mass, density)")


import re
from email.Header import decode_header
from email.utils import getaddresses

from django.core.validators import validate_email
from django.core.exceptions import ValidationError

def is_fwd(msg):
    if msg.get("subject").lstrip().rstrip().lower().startswith("fwd"):
        return True
    return False

def get_delivered_to(msg):
    return getaddresses(msg.get_all('delivered-to',[]))

def get_delivered_to_addr(msg):
    recipients = get_delivered_to(msg)
    return recipients[0][1].lower().lstrip().rstrip()

def get_from(msg):
    return getaddresses(msg.get_all('from',[]))

def get_from_addr(msg):
    recipients = get_from(msg)
    return recipients[0][1].lower().lstrip().rstrip()

def get_to_recipients(msg):
    return getaddresses(msg.get_all('to',[]))

def get_to_addrs(msg):
    return [y.lower().lstrip().rstrip() for x,y in get_to_recipients(msg)]

def get_cc_recipients(msg):
    return getaddresses(msg.get_all('cc',[]))

def get_cc_addrs(msg):
    return [y.lower().lstrip().rstrip() for x,y in get_cc_recipients(msg)]

def get_all_recipients(msg):
    tos = msg.get_all('to', [])
    ccs = msg.get_all('cc', [])
    resent_tos = msg.get_all('resent-to', [])
    resent_ccs = msg.get_all('resent-cc', [])
    return getaddresses(tos + ccs + resent_tos + resent_ccs)

def get_all_recipient_addrs(msg):
    recipients = get_all_recipients(msg)
    return [y.lower().lstrip().rstrip() for x,y in recipients]

def get_header(msg, header_name):
    header_content = decode_header(msg.get(header_name, ''))
    return_content = u''
    for line in header_content:
        str, enc = line
        if enc:
            content = str.decode(enc)
        else:
            content = str.encode('utf-8')
        return_content = u'%s%s' % (return_content, content)
    return return_content.lstrip().rstrip().replace('\n','')

def isolate_email(address):
    """Apply several regular expressions to detect
    common email addresses and
    return the isolated address
    """
    matches = [
        "(?P<name>[^<].*)<(?P<email>.*)>",
        "<(?P<email>.*)>",
        "(?P<email>.*)",
        "(?P<name>[^<].*?)<(?P<email>[^<].*?)<mailto.*",
        "[<(](?P<email>.*[^<])<mailto:.*",
    ]
    for regex in matches:
        #print "checking %s with %s" % (address, regex)
        m = re.match(r"%s" % regex, address)
        if m:
            likely_addr = m.group('email').lstrip().rstrip()
            if len(likely_addr.lstrip().rstrip()) > 0:
                try:
                    validate_email(likely_addr)
                    return likely_addr
                except ValidationError:
                    pass
                    #print "Couldn't validate %s" % likely_addr
    return ''
    #return None

def isolate_email_list(field):
        some = [isolate_email(x).lstrip().rstrip() for x in field.split(',') if x != '']
        more = [isolate_email(x).lstrip().rstrip() for x in field.split(' ') if x.find('@') > 0]
        return [x for x in set(some).union(set(more)) if x !='']

def isolate_name(address):
    m = re.match("(?P<name>[^<].*)<(?P<email>.*)>", address)
    if m:
        return m.group('name').lstrip().rstrip().lstrip('"').rstrip('"')
    return None


from django.shortcuts import render, redirect
from .models import *
from .forms import InputForm
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate, login
from django.contrib.auth import *

# Create your views here.

def index(request):
    form = InputForm
    total_tasks = Task.objects.count()
    tasks = Task.objects.all()

    if request.method == 'POST':
        form = InputForm(request.POST)
        if form.is_valid():
            form.save()
        return redirect('/')

    context = {
        'total_tasks': total_tasks,
        'tasks': tasks,
        'form': form,
    }
    return render(request, 'todo/index.html', context)

def edit_task(request, pk):
    task = Task.objects.get(id=pk)
    form = InputForm(instance=task)

    if request.method == 'POST':
        form = InputForm(request.POST, instance=task)
        if form.is_valid():
            form.save()
            return redirect('/')
    context = {'form': form}
    return render(request, 'todo/edit_task.html', context)

def delete(request, pk):
    item = Task.objects.get(id=pk)
    if request.method == 'POST':
        item.delete()
        return redirect('/')

    context = {'item': item}
    return render(request, 'todo/delete.html', context)


# -*- coding: utf-8 -*-

import numpy as np
import pandas as pd
import logging

from sklearn.model_selection import KFold
from sklearn.model_selection import RepeatedKFold
from sklearn.model_selection import ShuffleSplit

HEADER_INDEX = 'Index'; HEADER_MARKET = 'Market'; HEADER_DAY = 'Day'; HEADER_STOCK = 'Stock';
HEADER_X = ['x0', 'x1', 'x2', 'x3A', 'x3B', 'x3C', 'x3D', 'x3E', 'x4', 'x5', 'x6']
HEADER_Y = 'y'; HEADER_WEIGHT = 'Weight'
HEADER_Y_VARIANCE = 'yvar'; HEADER_Y_VARIANCE_GROUP = 'yvarGroup'; HEADER_Y_UPDOWN = 'yUpDown'; HEADER_Y_MAGNITUDE = 'yMagnitude'
HEADER_Y_REST = 'yrest'; HEADER_Y_TEST = 'ytest'; HEADER_Y_PREDICT = 'yprdct'

MAIN_LOGGER_NAME = 'mainLog'
TEST_TYPE_K_FOLD = 'KFold'
TEST_TYPE_REPEATED_K_FOLD = 'RepeatedKFold'
TEST_TYPE_RANDOM = 'random'
LABEL_INCREMENTS = 'increments'
LABEL_MUL_RATIO = 'mulRatio'
LABEL_AVG_TREND = 'avgTrend'
LABEL_AVG_MEDIAN = 'avgMedian'

LABEL_X_ORIGINAL = '[X]'
LABEL_X_LINEAR = '[X PCA]'
LABEL_X_LSUM_OF_FUNCTIONS = '[LF(X) PCA]'
LABEL_X_LINEAR_PER_STCK = '[X PCA p Stck]'
LABEL_X_LSUM_OF_FUNCTIONS_PER_STCK = '[LF(X) PCA p Stck]'

SEPARATOR = "_"

##############################################################################################################################
##############################################################################################################################
###########################################################  utils ###########################################################
####################################### manages constants and train / test strategies  #######################################
##############################################################################################################################

# Singleton/SingletonPattern
defaultConstantSet = {'YVarianceBuckets' : 22,
              'nbBucketsPerVarianceUnit' : 4,
              'randomState' : 12883823,
              'fractionFullSampleForTest' : 0.1,
              'testSamplingRepeats' : 20,
              'loggerName' : MAIN_LOGGER_NAME,
              'testType' : TEST_TYPE_K_FOLD,
              'nbThreads' : 4,
              'incrementalFunctionFit' : False,
              'distDayWeight' : 1,
              'distStockWeight' : 1000,
              'kInKNN' : 3}
class Constants:
    class _ConstantSingle:
        def __init__(self, **kwargs):
            self.YVarianceBuckets = self.getParam(kwargs,'YVarianceBuckets')
            self.nbBucketsPerVarianceUnit = self.getParam(kwargs,'nbBucketsPerVarianceUnit')
            self.randomState = self.getParam(kwargs,'randomState')
            self.FractionFullSampleForTest = self.getParam(kwargs,'fractionFullSampleForTest') # set to 10 equivalent to train on 90% of the data and tes on 10%
            self.testSamplingRepeats = self.getParam(kwargs,'testSamplingRepeats') # number of random partitions generated
            self.loggerName = self.getParam(kwargs,'loggerName') # name used as unique identifier for the logger
            self.testType = self.getParam(kwargs,'testType')
            self.nbThreads = self.getParam(kwargs,'nbThreads')
            self.incrementalFunctionFit = self.getParam(kwargs,'incrementalFunctionFit')
            self.distDayWeight = self.getParam(kwargs, 'distDayWeight')
            self.distStockWeight = self.getParam(kwargs, 'distStockWeight')
            self.kInKNN = self.getParam(kwargs, 'kInKNN')
        def __str__(self):
             return repr(self) + self.YVarianceBuckets + self.nbBucketsPerVarianceUnit + self.randomState + self.FractionFullSampleForTest + self.testSamplingRepeats + self.loggerName + self.testType + self.nbThreads + self.incrementalFunctionFit + self.distDayWeight + self.distStockWeight + self.kInKNN
        @staticmethod
        def getParam(paramSet, paramName):
            return paramSet.get(paramName, defaultConstantSet.get(paramName))

    instance = None
    def __init__(self, **kwargs):
        if not Constants.instance:
            Constants.instance = Constants._ConstantSingle(**kwargs)
    @staticmethod
    def tearDown():
        Constants.instance = None

    @property
    def YVarianceBuckets(self,*args,**kwargs):
        return self.instance.YVarianceBuckets
    @YVarianceBuckets.setter
    def YVarianceBuckets(self,*args,**kwargs):
        if args[0] % 2 == 0:
            self.instance.YVarianceBuckets = args[0]
        else:
            logging.getLogger(Constants().loggerName).log(logging.INFO, 'Cannot set YVarianceBuckets to odd number!')
    @property
    def nbBucketsPerVarianceUnit(self,*args,**kwargs):
        return self.instance.nbBucketsPerVarianceUnit
    @nbBucketsPerVarianceUnit.setter
    def nbBucketsPerVarianceUnit(self,*args,**kwargs):
        self.instance.nbBucketsPerVarianceUnit = args[0]
    @property
    def randomState(self,*args,**kwargs):
        return self.instance.randomState
    @randomState.setter
    def randomState(self,*args,**kwargs):
        self.instance.randomState = args[0]
    @property
    def fractionFullSampleForTest(self,*args,**kwargs):
        return self.instance.FractionFullSampleForTest
    @fractionFullSampleForTest.setter
    def fractionFullSampleForTest(self,*args,**kwargs):
        self.instance.FractionFullSampleForTest = args[0]
    @property
    def testSamplingRepeats(self,*args,**kwargs):
        return self.instance.testSamplingRepeats
    @property
    def loggerName(self,*args,**kwargs):
        return self.instance.loggerName
    @property
    def testType(self,*args,**kwargs):
        return self.instance.testType
    @testType.setter
    def testType(self,*args,**kwargs):
        self.instance.testType = args[0]
    @property
    def nbThreads(self,*args,**kwargs):
        return self.instance.nbThreads
    @property
    def incrementalFunctionFit(self,*args,**kwargs):
        return self.instance.incrementalFunctionFit
    @incrementalFunctionFit.setter
    def incrementalFunctionFit(self,*args,**kwargs):
        self.instance.incrementalFunctionFit = args[0]
    @property
    def distDayWeight(self,*args,**kwargs):
        return self.instance.distDayWeight
    @distDayWeight.setter
    def distDayWeight(self,*args,**kwargs):
        self.instance.distDayWeight = args[0]
    @property
    def distStockWeight(self,*args,**kwargs):
        return self.instance.distStockWeight
    @distStockWeight.setter
    def distStockWeight(self,*args,**kwargs):
        self.instance.distStockWeight = args[0]
    @property
    def kInKNN(self,*args,**kwargs):
        return self.instance.kInKNN
    @kInKNN.setter
    def kInKNN(self,*args,**kwargs):
        self.instance.kInKNN = args[0]

def parseFile(fileName):
    df = pd.read_csv(fileName, index_col=0)
    # remove rows with a nan parameter _ nan == * systematically returns false hence the filtering using (x1 != x1) | ...
    df_filtered = testNanInDF(df, HEADER_X + [HEADER_Y, HEADER_WEIGHT])
    df = df.drop(df_filtered.index.values)
    df = df.reset_index(drop=True) #to avoid missing rows in the index that cause K-fold to crash
    return df

def getXVectors(columns, regressionType):
    l = len(regressionType)
    return [x for x in columns if (x[-l:] == regressionType) and (str.lower(x[0]) == 'x')]

def getTestAndTrainSample():
    randomState = Constants().randomState
    fraction = Constants().fractionFullSampleForTest
    repeats = Constants().testSamplingRepeats
    testType = Constants().testType

    if testType == TEST_TYPE_K_FOLD:
        return KFold(n_splits=int(1 / fraction), randomState=randomState)
    if testType == TEST_TYPE_REPEATED_K_FOLD:
        return RepeatedKFold(n_splits=int(1 / fraction), n_repeats=repeats, randomState=randomState)
    if testType == TEST_TYPE_RANDOM:
        return ShuffleSplit(n_splits=repeats, test_size=fraction, random_state =randomState)

def getShapesToPlot(i : int):
    # 'o' removed to keep it for special display
    shapes = ['v', '^', '<', '>', '1', '2', '3', '4', 's', 'p', '*', 'h', 'H', '+', 'x', 'D', 'd']
    return shapes[i % len(shapes)]

def testNanInDF(df, headers):
    return df.replace([np.inf, -np.inf], np.nan).query(''.join(['(' + x + ' != ' + x + ') | ' for x in headers ])[:-2])


def rotate(key):
    # 회전 알고리즘 (90도 회전)
    n = len(key)
    ret = [[0] * n for _ in range(n)]

    for i in range(n):
        for j in range(n):
            ret[j][n - 1 - i] = key[i][j]

    return ret

def check(startX, startY, key, lock, board_size, start, end):
    # board 생성
    board = [[0] * board_size for _ in range(board_size)]

    # board에 key 넣기
    for i in range(len(key)):
        for j in range(len(key)):
            board[startX + i][startY + j] += key[i][j]

    # key가 들어간 board에 lock 넣기 (더하기)
    for i in range(start, end):
        for j in range(start, end):
            board[i][j] += lock[i - start][j - start]
            # 모든 lock이 1이어야만 잠금 풀림
            if board[i][j] != 1:
                return False
    else:
        return True

def solution(key, lock):
    start = len(key) - 1  # board에서 lock의 시작 위치
    end = start + len(lock)  # board에서 lock의 종료 위치
    board_size = len(lock) + start * 2

    # 1. board 생성
    # 2. check (move, rotate)

    # 4방향 회전
    for rotation in range(4):
        # key 회전
        for i in range(end):
            for j in range(end):
                if check(i, j, key, lock, board_size, start, end):
                    return True
        key = rotate(key)

    return False

2023/이것이_코딩_테스트다/2회독/implementation/자물쇠와_열쇠.py


import json
from .attribute import Attribute
from .packet_extend import PacketExtend

class Packet(object):

    instances_by_path = {}

    def __init__(self, packet_json_path):
        self.packet_json_path = packet_json_path
        self.id = None
        self.label = None
        self.type = None
        self.key = None
        self.auto_expand = True
        self.skip_every_instance_files = False
        self.limit_to_allowed_children = False
        self.auto_generate = False
        self.info_html = None
        self.attributes = []
        self.packet_extends = []
        self.attributes_by_lower_name = {}

        # generate unique module branch path to the repo of this packet
        parts = packet_json_path.split("/")
        self.module_branch_path = f'{parts[4]}\\{parts[5]}\\{parts[6]}\\{parts[7]}'
        self._load_from_json()

    def _load_from_json(self):
        with open(self.packet_json_path, 'r') as file:
            json_string = file.read()

        packet_json = json.loads(json_string)
        self.id = packet_json['id']
        self.label = packet_json['label']
        self.type = packet_json['type'] if type in packet_json else ''
        self.key = packet_json['key'] if type in packet_json else ''
        self.auto_expand = packet_json['autoExpand']
        self.skip_every_instance_files = packet_json['skipEveryInstanceFiles']
        self.limit_to_allowed_children = packet_json['limitToAllowedChildren']
        self.auto_generate = packet_json['autoGenerate'] if 'autoGenerate' in packet_json else False
        self.info_html = packet_json['infoHtml'] if type in packet_json else ''

        for attribute_json in packet_json['attributes']:
            attribute = Attribute.load(attribute_json)
            self.attributes.append(attribute)
            self.attributes_by_lower_name[attribute.name.lower()] = attribute

        if 'extends' in packet_json:
            for extends_packet_json in packet_json['extends']:
                packet_extend = PacketExtend.load(extends_packet_json)
                self.packet_extends.append(packet_extend)

    def get_default_value(self, attribute_name):
        if attribute_name.lower() in self.attributes_by_lower_name:
            return self.attributes_by_lower_name[attribute_name.lower()]


from scapy.all import *

p = rdpcap('bottle.cap')
for i in range(8):
    if not p[i].haslayer(DNS):
        continue
    if DNSQR in p[i]:
        if DNSRR in p[i] and len(p[i][DNSRR].rdata)>0: # downstream/server
            print("S[%i]: %r" % (i,p[i][DNSRR].rdata))
        else: # upstream/client
            print("C[%i]: %r" % (i,p[i][DNSQR].qname))


from sre_parse import State
import tkinter as tk

def say_hello():
    print('hello')

def add_lable():
    lable = tk.Label(win,text='new')
    lable.pack()

def counter():
    global count
    count+=1
    btn4['text'] = f'count: {count}'
    if count % 5 == 0:
        btn4['activebackgound']='green'

def disable():
    lable = tk.Label(win,text='new new')
    lable.pack()

count = 0

win = tk.Tk()
win.geometry('300x400+100+200')
win.title('Button test')

btn1 = tk.Button(win,text='hello',    # shows button that displays 'hello'
command=say_hello)                    # and returns 'hello' in console as written in function

btn2 = tk.Button(win,text='Add new lable',  # shows button that displays 'add new lable'
command=add_lable)                          # and returns 'new' in program as 'lable' as written in function

btn3 = tk.Button(win,text='Add new lambda',
command=lambda: tk.Label(win,text='new lambda')
)

btn4 = tk.Button(win,text=f'count: {count}',
command=counter,
bg='red',
# activebackground ='blue'
)

btn5 = tk.Button(win,text='new lable',
command=disable)

btn1.pack()
btn2.pack()
btn3.pack()
btn4.pack()
btn5.pack()

win.mainloop()

#.grid() allows us to use variables as table
# columnspan= / rowspan=  how many columns or rows will element take(grid)
#stick= with side to pin our object(n,s,w,e)


import datetime                        # datetime consists of year,month,days,hours,min's,sec's

Present_Date = datetime.datetime.now()               # gets the currentDate

DOB= input ('Enter your date of birth   dd mm yyyy : \t')       # your input
print("Your date of Birth is :", DOB)
DOB_Date= datetime.datetime.strptime(DOB,'%d %m %Y')
 #strptime has two arguments  , 1. string (your input ) ,2. convertedcode (yo string converted to code such as %d %m %y)
# dd - %d , mm - %m , yy - %y stores
print("Your Date of Birth in YY-MM-DD-HH-mm-SS is :",DOB_Date)
Present_Age = Present_Date-DOB_Date       # to get current age
print(Present_Age)                         # gets in days and time

years = ((Present_Age.total_seconds())/(365.242*24*3600))              # converts to seconds and gets year as integer
# .total_seconds() is a method to convert the years into seconds
yearsInt=int(years)

months=(years-yearsInt)*12
monthsInt=int(months)

days=(months-monthsInt)*(365.242/12)
daysInt=int(days)

hours = (days-daysInt)*24
hoursInt=int(hours)

minutes = (hours-hoursInt)*60
minutesInt=int(minutes)

seconds = (minutes-minutesInt)*60
secondsInt =int(seconds)

print('You are  \n {0:d} years, \n {1:d}  months, \n {2:d}  days, \n {3:d}  hours, \n {4:d} \
 minutes, \n {5:d} seconds old.'.format(yearsInt,monthsInt,daysInt,hoursInt,minutesInt,secondsInt))


def timeConversion(s):
    # Write your code here
    tr = s[:-2].split(":")
    flag = s[-2:]
    if flag == "AM":
        if tr[0] == "12":
            tr[0] = "00"
        return tr[0] + ":" + tr[1] + ":" + tr[2]
    if flag == "PM":
        if tr[0] == "12":
            return tr[0] + ":" + tr[1] + ":" + tr[2]

        return str(int(tr[0]) + 12) + ":" + tr[1] + ":" + tr[2]

print(timeConversion("12:40:22AM"))
print(timeConversion("12:40:22PM"))


# a = []
# a.append(1)
# a.append(2)
# a.append(3)
# print(a)
# a.pop()
# a.pop()
# a.pop()
# print(a)

# s = list()
# def push(item):
#     s.append(item)
#
# def pop():
#     if len(s) == 0:
#         return
#     else:
#         return s.pop(-1)
#
# def isEmpty():
#     if len(s) == 0: return True
#     else: return False
#
# def check_matching(data):
#     for i in range(len(data)):
#         if data[i] == '(':
#             push(data[i])
#         elif data[i] ==')':
#             if isEmpty(): return False
#             pop()
#     if not isEmpty(): return False
#     else: return True
#
# data = input()
# print(check_matching(data))

# def fact(n):
#     if n == 1:
#         return 1
#     else:
#         return n * fact(n-1)
#
# print(fact(4))

# def fibo(n):
#     global memoryview
#     if n >= 2 and len(memo) <= n:
#         memo.append(fibo(n-1) + fibo(n-2))
#     return memo[n]
#
# memo=[0,1]

# print(fibo(50))

# def fibo(n):
#     if n == 1 or n == 0:
#         return n
#     else:
#         return (fibo(n-1) + fibo(n-2))
#
# print(fibo(50))

# def fibo_dp(n):
#     f = [0, 1]
#
#     for i in range(2, n+1):
#         f.append(f[i-1] + f[i-2])
#
#     return f[n]
#
# print(fibo_dp(100))

# DFS
# 7 8
# 1,2,1,3,2,4,2,5,4,6,5,6,6,7,3,7
# graph = {'1': set(['2', '3']),
#          '2': set(['1', '4', '5']),
#          '3': set(['2', '7']),
#          '4': set(['2', '6']),
#          '5': set(['2', '6']),
#          '6': set(['7', '5'])
#          '7': set(['3'])}
#
# def dfs(graph, start):
#     visited = []
#     stack = [start]
#
#     while stack:
#         n = stack.pop()
#         if n not in visited:
#             visited.append(n)
#             stack += graph[n] - set(visited)
#     return visited
#
# print(dfs(graph, 'A'))

#선생님 방법

def dfs(v):
    visited[v] = 1
    print(v, end='')

    for w in range(V+1):
        if G[v][w] == 1 and visited[w] == 0:
            dfs(w)

V,E = map(int,input().split())
temp = list(map(int, input().split()))

G = [[0 for i in range(V+1)]for j in range(V+1)] #2차원 초기화
visited = [0 for i in range(V+1)]

for i in range(0, len(temp), 2):
    G[temp[i]][temp[1+i]] = 1
    G[temp[i+1]][temp[i]] = 1

for i in range(V+1):
    print('{} {}'.format(i, G[i]))

dfs(1)


# Absolutely atrocious solution but at least it works
import re
from collections import deque, defaultdict
from copy import deepcopy
from dataclasses import dataclass, field
from queue import PriorityQueue

class Floor:
    def __init__(self, chips, generators):
        self.chips = list(chips)
        self.generators = list(generators)

    def copy(self):
        return Floor(deepcopy(self.chips), deepcopy(self.generators))

    def hash(self):
        return tuple(sorted(self.chips)), tuple(sorted(self.generators))

    def __len__(self):
        return len(self.chips) + len(self.generators)

    def can_be_removed(self, items):
        c = list(self.chips)
        g = list(self.generators)
        for it in items:
            if it[1] == 'generator':
                g.remove(it[0])
            else:
                c.remove(it[0])
        if len(c) == 0:
            return True
        if len(g) == 0:
            return True
        for x in c:
            if x not in g:
                return False
        return True

    def can_be_added(self, items):
        c = list(self.chips)
        g = list(self.generators)
        for it in items:
            if it[1] == 'generator':
                g.append(it[0])
            else:
                c.append(it[0])
        if len(c) == 0:
            return True
        if len(g) == 0:
            return True
        for x in c:
            if x not in g:
                return False
        return True

class Vertex:
    def __init__(self, floors, elevator):
        self.floors = floors
        self.elevator = elevator

    def hash(self):
        return tuple(x.hash() for x in self.floors), self.elevator

    def move(self, items, is_up):
        new_floors = [f.copy() for f in self.floors]
        for it in items:
            if it[1] == 'generator':
                new_floors[self.elevator].generators.remove(it[0])
                new_floors[self.elevator + (1 if is_up else -1)].generators.append(it[0])
            else:
                new_floors[self.elevator].chips.remove(it[0])
                new_floors[self.elevator + (1 if is_up else -1)].chips.append(it[0])
        return Vertex(new_floors, self.elevator + (1 if is_up else -1))

    def is_goal(self):
        return len(self.floors[0]) == len(self.floors[1]) == len(self.floors[2]) == 0

def read_input():
    floors = []
    with open('input', 'r') as f:
        for line in f:
            chips = re.findall(r'(\w+)-compatible microchip', line)
            gens = re.findall(r'(\w+) generator', line)
            floors.append(Floor(chips, gens))
    return floors

@dataclass(order=True)
class QueueItem:
    priority: int
    vertex: Vertex = field(compare=False)

def astar_h(vert):
    return len(vert.floors[2]) * 2 + len(vert.floors[1]) * 4 + len(vert.floors[0]) * 8

def length(parents, v):
    l = 0
    c = v
    while c is not None:
        c = parents[c]
        l += 1
    return l - 1

def astar(initial):
    Q = PriorityQueue()
    Q.put(QueueItem(astar_h(initial), initial))
    queued = {initial.hash()}
    parents = {initial.hash(): None}
    gScore = defaultdict(lambda: 1000000)
    gScore[initial.hash()] = 0
    fScore = defaultdict(lambda: 1000000)
    fScore[initial.hash()] = astar_h(initial)
    while not Q.empty():
        c = Q.get(False)
        current = c.vertex
        current_hash = current.hash()
        queued.remove(current_hash)
        if current.is_goal():
            return parents, current.hash()
        nghs = []
        for move in generate_possible_moves(current.floors, current.elevator, True):
            nghs.append(current.move(move, True))
        for move in generate_possible_moves(current.floors, current.elevator, False):
            nghs.append(current.move(move, False))
        for ngh in nghs:
            gs = gScore[current_hash]
            h = ngh.hash()
            if gs < gScore[h]:
                parents[h] = current_hash
                gScore[h] = gs
                fScore[h] = gScore[h] + astar_h(ngh)
                if h not in queued:
                    queued.add(h)
                    Q.put(QueueItem(astar_h(ngh), ngh))

def bfs(initial, dl, first_up=True):
    Q = deque()
    Q.append(initial)
    visited = {initial.hash()}
    parents = {initial.hash(): None}
    distances = {initial.hash(): 0}
    while len(Q) > 0:
        v = Q.popleft()
        vh = v.hash()
        if distances[vh] > dl:
            return distances
        for move in generate_possible_moves(v.floors, v.elevator, first_up):
            ngh = v.move(move, first_up)
            h = ngh.hash()
            if h not in visited:
                visited.add(h)
                parents[h] = vh
                distances[h] = distances[vh] + 1
                Q.append(ngh)
        for move in generate_possible_moves(v.floors, v.elevator, not first_up):
            ngh = v.move(move, not first_up)
            h = ngh.hash()
            if h not in visited:
                visited.add(h)
                parents[h] = vh
                distances[h] = distances[vh] + 1
                Q.append(ngh)

def generate_possible_moves(floors, current_floor, up):
    if not up:
        res = []
        if current_floor > 0:
            floor_items = [(x, 'microchip') for x in floors[current_floor].chips] + [(x, 'generator') for x in floors[current_floor].generators]
            for i1, it in enumerate(floor_items):
                for it2 in floor_items[i1 + 1:]:
                    if floors[current_floor].can_be_removed([it, it2]) and floors[current_floor - 1].can_be_added([it, it2]):
                        res.append((it, it2))
            for it in floor_items:
                if floors[current_floor].can_be_removed([it]) and floors[current_floor - 1].can_be_added([it]):
                    res.append((it,))

        return res
    res = []
    if current_floor < 3:
        floor_items = [(x, 'microchip') for x in floors[current_floor].chips] + [(x, 'generator') for x in floors[current_floor].generators]
        for i1, it in enumerate(floor_items):
            for it2 in floor_items[i1 + 1:]:
                if floors[current_floor].can_be_removed([it, it2]) and floors[current_floor + 1].can_be_added([it, it2]):
                    res.append((it, it2))
        for it in floor_items:
            if floors[current_floor].can_be_removed([it]) and floors[current_floor + 1].can_be_added([it]):
                res.append((it,))
    return res

floors = read_input()

floors[0].generators.append('elerium')
floors[0].chips.append('elerium')
floors[0].generators.append('dilithium')
floors[0].chips.append('dilithium')

elevator_level = 0
parents, v = astar(Vertex(floors, 0))
upper_bound = length(parents, v)
final_floors = [Floor([], []), Floor([], []), Floor([], []),
                Floor(floors[0].chips + floors[1].chips + floors[2].chips + floors[3].chips,
                      floors[0].generators + floors[1].generators + floors[2].generators + floors[3].generators)]

left = bfs(Vertex(floors, 0), upper_bound//2 + 1, True)
right = bfs(Vertex(final_floors, 3), upper_bound//2 + 1, False)
common = set(left.keys()).intersection(right.keys())
min_dist = upper_bound
for c in common:
    d = left[c] + right[c]
    if d < min_dist:
        min_dist = d
print(min_dist)


def analyze(text):
    report = ""
    report += f"Número de plavras é {count_words(text)}\n"
    report += f"Ocorrências por carcter é {char_counter(text)}"

    return report

def count_words(text):
    return len(text.split(" "))

def char_counter(text):
    char_counter = dict()
    for char in text:
        if char in char_counter:
            char_counter[char] += 1
        else:
            char_counter[char] = 1
    return char_counter

text_to_analyze = (
    "Seremos a primeira escolha para quem quer alcançar profissões "
    "digitais na América Latina. No Brasil e no mundo, milhares de vagas "
    "criadas anualmente no mercado de tecnologia deixam de ser "
    "preenchidas por falta de pessoas qualificadas. Nós trabalhamos duro "
    "todos os dias para que as pessoas tenham a oportunidade de trilhar "
    "essas carreiras."
)

print(analyze(text_to_analyze))

Ciencia-Computação/Bloco 33 - Introdução a Python/Dia 2 - Entrada e Saída de Dados/live-lecture/32-1/aula/analyzer.py


import matplotlib as mpl

mpl.rcParams['xtick.labelsize'] = 24
mpl.rcParams['ytick.labelsize'] = 24
mpl.rcParams['font.size'] = 15
mpl.rcParams['figure.autolayout'] = True
mpl.rcParams['figure.figsize'] = [9.5, 6.45]
mpl.rcParams['axes.titlesize'] = 28
mpl.rcParams['axes.labelsize'] = 28
mpl.rcParams['lines.linewidth'] = 2
mpl.rcParams['lines.markersize'] = 8
mpl.rcParams['legend.fontsize'] = 20
mpl.rcParams['mathtext.fontset'] = 'stix'
mpl.rcParams['font.family'] = 'STIXGeneral'

COLORS_DICT = {'Joint DeepSIC': 'blue',
               'Joint ResNet10': 'blue',
               'Online DeepSIC': 'green',
               'Online ResNet10': 'green',
               'Meta-DeepSIC': 'red',
               'Meta-ResNet10': 'red',
               'Online DeepSIC - Modular Training': 'darkgreen',
               'Meta-DeepSIC - Modular Training': 'darkred'}

MARKERS_DICT = {'Joint DeepSIC': 'x',
                'Joint ResNet10': 'x',
                'Online DeepSIC': '.',
                'Online ResNet10': '.',
                'Meta-DeepSIC': 'd',
                'Meta-ResNet10': 'd',
                'Online DeepSIC - Modular Training': '.',
                'Meta-DeepSIC - Modular Training': 'd'}

LINESTYLES_DICT = {'Joint DeepSIC': '-',
                   'Joint ResNet10': 'dotted',
                   'Online DeepSIC': '-',
                   'Online ResNet10': 'dotted',
                   'Meta-DeepSIC': '-',
                   'Meta-ResNet10': 'dotted',
                   'Online DeepSIC - Modular Training': 'dashdot',
                   'Meta-DeepSIC - Modular Training': 'dashdot'}


import time
import textwrap

from tqdm import tqdm

def welcome_in_big_data():
    comments = [
        {'text': 'let\'s start some calculations', 'sleep': 2},
        {'text': 'fetching data', 'sleep': 3},
        {'text': 'still fetching data', 'sleep': 5},
        {'text': 'yup still fetching data', 'sleep': 6},
        {'text': 'ok starting some calculations', 'sleep': 6},
        {'text': 'calculating', 'sleep': 6},
        {'text': 'still calculating', 'sleep': 6},
        {'text': 'and again still calculating', 'sleep': 6},
        {'text': 'please wait', 'sleep': 2},
        {'text': 'just a litte bit more', 'sleep': 6},
        {'text': 'yes this is how it feels', 'sleep': 5},
        {'text': 'to work in big data', 'sleep': 5},
        {'text': 'still interested?!', 'sleep': 5},
        {'text': 'are you sure?!', 'sleep': 5},
        {'text': 'ok :-)', 'sleep': 3},
    ]

    pbar = tqdm(comments, bar_format='{l_bar}{bar}', ncols=100)
    for comment in pbar:
        pbar.set_description(comment['text'].rjust(32))
        time.sleep(comment['sleep'])

    print(textwrap.dedent('''
        ################################
        ################################

        Welcome is the World of Big Data

        ################################
        ################################
    '''))


import time
from bs4 import BeautifulSoup
from selenium import webdriver
from sql import SQLite

db = SQLite('database.db')

class Parser:
    def result(self):
        driver = webdriver.Chrome()
        url = 'https://qiwi.com/payment/exchange'
        driver.get(url)
        time.sleep(2)
        html = driver.page_source
        soup = BeautifulSoup(html, 'html.parser')
        divs = soup.findAll('p', class_='css-xk1yoo')
        res = [c.text for c in divs]
        driver.quit()
        return res


#!C:\Users\msing\AppData\Local\Programs\Python\Python37-32\python.exe
import sys
# print("Hello");
# output=$output
# print(sys.executable)
# print(sys.path)
# sys.path.extend(['C:\\xampp\\htdocs\\Shopitv1\\ml-latest-small', 'C:\\Users\\msing\\AppData\\Local\\Programs\\Python\\Python37-32\\python37.zip', 'C:\\Users\\msing\\AppData\\Local\\Programs\\Python\\Python37-32\\DLLs', 'C:\\Users\\msing\\AppData\\Local\\Programs\\Python\\Python37-32\\lib', 'C:\\Users\\msing\\AppData\\Local\\Programs\\Python\\Python37-32', 'C:\\Users\\msing\\AppData\\Local\\Programs\\Python\\Python37-32\\lib\\site-packages'])
# print(sys.path)

s=sys.argv
st=" "
st=st.join(s[1:])
# print("HELLO")
# print(s)
# print(st)
# print(sys.path)
# m=int(st)
# m=[1,2,3]
m=[int(i) for i in s[1:]]

# print(m)
recc=[]
frames=[]
import numpy as np
import pandas as pd

# print("HI")
data = pd.read_csv('ratings.csv')
# data.head(10)

# prod_titles_genre = pd.read_csv('prods.csv')

# # prod_titles_genre.head(10)
# data = data.merge(prod_titles_genre,on='prodId', how='left')
# data.head(10)

Average_ratings = pd.DataFrame(data.groupby('prodId')['rating'].mean())
# Average_ratings.head(10)

Average_ratings['Total Ratings'] = pd.DataFrame(data.groupby('prodId')['rating'].count())
# Average_ratings.head(10)
prod_user = data.pivot_table(index='userId',columns='prodId',values='rating')

for i in range(3):
	# print("Hello")
	if (m[i] in prod_user):
		correlations = prod_user.corrwith(prod_user[m[i]])
		recommendation = pd.DataFrame(correlations,columns=['Correlation'])
		recommendation.dropna(inplace=True)
		recommendation = recommendation.join(Average_ratings['Total Ratings'])
		recc.append((recommendation[recommendation['Total Ratings']>100].sort_values('Correlation',ascending=False).reset_index()))

# recc = recc.merge(prod_titles_genre,on='prodId', how='left')

for i in range(len(recc)):
	# print(recc[i].head(3))

	frames.append(recc[i].head(3))

output_df=pd.concat(frames)

output_df.to_csv("personal_recommendations.csv")
# print("HELLO")
# print(recc.head(10))
# recc.head(10).to_csv("recommendations.csv")


import sys
import re
S = str(input())

Texts = ['dream','dreamer','erase','eraser']

while len(S)>0:
  checkerr=0
  for oneText in Texts:
    if S.endswith(oneText):
      S=S[:-1 * len(oneText)]
      checkerr = 1
      break

  if checkerr == 0 and len(S)>0:
    print('NO')
    sys.exit()

print('YES')


import os
import os.path
import pathlib
import asyncio

from graphql import parse
from ariadne import MutationType, SubscriptionType, load_schema_from_path

from nomine.models import Namer
from nomine.models.folder_entry import FolderEntry, FILE_TYPE, DIRECTORY_TYPE

mutation = MutationType()
subscription = SubscriptionType()
bindables = [mutation, subscription]
schema_file = load_schema_from_path(
    pathlib.Path(__file__).parent.joinpath("schema.graphql").absolute()
)
schema = parse(schema_file)
queue = asyncio.Queue()

def get_or_create_entry(session, folder_id, dir_entry):
    if dir_entry.is_file():
        entry_type = FILE_TYPE
    elif dir_entry.is_dir():
        entry_type = DIRECTORY_TYPE
    else:
        return

    existing = (
        session.query(FolderEntry).filter(FolderEntry.path == dir_entry.path).first()
    )
    if existing:
        return existing

    entry = FolderEntry()
    entry.path = dir_entry.path
    entry.type = entry_type
    entry.folder_id = folder_id
    session.add(entry)
    return entry

def walk_folder(session, folder_id, folder):
    for dir_entry in os.scandir(folder):
        if dir_entry.is_file():
            entry = get_or_create_entry(session, folder_id, dir_entry)
            queue.put_nowait(entry)

        if dir_entry.is_dir():
            entry = get_or_create_entry(session, folder_id, dir_entry)
            queue.put_nowait(entry)
            walk_folder(session, folder_id, dir_entry.path)

@mutation.field("scan_namer")
def resolve_scan_namer(_, info, id):
    session = info.context["session"]
    namer = session.query(Namer).get(id)

    for folder in namer.folders:
        walk_folder(session, folder.id, folder.folder)
        session.commit()

@subscription.source("namer_entries")
async def namer_entries_generator(obj, info, id):
    while True:
        item = await queue.get()
        yield item
        queue.task_done()

@subscription.field("namer_entries")
def namer_entries_resolver(entry, info, id):
    print("resolving", entry)
    return entry


# python write_letters.py > _letters.py

from _sqlite import conn

def s_dot(csv=";"):
    strokes = ", ".join(["s." + stroke.strip() for stroke in csv.split(",")])
    return strokes

sql = """
select
    letter_name name,
    letter_variable variable,
    letter_strokes strokes
from tw_letters
where letter_strokes != ''
order by variable, letter_name
;"""
curr = conn.cursor()
rs = curr.execute(sql, ())

print("from _strokes import strokes")
print()
print("s = strokes()")
print()
print("class letters:")
for letter in rs:
    print("    {0:10} = [{1}]".format(letter["variable"], s_dot(letter["strokes"])))


# OSU CS 372 Winter 2023
# Programming Project 4 - Client Game
# Student Name: Anthony Wu
# Student ID: wuant
# Citation: Adapted from https://realpython.com/python-sockets/

import socket, pickle
from game import Board, TicTacToe

HOST = "localhost"  # The server's hostname or IP address
PORT = 3861  # The port used by the server

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    #connect thru socket
    s.connect((HOST, PORT))
    print("Connected to %s port %s" % (HOST, PORT))

    #initialize the game object
    this_game = TicTacToe()

    #choose the symbol
    player_char = this_game.get_player_char()
    this_game.board.draw_board()
    while True:
        #play the game
        this_game.get_player_input(player_char)

        #serialize the game object and send thru the socket
        s.sendall(pickle.dumps(this_game))

        #wait for turn and check if game over or tie
        if this_game.board.game_over or this_game.check_tie():
            break
        else:
            print(this_game.player_2_char + "'s turn...")
            this_game = pickle.loads(s.recv(1024))

            this_game.board.draw_board()

        #teminate if game over or tie
        if this_game.board.game_over:
            print("Game over, %s won the game" % this_game.player_2_char)
            break
        if this_game.check_tie():
            print("Game is a tie.")
            break


from Tabela import Tabela

class TabelaBD(Tabela):         #extends em Python (herança)
    def __init__(self, nome_arquivo = None):
        super().__init__(nome_arquivo)

    def conta(self, coluna):
        contagem = Tabela()
        contagem.add_cabecalho([coluna, "numero"])

        indice = 0
        for valor in self.cabecalho.dados:
            if valor == coluna:
                break
            indice += 1

        linha = 0
        for item in self.dados:
            achou = False
            contador = 0

            if linha == 0:
                for k in self.dados:
                    if self.dados[linha][indice] == k[indice]:
                        contador += 1
                contagem.dados.append([item[indice], contador])

            for j in contagem.dados:
                if j[0] == item[indice]:
                    achou = True
            if achou == False:
                for k in self.dados:
                    if self.dados[linha][indice] == k[indice]:
                        contador += 1
                contagem.dados.append([item[indice], contador])
            linha += 1

        return contagem

    def select(self, coluna, value):
        selected = Tabela()
        selected.cabecalho = self.cabecalho

        indice = 0
        for valor in self.cabecalho.dados:
            if valor == coluna:
                break
            indice += 1

        for item in self.dados:
            if item[indice] == value:
                selected.dados.append(item)

        return selected


import sys

import os

def args_to_command(*args):
    command = ""
    N = len(args)
    for index, arg in enumerate(args):
        if arg == "-s" or arg == "--save":
            if index + 1 < N and args[index + 1].startswith("-"):
                continue
            command += "/p %s" % args[index + 1]
        elif arg == "-n" or arg == "--name":
            if index + 1 < N and args[index + 1].startswith("-"):
                continue
            command += "/f %s" % args[index + 1]
    return command

def main(*args):
    com_args = args_to_command(*args)
    cli = "IDMan "

if __name__ == "__main__":
    main(*sys.argv)


napisy = []
with open("napisy.txt") as plik:
    for linia in plik:
        napisy.append(linia.split())

print("zad 72.1")

pierwszy = True
licznik = 0
for a,b in napisy:
    if len(a) * 3 <= len(b) or len(a) >= len(b) * 3:
        licznik += 1
        if pierwszy:
            print(a,b)
            pierwszy = False
print(licznik)

print("zad 72.2")

for a,b in napisy:
    if b[:len(a)] == a:
        print(a,b, b[len(a):])

print("zad 72.3")

def dl_koncowki(a, b):
    licznik = 0
    for i in range(min(len(a), len(b))):
        if a[len(a)-1-i] == b[len(b)-1-i]:
            licznik += 1
        else:
            break
    return licznik

maxx = 0
for a,b in napisy:
    maxx = max(maxx, dl_koncowki(a,b))
print(maxx)

for a,b in napisy:
    if dl_koncowki(a, b)== maxx:
        print(a,b)

print([i for i in range(5,-1,-1)])


import re
from enum import Enum
import random
import string

class Name(Enum):
    VAR = 1
    FUNC = 2

def computeIndentLevel(indentVar, line):
    """
    Inputs
        indentVar: String that represents our indentation character. Either 4 spaces or a tab character
        line: String that is the line we want the indentation level of

    Outputs
        retIndexLvl: The index level that we are at
    """
    retIndexLvl = 0
    retIndent = indentVar
    if (line[0] != ' ' and line[0] != '\t'):
        return retIndexLvl
    # We have at least one whitespace character on this line
    if (line[0] != indentVar[0]):
        fail ("inconsistent whitespace")
    # Count level of indentation
    indexLvl = 0
    while indexLvl < len(line) and (line[indexLvl] == indentVar[0]):
        indexLvl = indexLvl + 1
    # Divide by length of indent
    retIndexLvl = int(indexLvl // len(indentVar)) # Assuming no roundoff. This might be a problem it might not

    # Checking for roundoff that would lead to issues
    if (indexLvl != len(indentVar) * retIndexLvl):
        fail("Inconsistent number of spaces per line")
    return retIndexLvl

def isWhiteSpace(char):
    return char == " " or char == "\t"

def skip_end(line):
    trimmed_line = line.strip()
    return trimmed_line[:5] == "else:" or trimmed_line[:5] == "elif "

def my_hash(input):
    return ''.join(random.choices(string.ascii_uppercase + string.ascii_lowercase, k=random.randint(5,20)))

def translate(file_name, hash_varnames = False, randomized_spacing = False, doc_except = False, end_of_universe = False, increment_all = False):
    if random.random() < 1e-4:
        raise Exception("End of Universe. GG.")

    f = open(file_name)
    text = f.read()
    f.close()

    f = open("matlab.m", "w")
    lines = text.split("\n")
    indent_mode = None

    namespace = {}
    prev_depth = 0

    for line in lines:
        if not line or str.isspace(line):
            continue

        newline = line
        # count indents
        if indent_mode == None and isWhiteSpace(line[0]):
            indent_mode = " "*4 if line[0] == " " else "\t"
        my_depth = computeIndentLevel(indent_mode, line)
        gap = prev_depth - my_depth if not skip_end(line) else prev_depth - my_depth - 1
        if gap > 0:
            for i in range(gap):
                f.write("\t"*(my_depth - i + 1) + "end\n")
        prev_depth = my_depth

        # match expressions
        semicolon = True

        # increment
        if increment_all:
            num = re.compile(r"-?\d+(?P<dec>\.\d+)?", re.VERBOSE)
            for num_match in num.finditer(newline):
                start,end = num_match.span()
                if num_match["dec"] != None:
                    newline = f"{newline[:start]}{float(newline[start:end])+1}{newline[end:]}"
                else:
                    newline = f"{newline[:start]}{int(newline[start:end])+1}{newline[end:]}"

        # assignment
        assgn = re.compile(r"(?P<name>\w(\w|\_)*)\s*=", re.VERBOSE)
        assgn_match = assgn.search(newline)
        if assgn_match != None and assgn_match['name'] not in namespace:
            my_name = assgn_match['name'] if not hash_varnames else my_hash(assgn_match['name'])
            namespace[assgn_match['name']] = (Name.VAR, my_name)

        # for
        forloop = re.compile(r"for\s+(?P<name>\w(\w|\_|\d)*)\s+in\s+(?P<iter>.*):", re.VERBOSE)
        forloop_match = forloop.search(newline)
        if forloop_match != None:
            my_name = forloop_match['name'] if not hash_varnames else my_hash(forloop_match['name'])
            namespace[forloop_match['name']] = (Name.VAR, my_name)
            newline = f"for {my_name} = {forloop_match['iter']}"
            semicolon = False

        # if/else
        elseif = re.compile(r"elif\s+(?P<cond>.*):", re.VERBOSE)
        elseif_match = elseif.search(newline)
        if elseif_match != None:
            newline = f"elseif {elseif_match['cond']}"
            semicolon = False
        else:
            ifif = re.compile(r"if\s+(?P<cond>.*):", re.VERBOSE)
            ifif_match = ifif.search(newline)
            if ifif_match != None:
                newline = f"if {ifif_match['cond']}"
                semicolon = False

        elseelse = re.compile(r"else:", re.VERBOSE)
        elseelse_match = elseelse.search(newline)
        if elseelse_match != None:
            newline = "else"
            semicolon = False

        # while
        whileloop = re.compile(r"while\s+(?P<iter>.*):", re.VERBOSE)
        whileloop_match = whileloop.search(newline)
        if whileloop_match != None:
            newline = f"while {whileloop_match['iter']}"
            semicolon = False

        # function def
        func = re.compile(r"def\s+(?P<name>\w(\w|\_|\d)*)\((?P<args>.*)\):", re.VERBOSE)
        func_match = func.search(newline)
        if func_match != None:
            new_name = func_match['name'] if not hash_varnames else my_hash(func_match['name'])
            namespace[func_match['name']] = (Name.FUNC, new_name)
            newline = f"function {new_name}({func_match['args']})"
            semicolon = False

        # range
        rangere = re.compile(r"[^a-zA-Z_]range\(\s*(?P<start>[^,]+)(,\s*(?P<stop>[^,]+))?(,\s*(?P<step>[^,]+))?\)", re.VERBOSE)
        for rangere_match in rangere.finditer(newline):
            start, end = rangere_match.span()
            if rangere_match["step"] != None:
                newline = f"{newline[:start+1]}{rangere_match['start']}:{rangere_match['step']}:{rangere_match['stop']}{newline[end:]}"
            elif rangere_match["stop"] != None:
                newline = f"{newline[:start+1]}{rangere_match['start']}:{rangere_match['stop']}{newline[end:]}"
            else:
                newline = f"{newline[:start+1]}1:{rangere_match['start']}{newline[end:]}"

        # indexing arr[1] (and + 1 to index)
        index = re.compile(r"(\w|\_|\d)\[(?P<ind>.+?)\]", re.VERBOSE)
        for index_match in index.finditer(newline):
            adder = " + 1" if not increment_all else ""
            newline = newline.replace("[" + index_match['ind'] + "]",  "(" + index_match['ind'] + adder + ")")

        # f.write -> disp
        disp = re.compile(r"print(ln)?\((?P<str>.*)\)", re.VERBOSE)
        disp_match = disp.search(newline)
        if disp_match != None:
            newline = f"disp({disp_match['str']})"
            semicolon = False

        # ** -> ^
        newline = newline.replace("**", "^")

        # != -> ~=
        newline = newline.replace("!=", "~=")

        # comments
        if doc_except and "#" in newline:
            raise Exception("Documentation Exception: real programmers don't document things")
        newline = newline.replace("#", "%")

        # replace variable names
        if hash_varnames:
            for name in namespace:
                namere = re.compile(r"([^\w\_\d]|^)"+name+r"([^\w\_\d]|$)", re.VERBOSE)
                for name_match in namere.finditer(newline):
                    start,end = name_match.span()
                    newline = f"{newline[:start]}{newline[start:end].replace(name, namespace[name][1])}{newline[end:]}"

        if semicolon:
            newline = newline + ";"

        if randomized_spacing:
            space = " "*int(random.random()*20)
            f.write(space)
        else:
            f.write("\t"*prev_depth)
        f.write(newline.strip()+"\n")

    for i in range(prev_depth):
        f.write("\t"*(prev_depth-i-1)+"end\n")
    f.close()

translate("test.txt", hash_varnames=True, randomized_spacing=True, doc_except=False, end_of_universe=True, increment_all=True)


import sys
from pathlib import Path

import torch
from torch import nn

from element import Conv

ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
    sys.path.append(str(ROOT))

from utils import set_grid

class DetectLayer(nn.Module):
    def __init__(self, input_size, in_channels, num_classes, anchors, stride):
        super().__init__()
        self.stride = stride
        self.anchors = anchors
        self.num_anchors = len(anchors)
        self.num_attributes = 1 + 4 + num_classes
        self.conv = Conv(in_channels, in_channels*2, kernel_size=3, padding=1, act="leaky_relu")
        self.detect = nn.Conv2d(in_channels*2, self.num_attributes*self.num_anchors, kernel_size=1, padding=0)
        self.set_grid_xy(input_size=input_size)

    def forward(self, x):
        self.device = x.device
        bs = x.shape[0]

        out = self.conv(x)
        out = self.detect(out)
        out = out.permute(0, 2, 3, 1).flatten(1, 2).view((bs, -1, self.num_anchors, self.num_attributes))

        pred_obj = torch.sigmoid(out[..., :1])
        pred_box_txty = torch.sigmoid(out[..., 1:3])
        pred_box_twth = out[..., 3:5]
        pred_cls = out[..., 5:]

        if self.training:
            return torch.cat((pred_obj, pred_box_txty, pred_box_twth, pred_cls), dim=-1)
        else:
            pred_box = self.transform_pred_box(torch.cat((pred_box_txty, pred_box_twth), dim=-1))
            pred_score = pred_obj * torch.sigmoid(pred_cls)
            pred_score, pred_label = pred_score.max(dim=-1)
            pred_out = torch.cat((pred_score.unsqueeze(-1), pred_box, pred_label.unsqueeze(-1)), dim=-1)
            return pred_out.flatten(1, 2)

    def transform_pred_box(self, pred_box):
        xc = (pred_box[..., 0] + self.grid_x.to(self.device)) / self.grid_size
        yc = (pred_box[..., 1] + self.grid_y.to(self.device)) / self.grid_size
        w = torch.exp(pred_box[..., 2]) * self.anchors[:, 0].to(self.device)
        h = torch.exp(pred_box[..., 3]) * self.anchors[:, 1].to(self.device)
        return torch.stack((xc, yc, w, h), dim=-1)

    def set_grid_xy(self, input_size):
        self.grid_size = input_size // self.stride
        grid_x, grid_y = set_grid(grid_size=self.grid_size)
        self.grid_x = grid_x.contiguous().view((1, -1, 1))
        self.grid_y = grid_y.contiguous().view((1, -1, 1))

class YoloHead(nn.Module):
    def __init__(self, input_size, in_channels, num_classes, anchors):
        super().__init__()
        anchors = torch.tensor(anchors) if not torch.is_tensor(anchors) else anchors
        self.detect_s = DetectLayer(input_size=input_size, in_channels=in_channels[0]//2, num_classes=num_classes, anchors=anchors[0:3], stride=8)
        self.detect_m = DetectLayer(input_size=input_size, in_channels=in_channels[1]//2, num_classes=num_classes, anchors=anchors[3:6], stride=16)
        self.detect_l = DetectLayer(input_size=input_size, in_channels=in_channels[2]//2, num_classes=num_classes, anchors=anchors[6:9], stride=32)

    def forward(self, x):
        C1, C2, C3 = x
        pred_s = self.detect_s(C3)
        pred_m = self.detect_m(C2)
        pred_l = self.detect_l(C1)
        return pred_s, pred_m, pred_l

if __name__ == "__main__":
    from backbone import build_backbone
    from neck import FPN

    input_size = 320
    num_classes = 1

    anchors = [[0.248,      0.7237237 ],
                [0.36144578, 0.53      ],
                [0.42,       0.9306667 ],
                [0.456,      0.6858006 ],
                [0.488,      0.8168168 ],
                [0.6636637,  0.274     ],
                [0.806,      0.648     ],
                [0.8605263,  0.8736842 ],
                [0.944,      0.5733333 ]]

    backbone, feat_dims = build_backbone()
    neck = FPN(feat_dims=feat_dims)
    head = YoloHead(input_size=input_size, in_channels=feat_dims, num_classes=num_classes, anchors=anchors)

    x = torch.randn(1, 3, input_size, input_size)
    ftrs = backbone(x)
    ftrs = neck(ftrs)
    preds = head(ftrs)
    for pred in preds:
        print(pred.shape)

    head.eval()
    preds = head(ftrs)
    for pred in preds:
        print(pred.shape)


import logging
from typing import Dict

from fastapi import APIRouter, Depends
from sqlalchemy import func

from fetcher.database import Session
from fetcher.database.models import Story

import server.auth as auth
from server.util import as_timeseries_data, api_method, TimeSeriesData

DEFAULT_DAYS = 30

logger = logging.getLogger(__name__)

router = APIRouter(
    prefix="/api/stories",
    tags=["stories"],
)

@router.get("/fetched-by-day", dependencies=[Depends(auth.read_access)])
@api_method
def stories_fetched_counts() -> TimeSeriesData:
    return as_timeseries_data(
        [Story.recent_published_volume(limit=DEFAULT_DAYS)],
        ["stories"]
    )

@router.get("/published-by-day", dependencies=[Depends(auth.read_access)])
@api_method
def stories_published_counts() -> TimeSeriesData:
    return as_timeseries_data(
        [Story.recent_fetched_volume(limit=DEFAULT_DAYS)],
        ["stories"]
    )

@router.get("/by-source", dependencies=[Depends(auth.read_access)])
@api_method
def stories_by_source() -> Dict[str, object]:
    with Session() as session:
        # XXX could take a few seconds; async/await would be ideal!
        counts = session.query(Story.sources_id.label('sources_id'),
                               func.count(Story.id).label('count'))\
            .group_by(Story.sources_id)
        dates = session.query(func.max(Story.fetched_at).label('max'),
                              func.min(Story.fetched_at).label('min')).one()
        min = dates['min'].timestamp()
        max = dates['max'].timestamp()
        SECONDS_PER_DAY = 26 * 60 * 60

        # Return time span of data separately, and let the caller deal
        # with scaling; this call is slow as-is, and floating point
        # encode/decode is slow, and would yield a larger message,
        # and json decode is also slow.
        return {
            'days': (max - min) / SECONDS_PER_DAY,
            'sources': [dict(count) for count in counts]
        }


# testing ES whg index updating
from django.conf import settings
from django.shortcuts import render, get_object_or_404
import simplejson as json
import codecs, tempfile, os, re, sys, math
import pandas as pd
from places.models import *
from datasets.models import Dataset, Hit, DatasetFile
from datasets.utils import validate_lpf, validate_tsv
from elasticsearch7 import Elasticsearch
from elastic.es_utils import makeDoc, fetch_pids
es = settings.ES_CONN
idx='whg'

dsid=586 # 'diamonds' current file: user_whgadmin/diamonds135_rev3_g6cvm1l.tsv
# start: diamonds135_rev3; proposed update: diamonds135_rev21-125
ds = get_object_or_404(Dataset,pk=dsid)
[keepg,keepl]=[True,True]
oldids = list(Place.objects.filter(dataset=ds.label).values_list('src_id',flat=True))
curfile = 'user_whgadmin/diamonds135_hfl3svn.tsv'
# post tgn recon: 135 places, 135 names, 10 links, 25 geoms
newfile = 'user_whgadmin/diamonds135_rev2a-125.tsv'
tempfile = '/var/folders/f4/x09rdl7n3lg7r7gwt1n3wjsr0000gn/T/tmpwb8q_u5i.tsv'
#adf = pd.read_csv('media/'+curfile, delimiter='\t',dtype={'id':'str','ccodes':'str'})
#bdf = pd.read_csv(newfile, delimiter='\t',dtype={'id':'str','ccodes':'str'})

adf = pd.read_csv('media/'+curfile, delimiter='\t',dtype={'id':'str','ccodes':'str'})
bdf = pd.read_csv(tempfile, delimiter='\t',dtype={'id':'str','ccodes':'str'})
bdf = bdf.astype({"ccodes": str})

ids_a = adf['id'].tolist(); print(len(ids_a)) #135
ids_b = bdf['id'].tolist(); print(len(ids_b)) #125
#
delete_srcids = [str(x) for x in (set(ids_a)-set(ids_b))]
replace_srcids = set.intersection(set(ids_b),set(ids_a))
places = Place.objects.filter(dataset=ds.label)
rows_delete = list(places.filter(src_id__in=delete_srcids).values_list('id',flat=True));
rows_replace = list(places.filter(src_id__in=replace_srcids).values_list('id',flat=True));
rows_add=[str(x) for x in (set(ids_b)-set(ids_a))];
print('del',len(rows_delete),'replace',len(rows_replace),'add',len(rows_add) )

# DATABASE actions
# delete places with ids missing in new data (CASCADE includes links & geoms)
places.filter(id__in=rows_delete).delete()

ncount=PlaceName.objects.filter(place_id__in=places).count() # 134
gcount=PlaceGeom.objects.filter(place_id__in=places).count() # 17
lcount=PlaceLink.objects.filter(place_id__in=places).count() # 3
print(ncount,gcount,lcount) #123 23 9
# delete related instances for the rest (except links and geoms)
PlaceName.objects.filter(place_id__in=places).delete()
PlaceType.objects.filter(place_id__in=places).delete()
PlaceWhen.objects.filter(place_id__in=places).delete()
PlaceDescription.objects.filter(place_id__in=places).delete()
PlaceDepiction.objects.filter(place_id__in=places).delete()
#
ncount=PlaceName.objects.filter(place_id__in=places).count() # 134
gcount=PlaceGeom.objects.filter(place_id__in=places).count() # 17
lcount=PlaceLink.objects.filter(place_id__in=places).count() # 3
print(ncount,gcount,lcount) #0 23 9

# keep links and/or geoms is a form choice (keepg, keepl)
# rows created during reconciliation review have a task_id
if keepg == 'false':
  # keep none (they are being replaced in update)
  PlaceGeom.objects.filter(place_id__in=places).delete()
else:
  # keep augmentation rows; delete the rest
  PlaceGeom.objects.filter(place_id__in=places,task_id=None).delete()
if keepl == 'false':
  # keep none (they are being replaced in update)
  PlaceLink.objects.filter(place_id__in=places).delete()
else:
  PlaceLink.objects.filter(place_id__in=places,task_id=None).delete()

ncount=PlaceName.objects.filter(place_id__in=places).count() # 134
gcount=PlaceGeom.objects.filter(place_id__in=places).count() # 17
lcount=PlaceLink.objects.filter(place_id__in=places).count() # 3
print(ncount,gcount,lcount) #0 9 9 (augment geoms & links retained)

# Place instances to be kept remain, related are gone
ds.places.count() #123

# now update values in places; recreate place_xxxxx rows
# from ds_update line 676-714
count_updated, count_new = [0,0]
# update remaining place instances w/data from new file
# AND add new
from datasets.views import add_rels_tsv
place_fields = {'id', 'title', 'ccodes'}
for index, row in bdf.iterrows():
  rd = row.to_dict()
  rdp = {key:rd[key] for key in place_fields}
  # look for corresponding current place
  p = places.filter(src_id=rdp['id']).first()
  if p != None:
    # place exists, update it
    count_updated +=1
    p.title = rdp['title']
    p.ccodes = [] if str(rdp['ccodes']) == 'nan' else rdp['ccodes'].replace(' ','').split(';')
    p.save()
    #print('updated '+str(p.id)+', add related from '+str(rdrels))
    pobj = p
  else:
    # if not, entirely new place
    count_new +=1
    newpl = Place.objects.create(
      src_id = rdp['id'],
      title = re.sub('\(.*?\)', '', rdp['title']),
      ccodes = rdp['ccodes'].replace(' ','').split(';'),
      dataset = ds
    )
    newpl.save()
    pobj = newpl
    #print('new place, related:', newpl, rdrels)

  # create related records (place_name, etc)
  # pobj is either a current (now updated) place or entirely new
  # rd is row dict
  add_rels_tsv(pobj, rd)

pcount=ds.places.count()
ncount=PlaceName.objects.filter(place_id__in=places).count() # 134
gcount=PlaceGeom.objects.filter(place_id__in=places).count() # 17
lcount=PlaceLink.objects.filter(place_id__in=places).count() # 3
print(pcount,ncount,gcount,lcount) # 125 125 24 9
# 2 new rows, all w/names, 15+9 geoms, 9 links CHECK

# END DATABASE actions

# ES STUFF
# fetch place_ids for all docs in a dataset

pids = fetch_pids('diamonds')
# strip indexed places by Place.id; pids = place_id array
def deleteFromIndex(pids):
  if len(pids) > 0:
    delthese=[]
    # child: 6293916; parent with children: 13549548; parent w/no children 6293837
    for pid in pids:
      # get its index document
      res = es.search(index=idx, body=esq_pid(pid))
      doc = res['hits']['hits'][0]
      src = doc['_source']
      role = src['relation']['name']; print(role)
      sugs = list(set(src['suggest']['input'])) # distinct only
      searchy = list(set([item for item in src['searchy'] if type(item) != list]))
      # role-dependent action
      if role == 'parent':
        # convert to integers
        # kids = ['5991423', '85196', '83140', '82439']
        kids = [int(x) for x in src['children']]
        eligible = list(set(kids)-set(pids)) # not slated for deletion
        if len(eligible) == 0:
          # add to array for deletion
          print('childless parent '+str(pid)+' tagged for deletion')
          delthese.append(pid)
        else:
          # > 0 eligible children, first promote one to parent
          # TODO: can we make a logical choice?
          newparent = eligible[0]
          newkids = eligible.pop(newparent)
          # get its index record and update it:
          # make it a parent, give it a whg_id - _id,
          # update its sugs and searchy
          # update its children with newkids
          qget = {"query": {"bool": {"must": [{"match":{"place_id": newparent }}]}}}
          res = es.search(index=idx, body=qget)
          hit = res['hits']['hits'][0]
          _id = hit['_id']
          # elevate to parent
          q_update = {"script":{
            "source": "ctx._source.whg_id = params._id; \
              ctx._source.relation.name = 'parent'; \
              ctx._source.relation.remove('parent'); \
              ctx._source.children.addAll(params.newkids); \
              ctx._source.suggest.input.addAll(params.sugs); \
              ctx._source.searchy.addAll(params.sugs);",
            "lang": "painless",
            "params":{"_id": _id, "newkids": newkids, "sugs": sugs }
            },
            "query": {"match":{"place_id": newparent }}
          }
          try:
            es.update_by_query(index=idx,body=q_update)
          except:
            print('aw shit',sys.exit(sys.exc_info()))
          # parent status transfered to 'eligible' child, add to list
          print('parent w/kids '+hit['_source']['title'],pid+' transferred resp to: '+parent+'; tagged for deletion')
          delthese.append(pid)
      elif role == 'child':
        # get its parent
        parent = src['relation']['parent']
        qget = {"query": {"bool": {"must": [{"match":{"_id": parent }}]}}}
        res = es.search(index=idx, body=qget)
        # parent _source, suggest, searchy
        psrc = res['hits']['hits'][0]['_source']
        psugs = list(set(psrc['suggest']['input']))
        psearchy = list(set([item for item in psrc['searchy'] if type(item) != list]))
        # is parent slated for deletion? (walking dead)
        zombie = psrc['place_id'] in pids
        if not zombie: # skip zombies here; picked up above with if role == 'parent':
          # remove this id from children and remove its variants (sugs) from suggest.input and searchy
          newsugs = list(set(psugs)-set(sugs))
          newsearchy = list(set(psearchy)-set(searchy))
          q_update = {"script":{
            "source": "ctx._source.children.remove(ctx._source.children.indexOf(params.val)); \
                ctx._source.suggest.input = params.sugs; ctx._source.searchy = params.searchy;",
            "lang": "painless",
            "params":{"val": str(pid), "sugs": newsugs, "searchy": newsearchy }
            },
            "query": {"match":{"_id": parent }}
          }
          try:
            es.update_by_query(index=idx,body=q_update)
            print('child '+psrc['title'],pid+' excised from parent: '+parent+'; tagged for deletion')
          except:
            print('aw shit',sys.exit(sys.exc_info()))
        # child's presence in parent removed, add to delthese[]
        delthese.append(pid)
    es.delete_by_query(index=idx, body={"query": {"terms": {"place_id": delthese}}})
    print('deleted '+len(delthese)+': '+str(delthese))

# ES ACTIONS (database now current)
# 1) delete records in rows_delete[]
# 2) update records in rows_replace[]
# defer indexing new records in rows_add until reconciled

if len(rows_delete) > 0:
  for r in rows_delete:
    res = es.search(index=idx, body=esq_pid(r))
    doc = res['hits']['hits'][0]
    print(doc)

# delete from rows_delete
qdel = {}

# update from rows_replace
print(len(rows_replace),rows_replace)
qrepl = {}

# get db record
place = get_object_or_404(Place, pk=pid)

# make an ES doc for it
#pdoc = makeDoc(place,'none')
pdoc = makeDoc(place)

# find it in the index, if exists
qget = {"query": {"bool": {"must": [{"match":{"place_id": pid }}]}}}
res = es.search(index=idx, body=qget)
hits = res['hits']['hits']

if len(hits) > 0: # if indexed
  # if child get parent's _id else self._id
  if hits[0]['_source']['relation']['name'] == 'child':
    parent_whgid = res['hits']['hits'][0]['_source']['relation']['parent']
  else:
    parent_whgid = res['hits']['hits'][0]['_id'] #; print(parent_whgid)
else:
  pass

# 1) matches parent_whgid
# 2) adds str(place.id) to its children[]
# 3) adds match_names[] values to its suggest field
q_update = { "script": {
    "source": "ctx._source.suggest.input.addAll(params.names); ctx._source.children.add(params.id)",
    "lang": "painless",
    "params":{"names": match_names, "id": str(place.id)}
  },
  "query": {"match":{"_id": parent_whgid}}}
es.update_by_query(index=idx, body=q_update, conflicts='proceed')

# DELETE algorithm
# for r in rows_delete:
#  get doc from ES
#    if doc._source.relation.name = 'parent'
#      if len(_source.children) > 0
#         make first a parent and any siblings children
#         delete doc
#      else
#         delete doc
#    else if doc._source.relation.name = 'child'
#      get its doc._source.relation.parent
#      remove pid from its children[] list
#      delete doc

# REPLACE algorithm
# for r in rows_replace:
#   get doc from ES
#    if doc._source.relation.name = 'parent'
#
#
#
#
#
#    else if doc._source.relation.name = 'child'
#
#
#
#

  ## FILES (new has been validated [0], current became [1])
  #cur_fileobj = DatasetFile.objects.filter(dataset_id_id=dsid).order_by('-upload_date')[1]
  #cur_filename = cur_fileobj.file.name
  #cur_uribase = cur_fileobj.uri_base
  #new_fileobj = DatasetFile.objects.filter(dataset_id_id=dsid).order_by('-upload_date')[0]
  #new_filename = new_fileobj.file.name
  #new_uribase = new_fileobj.uri_base


from odoo import api, fields, models, _
from odoo.exceptions import UserError

class AccountAnalyticAccount(models.Model):
    _inherit = 'account.analytic.account'
    _description = 'Analytic Account'

    project_ids = fields.One2many('project.project', 'analytic_account_id', string='Projects')
    project_count = fields.Integer("Project Count", compute='_compute_project_count')

    @api.depends('project_ids')
    def _compute_project_count(self):
        project_data = self.env['project.project']._read_group([('analytic_account_id', 'in', self.ids)], ['analytic_account_id'], ['__count'])
        mapping = {analytic_account.id: count for analytic_account, count in project_data}
        for account in self:
            account.project_count = mapping.get(account.id, 0)

    @api.ondelete(at_uninstall=False)
    def _unlink_except_existing_tasks(self):
        projects = self.env['project.project'].search([('analytic_account_id', 'in', self.ids)])
        has_tasks = self.env['project.task'].search_count([('project_id', 'in', projects.ids)])
        if has_tasks:
            raise UserError(_('Please remove existing tasks in the project linked to the accounts you want to delete.'))

    def action_view_projects(self):
        kanban_view_id = self.env.ref('project.view_project_kanban').id
        result = {
            "type": "ir.actions.act_window",
            "res_model": "project.project",
            "views": [[kanban_view_id, "kanban"], [False, "form"]],
            "domain": [['analytic_account_id', '=', self.id]],
            "context": {"create": False},
            "name": _("Projects"),
        }
        if len(self.project_ids) == 1:
            result['views'] = [(False, "form")]
            result['res_id'] = self.project_ids.id
        return result


#!/usr/bin/env python3
""" calculates the weighted moving average of a data set """

def moving_average(data, beta):
    """
        data is the list of data to calculate the moving average of
        beta is the weight used for the moving average
    """
    moving = []
    V = 0
    for i in range(1, len(data) + 1):
        fix = ((beta * V) + ((1 - beta) * data[i - 1])) / (1 - (beta ** i))
        moving.append(fix)
        V = ((beta * V) + ((1 - beta) * data[i - 1]))
    return moving


import sys

class Node:
    def __init__(self, value:int):
        self.value:int = value
        self.sum:int = value

    def sequence(self):
        node = self
        while node is not None:
            yield node.value
            node = node.parent

N = int(sys.stdin.readline())
A = [Node(Ai) for Ai in map(int, sys.stdin.readline().split())]

for current in range(N):
    for parent in range(current+1):
        if not (A[parent].value < A[current].value):
            continue
        if A[parent].sum > (A[current].sum - A[current].value):
            A[current].sum = A[parent].sum + A[current].value

print(max(A, key=lambda node: node.sum).sum)

Baekjoon Online Judge/problem/11055/26835472 맞았습니다!! 28776 KB 276 ms.py.py


import re

from behave import *

from pysteel import command

@given(u'you have UAA Client {version} installed')
def step_impl(context, version):
    """
    :type context: behave.runner.Context
    :type version: str
    """
    cmd = command.Command(context, "uaac --version")
    cmd.run()
    actual = cmd.stdout
    actual.should.match(r'{}.*'.format(version))

@given(u'you have CloudFoundry service {service} installed')
def step_impl(context, service):
    """
    :type context: behave.runner.Context
    :type service: str
    """
    cmd = command.Command(context, "cf marketplace")
    cmd.run()
    actual = cmd.stdout
    actual.should.match(r'^{}\s'.format(service), re.MULTILINE)


# import get_float from cs50 library
from cs50 import get_float

# prompt user for positive value
while True:
    print("What is the change owed?")
    change = get_float()

    # keep prompting user until we get a positive value
    if(change > 0):
        break

# multiply change by 100 to work with non decimal values
change = round(change * 100)
coins = 0

# count quarters until change < 25
while(change >= 25):

    # keep track of coins given and update change
    coins += 1
    change -= 25

# count dimes until change < 10
while(change >= 10):

    # keep track of coins given and update change
    coins += 1
    change -= 10

# count five cents until change < 5
while(change >= 5):

    # keep track of coins given and update change
    coins += 1
    change -= 5

# count cents until change = 0
while(change >= 1):

    # keep track of coins given and update change
    coins += 1
    change -= 1

# print minimum number of coins required to give a user change.
print(coins)


#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2022/10/22 21:10
# @Author  : HuntingGame
# @FileName: 945. 使数组唯一的最小增量.py
# @Software: PyCharm
# C'est la vie. Enjoy ur day ! :D
from typing import List

class Solution:
    def minIncrementForUnique(self, nums: List[int]) -> int:
        nums.sort()
        ans = 0
        if len(nums) == 1:
            return 0
        for i in range(1,len(nums)):
            if nums[i] == nums[i-1]:
                ans +=1
                nums[i] +=1
            elif nums[i] < nums[i-1]:
                ans +=nums[i-1] - nums[i]+1
                nums[i] = nums[i-1] + 1

        return ans

计数/945. 使数组唯一的最小增量.py

945. 使数组唯一的最小增量.py


import os
import re
import pandas as pd
from tqdm import trange, tnrange
import torch as T
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader
from bert4rec_dataset import Bert4RecDataset
from bert4rec_model import RecommendationModel, RecommendationTransformer
from rich.table import Column, Table
from rich import box
from rich.console import Console
from torch import cuda
from train_validate import train_step, validate_step
from sklearn.model_selection import train_test_split
from AttentionTransformer.ScheduledOptimizer import ScheduledOptimizer
from IPython.display import clear_output
from AttentionTransformer.utilities import count_model_parameters
import random
import numpy as np

device = T.device('cuda') if cuda.is_available() else T.device('cpu')

def trainer(data_params,
            model_params,
            loggers,
            optimizer_params=None,
            warmup_steps=False,
            output_dir="./models/",
            modify_last_fc=False,
            validation=5):

    # console instance

    console = loggers.get("CONSOLE")

    # tables
    train_logger = loggers.get("TRAIN_LOGGER")
    valid_logger = loggers.get("VALID_LOGGER")

    # check if output_dir/model_files available; if not create
    if not os.path.exists(output_dir):
        console.log(f"OUTPUT DIRECTORY DOES NOT EXIST. CREATING...")
        os.mkdir(output_dir)
        os.mkdir(os.path.join(output_dir, "model_files"))
        os.mkdir(os.path.join(output_dir, "model_files_initial"))
    else:
        console.log(f"OUTPUT DIRECTORY EXISTS. CHECKING CHILD DIRECTORY...")
        if not os.path.exists(os.path.join(output_dir, "model_files")):
            os.mkdir(os.path.join(output_dir, "model_files"))
            os.mkdir(os.path.join(output_dir, "model_files_initial"))

    # seed
    console.log("SEED WITH: ", model_params.get("SEED"))
    T.manual_seed(model_params["SEED"])
    T.cuda.manual_seed(model_params["SEED"])
    np.random.seed(model_params.get("SEED"))
    random.seed(model_params.get("SEED"))

    T.backends.cudnn.deterministic = True

    # intialize model
    console.log("MODEL PARAMS: ", model_params)
    console.log("INITIALIZING MODEL: ", model_params)
    model = RecommendationTransformer(
        vocab_size=model_params.get("VOCAB_SIZE"),
        heads=model_params.get("heads", 4),
        layers=model_params.get("layers", 6),
        emb_dim=model_params.get("emb_dim", 512),
        pad_id=model_params.get("pad_id", 0),
        num_pos=model_params.get("history", 120))

    # model.encoder.sou
    if model_params.get("trained"):
        #   load the already trained model
        console.log("TRAINED MODEL AVAILABLE. LOADING...")
        model.load_state_dict(
            T.load(model_params.get("trained"))["state_dict"])
        console.log("MODEL LOADED")
    console.log(f'MOVING MODEL TO DEVICE: {device}')

    if modify_last_fc:

        new_word_embedding = nn.Embedding(model_params.get("NEW_VOCAB_SIZE"),
                                          model_params.get("emb_dim"), 0)
        new_word_embedding.weight.requires_grad = False
        console.log(
            f"REQUIRES GRAD for `NEW WORD EMBEDDING` set to {new_word_embedding.weight.requires_grad}"
        )

        new_word_embedding.weight[:model.encoder.word_embedding.weight.size(
            0)] = model.encoder.word_embedding.weight.clone().detach()

        model.encoder.word_embedding = new_word_embedding
        # model.encoder.word_embedding.weight.retain_grad()
        console.log(
            f"WORD EMBEDDING MODIFIED TO `{model.encoder.word_embedding}`")

        # console.log(
        #     f"WORD EMBEDDING REQUIRES GRAD `{model.encoder.word_embedding.weight.requires_grad}`"
        # )
        model.encoder.word_embedding.weight.requires_grad = True
        new_lin_layer = nn.Linear(model_params.get("emb_dim"),
                                  model_params.get("NEW_VOCAB_SIZE"))
        new_lin_layer.weight.requires_grad = False
        new_lin_layer.weight[:model.lin_op.weight.
                             size(0)] = model.lin_op.weight.clone().detach()
        model.lin_op = new_lin_layer
        # model.lin_op.weight.retain_grad()
        model.lin_op.weight.requires_grad = True
        console.log("MODEL LIN OP: ", model.lin_op.out_features)

    model = model.to(device)

    console.log(
        f"TOTAL NUMBER OF MODEL PARAMETERS: {round(count_model_parameters(model)/1e6, 2)} Million"
    )

    # if warmup_steps:
    #     optimizer = ScheduledOptimizer(
    #         T.optim.SGD(params=model.parameters(),
    #                     lr=model_params.get("LEARNING_RATE"),
    #                     momentum=0.8,
    #                     nesterov=True), 1e-6, model_params.get("emb_dim"))
    # else:
    optim_name = optimizer_params.get("OPTIM_NAME")
    if optim_name == "SGD":
        optimizer = T.optim.SGD(params=model.parameters(),
                                **optimizer_params.get("PARAMS"))
    elif optim_name == "ADAM":
        optimizer = T.optim.Adam(params=model.parameters(),
                                 **optimizer_params.get("PARAMS"))

    else:
        optimizer = T.optim.SGD(params=model.parameters(),
                                lr=model_params.get("LEARNING_RATE"),
                                momentum=0.8,
                                nesterov=True)

    if warmup_steps:
        optimizer = ScheduledOptimizer(optimizer, 1e-6,
                                       model_params.get("emb_dim"))

    console.log("OPTIMIZER AND MODEL DONE")

    console.log("CONFIGURING DATASET AND DATALOADER")
    console.log("DATA PARAMETERS: ", data_params)
    data = pd.read_csv(data_params.get("path"))
    train_data, valid_data = train_test_split(
        data, test_size=0.25, random_state=model_params.get("SEED"))

    console.log("LEN OF TRAIN DATASET: ", len(train_data))
    console.log("LEN OF VALID DATASET: ", len(valid_data))

    train_dataset = Bert4RecDataset(train_data,
                                    data_params.get("group_by_col"),
                                    data_params.get("data_col"),
                                    data_params.get("train_history", 120),
                                    data_params.get("valid_history", 5),
                                    data_params.get("padding_mode",
                                                    "right"), "train",
                                    data_params.get("threshold_column"),
                                    data_params.get("threshold"),
                                    data_params.get("timestamp_col"))
    train_dl = DataLoader(train_dataset,
                          **data_params.get("LOADERS").get("TRAIN"))
    # if validation:
    #     valid_dataset = Bert4RecDataset(
    #         valid_data, data_params.get("group_by_col"),
    #         data_params.get("data_col"), data_params.get("train_history", 120),
    #         data_params.get("valid_history", 5),
    #         data_params.get("padding_mode", "right"), "valid")
    console.save_text(os.path.join(output_dir,
                                   "logs_model_initialization.txt"),
                      clear=True)
    # if full_train:
    #     train_dl = DataLoader(train_dataset + valid_dataset,
    #                           **data_params.get("LOADERS").get("TRAIN"))
    # else:
    # train_dl = DataLoader(train_dataset,
    #                       **data_params.get("LOADERS").get("TRAIN"))

    # if validation:
    #     valid_dl = DataLoader(valid_dataset,
    #                           **data_params.get("LOADERS").get("VALID"))

    # if full_train:
    #     train_dl += valid_dl

    losses = []
    for epoch in tnrange(1, model_params.get("EPOCHS") + 1):
        # train_dataset = Bert4RecDataset(
        #     train_data, data_params.get("group_by_col"),
        #     data_params.get("data_col"), data_params.get("train_history", 120),
        #     data_params.get("valid_history", 5),
        #     data_params.get("padding_mode", "right"), "train")
        # train_dl = DataLoader(train_dataset,
        #                       **data_params.get("LOADERS").get("TRAIN"))
        if epoch % 3 == 0:
            clear_output(wait=True)
        train_loss, train_acc = train_step(model, device, train_dl,
                                           optimizer, warmup_steps,
                                           data_params.get("MASK"),
                                           model_params.get("CLIP"),
                                           data_params.get("chunkify"))
        train_logger.add_row(str(epoch), str(train_loss), str(train_acc))

        console.log(train_logger)

        if epoch == 1:
            console.log(f"Saving Initial Model")
            T.save(
                model,
                os.path.join(output_dir, "model_files_initial",
                             model_params.get("SAVE_NAME")))
            T.save(
                dict(state_dict=model.state_dict(),
                     epoch=epoch,
                     train_loss=train_loss,
                     train_acc=train_acc,
                     optimizer_dict=optimizer._optimizer.state_dict()
                     if warmup_steps else optimizer.state_dict()),
                os.path.join(output_dir, "model_files_initial",
                             model_params.get("SAVE_STATE_DICT_NAME")))

        if epoch > 1 and min(losses) > train_loss:
            console.log("SAVING BEST MODEL AT EPOCH -> ", epoch)
            console.log("LOSS OF BEST MODEL: ", train_loss)
            console.log("ACCURACY OF BEST MODEL: ", train_acc)
            T.save(
                model,
                os.path.join(output_dir, "model_files",
                             model_params.get("SAVE_NAME")))
            T.save(
                dict(state_dict=model.state_dict(),
                     epoch=epoch,
                     train_acc=train_acc,
                     train_loss=train_loss,
                     optimizer_dict=optimizer._optimizer.state_dict()
                     if warmup_steps else optimizer.state_dict()),
                os.path.join(output_dir, "model_files",
                             model_params.get("SAVE_STATE_DICT_NAME")))

        losses.append(train_loss)

        if validation and epoch > 1 and epoch % validation == 0:
            valid_dataset = Bert4RecDataset(
                valid_data, data_params.get("group_by_col"),
                data_params.get("data_col"),
                data_params.get("train_history", 120),
                data_params.get("valid_history", 5),
                data_params.get("padding_mode", "right"), "valid")
            valid_dl = DataLoader(valid_dataset,
                                  **data_params.get("LOADERS").get("VALID"))
            valid_loss, valid_acc = validate_step(model, valid_dl, device,
                                                  data_params.get("MASK"))

            valid_logger.add_row(str(epoch), str(valid_loss), str(valid_acc))
            console.log(valid_logger)

            del valid_dataset, valid_dl

            console.log("VALIDATION DONE AT EPOCH ", epoch)

            console.save_text(os.path.join(output_dir, "logs_training.txt"),
                              clear=True)
        console.save_text(os.path.join(output_dir, "logs_training.txt"),
                          clear=True)


from collections import defaultdict

from django.contrib.contenttypes.models import ContentType
from guardian.shortcuts import (
    assign_perm,
    remove_perm,
    get_perms,
    get_users_with_perms)

from onadata.apps.api.models import OrganizationProfile
from onadata.apps.main.models.user_profile import UserProfile
from onadata.apps.logger.models import XForm
from onadata.apps.api.models import Project

# Userprofile Permissions
CAN_ADD_USERPROFILE = 'add_userprofile'
CAN_CHANGE_USERPROFILE = 'change_userprofile'
CAN_DELETE_USERPROFILE = 'delete_userprofile'
CAN_ADD_XFORM_TO_PROFILE = 'can_add_xform'
CAN_VIEW_PROFILE = 'view_profile'

# Organization Permissions
CAN_VIEW_ORGANIZATION_PROFILE = 'view_organizationprofile'
CAN_ADD_ORGANIZATION_PROFILE = 'add_organizationprofile'
CAN_ADD_ORGANIZATION_XFORM = 'can_add_xform'
CAN_CHANGE_ORGANIZATION_PROFILE = 'change_organizationprofile'
CAN_DELETE_ORGANIZATION_PROFILE = 'delete_organizationprofile'
IS_ORGANIZATION_OWNER = 'is_org_owner'

# Xform Permissions
CAN_CHANGE_XFORM = 'change_xform'
CAN_ADD_XFORM = 'add_xform'
CAN_DELETE_XFORM = 'delete_xform'
CAN_VIEW_XFORM = 'view_xform'
CAN_ADD_SUBMISSIONS = 'report_xform'
CAN_TRANSFER_OWNERSHIP = 'transfer_xform'
CAN_MOVE_TO_FOLDER = 'move_xform'

# Project Permissions
CAN_VIEW_PROJECT = 'view_project'
CAN_CHANGE_PROJECT = 'change_project'
CAN_TRANSFER_PROJECT_OWNERSHIP = 'transfer_project'
CAN_DELETE_PROJECT = 'delete_project'

CAN_ADD_DATADICTIONARY = 'add_datadictionary'
CAN_CHANGE_DATADICTIONARY = 'change_datadictionary'
CAN_DELETE_DATADICTIONARY = 'delete_datadictionary'

class Role(object):
    class_to_permissions = None
    permissions = None
    name = None

    @classmethod
    def _remove_obj_permissions(self, user, obj):
        content_type = ContentType.objects.get(
            model=obj.__class__.__name__.lower(),
            app_label=obj.__class__._meta.app_label
        )
        object_permissions = user.userobjectpermission_set.filter(
            object_pk=obj.pk, content_type=content_type)

        for perm in object_permissions:
            remove_perm(perm.permission.codename, user, obj)

    @classmethod
    def add(cls, user, obj):
        cls._remove_obj_permissions(user, obj)

        for codename, klass in cls.permissions:
            if type(obj) == klass:
                assign_perm(codename, user, obj)

    @classmethod
    def has_role(cls, permissions, obj):
        """Check that permission correspond to this role for this object.

        :param permissions: A list of permissions.
        :param obj: An object to get the permissions of.
        """
        perms_for_role = set(cls.class_to_permissions[type(obj)])

        return perms_for_role.issubset(set(permissions))

    @classmethod
    def user_has_role(cls, user, obj):
        """Check that a user has this role.

        :param user: A user object.
        :param obj: An object to get the permissions of.
        """
        return user.has_perms(cls.class_to_permissions[type(obj)], obj)

class ReadOnlyRole(Role):
    name = 'readonly'
    permissions = (
        (CAN_VIEW_ORGANIZATION_PROFILE, OrganizationProfile),
        (CAN_VIEW_XFORM, XForm),
        (CAN_VIEW_PROJECT, Project),
    )

class DataEntryRole(Role):
    name = 'dataentry'
    permissions = (
        (CAN_ADD_SUBMISSIONS, XForm),
        (CAN_ADD_XFORM, Project),
        (CAN_VIEW_ORGANIZATION_PROFILE, OrganizationProfile),
        (CAN_VIEW_PROJECT, Project),
        (CAN_VIEW_XFORM, XForm),
    )

class EditorRole(Role):
    name = 'editor'
    permissions = (
        (CAN_ADD_SUBMISSIONS, XForm),
        (CAN_ADD_XFORM, Project),
        (CAN_CHANGE_PROJECT, Project),
        (CAN_CHANGE_XFORM, XForm),
        (CAN_VIEW_ORGANIZATION_PROFILE, OrganizationProfile),
        (CAN_VIEW_PROJECT, Project),
        (CAN_VIEW_XFORM, XForm),
    )

class ManagerRole(Role):
    name = 'manager'
    permissions = (
        (CAN_ADD_SUBMISSIONS, XForm),
        (CAN_ADD_XFORM, XForm),
        (CAN_ADD_XFORM_TO_PROFILE, OrganizationProfile),
        (CAN_ADD_XFORM_TO_PROFILE, UserProfile),
        (CAN_CHANGE_PROJECT, Project),
        (CAN_CHANGE_XFORM, XForm),
        (CAN_DELETE_PROJECT, Project),
        (CAN_VIEW_ORGANIZATION_PROFILE, OrganizationProfile),
        (CAN_VIEW_PROFILE, UserProfile),
        (CAN_VIEW_PROJECT, Project),
        (CAN_VIEW_XFORM, XForm),
    )

class MemberRole(Role):
    """This is a role for a member of an organization.
    """
    name = 'member'

class OwnerRole(Role):
    """This is a role for an owner of a dataset, organization, or project.
    """
    name = 'owner'
    permissions = (
        (CAN_ADD_SUBMISSIONS, XForm),
        (CAN_ADD_XFORM, Project),
        (CAN_ADD_XFORM, XForm),
        (CAN_VIEW_XFORM, XForm),
        (CAN_ADD_DATADICTIONARY, XForm),
        (CAN_CHANGE_DATADICTIONARY, XForm),
        (CAN_DELETE_DATADICTIONARY, XForm),
        (CAN_ADD_SUBMISSIONS, XForm),
        (CAN_DELETE_XFORM, XForm),
        (CAN_MOVE_TO_FOLDER, XForm),
        (CAN_TRANSFER_OWNERSHIP, XForm),
        (CAN_CHANGE_XFORM, XForm),
        (CAN_ADD_XFORM_TO_PROFILE, UserProfile),
        (CAN_ADD_USERPROFILE, UserProfile),
        (CAN_CHANGE_USERPROFILE, UserProfile),
        (CAN_DELETE_USERPROFILE, UserProfile),
        (CAN_ADD_XFORM_TO_PROFILE, UserProfile),
        (CAN_VIEW_PROFILE, UserProfile),
        (CAN_VIEW_ORGANIZATION_PROFILE, OrganizationProfile),
        (CAN_ADD_ORGANIZATION_PROFILE, OrganizationProfile),
        (CAN_ADD_ORGANIZATION_XFORM, OrganizationProfile),
        (CAN_CHANGE_ORGANIZATION_PROFILE, OrganizationProfile),
        (CAN_DELETE_ORGANIZATION_PROFILE, OrganizationProfile),
        (IS_ORGANIZATION_OWNER, OrganizationProfile),
        (CAN_ADD_XFORM_TO_PROFILE, OrganizationProfile),
        (CAN_VIEW_ORGANIZATION_PROFILE, OrganizationProfile),
        (CAN_CHANGE_PROJECT, Project),
        (CAN_CHANGE_XFORM, XForm),
        (CAN_DELETE_PROJECT, Project),
        (CAN_DELETE_XFORM, XForm),
        (CAN_MOVE_TO_FOLDER, XForm),
        (CAN_TRANSFER_OWNERSHIP, XForm),
        (CAN_TRANSFER_PROJECT_OWNERSHIP, Project),
        (CAN_VIEW_ORGANIZATION_PROFILE, OrganizationProfile),
        (CAN_VIEW_PROFILE, UserProfile),
        (CAN_VIEW_PROJECT, Project),
        (CAN_VIEW_XFORM, XForm),
        (CAN_ADD_DATADICTIONARY, XForm),
        (CAN_CHANGE_DATADICTIONARY, XForm),
        (CAN_DELETE_DATADICTIONARY, XForm),
        (CAN_ADD_SUBMISSIONS, XForm),
    )

ROLES_ORDERED = [ReadOnlyRole,
                 DataEntryRole,
                 EditorRole,
                 ManagerRole,
                 OwnerRole]

ROLES = {role.name: role for role in ROLES_ORDERED}

# Memoize a class to permissions dict.
for role in ROLES.values():
    role.class_to_permissions = defaultdict(list)
    [role.class_to_permissions[k].append(p) for p, k in role.permissions]

def is_organization(obj):
    try:
        obj.organizationprofile
        return True
    except OrganizationProfile.DoesNotExist:
        return False

def get_role(permissions, obj):
    for role in reversed(ROLES_ORDERED):
        if role.has_role(permissions, obj):
            return role.name

def get_role_in_org(user, organization):
    perms = get_perms(user, organization)

    if 'is_org_owner' in perms:
        return OwnerRole.name
    else:
        return get_role(perms, organization) or MemberRole.name

def get_object_users_with_permissions(obj, exclude=None, serializable=False):
    """Returns users, roles and permissions for a object.
    When called with with `serializable=True`, return usernames (strings)
    instead of User objects, which cannot be serialized by REST Framework.
    """
    result = []

    if obj:
        users_with_perms = get_users_with_perms(
            obj, attach_perms=True, with_group_users=False).items()

        result = [{
            'user': user if not serializable else user.username,
            'role': get_role(permissions, obj),
            'permissions': permissions} for user, permissions in
            users_with_perms if not is_organization(
                UserProfile.objects.get_or_create(user=user)[0]
            )
        ]

    return result


import torch
import between_bingham_fisher as bbf

def bingham_CE(VB1, LamB1, VB2, LamB2):
    """
    h(f1, f2)
    f1 is gt, f2 is prediction
    @param VB1, VB2: (b, 4, 4)
    @param LamB1, LamB2: (b, 4)
    """
    LamB1 = bbf.ensure_bingham_convention(LamB1)
    LamB2 = bbf.ensure_bingham_convention(LamB2)
    muF = VB1[:, :, LamB1.argmax()]       # (b, 3)

    VB1 = VB1[..., 1:]
    VB2 = VB2[..., 1:]
    LamB1 = LamB1[..., 1:]
    LamB2 = LamB2[..., 1:]

    first_term = torch.log(bingham_F(LamB2))
    second_term = 0
    A = VB1.transpose(1, 2) @ VB2       # (b, 3, 3)
    b = (muF[:, None, :] @ VB2).squeeze(1)      # (b, 3)
    for i in range(3):
        tmp1 = (A[:, i] ** 2 - b[:, i][:, None] ** 2) * (1 / bingham_F(LamB1)[:, None]) * bingham_dF(LamB1)   # (b, 3)
        tmp1 = tmp1.sum(1)      # (b, )
        second_term += LamB2[:, i] * (b[:, i] ** 2 + tmp1)
    cross_entropy = first_term - second_term        # (b, )
    assert not torch.isnan(cross_entropy).any() and not torch.isinf(cross_entropy).any()
    return cross_entropy

def bingham_entropy(LamB):
    """
    @param LamB: (b, 4)
    @return entropy: (b, )
    """
    LamB = bbf.ensure_bingham_convention(LamB)
    first_term = torch.log(bingham_F(LamB))
    second_term = - (LamB * bingham_dF(LamB) / bingham_F(LamB)[:, None]).sum(1)
    entropy = first_term + second_term
    return entropy

def bingham_F(LamB):
    """
    @param LamB: (b, 3) or (b, 4)
    @return F: (b, )
    """
    LamB = bbf.ensure_bingham_convention(LamB)
    c = LamB.sum(1) / 4
    S = bbf.LamB_to_S(LamB)
    F = bbf.constant_bingham_appr_fromS(S, c)
    return F

def bingham_dF(LamB):
    """
    @param LamB: (b, 3) or (b, 4)
    @return dF: (b, 3)
    """
    nelement = LamB.shape[1]
    LamB = bbf.ensure_bingham_convention(LamB)
    with torch.enable_grad():
        LamB.requires_grad_(True)
        F = bingham_F(LamB)
        dF = torch.autograd.grad(F, LamB, torch.ones_like(F))[0]
    if nelement == 3:
        return dF[:, 1:]
    else:
        return dF