#L1_A_30
from rdkit import Chem

def solve(core, chains):
    core = Chem.MolFromSmiles(core)
    chainMols = [Chem.MolFromSmiles(chain) for chain in chains]

    product_smi = []
    for chainMol in chainMols:
        product_mol = Chem.ReplaceSubstructs(core,Chem.MolFromSmarts('[#0]'),chainMol)
        product_smi.append(Chem.MolToSmiles(product_mol[0]))
    return set(product_smi)

对于如下问题:
------------

请写一个完整的Python函数`solve(cores, chains)`, 输入一个带有连接位点"*"符号的片段SMILES (core)，以及包含多个片段SMILES的列表(chains)，返回将每个chain片段中的第一个原子连接到core片段得到的分子SMILES集合。
连接可以通过将"*"原子替换为chain片段实现， 匹配"*"原子的SMARTS是"[#0]", 通过Chem.ReplaceSubstructs()函数可以做片段替换。

------------

尝试以下代码:
```python
from rdkit import Chem

def solve(core, chains):
    core_mol = Chem.MolFromSmiles(core)

    result_smiles = []

    for chain in chains:
        chain_mol = Chem.MolFromSmiles(chain)

        modified_mols = Chem.ReplaceSubstructs(core_mol, dummy_smarts, chain_mol)

        for modified_mol in modified_mols:
            result_smiles.append(Chem.MolToSmiles(modified_mol[0]))

    return result_smiles

cores = "C1=CC=C(*)C=C1"
chains = ["NCC", "OCC", "SCC"]
print(solve(cores, chains))
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmpplxgo7qo/tmpz8lhu8ou.py", line 32, in <module>
    print(solve(cores, chains))
  File "/tmp/tmpplxgo7qo/tmpz8lhu8ou.py", line 24, in solve
    result_smiles.append(Chem.MolToSmiles(modified_mol[0]))
TypeError: 'Mol' object is not subscriptable

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）

#<INSERT>

def check(solve):
    assert solve('*[n+]1cc[nH]c1', ['C','CC','CCC','CCCN']) == {'CCC[n+]1cc[nH]c1', 'C[n+]1cc[nH]c1', 'CC[n+]1cc[nH]c1', 'NCCC[n+]1cc[nH]c1'}
    assert solve('Nc1cc(*)ccc1', ['C','O','C#N','N#C']) == {'Nc1cccc(O)c1', 'C#Nc1cccc(N)c1', 'N#Cc1cccc(N)c1', 'Cc1cccc(N)c1'}
    assert solve('CCC*', ['Cl','O','C=C']) == {'CCCO', 'CCCCl', 'C=CCCC'}

check(solve)


#L1_A_40
from rdkit import Chem

def solve(smiles, atom_idx1, atom_idx2):
    mol = Chem.MolFromSmiles(smiles)
    path = Chem.GetShortestPath(mol, atom_idx1, atom_idx2)
    return [i for i in path if i not in [atom_idx1, atom_idx2]]

对于如下问题:
------------

请写一个完整的Python函数`solve(smiles, atom_idx1, atom_idx2)`，输入一个SMILES，指定2个原子的索引，
返回在这个分子中指定的两个原子之间的最短路径上所有原子索引的列表(不包括这两个指定的原子)。
已知RDKit中可以通过Chem.GetShortestPath()找到2个原子之间的最短路径。

------------

尝试以下代码:
```python
from rdkit import Chem

def solve(smiles, atom_idx1, atom_idx2):
    mol = Chem.MolFromSmiles(smiles)
    if not mol:
        raise ValueError("Invalid SMILES string provided.")

    if atom_idx1 >= mol.GetNumAtoms() or atom_idx2 >= mol.GetNumAtoms() or atom_idx1 < 0 or atom_idx2 < 0:
        raise IndexError("Atom indices are out of range.")

    path = mol.GetShortestPath(atom_idx1, atom_idx2)

    internal_path = path[1:-1] if len(path) > 2 else []

    return list(internal_path)
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmpnn7lh9kh/tmpaob8kr57.py", line 39, in <module>
    check(solve)
  File "/tmp/tmpnn7lh9kh/tmpaob8kr57.py", line 35, in check
    assert solve('CC(=O)OC(C(C)N)C(C)CO', 1, 7) == [3, 4, 5]
  File "/tmp/tmpnn7lh9kh/tmpaob8kr57.py", line 27, in solve
    path = mol.GetShortestPath(atom_idx1, atom_idx2)
AttributeError: 'Mol' object has no attribute 'GetShortestPath'

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）

问题：写一段 python 代码实现以下功能。
找出小于第n个斐波那契数的最大完全平方数
函数命名为 max_square_number，输入为整数 n

答案：
```python
def max_square_number(n):
    if n <= 2:
        return 0  # 对于斐波那契数列的前两个数，没有完全平方数可用

    fibs = [0, 1]  # 存储斐波那契数列的前两个数
    squares = []  # 存储完全平方数的列表

    max_square = 0
    i = 2

    while i <= n:
        fibs.append(fibs[i-1] + fibs[i-2])  # 计算下一个斐波那契数
        i += 1

    fib = fibs[-1]
    perfect_squares = [i**2 for i in range(1, int(math.sqrt(fib)) + 1)]
    max_square = max(filter(lambda x: x < fib, perfect_squares))
    return max_square
```

----------------

#<INSERT>

def check(solve):
    assert solve('CC(=O)OC(C(C)N)C(C)CO', 1, 7) == [3, 4, 5]
    assert solve('c1(C)cc(C)ccc1OCC(CCC)CC', 1, 14) == [0, 7, 8, 9, 10]

check(solve)


对于如下问题:
------------

求解线性规划问题

min z = x_1 + x_2 + x_3 + x_4 + x_5 + x_6

s.t.

x_6 + x_1 >= 10
x_3 + x_4 >= 20
x_1 + x_2 >= 15
x_4 + x_5 >= 18
x_2 + x_3 >= 25
x_5 + x_6 >= 12
x_i >= 0, i = 1, ..., 6

定义函数 solve() 解决这个问题，返回最优值 z

------------

尝试以下代码:
```python
from scipy.optimize import linprog

def solve():

    A = [
        [-1, 0, 0, 0, 0, -1],  # -x6 - x1 <= -10
    ]

    result = linprog(c, A_ub=A, b_ub=b, bounds=x_bounds, method='highs')

    if result.success:
        return result.fun
    else:
        raise Exception("Linear programming did not converge to a solution")

z_min = solve()
print(f"The minimum value of z is {z_min:.2f}")
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmpqnduhk21/tmpeu0bkadw.py", line 37, in <module>
    assert 53 == solve()
AssertionError

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）


#L0_B_33
from rdkit import Chem
from rdkit.Chem import ChemicalFeatures
from rdkit import RDConfig
import os

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    fdefName = os.path.join(RDConfig.RDDataDir,'BaseFeatures.fdef')
    factory = ChemicalFeatures.BuildFeatureFactory(fdefName)
    feats = factory.GetFeaturesForMol(mol)

    donar_set = set()
    for feat in feats:
        if feat.GetFamily() == 'Donor':
            donar_set.update(feat.GetAtomIds())
    return donar_set

对于如下问题:
------------

请写一个完整的Python函数`solve(smiles)`, 输入一个SMILES，返回分子中所有氢键供体的原子索引的集合

------------

尝试以下代码:
```python
from rdkit import Chem

def solve(smiles):
    molecule = Chem.MolFromSmiles(smiles)

    donor_indices = set()

    for atom in molecule.GetAtoms():
        if atom.GetSymbol() in {'O', 'N'}:
            for neighbor in atom.GetNeighbors():
                if neighbor.GetSymbol() == 'H':
                    donor_indices.add(atom.GetIdx())

    return donor_indices
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmp1l2gnkxy/tmp_gv_dbyk.py", line 39, in <module>
    check(solve)
  File "/tmp/tmp1l2gnkxy/tmp_gv_dbyk.py", line 34, in check
    assert solve('CC(O)C(\C)=C/c1cc(ccn1)-c1cc(C)ccc1N') == {2, 19}
AssertionError

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）

#<INSERT>

def check(solve):
    assert solve('CC(O)C(\C)=C/c1cc(ccn1)-c1cc(C)ccc1N') == {2, 19}
    assert solve('Cc1ccccc1') == set()
    assert solve('c1ccc(C(CCc2cccc3[nH]ccc23)c2cccc3ccccc23)cc1') == {12}

check(solve)


#L1_B_2
from rdkit import Chem
from rdkit.Chem.Scaffolds import MurckoScaffold

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    scaff = MurckoScaffold.GetScaffoldForMol(mol)
    scaff = MurckoScaffold.MakeScaffoldGeneric(scaff)
    scaf_smi = Chem.MolToSmiles(scaff)
    return scaf_smi

对于如下问题:
------------

已知CSK骨架(cyclic skeleton)是指，将一个分子骨架上的非碳重原子替换成碳原子，所有键替换成单键后得到的分子骨架。请写一个完整的Python函数`solve(smiles)`，
使用MurckoScaffold模块提取分子的Bemis-Murcko骨架，并转换为CSK, 返回CSK的SMILES。

------------

尝试以下代码:
```python
from rdkit import Chem
from rdkit.Chem.Scaffolds import MurckoScaffold

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)

    scaffold = MurckoScaffold.GetScaffoldForMol(mol)

    csk = Chem.RWMol(scaffold)
    for atom in csk.GetAtoms():

    for bond in csk.GetBonds():

    csk_smiles = Chem.MolToSmiles(csk, canonical=True)

    return csk_smiles

example_smiles = 'CC1=CC=C(C=C1)C2=CN=CC=C2'
csk_smiles = solve(example_smiles)
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmph84k_8s8/tmp66rgrnrb.py", line 34, in <module>
    check(solve)
  File "/tmp/tmph84k_8s8/tmp66rgrnrb.py", line 30, in check
    assert solve('c1ccc(Oc2cccnc2)cc1') == 'C1CCC(CC2CCCCC2)CC1'
AssertionError

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）

#<INSERT>

def check(solve):
    assert solve('c1ccc(Oc2cccnc2)cc1') == 'C1CCC(CC2CCCCC2)CC1'
    assert solve('Cc1ccc(-c2ccccc2)c(C)c1') == 'C1CCC(C2CCCCC2)CC1'
    assert solve('CC(CC1CCC(O)C1)CC1CCCC(C)N1') == 'C1CCC(CCCC2CCCC2)CC1'

check(solve)


#L0_A_23
from rdkit import Chem
from rdkit.Chem import GetPeriodicTable

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    pt = GetPeriodicTable()
    vdw_radii = []
    for atom in mol.GetAtoms():
        if atom.GetSymbol() == "H":
            continue
        vdw_radii.append(round(pt.GetRvdw(atom.GetSymbol()), 2))
    return vdw_radii

对于如下问题:
------------

请写一个完整的Python函数`solve(smiles)`，输入一个SMILES，通过RDKit获取分子中非氢原子的范德华半径列表（顺序与原子索引相同, 范德华半径值保留2位小数）

------------

尝试以下代码:
```python
from rdkit import Chem
from rdkit.Chem import AllChem

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)

    van_der_waals_radii = []

    for atom in mol.GetAtoms():
        if atom.GetAtomicNum() != 1:
            vdw_radius = atom.GetVdwRadius()
            van_der_waals_radii.append(round(vdw_radius, 2))

    return van_der_waals_radii

vdw_radii = solve(smiles)
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmp_som4io5/tmp5xo7kyhm.py", line 25, in <module>
    vdw_radii = solve(smiles)
  File "/tmp/tmp_som4io5/tmp5xo7kyhm.py", line 16, in solve
    vdw_radius = atom.GetVdwRadius()
AttributeError: 'Atom' object has no attribute 'GetVdwRadius'

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）


import numpy as np
def get_bootstrap_ci(N, df, B):
    bootstrap_estimates = []
    samples = np.random.chisquare(df,N)
    for _ in range(B):
        bs_sample = np.random.choice(samples, size=len(samples), replace=True)
        bootstrap_estimates.append(bs_sample.mean())
    return np.percentile(bootstrap_estimates, [2.5,97.5])

对于如下问题:
------------

写一个python函数get_bootstrap_ci(N,df,B)实现以下功能：生成N个自由度为df的卡方分布的随机数，估计自由度参数df，并通过B次bootstrap，返回一个numpy array表示df估计的95%置信区间. 可以调用numpy

------------

尝试以下代码:
```python
import numpy as np

def get_bootstrap_ci(N, df, B):
    data = np.random.chisquare(df, N)

    df_estimate = np.mean(data)

    bootstrap_estimates = np.zeros(B)

    for i in range(B):
        sample = np.random.choice(data, size=N, replace=True)
        bootstrap_estimates[i] = np.mean(sample)

    lower_bound = np.percentile(bootstrap_estimates, 2.5)
    upper_bound = np.percentile(bootstrap_estimates, 97.5)

    return np.array([lower_bound, upper_bound])

N = 1000
df = 5
B = 10000
ci = get_bootstrap_ci(N, df, B)
print(f"Estimated 95% confidence interval for df: {ci}")
```

但执行时报错:
------------
/bin/bash: 1: Syntax error: end of file unexpected

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）

#<INSERT>

N=1000
df=10
B=500
np.random.seed(42)
bootstrap_ci = get_bootstrap_ci(N,df, B)
assert bootstrap_ci[0] < df < bootstrap_ci[1]


import numpy as np
from scipy.optimize import milp, LinearConstraint

def solve():
    c = -np.array([5, 8], dtype=np.int32)
    A = np.array([[1, 1], [5, 9]], dtype=np.int32)
    b_u = np.array([6, 45], dtype=np.int32)
    b_l = np.full_like(b_u, -np.inf)
    cons = LinearConstraint(A, b_l, b_u)
    integrality = np.ones_like(c)
    res = milp(c = c, constraints=cons, integrality=integrality)
    return -1 * res.fun

对于如下问题:
------------

max z = 5x + 8y
s.t.
x + y <= 6
5x + 9y <= 45
x, y 是整数

定义python函数solve()求解这个问题，返回最大的z值。

------------

尝试以下代码:
```python
from scipy.optimize import linprog
import numpy as np

def solve():

    A = [[1, 1], [5, 9]]
    b = [6, 45]

    x_bounds = (0, None)
    y_bounds = (0, None)

    res = linprog(c, A_ub=A, b_ub=b, bounds=[x_bounds, y_bounds], method='highs')

    x, y = res.x

    x_int = int(round(x))
    y_int = int(round(y))

    max_z = 5 * x_int + 8 * y_int

    return max_z

print(solve())
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmpw928wlon/tmp18xtmd4g.py", line 34, in <module>
    assert 40 == solve()
AssertionError

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）


from sympy import integrate, oo, Symbol

def limit_of_an():
    # Defining the continuous variable and function for approximation
    x = Symbol('x')
    f = 1 / (1 + x**2)

    # Integrating the function over the interval [0, 1]
    integral_result = integrate(f, (x, 0, 1))
    return integral_result.evalf()

对于如下问题:
------------

请编写一个 Python 函数 limit_of_an() 来计算序列 \{a_n\}_{n=1}^{\infinity} 的极限，其中 a_n 定义为 a_n = \sum_{k=1}^n n/(n^2+k^2)。
需要计算的是，当 n 趋向于无穷大时，an 的极限值是多少？

------------

尝试以下代码:
```python
import numpy as np

def limit_of_an(epsilon=1e-7, max_iter=100000):
    n = 1
    prev_an = 0
    while n < max_iter:
        k = np.arange(1, n+1)
        terms = n / (n**2 + k**2)
        an = np.sum(terms)

        if abs(an - prev_an) < epsilon:
            return an

        prev_an = an
        n += 1

    return None

limit = limit_of_an()
print(f"The estimated limit of the sequence is approximately: {limit}")
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmpxlhw22vg/tmpdytn6b0a.py", line 31, in <module>
    assert (abs(limit_of_an() - ans) < tolerance)
AssertionError

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）

#<INSERT>

import math
ans = math.pi / 4
tolerance = 1e-6

assert (abs(limit_of_an() - ans) < tolerance)


#L0_B_53
from rdkit import Chem
from rdkit.Chem.SaltRemover import SaltRemover
from rdkit.Chem import Descriptors

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    remover = SaltRemover()
    res = remover.StripMol(mol)
    logp = Descriptors.MolLogP(res)
    return round(logp, 3)

对于如下问题:
------------

实现一个python完整函数`solve(smiles)`，输入为一个分子的SMILES，去掉分子中的盐，并计算产物的logP，结果保留3位小数。

------------

尝试以下代码:
```python
from rdkit import Chem
from rdkit.Chem import Descriptors, SaltRemover

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    if mol is None:
        raise ValueError("Invalid SMILES string")

    remover = SaltRemover.SaltRemover()

    mol_no_salts = remover.StripMol(mol)

    logP = Descriptors.MolLogP(mol_no_salts)

    return f"{logP:.3f}"

```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmpcd9sw6rb/tmpjds3uv3_.py", line 30, in <module>
    check(solve)
  File "/tmp/tmpcd9sw6rb/tmpjds3uv3_.py", line 26, in check
    assert abs(solve("Cl.NCCC1(O)CCC2(CC1)OCCO2") - 0.3834) < 1e-3
TypeError: unsupported operand type(s) for -: 'str' and 'float'

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）

#<INSERT>

def check(solve):
    assert abs(solve("Cl.NCCC1(O)CCC2(CC1)OCCO2") - 0.3834) < 1e-3
    assert abs(solve("Cl.NCC(C)C.Cl.Br") - 0.6011) < 1e-3
    assert abs(solve("c1ccccc1") - 1.6866) < 1e-3

check(solve)


def single_num(nums):
    seen_once = seen_twice = 0

    for num in nums:
        seen_once = ~seen_twice & (seen_once ^ num)
        seen_twice = ~seen_once & (seen_twice ^ num)

    return seen_once

对于如下问题:
------------

给定一个非空整数数组，除了某个元素只出现一次以外，其余每个元素均出现了三次。找出那个只出现了一次的元素。
用python定义函数single_num来解决这个问题，输入非空整数数组，返回只出现一次的元素。
在这个问题中，可以通过遍历列表，对每个数字进行异或运算来解决这个问题，主要步骤如下：

循环列表，通过异或运算判断当前元素是否重复出现，若不是重复出现，则记录当前元素。若重复出现，则记录它包含出现多次的元素的位模式。

------------

尝试以下代码:
```python
def single_num(nums):
    seen_once = 0
    seen_twice = 0
    seen_thrice = 0

    for num in nums:
        seen_once = ~seen_twice & (seen_once ^ num)
        seen_twice = ~seen_once & (seen_twice ^ num)
        seen_thrice = ~seen_twice & (seen_thrice ^ num)

        seen_once &= ~seen_thrice
        seen_twice &= ~seen_thrice

    return seen_once

nums = [2, 2, 3, 2]
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmpcphx8hem/tmphakvhpq0.py", line 23, in <module>
    assert(1 == single_num([1, 2, 2, 2, 3, 3, 3]))
AssertionError

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）


def bytes_to_int32(bytes_obj):
    if len(bytes_obj) != 4:
        raise ValueError("32-bit integer must be 4 bytes in length")
    return int.from_bytes(bytes_obj, byteorder='big', signed=False)

对于如下问题:
------------

我从远程计算机获取到一些bytes，需要通过python转为无符号int32类型，
比如4个字节\x00\x00\x01\x01，会转化为257，\x01\x02\x01\x01，会转化为16908545。
但是我下面的代码一直有问题，帮我找找原因并fix, 给出修复之后的代码。
def bytes_to_int32(bytes_obj):
    if len(bytes_obj) != 4:
        raise ValueError("32-bit integer must be 4 bytes in length")
    return int.from_bytes(bytes_obj, byteorder='little', signed=True)

------------

尝试以下代码:
```python
def bytes_to_int32(bytes_obj):
    if len(bytes_obj) != 4:
        raise ValueError("32-bit integer must be 4 bytes in length")
    return int.from_bytes(bytes_obj, byteorder='little', signed=False)
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmp40gdlnj0/tmpcvxvyg3o.py", line 6, in <module>
    assert bytes_to_int32(b'\x00\x00\x01\x01') == 257
AssertionError

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）


from git import Repo
import datetime

def create_local_tag(repo_path):
    repo = Repo(repo_path)
    tag_name = datetime.datetime.now().strftime("tag-%Y%m%d-%H%M%S")
    new_tag = repo.create_tag(tag_name)
    print(f"Tag created: {new_tag.name}")
    return new_tag.name

对于如下问题:
------------

给定一个路径，要求用 git python sdk 在本地仓库创建一个新的标签（tag），并返回创建的标签名称。新标签的名称应基于当前日期和时间。函数名定义为 create_local_tag

------------

尝试以下代码:
```python
import git
import datetime

def create_local_tag(repo_path):
    repo = git.Repo(repo_path)

    now = datetime.datetime.now()
    tag_name = f"tag_{now.strftime('%Y%m%d_%H%M%S')}"

    new_tag = repo.create_tag(tag_name)

    return new_tag.name
```

但执行时报错:
------------
/bin/bash: 1: Syntax error: end of file unexpected

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）

#<INSERT>

from git import Repo
def check():
    repo_path = "./git_python_test"
    def init(repo_path):
        import os, shutil
        from git import Repo, Actor, Commit
        if os.path.exists(repo_path):
            shutil.rmtree(repo_path)
        os.makedirs(repo_path)
        repo = Repo.init(repo_path)
        index = repo.index
        index.add('*')
        author = Actor('author', 'author@xxx.com')
        index.commit('test', author=author)
        return
    init(repo_path)

    tag_created = create_local_tag(repo_path)
    assert tag_created
    repo = Repo(repo_path)
    tags = [tag.name for tag in repo.tags]
    assert tag_created in tags

check()


from io import StringIO
import pandas as pd
from sklearn.cluster import KMeans

def kmeans_iris(csv_str):
    df = pd.read_csv(StringIO(csv_str), sep=',')
    X = df[['sepal_length', 'sepal_width', 'petal_length', 'petal_width']].to_numpy()
    kmeans = KMeans(n_clusters = 3, random_state=0, n_init="auto").fit(X)
    df = df.assign(cluster_id=kmeans.labels_)
    return df

iris数据集是一个关于鸢尾花分类的数据集，这里面对每一种鸢尾花记录了4种数值特征：
sepal_length,sepal_width,petal_length,petal_width

有一个csv文件存储了这个数据集，样例如下

sepal_length,sepal_width,petal_length,petal_width,species
5.1,3.5,1.4,0.2,setosa
4.9,3.0,1.4,0.2,setosa
4.7,3.2,1.3,0.2,setosa
4.6,3.1,1.5,0.2,setosa
5.0,3.6,1.4,0.2,setosa

实现 python 函数 kmeans_iris(csv_str), 输入 csv 文件的内容字符串 csv_str, 按照4种特征对鸢尾花聚类聚成3个类(0, 1, 2)，最终在dataframe里加入一列，记录每行数据属于的聚类id，列名cluster_id，最后返回聚类后的dataframe。


from sympy import symbols, Eq, solve

def f():
    total_parts = symbols('total_parts')

    equation = Eq(total_parts, (2/7) * total_parts + 1600 + 1/2 * ((2/7) * total_parts + 1600))

    solution = solve(equation, total_parts)

    return int(solution[0])

对于如下问题:
------------

某车间3个小组做一批零件，第一组做了总数的2/7，第二组做了1600个零件，第三组做的零件是前2组总和的一半。请问一共有多少零件。用python写代码解决，函数名 `f()`，返回一个整数。

------------

尝试以下代码:
```python
def f():
    second_group = 1600

    # (5/14) * total = 2400

    total = 6720
    return total

f()
```

但执行时报错:
------------
Traceback (most recent call last):
  File "/tmp/tmpu9r0sybb/tmp_kupvrw4.py", line 28, in <module>
    assert(f() == 4200)
AssertionError

------------

请尝试分析错误原因并给出修改后的完整代码（使用 markdown code block 格式）


from io import StringIO
import pandas as pd

def corr_sepal_petal(csv_str):
    df = pd.read_csv(StringIO(csv_str), sep=',')
    return df['sepal_length'].corr(df['petal_length'], method='pearson'), df['sepal_width'].corr(df['petal_width'], method='pearson')

iris数据集是一个关于鸢尾花分类的数据集，这里面对每一种鸢尾花记录了4种数值特征：
sepal_length,sepal_width,petal_length,petal_width

有一个csv文件存储了这个数据集，样例如下

sepal_length,sepal_width,petal_length,petal_width,species
5.1,3.5,1.4,0.2,setosa
4.9,3.0,1.4,0.2,setosa
4.7,3.2,1.3,0.2,setosa
4.6,3.1,1.5,0.2,setosa
5.0,3.6,1.4,0.2,setosa

实现 python 函数 corr_sepal_petal(csv_str), 输入 csv 文件的内容字符串 csv_str, 计算sepal_length和petal_length的pearson相关系数，以及sepal_width和petal_width的pearson相关系数，返回2个相关系数。


from io import StringIO
import pandas as pd

def solve(csv_str, n):
    df = pd.read_csv(StringIO(csv_str))
    top_n = df.nlargest(n, 'sepal_length')
    species_counts = top_n['species'].value_counts().to_dict()
    return species_counts

iris数据集是一个关于鸢尾花分类的数据集，这里面对每一种鸢尾花记录了4种数值特征：
sepal_length,sepal_width,petal_length,petal_width

有一个csv文件存储了这个数据集，样例如下

sepal_length,sepal_width,petal_length,petal_width,species
5.1,3.5,1.4,0.2,setosa
4.9,3.0,1.4,0.2,setosa
4.7,3.2,1.3,0.2,setosa
4.6,3.1,1.5,0.2,setosa
5.0,3.6,1.4,0.2,setosa

实现 python 函数 solve(csv_str, n), 输入 csv 文件的内容字符串 csv_str 和整数 n, 计算那种鸢尾花的平均 sepal_length 最大的n条数据里，不同种类的鸢尾花出现的次数，返回一个dict。


from io import StringIO
import pandas as pd

def solve(csv_str):
    df = pd.read_csv(StringIO(csv_str), sep=',')
    df = df.groupby('species').mean()
    return df[df['sepal_length'] > df['sepal_width'] * 2].index.to_list()

iris数据集是一个关于鸢尾花分类的数据集，这里面对每一种鸢尾花记录了4种数值特征：
sepal_length,sepal_width,petal_length,petal_width

有一个csv文件存储了这个数据集，样例如下

sepal_length,sepal_width,petal_length,petal_width,species
5.1,3.5,1.4,0.2,setosa
4.9,3.0,1.4,0.2,setosa
4.7,3.2,1.3,0.2,setosa
4.6,3.1,1.5,0.2,setosa
5.0,3.6,1.4,0.2,setosa

实现 python 函数 solve(csv_str), 输入 csv 文件的内容字符串 csv_str, 计算那种鸢尾花的平均 sepal_length 大于 sepal_width 的2倍，返回满足条件的鸢尾花列表。


from io import StringIO
import pandas as pd

def species_with_min_petal_width(csv_str):
    df = pd.read_csv(StringIO(csv_str), sep=',')
    return df.groupby('species').mean().sort_values('petal_width').iloc[0].name

iris数据集是一个关于鸢尾花分类的数据集，这里面对每一种鸢尾花记录了4种数值特征：
sepal_length,sepal_width,petal_length,petal_width

有一个csv文件存储了这个数据集，样例如下

sepal_length,sepal_width,petal_length,petal_width,species
5.1,3.5,1.4,0.2,setosa
4.9,3.0,1.4,0.2,setosa
4.7,3.2,1.3,0.2,setosa
4.6,3.1,1.5,0.2,setosa
5.0,3.6,1.4,0.2,setosa

实现 python 函数 species_with_min_petal_width(csv_str), 输入 csv 文件的内容字符串 csv_str, 计算平均petal_width最小的鸢尾花品种并返回。


import ipaddress

def summarise_ip(ip_list):
    total_ips = len(ip_list)
    valid_ipv4 = 0
    valid_ipv6 = 0
    private_ips = 0
    public_ips = 0
    special_ips = 0

    for ip in ip_list:
        try:
            parsed_ip = ipaddress.ip_address(ip)
            if isinstance(parsed_ip, ipaddress.IPv4Address):
                valid_ipv4 += 1
                if parsed_ip.is_private:
                    private_ips += 1
                elif parsed_ip.is_global:
                    public_ips += 1
                elif parsed_ip.is_loopback or parsed_ip.is_link_local:
                    special_ips += 1
            elif isinstance(parsed_ip, ipaddress.IPv6Address):
                valid_ipv6 += 1
                if parsed_ip.is_private:
                    private_ips += 1
                elif parsed_ip.is_global:
                    public_ips += 1
                elif parsed_ip.is_loopback or parsed_ip.is_link_local:
                    special_ips += 1
        except ValueError:
            # 如果解析失败，跳过该地址
            continue

    return [total_ips, valid_ipv4, valid_ipv6, private_ips, public_ips, special_ips]

编写一个 Python函数summarise_ip来处理和分析一系列的IP地址。函数的参数是一个包含了字符串的列表，每个字符串是一个ip地址。函数返回一个列表，列表元素分别是总ip地址的数量、有效的ipv4地址的数量、有效的ipv6地址的数量、私有ip的数量、公有ip的数量和特殊ip的数量。


def get_most_active_users(json_data, number):
    # Dictionary to keep track of user activity scores
    user_scores = {}

    # Process each post in the json data
    for post in json_data:
        # Count the post for the author
        author = post['author']
        user_scores[author] = user_scores.get(author, 0) + 1

        # Count likes (0.1 points each)
        for user in post['likes']:
            user_scores[user] = user_scores.get(user, 0) + 0.1

        # Count comments (0.5 points each)
        for comment in post['comments']:
            commenter = comment['author']
            user_scores[commenter] = user_scores.get(commenter, 0) + 0.5

    # Sort the users by their scores in descending order and get the top 'number' users
    most_active_users = sorted(user_scores, key=user_scores.get, reverse=True)[:number]
    return most_active_users

你获得了一份社交媒体网站的原始数据，格式为从JSON解析出的python dict。这些数据包含用户的帖子、帖子的点赞数以及评论数量。你的任务是编写一个Python程序来分析这些数据，找出最活跃的N个用户。

输入的数据格式为：

[
    {
        'title': 'Post title',
        'content': 'Post content',
        'likes': [
            'user ID 1',
            'user ID 2',
            ...
            'user ID N'
        ]
        'comments': [
            {
                'content': 'comment content',
                'author': 'comment user ID'
            }
            ...
        ],
        'author': 'author ID'
    }
]

请编写get_most_active_users(json_data, number)函数，返回一个list，包含最活跃的number个用户的ID。其中json_data为dict格式的原始数据。其中活跃度为帖子数量、点赞数量（系数为0.1）和评论数量（系数为0.5）的总和。

#<INSERT>

test_data = [
    {
        "title": "Post 1",
        "content": "Content of post 1",
        "likes": ["user1", "user5"],
        "comments": [
            {"content": "Great post!", "author": "user2"},
            {"content": "I agree!", "author": "user4"}
        ],
        "author": "user1"
    },
    {
        "title": "Post 2",
        "content": "Content of post 2",
        "likes": ["user4"],
        "comments": [
            {"content": "Interesting perspective.", "author": "user1"},
            {"content": "Thanks for sharing.", "author": "user3"}
        ],
        "author": "user2"
    },
    {
        "title": "Post 3",
        "content": "Content of post 3",
        "likes": ["user1", "user3", "user4"],
        "comments": [
            {"content": "Nice post!", "author": "user5"}
        ],
        "author": "user3"
    }
]

assert set(get_most_active_users(test_data, 1)) == {'user1'}
assert set(get_most_active_users(test_data, 2)) == {'user1', 'user3'}
assert set(get_most_active_users(test_data, 3)) == {'user1', 'user2', 'user3'}
assert set(get_most_active_users(test_data, 4)) == {'user1', 'user2', 'user3', 'user4'}
assert set(get_most_active_users(test_data, 5)) == {'user1', 'user2', 'user3', 'user4', 'user5'}


export interface Imcard {
    bg_url: string;
    cover_url: string;
    title: string;
    subtitle: string;
    schema: string;
}

export interface Reflow {
    schema: string;
}

export interface Data {
    min_version: number;
    imcard: Imcard;
    reflow: Reflow;
}

{
    "min_version": 2901,
    "imcard": {
      "bg_url": "https://picsum.photos/200/300",
      "cover_url": "https://picsum.photos/200/300",
      "title": "红包雨来袭",
      "subtitle": "点我抢红包",
      "schema": "aweme://lynxview_popup/..."
    },
    "reflow": {
      "schema": "aweme://lynxview_popup/..."
    }
}
帮我转成 typescript 定义，类型名为 Data
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test } from '@jest/globals';

#<INSERT>

describe('Data Type Test', () => {
  const mockData: Data = {
    "min_version": 2901,
    "imcard": {
      "bg_url": "https://picsum.photos/200/300",
      "cover_url": "https://picsum.photos/200/300",
      "title": "红包雨来袭",
      "subtitle": "点我抢红包",
      "schema": "aweme://lynxview_popup/?surl=https%3A%2F%2Flf-normal-gr-sourcecdn.bytegecko.com%2Fobj%2Fbyte-gurd-source-gr%2Flife%2Fmarketing%2Flynx%2Flife_marketing_lynx_red_rain_base%2Freflow%2Ftemplate.js&hide_nav_bar=1&trans_status_bar=1&use_bdx=1&close_by_mask=0&mask_color=00000000&width_percent=100&popup_enter_type=center&enable_prefetch=1&is_hidden=1&hide_loading=1&share_config=1"
    },
    "reflow": {
      "schema": "aweme://lynxview_popup/?trans_status_bar=1&surl=https%3A%2F%2Flf-normal-gr-sourcecdn.bytegecko.com%2Fobj%2Fbyte-gurd-source-gr%2Flife%2Fmarketing%2Flynx%2Flife_marketing_lynx_red_rain_base%2Fred%2Ftemplate.js&hide_nav_bar=1&popup_enter_type=center&height_percent=100&width_percent=100&dynamic=1&hide_loading=1&enable_canvas=1&enable_canvas_optimize=1&enable_dynamic_v8=1&hide_loading=1&delay_open=1&block_back_press=1"
    }
  };

  test('should match the Data type structure', () => {
    expect(mockData).toHaveProperty('min_version');
    expect(mockData).toHaveProperty('imcard');
    expect(mockData).toHaveProperty('reflow');
    expect(mockData.imcard).toHaveProperty('bg_url');
    expect(mockData.imcard).toHaveProperty('cover_url');
    expect(mockData.imcard).toHaveProperty('title');
    expect(mockData.imcard).toHaveProperty('subtitle');
    expect(mockData.imcard).toHaveProperty('schema');
    expect(mockData.reflow).toHaveProperty('schema');
  });

  // More detailed tests about the structure can be added
});


import random
import os

def write_by_line(path, data, mod="w", encode="utf-8"):
    """write the data"""
    with open(path, mod, encoding=encode) as outfile:
        [outfile.write(d + "\n") for d in data]

def dataset_process(data, output_folder, max_len=20):
    # 去掉内容长度超过长度的数据
    data = [(content, label) for content, label in data if len(content) <= max_len]
    # 按内容去重
    data = list(set(tuple(d) for d in data))

    # 随机打乱数据
    random.shuffle(data)

    # 划分数据集
    total_samples = len(data)
    train_samples = int(total_samples * 0.8)
    valid_samples = int(total_samples * 0.1)
    test_samples = total_samples - train_samples - valid_samples

    train_data = ["\t".join(d) for d in data[:train_samples]]
    valid_data = ["\t".join(d) for d in data[train_samples: train_samples + valid_samples]]
    test_data = ["\t".join(d) for d in data[train_samples + valid_samples:]]

    # 保存数据集到指定目录下
    os.makedirs(output_folder, exist_ok=True)
    write_by_line(os.path.join(output_folder, 'train.txt'), train_data)
    write_by_line(os.path.join(output_folder, 'valid.txt'), valid_data)
    write_by_line(os.path.join(output_folder, 'test.txt'), test_data)

python实现数据集处理方法 dataset_process(data, output_folder, max_len=20) ，将输入的数据（数据格式为[[内容, 标签], ...]）处理，并保存到指定文件夹下
处理要求：
1、按照内容部分去重数据
2、去掉内容长度超过20的
3、随机打乱数据
4、train、valid、test按照8:1:1划分，保存到指定目录下的 train.txt, valid.txt, test.txt

#<INSERT>

def check():
    def del_file(file_path):
        if os.path.exists(file_path):
            os.remove(file_path)

    import os
    datas = [["周杰伦身高多少", "需求"],
            ["周杰身高多少", "需求"],
            ["你好", "非需求"],
            ["你好", "非需求"],
            ["谢娜身高多少", "需求"],
            ["谢娜身高多少", "需求"],
            ["周的身高多少", "需求"],
            ["周的xx身高多少", "需求"],
            ["周的ewr身高多少", "需求"],
            ["你好啊", "非需求"],
            ["你好啊", "非需求"],
            ["周的earthyr身高多少", "需求"],
            ["周的enter身高多少", "需求"],
            ["周的en32435身高多少", "需求"],
            ["周的en32435身高3456789876543223456多少", "需求"],
            ["周的en32435身高34567223456多少", "需求"]]
    file_dir = "dataset_test_1"
    del_file(os.path.join(file_dir, "train.txt"))
    del_file(os.path.join(file_dir, "valid.txt"))
    del_file(os.path.join(file_dir, "test.txt"))

    dataset_process(datas, file_dir)
    assert os.path.exists(os.path.join(file_dir, "train.txt"))
    assert os.path.exists(os.path.join(file_dir, "valid.txt"))
    assert os.path.exists(os.path.join(file_dir, "test.txt"))

check()


from typing import List, Tuple, Optional, Dict, Any

class CategoryNode:
    def __init__(self, name: str):
        self.name = name
        self.children: List[CategoryNode] = []

    def add_child(self, child: 'CategoryNode') -> None:
        self.children.append(child)

def convert_category_tree(categories: List[Tuple[str, str]]) -> Optional[CategoryNode]:
    # 创建一个字典来存储所有的节点，方便后续查找
    nodes: Dict[str, CategoryNode] = {}
    # 创建一个字典来存储所有节点的父节点名称
    parent_names: Dict[str, str] = {}

    # 首先创建所有的节点
    for category, parent in categories:
        nodes[category] = CategoryNode(category)
        parent_names[category] = parent

    # 定义根节点
    root: Optional[CategoryNode] = None

    # 找到根节点
    for _, parent in categories:
        if parent in nodes:
            continue
        if root:
            return False
        else:
            root = CategoryNode(parent)
            nodes[parent] = root

    # 构建树结构
    for category, parent in categories:
        nodes[parent].add_child(nodes[category])

    # 检查是否所有节点都正确连接到树上
    for category, parent in parent_names.items():
        if category != parent and nodes[category] not in nodes[parent].children:
            return False

    return root

请用python实现一个将查询出来的电商产品分类体系转为树结构表示。
要求：
1、实现一个将存储在列表中的产品分类体系转为树结构的方法convert_category_tree
2、输入为列表，列表中的每个元素为一个元组，元组中包含了产品分类的名称和父分类名称
3、产品体系只有1个，有多个时应当返回 False
4、请按照python3的写法增加类型注解

#<INSERT>

def check():
    categories_1 = [
        ("电子产品", "root"),
        ("手机", "电子产品"),
        ("电子产品", ""),
        ("笔记本电脑", "电子产品"),
        ("耳机", "手机配件"),
        ("手机配件", "电子产品"),
        ("充电器", "手机配件"),
        ("连衣裙", "服饰")
    ]

    categories_2 = [
        ("电子产品", "root"),
        ("服饰", "root"),
        ("清洁用品", "root"),
        ("手机", "电子产品"),
        ("笔记本电脑", "电子产品"),
        ("耳机", "手机配件"),
        ("手机配件", "电子产品"),
        ("充电器", "手机配件"),
        ("连衣裙", "服饰"),
        ("内衣裤", "服饰"),
        ("羽绒服", "服饰")
    ]
    assert not convert_category_tree(categories_1)
    assert convert_category_tree(categories_2)

check()


def print_dir_tree(dir_structure):
    def build_tree(structure, prefix=''):
        tree = []
        # First, process directories
        for directory in sorted(structure.get('dirs', {})):
            tree.append(f"{prefix}├── {directory}")
            subdir_structure = structure['dirs'][directory]
            sub_tree = build_tree(subdir_structure, prefix + "│   ")
            tree.extend(sub_tree)

        # Then, process files
        for file in sorted(structure.get('files', [])):
            tree.append(f"{prefix}├── {file}")

        # Replace last "├──" with "└──" for the last element
        if tree:
            tree[-1] = tree[-1].replace("├──", "└──")

        return tree

    return '\n'.join(build_tree(dir_structure))

编写一个print_dir_tree(dir_structure)函数，以树形结构打印文件夹的结构，同级文件夹内先展示所有子文件夹，再展示所有子文件，文件和子文件夹以字典顺序排列。

参数dir_structure是如下格式的dict数据：

{
    "files: [
        "file1.txt",
        "file2.txt"
    ],
    "dirs": [
        "dir1": {
            "files": [
                "pic.png",
                "photos": [
                    "1.jpg"
                ]
            ]
        }
    ]
}

以上文件夹对应的树形结构的格式如下：

├── dir1
│   ├── photos
│   │   └── 1.jpg
│   └── pic.png
├── file1.txt
├── file2.txt

函数的输出为表示以上树形文件夹结构的字符串。

#<INSERT>

dir_structure = {
    "dirs": {
        "eval": {
            "dirs": {
                "test": {
                    "files": ["test.txt"]
                },
                "test2": {
                    "files": ["1.txt"]
                }
            },
            "files": [
                "eval.py"
            ]
        }
    },
    "files": [
        "README.md",
        "LICENSE"
    ]
}

# Print the directory tree
assert print_dir_tree(dir_structure).strip() == """
├── eval
│   ├── test
│   │   └── test.txt
│   ├── test2
│   │   └── 1.txt
│   └── eval.py
├── LICENSE
└── README.md
""".strip()


import json
import csv
from collections import defaultdict

def process_data(json_path, csv_path):
    # 读取产品信息
    with open(json_path, 'r') as json_file:
        products = json.load(json_file)

    # 将产品信息存储在字典中，方便查找
    product_info = {product['product_id']: product for product in products}

    # 读取订单信息
    sales = defaultdict(int)  # 用于存储每个产品的销售额
    with open(csv_path, newline='') as csv_file:
        reader = csv.DictReader(csv_file)
        for row in reader:
            product_id = row['product_id']
            quantity = int(row['quantity'])
            price = float(product_info[product_id]['price'])
            sales[product_id] += price * quantity

    # 找出销售额最高的产品ID
    max_sales = max(sales.values())
    top_selling_products = [product_id for product_id, total in sales.items() if total == max_sales]

    return top_selling_products

假设你正在处理一个电子商务公司的数据。你的任务是编写一个process_data(json_path, csv_path)函数来完成以下任务：

从json_path读取JSON文件：该文件包含了多个产品的信息。每个产品有以下字段：product_id（产品ID，唯一）、name（产品名称）、category（产品类别）、price（产品价格）。

从csv_path读取CSV文件：该文件包含了一系列订单信息。每个订单有以下字段：order_id（订单ID，唯一）、product_id（产品ID）、quantity（购买数量）。

数据处理：

以列表的形式返回销售额（产品价格乘以购买数量）并列最高的产品ID。

#<INSERT>

assert process_data("structured_io_test_data/sales_data_1.json", "structured_io_test_data/sales_data_1.csv") == ['202']
assert process_data("structured_io_test_data/sales_data_1.json", "structured_io_test_data/sales_data_2.csv") == ['201', '202', '203']


import argparse

def get_parser():
    # 创建 ArgumentParser 对象
    parser = argparse.ArgumentParser(description="PDF file assistant program")

    # 创建子命令的解析器
    subparsers = parser.add_subparsers(dest="command", help="Subcommands")

    # 创建 merge 子命令的解析器
    merge_parser = subparsers.add_parser("merge", help="Merge multiple PDF files into one")
    merge_parser.add_argument("files", nargs='+', help="PDF files to merge")
    merge_parser.add_argument("--output", required=True, help="Output file name for merged PDF")

    # 创建 split 子命令的解析器
    split_parser = subparsers.add_parser("split", help="Split a PDF file into multiple files")
    split_parser.add_argument("file", help="PDF file to split")

    return parser

帮我写一个get_parser()函数，这个函数为返回一个ArgumentParser对象，为一个PDF文件助手程序解析命令行参数。

这个程序支持两个子命令：merge和split。

merge命令支持多个文件名，并将它们合并成一个PDF文件，新文件名通过--output参数指定。如 merge --output merged.pdf file1.pdf file2.pdf file3.pdf等，输入文件的数量不限，以list的形式存在变量files中。

split命令支持一个PDF文件名，将其分割成多个PDF文件，这个子命令只接受一个参数，即要分割的PDF文件名。如 split file.pdf，文件名存在变量file中。

#<INSERT>

parser = get_parser()

command_line = "merge 1.pdf 2.pdf 3.pdf 4.pdf --output merged.pdf"
arguments = parser.parse_args(command_line.split())
assert arguments.files == ['1.pdf', '2.pdf', '3.pdf', '4.pdf']
assert arguments.output == 'merged.pdf'
assert "file" not in arguments

command_line = "split input.pdf"
arguments = parser.parse_args(command_line.split())
assert "files" not in arguments
assert "output" not in arguments
assert arguments.file == "input.pdf"


from typing import List
import math

def doc_cosine_similarity(doc1: List[str], doc2: List[str]) -> float:
    # 创建词频字典
    word_freq1 = {}
    word_freq2 = {}
    # 计算第一篇文章的词频
    for word in doc1:
        word_freq1[word] = word_freq1.get(word, 0) + 1

    # 计算第二篇文章的词频
    for word in doc2:
        word_freq2[word] = word_freq2.get(word, 0) + 1

    # 计算词频向量的点积
    dot_product = 0
    for word, freq in word_freq1.items():
        if word in word_freq2:
            dot_product += freq * word_freq2[word]

    # 计算两个词频向量的模
    magnitude1 = math.sqrt(sum([freq ** 2 for freq in word_freq1.values()]))
    magnitude2 = math.sqrt(sum([freq ** 2 for freq in word_freq2.values()]))

    # 避免除以零
    if magnitude1 == 0 or magnitude2 == 0:
        return 0.0

    # 计算余弦相似度
    cosine_similarity = dot_product / (magnitude1 * magnitude2)

    return cosine_similarity

请用python实现计算两篇文章的余弦相似度。
要求：
1、包含一个文章余弦相似度计算函数名为 `doc_cosine_similarity`，
2、使用哈希表高效实现，避免调用其他现成方法
3、每篇文章都分好词，使用list输入
5、请按照python3的写法增加类型注解

#<INSERT>

def check():
    doc1 = ["我", "喜欢", "看", "电影", "因为", "电影", "质量", "高"]
    doc2 = ["电影", "是", "我", "的", "爱好"]
    doc3 = []

    assert round(doc_cosine_similarity(doc1, doc2), 5) == 0.42426
    assert round(doc_cosine_similarity(doc1, doc1), 5) == 1.0
    assert doc_cosine_similarity(doc1, doc3) == 0.0

check()


function deepCopy<T>(obj: T): T {
    if (typeof obj === 'object' && obj !== null) {
        if (Array.isArray(obj)) {
            return obj.map(deepCopy) as unknown as T;
        } else if (obj instanceof Date) {
            return new Date(obj.getTime()) as unknown as T;
        } else if (obj instanceof Map) {
            return new Map(Array.from(obj.entries()).map(([k, v]) => [k, deepCopy(v)])) as unknown as T;
        } else if (obj instanceof Set) {
            return new Set(Array.from(obj.values()).map(deepCopy)) as unknown as T;
        } else {
            const copiedObj = Object.create(Object.getPrototypeOf(obj));
            for (const key in obj) {
                if (obj.hasOwnProperty(key)) {
                    copiedObj[key] = deepCopy(obj[key]);
                }
            }
            return copiedObj;
        }
    } else {
        return obj;
    }
}

TypeScript 对象深拷贝 ，方法名为deepCopy，用markdown包裹答案
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test } from '@jest/globals';

#<INSERT>

describe('deepCopy', () => {
    test('should create a deep copy of a simple object', () => {
        const obj = { a: 1, b: 'test' };
        const copiedObj = deepCopy(obj);
        expect(copiedObj).toEqual(obj);
        expect(copiedObj).not.toBe(obj);
    });

    test('should create a deep copy of a nested object', () => {
        const nestedObj = { a: { b: { c: { d: 1 } } } };
        const copiedNestedObj = deepCopy(nestedObj);
        expect(copiedNestedObj).toEqual(nestedObj);
        expect(copiedNestedObj.a).not.toBe(nestedObj.a);
    });

    test('should create a deep copy of an array', () => {
        const array = [1, 2, 3, { a: 4 }];
        const copiedArray = deepCopy(array);
        expect(copiedArray).toEqual(array);
        expect(copiedArray[3]).not.toBe(array[3]);
    });

    test('should create a deep copy of an object with a Date', () => {
        const dateObj = { now: new Date() };
        const copiedDateObj = deepCopy(dateObj);
        expect(copiedDateObj.now).toEqual(dateObj.now);
        expect(copiedDateObj.now).not.toBe(dateObj.now);
    });

    // Add more tests for Map, Set, etc., if your deepCopy function supports those.
});


function heapify(arr: number[], n: number, i: number): void {
    let largest = i;
    const left = 2 * i + 1;
    const right = 2 * i + 2;

    if (left < n && arr[left] > arr[largest]) {
        largest = left;
    }

    if (right < n && arr[right] > arr[largest]) {
        largest = right;
    }

    if (largest !== i) {
        [arr[i], arr[largest]] = [arr[largest], arr[i]];
        heapify(arr, n, largest);
    }
}

export function heapSort(arr: number[]): number[] {
    const n = arr.length;

    // Build max heap
    for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
        heapify(arr, n, i);
    }

    // Extract elements from the heap
    for (let i = n - 1; i > 0; i--) {
        [arr[0], arr[i]] = [arr[i], arr[0]]; // Move current root to end
        heapify(arr, i, 0); // call max heapify on the reduced heap
    }

    return arr;
}

给我讲一下typescript实现堆排序，方法名为heapSort，用markdown包裹答案
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test } from '@jest/globals';

#<INSERT>

describe('heapSort', () => {
    test('sorts an array in ascending order', () => {
        expect(heapSort([3, 0, 2, 5, -1, 4, 1])).toEqual([-1, 0, 1, 2, 3, 4, 5]);
        expect(heapSort([])).toEqual([]);
        expect(heapSort([1])).toEqual([1]);
        expect(heapSort([2, 1])).toEqual([1, 2]);
    });
});


import matplotlib.pyplot as plt

def plot_bar_chart(data, title="chart", xlabel="X-axis", ylabel="Y-axis"):
    quarters = list(data.keys())
    categories = list(data[quarters[0]].keys())
    num_categories = len(categories)
    fig, ax = plt.subplots()
    bar_width = 0.1
    positions = [i * bar_width for i in range(num_categories)]
    for i, quarter in enumerate(quarters):
        values = [data[quarter][category] for category in categories]
        ax.bar([p + i * bar_width for p in positions], values, bar_width, label=quarter)

    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    ax.set_title(title)

    ax.set_xticks([p + (num_categories - 1) * bar_width / 2 for p in positions])
    ax.set_xticklabels(categories)
    ax.legend()
    return plt

python实现对不同季度经济数据比较的直方图 plot_bar_chart(data, title="chart", xlabel="X-axis", ylabel="Y-axis") ，数据格式为{"2023Q1": {"a": 0.1, "b": 0.2}, ...}，请使用matplotlib库实现该方法，图的标题、横坐标、纵坐标名都由参数指定，方法返回对应图的对象


import json

def find_common_friends(json_data, user_id1, user_id2):
    # 将字符串形式的JSON数据解析为字典
    data = json.loads(json_data)

    # 初始化两个用户的好友列表
    friends_of_user1 = []
    friends_of_user2 = []

    # 遍历用户数据，找到两个用户的好友列表
    for user in data["users"]:
        if user["id"] == user_id1:
            friends_of_user1 = user["friends"]
        elif user["id"] == user_id2:
            friends_of_user2 = user["friends"]

    # 计算共同好友
    common_friends = list(set(friends_of_user1) & set(friends_of_user2))

    return common_friends

假设你有一个社交网络的JSON数据文件，其中包含用户信息和他们的好友关系。每个用户有一个唯一的ID，以及一个好友列表，好友列表中是他们好友的ID。

数据结构示例
```json
{
    "users": [
        {"id": "user1", "friends": ["user2", "user5", "user6"]},
        {"id": "user2", "friends": ["user1", "user3"]},
        {"id": "user3", "friends": ["user2", "user4"]},
        // 更多用户...
    ]
}
```

编写一个find_common_friends函数，函数的第一个参数是字符串形式的json数据，第二和第三个参数分别是两个用户的ID，返回这两个用户的共同好友列表。

#<INSERT>

json_data = '''
{
    "users": [
        {"id": "user1", "friends": ["user2", "user3", "user6"]},
        {"id": "user2", "friends": ["user1", "user3"]},
        {"id": "user3", "friends": ["user2", "user4", "user1"]}
    ]
}
'''

assert find_common_friends(json_data, "user1", "user2") == ['user3']


import math
from collections import Counter

def cal_tf_idf(documents):
    # 计算tf值
    tf_docs = []
    for doc in documents:
        word_counts = Counter(doc)
        total_words = len(doc)
        tf_doc = {word: count/total_words for word, count in word_counts.items()}
        tf_docs.append(tf_doc)

    # Step 2: 计算idf
    all_words = set(word for doc in documents for word in doc)
    idf = {}
    num_docs = len(documents)
    for word in all_words:
        num_docs_with_word = sum(word in doc for doc in documents)
        idf[word] = math.log(num_docs / (1 + num_docs_with_word))

    # Step 3: 计算tf-idf
    tf_idf_docs = []
    for tf_doc in tf_docs:
        tf_idf_doc = {word: tf * idf[word] for word, tf in tf_doc.items()}
        tf_idf_docs.append(tf_idf_doc)

    return tf_idf_docs

python实现计算tf-idf方法 cal_tf_idf(documents) ，输入一个文档的列表，每个文档是一个单词的列表，返回文档中每个词到tf-idf值的字典

#<INSERT>

def check():
    documents = [
        ["apple", "banana", "apple", "orange", "orange", "hello"],
        ["banana", "orange", "grape", "hello"],
        ["apple", "grape", "kiwi", "banana", "apple"],
        ["orange", "kiwi", "kiwi", "new", "abstract"]
    ]
    tf_idf_documents = cal_tf_idf(documents)
    assert len(tf_idf_documents) == 4
    assert round(tf_idf_documents[2]["kiwi"], 4) == 0.0575

check()


import json

def fix_json_data(file_path, new_path):
    # 读取JSON文件
    data = []
    with open(file_path, 'r') as file:
        for line in file:
            data.append(json.loads(line.strip()))

    # 确保数据是列表形式
    if not isinstance(data, list):
        raise ValueError("JSON data must be a list of objects")

    # 计算所有数据的cost的平均值
    total_cost = sum(item['cost'] for item in data)
    average_cost = total_cost / len(data)

    # 更新数据，每个项目的cost减去平均值
    for item in data:
        item['cost_diff'] = item['cost'] - average_cost

    # 写入修改后的数据到新的JSON文件
    with open(new_path, 'w') as file:
        json.dump(data, file, indent=4, ensure_ascii=False)

python实现操作json文件方法fix_json_data(file_path, new_path)，该方法根据file_path读取jsonl文件（每行一个json），统计所有数据的cost并求平均值，所有的json数据的cost都减去平均值保存到cost_diff属性，并把新的json写入到new_path中

#<INSERT>

def check():
    import os
    save_path = "file_test_4/data_new.json"
    if os.path.exists(save_path):
        os.remove(save_path)
    path = "file_test_4/data.json"
    fix_json_data(path, save_path)

check()


function MinSubArrayLen(target: number, nums: number[]): number {
    let n = nums.length;
    let minLength = Infinity; // 初始化为极大值
    let sum = 0; // 存储子数组的和
    let start = 0; // 子数组的起始索引

    for (let end = 0; end < n; end++) {
        sum += nums[end]; // 将当前元素加到和中

        while (sum >= target) {
            minLength = Math.min(minLength, end - start + 1); // 更新最小长度
            sum -= nums[start]; // 移动起始索引，并减去这个值
            start++;
        }
    }

    return minLength === Infinity ? 0 : minLength; // 如果长度未被更新过，则返回0，表示没有找到
}

给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ，并返回其长度。如果不存在符合条件的子数组，返回 0
请用ts回答，实现函数 "function MinSubArrayLen(s: number, nums: number[]): number"
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test } from '@jest/globals';

#<INSERT>

describe('MinSubArrayLen', () => {
    test('finds minimum length of a subarray with sum >= target', () => {
        expect(MinSubArrayLen(7, [2, 3, 1, 2, 4, 3])).toBe(2);
        expect(MinSubArrayLen(15, [1, 2, 3, 4, 5])).toBe(5);
        expect(MinSubArrayLen(4, [1, 4, 4])).toBe(1);
        expect(MinSubArrayLen(11, [1, 1, 1, 1, 1, 1, 1, 1])).toBe(0);
    });

    test('returns 0 if no such subarray exists', () => {
        expect(MinSubArrayLen(100, [1, 2, 3, 4, 5])).toBe(0);
        expect(MinSubArrayLen(7, [2, 1])).toBe(0);
    });

    test('works with single element array', () => {
        expect(MinSubArrayLen(3, [3])).toBe(1);
        expect(MinSubArrayLen(3, [1])).toBe(0);
    });

    test('works with a large array', () => {
        // 这个测试用例是用于验证算法在处理大数据量时的性能
        const largeArray = Array(10000).fill(1);
        expect(MinSubArrayLen(9999, largeArray)).toBe(9999);
    });
});


import requests

def download_txt(url, filename):
    response = requests.get(url)
    with open(filename, 'w') as file:
        file.write(response.text)

import csv

def txt_to_csv(txt_filename, csv_filename):
    with open(txt_filename, 'r') as in_file, open(csv_filename, 'w', newline='') as out_file:
        lines = in_file.read().splitlines()
        writer = csv.writer(out_file)
        for line in lines:
            writer.writerow(line.split(','))

def download_txt_and_convert_to_csv(url, txt_filename, csv_filename):
    download_txt(url, txt_filename)
    txt_to_csv(txt_filename, csv_filename)

利用python编写函数实现网页txt文件的下载，并把文件最终整理csv文件输出。txt包含按逗号分隔的内容。
1. 下载txt的函数为download_txt，输入url和filename
2. 转换的函数为txt_to_csv，输入txt_filename和csv_filename
3. 将两个函数的调用集合为一个函数download_txt_and_convert_to_csv

#pyqt_test_32

#<INSERT>

def check():
    import os
    url = 'https://m-selig.ae.illinois.edu/ads/coord_updates/ag23.dat'
    txt_filename = 'example.txt'
    csv_filename = 'example.csv'
    download_txt_and_convert_to_csv(url, txt_filename, csv_filename)
    assert os.path.exists(csv_filename)
    if os.path.exists(txt_filename):  # 清理测试文件
        os.remove(txt_filename)
    if os.path.exists(csv_filename):  # 清理测试文件
        os.remove(csv_filename)

check()


import json

def read_json(key_path, json_str):
    try:
        # 将 JSON 字符串转换为字典
        data = json.loads(json_str)

        # 分割键路径
        keys = key_path.split('.')

        # 遍历键路径
        for key in keys:
            if '[' in key and ']' in key:
                # 提取数组下标
                index = int(key[key.find('[') + 1:key.find(']')])
                # 提取键名
                key = key[:key.find('[')]
                # 获取数组元素
                data = data[key][index]
            else:
                # 获取键值
                data = data[key]

        return data
    except (KeyError, IndexError, ValueError, TypeError):
        # 如果路径不正确或键不存在，返回 None
        return None

编写一个read_json函数，函数的参数是key的路径和一个包含json数据的字符串，key的路径以.分割子键名、以[]表示下标。例如，"key1.key2[0]"。函数返回键值，键名不存在时返回None

#<INSERT>

json_data = '{"key1": {"key2": ["value1", "value2"]}, "key2": "value2"}'
key_path = "key1.key2[0]"
assert read_json(key_path, json_data) == "value1"
key_path = "key2"
assert read_json(key_path, json_data) == "value2"


import argparse

def get_parser():
    parser = argparse.ArgumentParser(description="Process command line arguments.")

    # 添加 files 参数，用于指定要处理的文件列表
    parser.add_argument("--files", "-f", nargs=2, required=True, help="Specify two files to process")

    # 添加 output 参数，用于指定输出文件
    parser.add_argument("--output", "-o", type=str, required=True, help="Specify the output file")

    # 添加 optimiser 参数，可以被多次调用
    parser.add_argument("--optimiser", action="append", help="Specify the name of the optimiser, can be called multiple times")

    return parser

帮我创建一个get_parser()函数，它应该返回一个ArgumentParser对象，该对象可以用于解析命令行参数，以支持下面的命令行命令处理：

--files, -f 2个连续的字符串，指定要处理的文件列表
--output, -o 字符串，指定输出文件
--optimiser 字符串，指定优化器的名字，可被多次调用，例如 --optimiser=adam --optimiser=sgd，结果保存在list中

#<INSERT>

parser = get_parser()

command_line = "--files 1.txt 2.txt --output 3.txt --optimiser a --optimiser b"
arguments = parser.parse_args(command_line.split())
assert arguments.files == ['1.txt', '2.txt']
assert arguments.output == '3.txt'
assert arguments.optimiser == ['a', 'b']

command_line = "-f 1.txt 2.txt -o 3.txt --optimiser a --optimiser b"
arguments = parser.parse_args(command_line.split())
assert arguments.files == ['1.txt', '2.txt']
assert arguments.output == '3.txt'
assert arguments.optimiser == ['a', 'b']


import json
import csv

def save_to_csv(json_str, csv_filename):
    # 解析 JSON 字符串
    data = json.loads(json_str)

    # 打开 CSV 文件进行写入
    with open(csv_filename, 'w', newline='', encoding='utf-8') as csvfile:
        # 如果列表不为空，提取键名作为列名
        if data:
            fieldnames = data[0].keys()

            # 创建一个 csv 写入器对象
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

            # 写入列名（键名）
            writer.writeheader()

            # 写入数据行
            for row in data:
                writer.writerow(row)
        else:
            print("JSON data is empty. No data written to CSV.")

编写一个save_to_csv函数，参数是一个json的字符串和一个输出的csv文件名。这个函数的任务是将json字符串解析成json对象，json的格式是一个由字典组成的列表，然后将json对象保存到csv文件中。csv文件的第一行应当是从字典中提取出的键名作为列名。

#<INSERT>

import csv
import os
json_str = '[{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]'
csv_filename = 'output.csv'
save_to_csv(json_str, csv_filename)
with open(csv_filename, 'r') as f:
    csv_reader = csv.reader(f)
    header = next(csv_reader)
    assert header == ['name', 'age']
    rows = list(csv_reader)
    assert rows == [['Alice', '30'], ['Bob', '25']]
os.remove(csv_filename)


def split(n, k):
    d,r = divmod(n, k)
    return [d+1]*r + [d]*(k-r)

def divideNumber(n, k):
    return [2 * x for x in split(n // 2, k)]

将一个偶数分成N个部分，每个部分都是2的倍数

假设我有一个数字100，我需要将其分成N个部分，每个部分最初不应超过30。所以最初的分组应该是（30,30,30）。剩余的部分（也就是10）需要被分配到这三个组中，通过依次给每个组添加2，从而确保每个分组都是2的倍数。因此，理想的输出应该是（34,34,32）。

注：原始数字总是偶数。

我尝试用Python来解答这个问题，下面就是我的答案。显然，它并没有按照我想的那样运行。它通过给每个组添加1（而不是期望的2）来分配剩余的部分。

```python
num = 100
parts = num//30  # 'num' 要被分成的部分数量

def split(a, b):
  result = ([a//b + 1] * (a%b) + [a//b] * (b - a%b))
  return(result)

print(split(num, parts))
```

输出：

```
[34, 33, 33]
```

期望的输出：

```
[34, 34, 32]
```

请用Python编写一个函数 `divideNumber`，该函数接受 `num` 和 `n` 作为参数，根据我以上的要求返回分割结果（将 `num` 分成 `n` 个部分）。

函数的签名是：`divideNumber(num, n)`

#<INSERT>

def split(n, k):
    d,r = divmod(n, k)
    return [d+1]*r + [d]*(k-r)

def split_even(n, k):
    return [2 * x for x in split(n // 2, k)]

assert split_even(100, 3) == divideNumber(100, 3)
assert split_even(1000, 3) == divideNumber(1000, 3)
assert split_even(10000, 5) == divideNumber(10000, 5)
assert split_even(666, 7) == divideNumber(666, 7)


def mu(n):
    if n == 1:
        return 1
    prime_factors = {}
    original_n = n
    factor = 2
    # 素因数分解
    while factor * factor <= n:
        while (n % factor) == 0:
            if factor in prime_factors:
                prime_factors[factor] += 1
            else:
                prime_factors[factor] = 1
            n //= factor
        factor += 1
    if n > 1:  # 这是最后的素因子，如果有的话
        prime_factors[n] = 1

    # 检查是否含有平方因子
    for count in prime_factors.values():
        if count > 1:
            return 0  # n 是平方数的倍数

    # 根据素因子的个数决定返回值
    if len(prime_factors) % 2 == 0:
        return 1
    else:
        return -1

用 python 实现函数 mu(n) 给定正整数n，返回n的莫比乌斯函数值


import shlex
def process_command(command):
    # 分割命令字符串为单独的部分
    parts = shlex.split(command)

    # 处理主命令：第一个元素，并以绿色显示
    parts[0] = f'{parts[0]}'

    for i in range(1, len(parts)):
        if parts[i].startswith("-") and i + 1< len(parts) and not parts[i + 1].startswith("-"):
            parts[i + 1] = f'{parts[i + 1]}'
            i += 1

    # 将处理后的部分用空格连接并返回
    return ' '.join(parts)

编写一个process_command(command)函数，输入是一个command字符串，返回带样式的html字符串。

以ls -la *.txt为例，要求如下：

主command命名使用绿色：ls用ls表示。
参数名不变，如-la不变。
参数的值加下划线，如*.txt用*.txt表示。

因此，对应以上例子的完整的返回值为ls -la *.txt

#<INSERT>

# 示例
command = "ls -la *.txt"
assert process_command(command).strip() == "ls -la *.txt"

command = "gcc main.cpp -O3 -o main.o -c"
print(process_command(command).strip())
assert process_command(command).strip() == "gcc main.cpp -O3 -o main.o -c"


import configparser

def read_conf(key, ini_content):
    # 读取 INI 内容
    config = configparser.ConfigParser()
    config.read_string(ini_content)

    # 分割键名和子键名
    parts = key.split('.')

    # 确保键名格式正确
    if len(parts) != 2:
        raise ValueError("Key format is incorrect. Expected format: 'section.key'")

    section, option = parts

    # 尝试获取值
    try:
        value = config.get(section, option)
        return value
    except (configparser.NoSectionError, configparser.NoOptionError):
        # 如果指定的节或选项不存在
        return None

编写一个read_conf函数，函数的参数是键名（以.分割子键名，例如"key1.key2"）和ini格式的配置文件的内容。函数返回键值。

#<INSERT>

ini_content = """
[section1]
key1 = value1
key2 = value2
"""

key = 'section1.key1'
assert read_conf(key, ini_content) == "value1"

key = 'section1.key3'  # 不存在的键
assert read_conf(key, ini_content) is None


def text_wrap(text):
    wrapped_text = ""
    for line in text.splitlines():
        while len(line) > 80:
            # 找到最后一个空格的位置，用于拆分行
            split_index = line.rfind(' ', 0, 80)
            if split_index == -1:  # 如果找不到空格，直接在80个字符处截断
                split_index = 80

            # 添加新行并更新当前行
            wrapped_text += line[:split_index] + '\n'
            line = line[split_index:].lstrip()  # 去除左边的空格

        wrapped_text += line + '\n'

    return wrapped_text

编写一个text_wrap(text)函数，输入是一段字符串文本，要求对每一个超过80个字符的行进行截断、拆成若干行，使得每一行都不超过80个字符，当截断行会截断某个单词时，将整个单词挪到下一行。函数返回处理后的字符串
如果单个单词长度超过80，可以截断该单词。

#<INSERT>

# 正常长度的行
assert text_wrap("This is a normal line.") == "This is a normal line.\n"

# 超长行无单词
long_text_no_space = "a" * 85
expected_wrapped_no_space = "a" * 80 + "\n" + "a" * 5 + "\n"
assert text_wrap(long_text_no_space) == expected_wrapped_no_space

# 超长行有单词
long_text_with_space = "This line has some words and then a very long sequence of characters: " + "a" * 60
expected_wrapped_with_space = "This line has some words and then a very long sequence of characters:" + "\n" +"a" * 60 + "\n"
assert text_wrap(long_text_with_space).strip() == expected_wrapped_with_space.strip()

# 多行混合
mixed_lines = "Short line\n" + "a" * 85 + "\nAnother short line that is actually quite long and needs to be wrapped properly."
expected_mixed = "Short line\n" + "a" * 80 + "\n" + "a" * 5 + "\nAnother short line that is actually quite long and needs to be wrapped properly.\n"
assert text_wrap(mixed_lines).strip() == expected_mixed.strip()

# 空字符串
assert text_wrap("").strip() == ""

print("All test cases passed!")


function isPrime(num: number): boolean {
    if (num <= 1) return false;
    if (num <= 3) return true;

    if (num % 2 === 0 || num % 3 === 0) return false;

    for (let i = 5; i * i <= num; i += 6) {
        if (num % i === 0 || num % (i + 2) === 0) return false;
    }

    return true;
}

function findFirstPrimeInRange(start: number, end: number): number | undefined {
    for (let i = start; i <= end; i++) {
        if (isPrime(i)) {
            return i;
        }
    }
}

用ts实现一个findFirstPrimeInRange的方法找出100-1000的第一个素数，用markdown包裹答案
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test } from '@jest/globals';

#<INSERT>

describe('prime numbers tests', () => {

    test('test if number is prime', () => {
        // 一些已知的素数情况
        expect(isPrime(2)).toBe(true);
        expect(isPrime(3)).toBe(true);
        expect(isPrime(5)).toBe(true);
        expect(isPrime(7)).toBe(true);
        // 非素数情况
        expect(isPrime(1)).toBe(false);
        expect(isPrime(4)).toBe(false);
        expect(isPrime(6)).toBe(false);
        expect(isPrime(8)).toBe(false);
        expect(isPrime(9)).toBe(false);
    });

    test('find first prime number between 100 and 1000', () => {
        const firstPrime = findFirstPrimeInRange(100, 1000);
        expect(firstPrime).toBeDefined();
        expect(isPrime(firstPrime as number)).toBe(true);
    });

});


import csv
from datetime import datetime

def sales_data(file_path):
    total_sales = 0
    with open(file_path, "r") as csv_file:
        csv_reader = csv.reader(csv_file)
        header = next(csv_reader)
        for row in csv_reader:
            sales_date = datetime.strptime(row[0], '%Y-%m-%d')
            if sales_date >= datetime(2021, 1, 1):
                total_sales += (int(row[2]) * int(row[3]))
    return total_sales

编写一个sales_data函数，输入为一个csv文件的地址。它包含了一家公司的销售数据。这个文件带有标题行，包含以下列：

Date (日期，格式为YYYY-MM-DD)
Product (产品名称)
Price (产品单价)
Quantity (销售数量)

读取这个文件的数据，计算2021年1月1日后的总销售额，并返回这个数值

#<INSERT>

assert sales_data("structured_io_test_data/sales_data_3.csv") == 165


编写一个text_wrap(text)函数，输入是一段字符串文本，要求对每一个超过80个字符的行进行截断、拆成若干行，使得每一行都不超过80个字符，当截断行会截断某个单词时，将整个单词挪到下一行。函数返回处理后的字符串


import subprocess
import os

def check_git(dir_path):
    # 切换到指定的目录
    original_dir = os.getcwd()
    os.chdir(dir_path)

    # 执行git命令获取更改的文件列表
    result = subprocess.run(['git', 'status', '--porcelain'], stdout=subprocess.PIPE)

    # 恢复到原始目录
    os.chdir(original_dir)

    # 解析命令输出
    changed_files = []
    for line in result.stdout.decode().splitlines():
        # 获取文件的相对路径
        file_path = line[3:]
        changed_files.append(file_path)

    return changed_files

编写一个check_git(dir_path)函数，参数是一个使用git管理的子文件夹地址，返回文件夹内（包含子文件夹内）所有已经变更的文件相对路径（相对dir_path），返回包含这些路径的list。

#<INSERT>

import zipfile
import shutil

with zipfile.ZipFile("./git_test_1.zip", "r") as zip_ref:
    zip_ref.extractall("./")

assert set(check_git("./git_test_1/")) == {'LICENSE', 'src/main.cpp'}

shutil.rmtree("./git_test_1")


def getMin(df):
    return df.loc[df.groupby('A').B.idxmin()]

我有一个包含列 A，B 和 C 的 DataFrame。对于 A 列的每个值，我想选择 B 列中值最小的那一行。

也就是说，从这个：

```python
df = pd.DataFrame({'A': [1, 1, 1, 2, 2, 2],
                   'B': [4, 5, 2, 7, 4, 6],
                   'C': [3, 4, 10, 2, 4, 6]})
    A   B   C
0   1   4   3
1   1   5   4
2   1   2   10
3   2   7   2
4   2   4   4
5   2   6   6
```

我想得到：

```
    A   B   C
0   1   2   10
1   2   4   4
```

请编写一个 Python 函数 `getMin`，该函数接受 DataFrame 变量 `df` 作为参数（列与上述示例相同），并根据我的要求返回一个 dataframe。

函数签名是：`getMin(df)`

#<INSERT>

def f(df):
    return df.loc[df.groupby('A').B.idxmin()]

import pandas as pd
import numpy as np
df = pd.DataFrame({'A': [1, 2, 2, 1, 3, 3],
                   'B': [1, 2, 3, 4, 5, 6],
                   'C': [2, 4, 6, 8, 10, 12]})
from copy import deepcopy

assert all(getMin(deepcopy(df)) == f(deepcopy(df)))


from datetime import datetime

def days_between_dates(date_str1, date_str2):
    try:
        # 将字符串转换为日期对象
        date_obj1 = datetime.strptime(date_str1, '%Y-%m-%d')
        date_obj2 = datetime.strptime(date_str2, '%Y-%m-%d')

        # 计算两个日期之间的差异
        delta = date_obj2 - date_obj1

        # 返回相差的天数
        return delta.days
    except ValueError:
        # 如果输入的日期格式不正确，返回错误信息
        return None

编写一个Python程序days_between_dates，该程序的两个参数都是格式为 YYYY-MM-DD的日期字符串，函数返回这两天相差多少天，如果第二个日期在前，则返回负数，如果任意日期不合法，则返回None


import requests

def fetch_favicon(url, filename):
    response = requests.get(url, stream=True)
    if response.status_code == 200:
        with open(filename, 'wb') as file:
            for chunk in response.iter_content(1024):
                file.write(chunk)
    else:
        print("Unable to fetch favicon: HTTP status code", response.status_code)

利用python编写函数实现网页二进制文件的抓取，实现图标 favicon 的抓取
1. 函数命名为fetch_favicon，包含两个参数，一个url表示favicon的地址，和一个filename用于保存最终的抓取结果
2. 如果网页请求成功则保存相关的favicon文件，否则打印错误信息

#pyqt_test_26

#<INSERT>

import os

def check():
    url = 'https://www.bytedance.com/favicon.ico'
    filename = 'bytedance_favicon.ico'
    fetch_favicon(url, filename)
    assert os.path.exists(filename)

check()


import requests
from concurrent.futures import ThreadPoolExecutor
def fetch_url(url):
    response = requests.get(url)
    return response.status_code

def execute_concurrently(func, urls, max_workers=5):
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        results = executor.map(func, urls)
    return list(results)

利用python编写一个网页并发请求的函数，最大并发数为5
1. 网页请求函数为fetch_url，输入为url的list，返回为网页的status_code
2. 并发请求的函数为execute_concurrently，输入为函数fetch_url和url_list

#<INSERT>

def check():
    import time
    urls = [#"http://www.baidu.com",
            "https://www.bytedance.com",
            "http://www.bing.com",
            "https://www.bytedance.com/zh/",
            "https://www.bytedance.com/zh/news",]
    expected_results = [200, 200, 200, 200]  # Assuming all URLs return HTTP 200 status code

    start_time = time.time()
    results = execute_concurrently(fetch_url, urls)
    elapsed_time = time.time() - start_time

    assert results == expected_results, f"Expected {expected_results}, but got {results}"
    assert elapsed_time < 2 * len(urls), f"Execution took longer than expected. Expected less than {2 * len(urls)} seconds, but took {elapsed_time} seconds."

    print("All tests passed.")

check()


根据以下示例，利用python编写一个页并发请求的函数，
1. 网页请求函数为fetch_url，输入为url的list，返回为网页的status_code
2. 并发请求的函数为execute_concurrently，输入为函数fetch_url和url_list


import re
def cal_n_gram(text, n_gram):
    text = text.lower()
    text = re.sub(r'[^\w\s]', '', text)
    text = re.sub(r'\s+', '', text)
    # 初始化结果列表
    result = []
    # 遍历文本，生成 N-Gram
    for n in range(1, n_gram + 1):
        for i in range(len(text) - n + 1):
            result.append(text[i:i+n])
    return result

python实现计算文档的ngram的方法 cal_n_gram(text, n_gram) ，需要对输入文本处理成小写、去掉其中的符号、空格，同时计算出1-n所有长度范围内的gram，并返回ngram计算结果的列表

#<INSERT>

def check():
    doc = "近日，长春的冬天仿佛将整个城市都冻结成了一个巨大的冰箱。在这个寒冷的季节里，就连动物园里的企鹅都感受到了东北的冷气，冻得直哆嗦，脚丫子都不敢着地。\n据报道，21日，黑龙江大部以及内蒙古中东部等地最高气温普遍不足-18℃，如同在冰箱的冷冻层，吉林东部部分地区也将在22日加入这一行列。这样的低温让人们不禁感叹，东北的冬天真是名副其实的寒冷。"
    ret = cal_n_gram(doc, 5)
    assert len(ret) == 755
    assert "企鹅都感受" in ret

check()


import matplotlib.pyplot as plt

def plot_data(data, title="line chart", xlabel="X-axis", ylabel="Y-axis"):
    x = range(len(data))
    y = data

    plt.plot(x, y)
    plt.xlabel(xlabel)
    plt.ylabel(ylabel)
    plt.title(title)
    plt.grid(True)

    return plt

python实现一维列表数据的生成折线图的方法plot_data(data, title="line chart", xlabel="X-axis", ylabel="Y-axis")，请使用matplotlib库实现该方法，data是一个一维整型列表，图的标题、横坐标、纵坐标名都由参数指定，方法返回对应图的对象

#<INSERT>

def check():
    # 示例用法

    data = [1, 3, 5, 2, 4, 19, 20]
    plt_obj = plot_data(data, "折线图", "班级人数变化", "数量")
    ax = plt_obj.gca()
    assert ax.get_title() == "折线图"
    assert ax.get_xlabel() == "班级人数变化"

check()


export function stringToNumber(str: string): number {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
        const character = str.charCodeAt(i);
        hash = (hash << 5) - hash + character;
        hash |= 0; // Convert to 32bit integer
    }
    return hash;
}

在TypeScript中如何将一段字符串转成一段唯一对应的number类型数字？方法名为heapSort，用markdown包裹答案
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test } from '@jest/globals';

#<INSERT>

describe('heapSort', () => {
    test('converts a string to a unique number', () => {
        const testString = "testString";
        const result = heapSort(testString);
        expect(typeof result).toBe('number');
    });

    test('produces consistent results for the same input', () => {
        const testString = "consistent";
        const result1 = heapSort(testString);
        const result2 = heapSort(testString);
        expect(result1).toBe(result2);
    });

    test('produces different numbers for different strings', () => {
        const string1 = "string1";
        const string2 = "string2";
        const result1 = heapSort(string1);
        const result2 = heapSort(string2);
        expect(result1).not.toBe(result2);
    });
});


function traverseNestedArray(arr: any[], callback: (item: any) => void): void {
    arr.forEach((item) => {
        if (Array.isArray(item)) {
            traverseNestedArray(item, callback);
        } else {
            callback(item);
        }
    });
}

在TypeScript中，如何递归遍历嵌套数组？ 方法名为traverseNestedArray，用markdown包裹答案
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test, jest } from '@jest/globals';

#<INSERT>

describe('traverseNestedArray', () => {
    test('should call callback for each non-array item in a nested array', () => {
        const nestedArray = [1, [2, [3, 4], 5], [6]];
        const mockCallback = jest.fn();

        traverseNestedArray(nestedArray, mockCallback);

        expect(mockCallback.mock.calls.length).toBe(6);
        expect(mockCallback).toHaveBeenNthCalledWith(1, 1);
        expect(mockCallback).toHaveBeenNthCalledWith(2, 2);
        expect(mockCallback).toHaveBeenNthCalledWith(3, 3);
        expect(mockCallback).toHaveBeenNthCalledWith(4, 4);
        expect(mockCallback).toHaveBeenNthCalledWith(5, 5);
        expect(mockCallback).toHaveBeenNthCalledWith(6, 6);
    });

    test('should handle an empty array', () => {
        const emptyArray: any[] = [];
        const mockCallback = jest.fn();

        traverseNestedArray(emptyArray, mockCallback);

        expect(mockCallback.mock.calls.length).toBe(0);
    });

    // More tests can be added to test for specific edge cases
});


import argparse

def get_parser():
    parser = argparse.ArgumentParser(description="Process command line arguments.", exit_on_error=False)

    # 添加必选参数
    parser.add_argument("--num", type=int, required=True, help="Number")

    return parser

定义一个get_parser()函数，它返回一个argparser，支持下面的命令行格式处理：

--num NUM

其中，num是一个必选参数，类型为整数。

当num的类型无法转换为整数时，程序不会自动退出。

#<INSERT>

from argparse import ArgumentError
parser = get_parser()

command_line = "--num 12".split(" ")
assert parser.parse_args(command_line).num == 12

exception_got = False
command_line = "--num string".split(" ")
try:
    parser.parse_args(command_line)
except ArgumentError:
    exception_got = True
assert exception_got


def replace(x, n):
    zero_positions = [i for i in range(x.bit_length()) if (x & (1 << i)) == 0]
    ret = x
    k = 0
    for pos in zero_positions:
        if n & (1 << k):
            ret += (1 << pos)
        k += 1
    return ret

给定一个整数x，得到x的二进制表示，然后在二进制表示中0的位置上填入一个数n，得到新的整数。比如 110001 如果在0的位置填入 2 (010)，就变成 110101。
用 python 实现，函数定义是 `replace(x, n)`


import pandas as pd

def read_excel(file_name, sheet_name):
    # 读取Excel文件
    df = pd.read_excel(file_name, sheet_name=sheet_name)

    # 按行读取数据并打印
    output = []
    for index, row in df.iterrows():
        output.append(list(row))
    return output

使用python实现读取excel文件，文件名由参数输入，并指定sheet，按行读取数据并返回一个二维数组，实现函数 `read_excel(file_name, sheet_name)`

#<INSERT>

def check():
    path = "file_test_2/data.xlsx"
    sheet = "用户消费数据"
    ret = read_excel(path, sheet)
    assert ret[0][0] == "用户1"
    assert ret[2][1] == 15

check()


import requests

def http_client(url, method='GET', filename='response.txt'):
    response = requests.request(method, url)
    with open(filename, 'w') as file:
        file.write(response.text)
    return response.text

用Python编写的简单HTTP客户端函数http_client。这个函数的参数为url，method，以及filename用于保存响应，并返回服务器的响应。
1. 要求返回服务器的文本信息
2. 要求将文本信息保存成txt文件

#pyqt_test_30

#<INSERT>

def check():
    import os
    url = 'http://example.com'
    filename = 'test_response.txt'
    response = http_client(url, filename=filename)
    assert 'Example Domain' in response
    with open(filename, 'r') as file:
        file_content = file.read()
    assert 'Example Domain' in file_content
    if os.path.exists(filename):  # 清理测试文件
        os.remove(filename)

check()


function maxInArray(numbers: number[]): number {
    if (!Array.isArray(numbers) || numbers.length === 0) {
        throw new Error("Input must be a non-empty array of numbers.");
    }
    return Math.max(...numbers);
}

TypeScript获取数组中的最大值 ，方法名为maxInArray，用markdown包裹答案
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test } from '@jest/globals';

#<INSERT>

describe('maxInArray', () => {
    test('should return the maximum value in an array of numbers', () => {
        const numbers = [1, 3, 2, 5, 4];
        expect(maxInArray(numbers)).toBe(5);
    });

    test('should return the maximum value when array contains negative values', () => {
        const numbers = [-10, -3, -1, -7];
        expect(maxInArray(numbers)).toBe(-1);
    });

    test('should throw an error for an empty array', () => {
        const emptyArray: number[] = [];
        expect(() => maxInArray(emptyArray)).toThrow("Input must be a non-empty array of numbers.");
    });

    test('should return the value itself if the array has only one number', () => {
        const singleValueArray = [7];
        expect(maxInArray(singleValueArray)).toBe(7);
    });

    // Add more tests if necessary
});


function toUpperCase(input: string): string {
    return input.toUpperCase();
}

function toLowerCase(input: string): string {
    return input.toLowerCase();
}

ts大小写转换，小写转大写方法名为“toUpperCase”，大写转小写方法名为：“toLowerCase”，用markdown包裹答案
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test } from '@jest/globals';

#<INSERT>

describe('String Case Conversion', () => {

    test('should convert string to uppercase', () => {
        const input = 'TypeScript is awesome!';
        const expectedOutput = 'TYPESCRIPT IS AWESOME!';
        expect(toUpperCase(input)).toBe(expectedOutput);
    });

    test('should convert string to lowercase', () => {
        const input = 'TypeScript is AWESOME!';
        const expectedOutput = 'typescript is awesome!';
        expect(toLowerCase(input)).toBe(expectedOutput);
    });

    test('should not change case for uppercase string when converting to uppercase', () => {
        const input = 'ALREADY UPPERCASE';
        expect(toUpperCase(input)).toBe(input);
    });

    test('should not change case for lowercase string when converting to lowercase', () => {
        const input = 'already lowercase';
        expect(toLowerCase(input)).toBe(input);
    });

    test('should correctly handle empty string', () => {
        const input = '';
        expect(toUpperCase(input)).toBe('');
        expect(toLowerCase(input)).toBe('');
    });
});


// 定义字符串字面量类型
type StringLiteral = 'myStringLiteral';

// 创建一个具有该字符串字面量类型的变量
const myLiteral: StringLiteral = 'myStringLiteral';

在TypeScript中，如何定义一个字符串字面量类型的变量？字符串字面量为myStringLiteral，用markdown包裹答案
请将答案代码用 markdown code block 格式包裹，如
```typescript
[code]
```

import { describe, expect, test } from '@jest/globals';

#<INSERT>

describe('String Literal Type', () => {
  test('should only allow the specified string literal', () => {
    expect(myLiteral).toBe('myStringLiteral');
  });

  // 如果需要检验类型，可以使用TS的类型检查，但在运行时无法这样测试。
});


#L1_C_57
from rdkit import Chem
import itertools
from rdkit.Chem import rdRGroupDecomposition
from rdkit.Chem import rdFMCS

def enumerate_all_products(core, rgroups):
    # preserve the positions of the non-dummy core atoms,
    # Python's itertools handles doing the combinatorics of generating
    # every possible combination of R groups:
    order = itertools.product(*rgroups)
    # now we just loop over each combination, copy all the pieces into
    # one molecule, and zip it. That's our product
    for tpl in order:
        tm = Chem.RWMol(core)
        for r in tpl:
            tm.InsertMol(r)
        prod = Chem.molzip(tm)
        if prod is not None:
            # and finally yield the product molecule
            yield prod

def solve(smiles_lst):
    mols = [Chem.MolFromSmiles(smi) for smi in smiles_lst]
    res = Chem.MolFromSmarts(rdFMCS.FindMCS(mols).smartsString)

    rgd, failed = rdRGroupDecomposition.RGroupDecompose([res], mols, asRows=False)
    all_r_groups = []
    core = rgd['Core'][0]
    for k, v in rgd.items():
        if k == 'Core':
            continue
        r_groups = set()
        for r_group in v:
            r_groups.add(Chem.MolToSmiles(r_group))
        all_r_groups.append([Chem.MolFromSmiles(i) for i in r_groups])
    prod_gen = enumerate_all_products(core, all_r_groups)
    prod_smi_set = set([Chem.CanonSmiles(Chem.MolToSmiles(i)) for i in prod_gen])
    return prod_smi_set

请写一个完整的Python函数`solve(smiles_lst)`, 输入一个分子的SMILES的列表，
包含一组有共同母核结构的分子SMILES，将它们连接到母核上的取代基切下来，
再以取代基组合枚举的方式拼接回母核结构原本的取代基位点上，
产生一组新的分子，返回这组新分子正则化SMILES（canonical SMILES）的集合（输入的分子结构也会被枚举到，所以也包含在内）。
例如在两个分子上有R1和R2个取代基位点，
它们在R1位点上有{A, B}两种取代基,  在R2位点上有{B, C, D}三种取代基，
那么会枚举出6种R1, R2的取代基组合[[A, B], [A, C], [A, D], [B, B], [B, C], [B, D]]，
将它们拼接到两个分子的共同母核上产生6个分子结构
已知在RDKit中，rdkit.Chem.rdFMCS.FindMCS()可以找到一组分子的最大公共子结构；
rdkit.Chem.rdRGroupDecomposition.RGroupDecompose()函数
可以将一个分子分解成核心部分(Core)和取代基部分(R groups)；
rdkit.Chem.molzip()函数可以将标记有连接位点的片段和母核进行拼接；
rdkit.Chem.CanonSmiles()可以将SMILES正则化。

#<INSERT>

def check(solve):
    result1 = solve(['CCc1cccc(Cl)c1', 'CCc1cccc(Br)c1', 'COc1cc(N)cc(F)c1'])
    assert result1 == {'COc1cccc(Cl)c1', 'CCc1cccc(Br)c1', 'COc1cc(N)cc(F)c1',
                       'CCc1cc(N)cc(Cl)c1', 'COc1cc(N)cc(Cl)c1', 'CCc1cc(N)cc(Br)c1',
                       'CCc1cccc(Cl)c1', 'CCc1cccc(F)c1', 'COc1cccc(F)c1',
                       'COc1cc(N)cc(Br)c1', 'COc1cccc(Br)c1', 'CCc1cc(N)cc(F)c1'} or \
           result1 == {'CCc1cc(N)cc(Br)c1', 'CCc1cc(N)cc(Cl)c1', 'CCc1cc(N)cc(F)c1',
                       'COc1cc(N)cc(Br)c1', 'COc1cc(N)cc(Cl)c1', 'COc1cc(N)cc(F)c1',
                       '[H]c1cc(Br)cc(CC)c1', '[H]c1cc(Br)cc(OC)c1', '[H]c1cc(Cl)cc(CC)c1',
                       '[H]c1cc(Cl)cc(OC)c1', '[H]c1cc(F)cc(CC)c1', '[H]c1cc(F)cc(OC)c1'}

    result2 = solve(['CC(C)C(C)c1ccc(O)cc1', 'CC(C)C(C)c1cccc(O)c1', 'CC(C)C(C)c1ccc(Cl)c(O)c1', 'CC(C)C(C)c1ccc(Cl)c(N)c1'])
    assert result2 == {'CC(C)C(C)c1ccc(O)c(O)c1', 'CC(C)C(C)c1ccc(Cl)cc1', 'CC(C)C(C)c1ccc(O)cc1',
                       'CC(C)C(C)c1ccc(O)c(N)c1', 'CC(C)C(C)c1cccc(O)c1', 'CC(C)C(C)c1ccc(Cl)c(O)c1',
                       'CC(C)C(C)c1ccccc1', 'CC(C)C(C)c1cccc(N)c1', 'CC(C)C(C)c1ccc(Cl)c(N)c1'} or \
           result2 == {'CC(C)C(C)c1ccc(O)c(O)c1', 'CC(C)C(C)c1ccc(Cl)c(O)c1', 'CC(C)C(C)c1ccc(Cl)c(N)c1',
                       '[H]c1cc(C(C)C(C)C)ccc1Cl', '[H]c1cc(C(C)C(C)C)ccc1O', 'CC(C)C(C)c1ccc(O)c(N)c1',
                       '[H]c1ccc(C(C)C(C)C)cc1O', '[H]c1ccc(C(C)C(C)C)cc1N', '[H]c1ccc(C(C)C(C)C)cc1[H]'}

check(solve)


#L1_B_61
from rdkit import Chem
from rdkit.Chem import Descriptors, Lipinski
def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    if mol is None:
        return "Invalid SMILES string"

    # 计算分子属性
    mol_weight = Descriptors.MolWt(mol)
    logP = Descriptors.MolLogP(mol)
    h_donors = Lipinski.NumHDonors(mol)
    h_acceptors = Lipinski.NumHAcceptors(mol)
    tpsa = Descriptors.TPSA(mol)
    rotatable_bonds = Lipinski.NumRotatableBonds(mol)
    # 检查所有环的大小是否不超过6
    ring_sizes = [len(ring) for ring in mol.GetRingInfo().AtomRings()]
    max_ring_size = max(ring_sizes) if ring_sizes else 0
    # 检查条件是否满足
    conditions_met = (
        250 <= mol_weight <= 700,
        0 <= logP <= 5,
        h_donors <= 5,
        h_acceptors <= 10,
        tpsa <= 150,
        rotatable_bonds <= 9,
        max_ring_size <= 6
    )
    # 返回结果
    if all(conditions_met):
        return True
    else:
        return False

在药物筛选中，我们通常需要分子满足下列条件使其有更高的类药性：分子量在250到700之间，logP在0到5之间，氢键供体的数目不大于5个，氢键受体的数目不大于10个，分子的TPSA不大于150，分子的可旋转键不多于9个，并且所有环的大小不超过6。请实现一个完整的Python函数`solve(smiles)`，输入为一个分子的SMILES，判断分子是否满足上面的所有规则，返回True/False。
其中，我们可以使用`rdkit.Chem.Descriptors`模块下的`MolWt`、`MolLogP`以及`TPSA`函数来分别计算分子的分子量、LogP、TPSA值，使用rdkit.Chem.Lipinski模块下的`NumHDonors`、`NumHAcceptors`、`NumRotatableBonds`函数来计算分子中的氢键供体、氢键受体以及可旋转键的数目，使用`GetRingInfo`函数来获取分子中的环的信息。

#<INSERT>

def check(solve):
    assert solve('COc1ccccc1CNC(=O)CS(=O)(=O)CCCc1ccccc1') == True
    assert solve('CCOC(=O)C1CCN(CC1)C(=O)c1nnn(c1)c1ccc(cc1)C') == True
    assert solve('C[C@H]1C[C@@H]1CNS(=O)(=O)c1cccs1') == False
    assert solve('COc1ccc(cc1Cl)NC(=O)c1cc2c(o1)c(Br)ccc2') == False

check(solve)


#L1_C_19
from rdkit import Chem
from rdkit.Chem import ChemicalFeatures
from rdkit import RDConfig
import os

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    mol = Chem.AddHs(mol)
    fdefName = os.path.join(RDConfig.RDDataDir,'BaseFeatures.fdef')
    factory = ChemicalFeatures.BuildFeatureFactory(fdefName)
    feats = factory.GetFeaturesForMol(mol)

    don_set = set()
    acc_set = set()
    for feat in feats:
        if feat.GetFamily() == 'Donor':
            don_set.update(feat.GetAtomIds())
        elif feat.GetFamily() == 'Acceptor':
            acc_set.update(feat.GetAtomIds())

    inner_hb = 0
    used_acc_set = set()
    for i in don_set:
        for j in acc_set:
            if i == j:
                continue
            if j in used_acc_set:
                continue
            path = Chem.GetShortestPath(mol, i, j)
            if len(path) - 1 == 4 or len(path) - 1 == 5:
                inner_hb += 1
                used_acc_set.add(j)
                break
    return inner_hb

定义一个分子中如果有间隔4或5根化学键的氢键供体和受体，就可能形成一个分子内氢键。请写一个完整的Python函数`solve(smiles)`，根据2D拓扑结构判断分子中有可能形成多少个分子内氢键。
其中，氢键的供体和受体可以先通过ChemicalFeatures模块得到MolChemicalFeature，并根据`GetFamily`方法确定为Donar或Acceptor。两个原子之间的化学键间隔数，可以通过`Chem.GetShortestPath`函数来计算得到

#<INSERT>

def check(solve):
    assert solve('CC(O)C(\C)=C/c1cc(ccn1)-c1cc(C)ccc1N') == 1
    assert solve('CC(=O)OC(C(C)N)C(C)CO') == 2

check(solve)


#L2_C_24
from rdkit import Chem

def neutralize_atoms(mol):
    pattern = Chem.MolFromSmarts("[+1!h0!$([*]~[-1,-2,-3,-4]),-1!$([*]~[+1,+2,+3,+4])]")
    at_matches = mol.GetSubstructMatches(pattern)
    at_matches_list = [y[0] for y in at_matches]
    if len(at_matches_list) > 0:
        for at_idx in at_matches_list:
            atom = mol.GetAtomWithIdx(at_idx)
            chg = atom.GetFormalCharge()
            hcount = atom.GetTotalNumHs()
            atom.SetFormalCharge(0)
            atom.SetNumExplicitHs(hcount - chg)
            atom.UpdatePropertyCache()
    return mol

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    mol = neutralize_atoms(mol)
    new_smiles = Chem.MolToSmiles(mol)
    return new_smiles

#<INSERT>

def check(solve):
    assert solve('C[NH+](C)CC[S-]') == 'CN(C)CCS'
    assert solve('CP([O-])(=O)OC[NH3+]') == 'CP(=O)(O)OCN'

check(solve)


#L1_B_58
from rdkit import Chem
from rdkit.Chem.Scaffolds import MurckoScaffold
from rdkit.Chem import AllChem
from rdkit import DataStructs

def solve(smiles_lst):
    new_mols = []
    for smiles in smiles_lst:
        mol = Chem.MolFromSmiles(smiles)
        scaff = MurckoScaffold.GetScaffoldForMol(mol)
        new_mols.append(scaff)

    simi_lst = []
    for idx, mol1 in enumerate(new_mols):
        fp1 = AllChem.GetMorganFingerprintAsBitVect(mol1, 2, nBits=1024)
        for mol2 in new_mols[idx+1:]:
            fp2 = AllChem.GetMorganFingerprintAsBitVect(mol2, 2, nBits=1024)
            simi = DataStructs.TanimotoSimilarity(fp1,fp2)
            simi_lst.append(simi)
    mean_simi = round(sum(simi_lst)/len(simi_lst), 4)
    return mean_simi

#<INSERT>

def check(solve):
    assert solve(['CC(c1ccccc1)C(CCl)C(C)c1ccccc1', 'CC(c1ccccc1)C(CNC1CC1)C(c1ccccc1)C1CCCC1', 'COC(C)C(N)C(C(CO)c1ccccc1)C1CCCC1C']) == 0.3302
    assert solve(['CCC(CC)c1ccccc1', 'Cc1cccc(-c2ccc(F)cc2)c1', 'CC(C)c1ccccc1-c1ccccc1C(C)Cc1cccc2c1CCC2']) == 0.2267

check(solve)


#L0_B_61
from rdkit import Chem
from rdkit.Chem import Descriptors, Lipinski
def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    if mol is None:
        return "Invalid SMILES string"

    # 计算分子属性
    mol_weight = Descriptors.MolWt(mol)
    logP = Descriptors.MolLogP(mol)
    h_donors = Lipinski.NumHDonors(mol)
    h_acceptors = Lipinski.NumHAcceptors(mol)
    tpsa = Descriptors.TPSA(mol)
    rotatable_bonds = Lipinski.NumRotatableBonds(mol)
    # 检查所有环的大小是否不超过6
    ring_sizes = [len(ring) for ring in mol.GetRingInfo().AtomRings()]
    max_ring_size = max(ring_sizes) if ring_sizes else 0
    # 检查条件是否满足
    conditions_met = (
        250 <= mol_weight <= 700,
        0 <= logP <= 5,
        h_donors <= 5,
        h_acceptors <= 10,
        tpsa <= 150,
        rotatable_bonds <= 9,
        max_ring_size <= 6
    )
    # 返回结果
    if all(conditions_met):
        return True
    else:
        return False

在药物筛选中，我们通常需要分子满足下列条件使其有更高的类药性：分子量在250到700之间，logP在0到5之间，氢键供体的数目不大于5个，氢键受体的数目不大于10个，分子的TPSA不大于150，分子的可旋转键不多于9个，并且所有环的大小不超过6。请实现一个完整的Python函数`solve(smiles)`，输入为一个分子的SMILES，判断分子是否满足上面的所有规则，返回True/False。


#L0_B_62
from rdkit import Chem
from rdkit import DataStructs
from rdkit.Chem import AllChem

def is_similar(smiles):
    # 将一个分子的smiles转成rdkit Mol对象
    mol = Chem.MolFromSmiles(smiles)

    # 计算一个Mol对象2048 Bits的ECFP4分子指纹，并且比较与"NCc1ccc2c(N(C/C(=C/c3ccccc3)c3ccc(Cl)cc3)c3cc(Br)c4oc(C(=O)O)cc4c3)[nH]nc2c1"分子之间的Tonimoto相似度
    ref_mol = Chem.MolFromSmiles("NCc1ccc2c(N(C/C(=C/c3ccccc3)c3ccc(Cl)cc3)c3cc(Br)c4oc(C(=O)O)cc4c3)[nH]nc2c1")
    fp_ref = AllChem.GetMorganFingerprintAsBitVect(ref_mol, 2, nBits=2048)
    fp_mol = AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048)
    similarity = DataStructs.TanimotoSimilarity(fp_ref, fp_mol)

    # 判断一个值是否大于0.5，返回True或False
    flag = similarity > 0.5

    return flag

写一个完整的python函数`is_similar(smiles)`，输入一个分子，
计算它和分子"NCc1ccc2c(N(C/C(=C/c3ccccc3)c3ccc(Cl)cc3)c3cc(Br)c4oc(C(=O)O)cc4c3)[nH]nc2c1"相似度，
如果相似度>0.5，返回True，否则返回False。
相似度定义为两个分子ECFP4 2048 bits指纹的Tanimoto similarity。

#<INSERT>

def check(is_similar):
    assert is_similar("NCc1ccc2c(N(C/C(=C/c3ccccc3)c3ccc(Cl)cc3)c3cc(Br)c4oc(C(=O)O)cc4c3)[nH]nc2c1")
    assert is_similar("NCc1ccc2c(N(C/C(=C/c3ccccc3)c3ccc(Cl)cc3)c3cc(Br)c4occc4c3)[nH]nc2c1")
    assert is_similar("NCc1ccc2c(N(C/Cc3ccc(Cl)cc3)c3cc(Br)c4occc4c3)[nH]nc2c1")
    assert is_similar("NCc1ccc2c(N(C/C=C/c3ccccc3)c3cc(Br)c4occc4c3)[nH]nc2c1")
    assert not is_similar("NCc1ccc2c(Nc3cc(Br)c4occc4c3)[nH]nc2c1")
    assert is_similar("NCc1ccc2c(N(C/Cc3ccc(Cl)cc3)c3cc(Br)c4oc(C(=O)O)cc4c3)[nH]nc2c1")
    assert not is_similar('c1ccccc1')

check(is_similar)


#L2_B_28
from rdkit import Chem
from rdkit.Chem.Lipinski import RotatableBondSmarts

def decompose_mol(mol):
    rot_atom_pairs = mol.GetSubstructMatches(RotatableBondSmarts)
    bond_indices = list(set([mol.GetBondBetweenAtoms(*ap).GetIdx() for ap in rot_atom_pairs]))

    all_frags_set = set()
    i = Chem.FragmentOnBonds(mol, bond_indices)
    frags = Chem.GetMolFrags(i, asMols=True)
    for frag in frags:
        frag_smi = Chem.MolToSmiles(frag)
        all_frags_set.add(frag_smi)
    return all_frags_set

def solve(smiles):
    m = Chem.MolFromSmiles(smiles)
    return decompose_mol(m)


#L1_C_59
from rdkit import Chem
from itertools import combinations
from rdkit import DataStructs

def solve(smiles, N=1):
    mol = Chem.MolFromSmiles(smiles)
    out_mol_list = []
    used = set()
    aromatic_cH = Chem.MolFromSmarts("[cH]")
    match_atms = [x[0] for x in mol.GetSubstructMatches(aromatic_cH)]
    n_combos = combinations(match_atms, N)
    for combo in n_combos:
        new_mol = Chem.RWMol(mol)
        for idx in combo:
            atm = new_mol.GetAtomWithIdx(idx)
            atm.SetAtomicNum(7)
        smi = Chem.MolToSmiles(new_mol)
        if smi not in used:
            used.add(smi)
            out_mol_list.append(new_mol)
    return used

请写一个完整的Python函数`solve(smiles, N)`, 输入一个分子的SMILES，以及氮的数量(N)，
将这个分子中的"N"个无取代基的芳香碳原子（这些碳原子与1个氢原子相连）替换为氮原子，
返回进行该替换可能产生的所有分子结构的SMILES的集合。已知要被替换的芳香碳原子可以通过SMARTS "[cH]" 进行匹配。

#<INSERT>

def check(solve):
    assert solve('CCc1cc(C)ccn1', 1) == {'CCc1cc(C)ncn1', 'CCc1nccc(C)n1', 'CCc1cc(C)cnn1'}
    assert solve('CC(C)CC1C=Cc2c(F)cccc21', 2) == {'CC(C)CC1C=Cc2c(F)ncnc21', 'CC(C)CC1C=Cc2c1cnnc2F', 'CC(C)CC1C=Cc2c(F)cnnc21'}
    assert solve('CC(CC1N=Cc2c(F)cccc21)n1cccc1', 2) == {'CC(CC1N=Cc2c1ccnc2F)n1ccnc1', 'CC(CC1N=Cc2c1cnnc2F)n1cccc1', 'CC(CC1N=Cc2c(F)cnnc21)n1cccc1',
                                                  'CC(CC1N=Cc2c1ccnc2F)n1cccn1', 'CC(CC1N=Cc2c(F)ccnc21)n1cccn1', 'CC(CC1N=Cc2c(F)cccc21)n1ccnn1',
                                                  'CC(CC1N=Cc2c(F)cncc21)n1cccn1', 'CC(CC1N=Cc2c(F)ccnc21)n1ccnc1', 'CC(CC1N=Cc2c(F)ncnc21)n1cccc1',
                                                  'CC(CC1N=Cc2c(F)cncc21)n1ccnc1', 'CC(CC1N=Cc2c(F)cccc21)n1nccn1', 'CC(CC1N=Cc2c(F)cccc21)n1cnnc1',
                                                  'CC(CC1N=Cc2c(F)cccc21)n1cncn1'}

check(solve)


#L1_B_28
from rdkit import Chem
from rdkit.Chem.Lipinski import RotatableBondSmarts

def decompose_mol(mol):
    rot_atom_pairs = mol.GetSubstructMatches(RotatableBondSmarts)
    bond_indices = list(set([mol.GetBondBetweenAtoms(*ap).GetIdx() for ap in rot_atom_pairs]))

    all_frags_set = set()
    i = Chem.FragmentOnBonds(mol, bond_indices)
    frags = Chem.GetMolFrags(i, asMols=True)
    for frag in frags:
        frag_smi = Chem.MolToSmiles(frag)
        all_frags_set.add(frag_smi)
    return all_frags_set

def solve(smiles):
    m = Chem.MolFromSmiles(smiles)
    return decompose_mol(m)


#L2_B_9
from rdkit.Chem import AllChem
from rdkit import Chem
from rdkit.Chem.Lipinski import RotatableBondSmarts

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    patt = Chem.MolFromSmarts('c1ccccc1')
    repl = Chem.MolFromSmiles('[H]')
    rms = AllChem.ReplaceSubstructs(mol, patt, repl, replaceAll=True)[0]
    rms = Chem.MolFromSmiles(Chem.MolToSmiles(rms))
    rot_atom_pairs = rms.GetSubstructMatches(RotatableBondSmarts)
    bond_indices = set([rms.GetBondBetweenAtoms(*ap).GetIdx() for ap in rot_atom_pairs])
    return len(bond_indices)

已知苯环的smarts为"c1ccccc1"，氢原子的smarts为"[H]"，使用`from rdkit.Chem.Lipinski import RotatableBondSmarts`可以获得可旋转键的smarts定义。
请写一个完整的Python函数`solve(smiles)`，输入一个SMILES，先使用`AllChem.ReplaceSubstructs`函数将分子中的每个末端的苯环结构都替换为一个氢原子，
再根据`GetSubstructMatches`函数获取分子所有的可旋转键，去重后返回可旋转键数目

#<INSERT>

def check(solve):
    assert solve('CCN(c1ccccc1)C1CC(OC)CN1') == 3
    assert solve('CCC1C(OC)C(c2ccccc2)C(N(C)c2ccccc2)N1CC') == 4
    assert solve('CC1CCCCC1NC') == 1

check(solve)


#L2_C_26
from rdkit import Chem

def GetRingSystems(mol, includeSpiro=True):
    ri = mol.GetRingInfo()
    systems = []
    for ring in ri.AtomRings():
        ringAts = set(ring)
        nSystems = []
        for system in systems:
            nInCommon = len(ringAts.intersection(system))
            if nInCommon and (includeSpiro or nInCommon>1):
                ringAts = ringAts.union(system)
            else:
                nSystems.append(system)
        nSystems.append(ringAts)
        systems = nSystems
    return systems

def solve(smiles):
    m = Chem.MolFromSmiles(smiles)
    systems = GetRingSystems(m)
    return len(systems)

请写一个完整的Python函数`solve(smiles)`, 输入一个分子的SMILES，计算其中环体系的数量，有共享相同原子的多个环都会被视为一个环体系。
可以通过mol.GetRingInfo().AtomRings()获取所有的环原子的索引，然后双循环遍历这些环原子索引，两两比较是否存在交集，如果存在交集，则合并为一个环体系。

#<INSERT>

def check(solve):
    assert solve('Nc1cc(-c2cccc3c2CCC3)c(C(=O)O)cc1C1CCCC1') == 3
    assert solve('CN1C(=O)CN=C(c2ccccc2)c2cc(Cl)ccc21') == 2
    assert solve('c1ccccc1') == 1

check(solve)


#L0_C_59
from rdkit import Chem
from itertools import combinations
from rdkit import DataStructs

def solve(smiles, N=1):
    mol = Chem.MolFromSmiles(smiles)
    out_mol_list = []
    used = set()
    aromatic_cH = Chem.MolFromSmarts("[cH]")
    match_atms = [x[0] for x in mol.GetSubstructMatches(aromatic_cH)]
    n_combos = combinations(match_atms, N)
    for combo in n_combos:
        new_mol = Chem.RWMol(mol)
        for idx in combo:
            atm = new_mol.GetAtomWithIdx(idx)
            atm.SetAtomicNum(7)
        smi = Chem.MolToSmiles(new_mol)
        if smi not in used:
            used.add(smi)
            out_mol_list.append(new_mol)
    return used

请写一个完整的Python函数`solve(smiles, N)`, 输入一个分子的SMILES，以及氮的数量(N)，
将这个分子中的"N"个无取代基的芳香碳原子（这些碳原子与1个氢原子相连）替换为氮原子，
返回进行该替换可能产生的所有分子结构的SMILES的集合。


#L1_B_16
from rdkit import Chem
from rdkit.Chem import ChemicalFeatures
from rdkit import RDConfig
import os

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    fdefName = os.path.join(RDConfig.RDDataDir,'BaseFeatures.fdef')
    factory = ChemicalFeatures.BuildFeatureFactory(fdefName)
    feats = factory.GetFeaturesForMol(mol)

    hyd_atoms = set()
    for feat in feats:
        if feat.GetFamily() == 'Hydrophobe' or feat.GetFamily() == 'LumpedHydrophobe':
            hyd_atoms.update(feat.GetAtomIds())
    return len(hyd_atoms)


#L0_B_55
from rdkit import Chem
from rdkit.Chem import AllChem
from rdkit import DataStructs

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    if mol is None:
        return None
    rxn_dBOC = AllChem.ReactionFromSmarts("[#7:1][CX3:2](=[OD1])[OD2]C([CH3])([CH3])[CH3]>>[#7:1][H:2]")

    mol.UpdatePropertyCache()
    prod = rxn_dBOC.RunReactants([mol])
    if prod:
        prod = prod[0][0]
        Chem.SanitizeMol(prod)

    fp1 = AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048)
    fp2 = AllChem.GetMorganFingerprintAsBitVect(prod, 2, nBits=2048)
    simi = DataStructs.TanimotoSimilarity(fp1,fp2)
    return round(simi, 3)

实现一个完整的Python函数`solve(smiles)`，输入为一个分子的SMILES，脱去分子中的Boc保护基，并计算前后分子2048位ECFP4指纹的Tanimoto相似度，结果保留3位小数。

#<INSERT>

def check(solve):
    assert abs(solve('Cc1ccccc1CNC(=O)OC(C)(C)C') - 0.3333) < 1e-3
    assert abs(solve('CCC(C)CCNC(=O)OC(C)(C)C') - 0.2778) < 1e-3
    assert abs(solve('CCN(C)C(=O)OC(C)(C)C') - 0.1071) < 1e-3

check(solve)


#L2_B_4
from rdkit.Chem import AllChem
from rdkit import Chem

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    if mol is None:
        return None
    rxn_dBOC = AllChem.ReactionFromSmarts("[#7:1][CX3:2](=[OD1])[OD2]C([CH3])([CH3])[CH3]>>[#7:1][H:2]")

    mol.UpdatePropertyCache()
    prod = rxn_dBOC.RunReactants([mol])
    if prod:
        mol = prod[0][0]

    new_smi = Chem.MolToSmiles(mol)
    new_smi = Chem.CanonSmiles(new_smi)
    return new_smi

#<INSERT>

def check(solve):
    result1 = solve('Cc1ccccc1CNC(=O)OC(C)(C)C')
    result2 = solve('CCC(C)CCNC(=O)OC(C)(C)C')
    result3 = solve('CCN(C)C(=O)OC(C)(C)C')
    assert result1 == 'Cc1ccccc1CN' or result1 == '[H]NCc1ccccc1C'
    assert result2 == 'CCC(C)CCN' or result2 == '[H]NCCC(C)CC'
    assert result3 == 'CCNC' or result3 == '[H]N(C)CC'

check(solve)


#L2_A_30
from rdkit import Chem

def solve(core, chains):
    core = Chem.MolFromSmiles(core)
    chainMols = [Chem.MolFromSmiles(chain) for chain in chains]

    product_smi = []
    for chainMol in chainMols:
        product_mol = Chem.ReplaceSubstructs(core,Chem.MolFromSmarts('[#0]'),chainMol)
        product_smi.append(Chem.MolToSmiles(product_mol[0]))
    return set(product_smi)

请写一个完整的Python函数`solve(cores, chains)`, 输入一个带有连接位点"*"符号的片段SMILES (core)，以及包含多个片段SMILES的列表(chains)，返回将每个chain片段中的第一个原子连接到core片段得到的分子SMILES集合。
连接可以通过将"*"原子替换为chain片段实现， 匹配"*"原子的SMARTS是"[#0]"。 通过Chem.ReplaceSubstructs()函数可以做片段替换，
这个函数接收3个参数：要执行替换的mol对象（这里应用core片段），要被替换的mol对象（这里就用Chem.MolFromSmarts('[#0]'), 即"*"原子）， 以及要被替换成的mol对象（这里就是chain片段）。

#<INSERT>

def check(solve):
    assert solve('*[n+]1cc[nH]c1', ['C','CC','CCC','CCCN']) == {'CCC[n+]1cc[nH]c1', 'C[n+]1cc[nH]c1', 'CC[n+]1cc[nH]c1', 'NCCC[n+]1cc[nH]c1'}
    assert solve('Nc1cc(*)ccc1', ['C','O','C#N','N#C']) == {'Nc1cccc(O)c1', 'C#Nc1cccc(N)c1', 'N#Cc1cccc(N)c1', 'Cc1cccc(N)c1'}
    assert solve('CCC*', ['Cl','O','C=C']) == {'CCCO', 'CCCCl', 'C=CCCC'}

check(solve)


#L1_B_9
from rdkit.Chem import AllChem
from rdkit import Chem
from rdkit.Chem.Lipinski import RotatableBondSmarts

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    patt = Chem.MolFromSmarts('c1ccccc1')
    repl = Chem.MolFromSmiles('[H]')
    rms = AllChem.ReplaceSubstructs(mol, patt, repl, replaceAll=True)[0]
    rms = Chem.MolFromSmiles(Chem.MolToSmiles(rms))
    rot_atom_pairs = rms.GetSubstructMatches(RotatableBondSmarts)
    bond_indices = set([rms.GetBondBetweenAtoms(*ap).GetIdx() for ap in rot_atom_pairs])
    return len(bond_indices)

已知苯环的smarts为"c1ccccc1"，氢原子的smarts为"[H]". 请写一个完整的Python函数`solve(smiles)`，输入一个SMILES，先将分子中的每个末端的苯环结构都替换为一个氢原子，
再计算分子中的可旋转键（按照RDKit中RotatableBondSmarts定义）数量


#L2_A_18
from rdkit import Chem
from rdkit.Chem import AllChem
from rdkit import DataStructs

def solve(smiles1, smiles2):
    mol1 = Chem.MolFromSmiles(smiles1)
    mol2 = Chem.MolFromSmiles(smiles2)
    fp1 = AllChem.GetMorganFingerprintAsBitVect(mol1, 2, nBits=2048)
    fp2 = AllChem.GetMorganFingerprintAsBitVect(mol2, 2, nBits=2048)
    simi = DataStructs.TanimotoSimilarity(fp1,fp2)
    return round(simi, 2)

#<INSERT>

def check(solve):
    assert solve('Cc1cccc(-c2cc(N)cc(COC3CC(C)CC3C)c2)c1', 'CC(CC(C)N(C)/C=C/c1ccccc1)c1ccccc1') == 0.1
    assert solve('CCCCNC', 'CCC(N)CC') == 0.15
    assert solve('CCCCCCC', 'CCCCCCC=O') == 0.5

check(solve)


#L2_A_39
from rdkit import Chem
from rdkit.Chem.rdPartialCharges import ComputeGasteigerCharges

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    ComputeGasteigerCharges(mol)
    charge_lst = []
    for atom in mol.GetAtoms():
        charge_lst.append(round(float(atom.GetProp('_GasteigerCharge')), 2))
    return charge_lst


#L1_B_52
from rdkit import Chem
from rdkit.Chem import AllChem
from rdkit.Chem import Descriptors

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles)
    patt = Chem.MolFromSmarts('[C](=[O])[OH]')
    repl = Chem.MolFromSmiles('[C](=[O])[O][CH3]')
    rms = AllChem.ReplaceSubstructs(mol, patt, repl, replaceAll=True)
    prod = rms[0]
    Chem.SanitizeMol(prod)
    tpsa_before = Descriptors.TPSA(mol)
    tpsa_after = Descriptors.TPSA(prod)
    return round(tpsa_after - tpsa_before, 3)

实现一个完整的Python函数`solve(smiles)`，输入为一个分子的SMILES，将分子内的所有羧基（smarts为[C](=[O])[OH]）进行甲酯化（改变后的结构smarts为[C](=[O])[O][CH3]），计算并返回分子甲酯化后的TPSA变化，结果保留3位小数。分子的TPSA值可以通过调用`Descriptors.TPSA`函数获得。

#<INSERT>

def check(solve):
    assert abs(solve("CCC(=O)O")) - 11.0 < 1e-5
    assert abs(solve("c1cc(C(=O)O)cc(C(=O)O)c1")) - 22.0 < 1e-5
    assert abs(solve("c1cc(C(=O)O)c(CC(=O)O)c(C(=O)O)c1")) - 33.0 < 1e-5

check(solve)


#L1_C_3
from rdkit import Chem

def solve(smiles):
    mol = Chem.MolFromSmiles(smiles, sanitize=False)
    for atom in mol.GetAtoms():
        if not atom.IsInRing():
            if atom.GetIsAromatic():
                atom.SetIsAromatic(False)
                for bond in atom.GetBonds():
                    bond.SetBondType(Chem.BondType.SINGLE)
    new_smi = Chem.MolToSmiles(mol)
    return new_smi

已知在rdkit中可以使用`atom.SetIsAromatic`设置原子的芳香性，atom.IsInRing可以判断原子是否在环内，`bond.SetBondType`可以修改化学键的类型。
请写一个完整的Python函数`solve(smiles)`, 输入一个SMILES(注意解析这个SMILES可能需要设置sanitize=False)， 如果分子结构中存在不在环里的芳香原子，
请编写代码将分子中不在环里的芳香原子改为非芳香的，并且将与这些原子相连的化学键也改为单键，最终返回修改后的分子结构的SMILES

#<INSERT>

def check(solve):
    assert solve('c1ccccc1ccCCOCnC') == 'CNCOCCCCc1ccccc1'
    assert solve('CCOc(c1ccccc1)C') == 'CCOC(C)c1ccccc1'
    assert solve('CCC(C1CC1)CoCC') == 'CCOCC(CC)C1CC1'
    assert solve('NCc1ccccc1') == 'NCc1ccccc1'

check(solve)