@@ -1934,6 +1934,171 @@ msgid ""
19341934" while True:\n"
19351935" yield func()"
19361936msgstr ""
1937+ "import collections\n"
1938+ "import contextlib\n"
1939+ "import functools\n"
1940+ "import math\n"
1941+ "import operator\n"
1942+ "import random\n"
1943+ "\n"
1944+ "def take(n, iterable):\n"
1945+ " \" Return first n items of the iterable as a list.\" \n"
1946+ " return list(islice(iterable, n))\n"
1947+ "\n"
1948+ "def prepend(value, iterable):\n"
1949+ " \" Prepend a single value in front of an iterable.\" \n"
1950+ " # prepend(1, [2, 3, 4]) → 1 2 3 4\n"
1951+ " return chain([value], iterable)\n"
1952+ "\n"
1953+ "def tabulate(function, start=0):\n"
1954+ " \" Return function(0), function(1), ...\" \n"
1955+ " return map(function, count(start))\n"
1956+ "\n"
1957+ "def repeatfunc(func, times=None, *args):\n"
1958+ " \" Repeat calls to func with specified arguments.\" \n"
1959+ " if times is None:\n"
1960+ " return starmap(func, repeat(args))\n"
1961+ " return starmap(func, repeat(args, times))\n"
1962+ "\n"
1963+ "def flatten(list_of_lists):\n"
1964+ " \" Flatten one level of nesting.\" \n"
1965+ " return chain.from_iterable(list_of_lists)\n"
1966+ "\n"
1967+ "def ncycles(iterable, n):\n"
1968+ " \" Returns the sequence elements n times.\" \n"
1969+ " return chain.from_iterable(repeat(tuple(iterable), n))\n"
1970+ "\n"
1971+ "def loops(n):\n"
1972+ " \" Loop n times. Like range(n) but without creating integers.\" \n"
1973+ " # for _ in loops(100): ...\n"
1974+ " return repeat(None, n)\n"
1975+ "\n"
1976+ "def tail(n, iterable):\n"
1977+ " \" Return an iterator over the last n items.\" \n"
1978+ " # tail(3, 'ABCDEFG') → E F G\n"
1979+ " return iter(collections.deque(iterable, maxlen=n))\n"
1980+ "\n"
1981+ "def consume(iterator, n=None):\n"
1982+ " \" Advance the iterator n-steps ahead. If n is None, consume entirely.\" \n"
1983+ " # 使用以速度 C 消耗迭代器的函数。\n"
1984+ " if n is None:\n"
1985+ " collections.deque(iterator, maxlen=0)\n"
1986+ " else:\n"
1987+ " next(islice(iterator, n, n), None)\n"
1988+ "\n"
1989+ "def nth(iterable, n, default=None):\n"
1990+ " \" Returns the nth item or a default value.\" \n"
1991+ " return next(islice(iterable, n, None), default)\n"
1992+ "\n"
1993+ "def quantify(iterable, predicate=bool):\n"
1994+ " \" Given a predicate that returns True or False, count the True results.\" \n"
1995+ " return sum(map(predicate, iterable))\n"
1996+ "\n"
1997+ "def first_true(iterable, default=False, predicate=None):\n"
1998+ " \" Returns the first true value or the *default* if there is no true value.\" \n"
1999+ " # first_true([a,b,c], x) → a or b or c or x\n"
2000+ " # first_true([a,b], x, f) → a if f(a) else b if f(b) else x\n"
2001+ " return next(filter(predicate, iterable), default)\n"
2002+ "\n"
2003+ "def all_equal(iterable, key=None):\n"
2004+ " \" Returns True if all the elements are equal to each other.\" \n"
2005+ " # all_equal('4٤௪౪໔', key=int) → True\n"
2006+ " return len(take(2, groupby(iterable, key))) <= 1\n"
2007+ "\n"
2008+ "def unique_justseen(iterable, key=None):\n"
2009+ " \" Yield unique elements, preserving order. Remember only the element just seen.\" \n"
2010+ " # unique_justseen('AAAABBBCCDAABBB') → A B C D A B\n"
2011+ " # unique_justseen('ABBcCAD', str.casefold) → A B c A D\n"
2012+ " if key is None:\n"
2013+ " return map(operator.itemgetter(0), groupby(iterable))\n"
2014+ " return map(next, map(operator.itemgetter(1), groupby(iterable, key)))\n"
2015+ "\n"
2016+ "def unique_everseen(iterable, key=None):\n"
2017+ " \" Yield unique elements, preserving order. Remember all elements ever seen.\" \n"
2018+ " # unique_everseen('AAAABBBCCDAABBB') → A B C D\n"
2019+ " # unique_everseen('ABBcCAD', str.casefold) → A B c D\n"
2020+ " seen = set()\n"
2021+ " if key is None:\n"
2022+ " for element in filterfalse(seen.__contains__, iterable):\n"
2023+ " seen.add(element)\n"
2024+ " yield element\n"
2025+ " else:\n"
2026+ " for element in iterable:\n"
2027+ " k = key(element)\n"
2028+ " if k not in seen:\n"
2029+ " seen.add(k)\n"
2030+ " yield element\n"
2031+ "\n"
2032+ "def unique(iterable, key=None, reverse=False):\n"
2033+ " \" Yield unique elements in sorted order. Supports unhashable inputs.\" \n"
2034+ " # unique([[1, 2], [3, 4], [1, 2]]) → [1, 2] [3, 4]\n"
2035+ " return unique_justseen(sorted(iterable, key=key, reverse=reverse), key=key)\n"
2036+ "\n"
2037+ "def sliding_window(iterable, n):\n"
2038+ " \" Collect data into overlapping fixed-length chunks or blocks.\" \n"
2039+ " # sliding_window('ABCDEFG', 4) → ABCD BCDE CDEF DEFG\n"
2040+ " iterator = iter(iterable)\n"
2041+ " window = collections.deque(islice(iterator, n - 1), maxlen=n)\n"
2042+ " for x in iterator:\n"
2043+ " window.append(x)\n"
2044+ " yield tuple(window)\n"
2045+ "\n"
2046+ "def grouper(iterable, n, *, incomplete='fill', fillvalue=None):\n"
2047+ " \" Collect data into non-overlapping fixed-length chunks or blocks.\" \n"
2048+ " # grouper('ABCDEFG', 3, fillvalue='x') → ABC DEF Gxx\n"
2049+ " # grouper('ABCDEFG', 3, incomplete='strict') → ABC DEF ValueError\n"
2050+ " # grouper('ABCDEFG', 3, incomplete='ignore') → ABC DEF\n"
2051+ " iterators = [iter(iterable)] * n\n"
2052+ " match incomplete:\n"
2053+ " case 'fill':\n"
2054+ " return zip_longest(*iterators, fillvalue=fillvalue)\n"
2055+ " case 'strict':\n"
2056+ " return zip(*iterators, strict=True)\n"
2057+ " case 'ignore':\n"
2058+ " return zip(*iterators)\n"
2059+ " case _:\n"
2060+ " raise ValueError('Expected fill, strict, or ignore')\n"
2061+ "\n"
2062+ "def roundrobin(*iterables):\n"
2063+ " \" Visit input iterables in a cycle until each is exhausted.\" \n"
2064+ " # roundrobin('ABC', 'D', 'EF') → A D E B F C\n"
2065+ " # 此算法由 George Sakkis 首创\n"
2066+ " iterators = map(iter, iterables)\n"
2067+ " for num_active in range(len(iterables), 0, -1):\n"
2068+ " iterators = cycle(islice(iterators, num_active))\n"
2069+ " yield from map(next, iterators)\n"
2070+ "\n"
2071+ "def subslices(seq):\n"
2072+ " \" Return all contiguous non-empty subslices of a sequence.\" \n"
2073+ " # subslices('ABCD') → A AB ABC ABCD B BC BCD C CD D\n"
2074+ " slices = starmap(slice, combinations(range(len(seq) + 1), 2))\n"
2075+ " return map(operator.getitem, repeat(seq), slices)\n"
2076+ "\n"
2077+ "def iter_index(iterable, value, start=0, stop=None):\n"
2078+ " \" Return indices where a value occurs in a sequence or iterable.\" \n"
2079+ " # iter_index('AABCADEAF', 'A') → 0 1 4 7\n"
2080+ " seq_index = getattr(iterable, 'index', None)\n"
2081+ " if seq_index is None:\n"
2082+ " iterator = islice(iterable, start, stop)\n"
2083+ " for i, element in enumerate(iterator, start):\n"
2084+ " if element is value or element == value:\n"
2085+ " yield i\n"
2086+ " else:\n"
2087+ " stop = len(iterable) if stop is None else stop\n"
2088+ " i = start\n"
2089+ " with contextlib.suppress(ValueError):\n"
2090+ " while True:\n"
2091+ " yield (i := seq_index(value, i, stop))\n"
2092+ " i += 1\n"
2093+ "\n"
2094+ "def iter_except(func, exception, first=None):\n"
2095+ " \" Convert a call-until-exception interface to an iterator interface.\" \n"
2096+ " # iter_except(d.popitem, KeyError) → 非阻塞的字典迭代器\n"
2097+ " with contextlib.suppress(exception):\n"
2098+ " if first is not None:\n"
2099+ " yield first()\n"
2100+ " while True:\n"
2101+ " yield func()"
19372102
19382103#: ../../library/itertools.rst:1013
19392104msgid "The following recipes have a more mathematical flavor:"
@@ -2058,3 +2223,119 @@ msgid ""
20582223" n -= n // prime\n"
20592224" return n"
20602225msgstr ""
2226+ "def powerset(iterable):\n"
2227+ " \" powerset([1,2,3]) → () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)\" \n"
2228+ " s = list(iterable)\n"
2229+ " return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))\n"
2230+ "\n"
2231+ "def sum_of_squares(iterable):\n"
2232+ " \" Add up the squares of the input values.\" \n"
2233+ " # sum_of_squares([10, 20, 30]) → 1400\n"
2234+ " return math.sumprod(*tee(iterable))\n"
2235+ "\n"
2236+ "def reshape(matrix, cols):\n"
2237+ " \" Reshape a 2-D matrix to have a given number of columns.\" \n"
2238+ " # reshape([(0, 1), (2, 3), (4, 5)], 3) → (0, 1, 2), (3, 4, 5)\n"
2239+ " return batched(chain.from_iterable(matrix), cols, strict=True)\n"
2240+ "\n"
2241+ "def transpose(matrix):\n"
2242+ " \" Swap the rows and columns of a 2-D matrix.\" \n"
2243+ " # transpose([(1, 2, 3), (11, 22, 33)]) → (1, 11) (2, 22) (3, 33)\n"
2244+ " return zip(*matrix, strict=True)\n"
2245+ "\n"
2246+ "def matmul(m1, m2):\n"
2247+ " \" Multiply two matrices.\" \n"
2248+ " # matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]) → (49, 80), (41, 60)\n"
2249+ " n = len(m2[0])\n"
2250+ " return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)\n"
2251+ "\n"
2252+ "def convolve(signal, kernel):\n"
2253+ " \"\"\" Discrete linear convolution of two iterables.\n"
2254+ " Equivalent to polynomial multiplication.\n"
2255+ "\n"
2256+ " Convolutions are mathematically commutative; however, the inputs are\n"
2257+ " evaluated differently. The signal is consumed lazily and can be\n"
2258+ " infinite. The kernel is fully consumed before the calculations begin.\n"
2259+ "\n"
2260+ " Article: https://betterexplained.com/articles/intuitive-convolution/\n"
2261+ " Video: https://www.youtube.com/watch?v=KuXjwB4LzSA\n"
2262+ " \"\"\" \n"
2263+ " # convolve([1, -1, -20], [1, -3]) → 1 -4 -17 60\n"
2264+ " # convolve(data, [0.25, 0.25, 0.25, 0.25]) → 移动平均(模糊)\n"
2265+ " # convolve(data, [1/2, 0, -1/2]) → 1 阶导数预测\n"
2266+ " # convolve(data, [1, -2, 1]) → 2 阶导数预测\n"
2267+ " kernel = tuple(kernel)[::-1]\n"
2268+ " n = len(kernel)\n"
2269+ " padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))\n"
2270+ " windowed_signal = sliding_window(padded_signal, n)\n"
2271+ " return map(math.sumprod, repeat(kernel), windowed_signal)\n"
2272+ "\n"
2273+ "def polynomial_from_roots(roots):\n"
2274+ " \"\"\" Compute a polynomial's coefficients from its roots.\n"
2275+ "\n"
2276+ " (x - 5) (x + 4) (x - 3) expands to: x³ -4x² -17x + 60\n"
2277+ " \"\"\" \n"
2278+ " # polynomial_from_roots([5, -4, 3]) → [1, -4, -17, 60]\n"
2279+ " factors = zip(repeat(1), map(operator.neg, roots))\n"
2280+ " return list(functools.reduce(convolve, factors, [1]))\n"
2281+ "\n"
2282+ "def polynomial_eval(coefficients, x):\n"
2283+ " \"\"\" Evaluate a polynomial at a specific value.\n"
2284+ "\n"
2285+ " Computes with better numeric stability than Horner's method.\n"
2286+ " \"\"\" \n"
2287+ " # 设 x = 5 对 x³ -4x² -17x + 60 求值 \n"
2288+ " # polynomial_eval([1, -4, -17, 60], x=5) → 0\n"
2289+ " n = len(coefficients)\n"
2290+ " if not n:\n"
2291+ " return type(x)(0)\n"
2292+ " powers = map(pow, repeat(x), reversed(range(n)))\n"
2293+ " return math.sumprod(coefficients, powers)\n"
2294+ "\n"
2295+ "def polynomial_derivative(coefficients):\n"
2296+ " \"\"\" Compute the first derivative of a polynomial.\n"
2297+ "\n"
2298+ " f(x) = x³ -4x² -17x + 60\n"
2299+ " f'(x) = 3x² -8x -17\n"
2300+ " \"\"\" \n"
2301+ " # polynomial_derivative([1, -4, -17, 60]) → [3, -8, -17]\n"
2302+ " n = len(coefficients)\n"
2303+ " powers = reversed(range(1, n))\n"
2304+ " return list(map(operator.mul, coefficients, powers))\n"
2305+ "\n"
2306+ "def sieve(n):\n"
2307+ " \" Primes less than n.\" \n"
2308+ " # sieve(30) → 2 3 5 7 11 13 17 19 23 29\n"
2309+ " if n > 2:\n"
2310+ " yield 2\n"
2311+ " data = bytearray((0, 1)) * (n // 2)\n"
2312+ " for p in iter_index(data, 1, start=3, stop=math.isqrt(n) + 1):\n"
2313+ " data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))\n"
2314+ " yield from iter_index(data, 1, start=3)\n"
2315+ "\n"
2316+ "def is_prime(n):\n"
2317+ " \" Return True if n is prime.\" \n"
2318+ " # is_prime(1_000_000_000_000_403) → True\n"
2319+ " return n > 1 and all(n % p for p in sieve(math.isqrt(n) + 1))\n"
2320+ "\n"
2321+ "def factor(n):\n"
2322+ " \" Prime factors of n.\" \n"
2323+ " # factor(99) → 3 3 11\n"
2324+ " # factor(1_000_000_000_000_007) → 47 59 360620266859\n"
2325+ " # factor(1_000_000_000_000_403) → 1000000000000403\n"
2326+ " for prime in sieve(math.isqrt(n) + 1):\n"
2327+ " while not n % prime:\n"
2328+ " yield prime\n"
2329+ " n //= prime\n"
2330+ " if n == 1:\n"
2331+ " return\n"
2332+ " if n > 1:\n"
2333+ " yield n\n"
2334+ "\n"
2335+ "def totient(n):\n"
2336+ " \" Count of natural numbers up to n that are coprime to n.\" \n"
2337+ " # https://mathworld.wolfram.com/TotientFunction.html\n"
2338+ " # totient(12) → 4 因为 len([1, 5, 7, 11]) == 4\n"
2339+ " for prime in set(factor(n)):\n"
2340+ " n -= n // prime\n"
2341+ " return n"
0 commit comments