Bitcoin/public point to address

elliptic curve public point into a short ASCII string.  The purpose of this task is to perform such a conversion.

The encoding steps are:
* take the X and Y coordinates of the given public point, and concatenate them in order to have a 64 byte-longed string ;
* add one byte prefix equal to 4 (it is a convention for this way of encoding a public point) ;
* compute the [[SHA-256]] of this string ;
* compute the [[RIPEMD-160]] of this SHA-256 digest ;
* compute the checksum of the concatenation of the version number digit (a single zero byte) and this RIPEMD-160 digest, as described in [[bitcoin/address validation]] ;
* Base-58 encode (see below) the concatenation of the version number (zero in this case), the ripemd digest and the checksum

The base-58 encoding is based on an alphabet of alphanumeric characters (numbers, upper case and lower case, in that order) but without the four characters 0, O, l and I.

Here is an example public point:
X = 0x50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352
Y = 0x2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6

The corresponding address should be:
16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM

Nb.  The leading '1' is not significant as 1 is zero in base-58.  It is however often added to the bitcoin address for various reasons.  There can actually be several of them.  You can ignore this and output an address without the leading 1.

''Extra credit:'' add a verification procedure about the public point, making sure it belongs to the secp256k1 elliptic curve

Solution:
#!/usr/bin/env python3

import binascii
import functools
import hashlib

digits58 = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def b58(n):
    return b58(n//58) + digits58[n%58:n%58+1] if n else b''

def public_point_to_address(x, y):
    c = b'\x04' + binascii.unhexlify(x) + binascii.unhexlify(y)
    r = hashlib.new('ripemd160')
    r.update(hashlib.sha256(c).digest())
    c = b'\x00' + r.digest()
    d = hashlib.sha256(hashlib.sha256(c).digest()).digest()
    return b58(functools.reduce(lambda n, b: n<<8|b, c + d[:4]))

if __name__ == '__main__':
    print(public_point_to_address(
        b'50863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B2352',
        b'2CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6'))


Bitwise IO

The aim of this task is to write functions (or create a class if yourlanguage is Object Oriented and you prefer) for reading and writing sequences of
bits, most significant bit first. While the output of a asciiprint "STRING" is the ASCII byte sequence
"S", "T", "R", "I", "N", "G", the output of a "print" of the bits sequence
0101011101010 (13 bits) must be 0101011101010; real I/O is performed always
''quantized'' by byte (avoiding endianness issues and relying on underlying
buffering for performance), therefore you must obtain as output the bytes
0101 0111 0101 0'''000''' (bold bits are padding bits), i.e. in hexadecimal 57 50.

As test, you can implement a '''rough''' (e.g. don't care about error handling or
other issues) compression/decompression program for ASCII sequences
of bytes, i.e. bytes for which the most significant bit is always unused, so that you can write
seven bits instead of eight (each 8 bytes of input, we write 7 bytes of output).

These bit oriented I/O functions can be used to implement compressors and
decompressors; e.g. Dynamic and Static Huffman encodings use variable length
bits sequences, while LZW (see [[LZW compression]]) use fixed or variable ''words''
nine (or more) bits long.

* Limits in the maximum number of bits that can be written/read in a single read/write operation are allowed.
* Errors handling is not mandatory

Solution:
class BitWriter(object):
    def __init__(self, f):
        self.accumulator = 0
        self.bcount = 0
        self.out = f

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.flush()

    def __del__(self):
        try:
            self.flush()
        except ValueError:   # I/O operation on closed file.
            pass

    def _writebit(self, bit):
        if self.bcount == 8:
            self.flush()
        if bit > 0:
            self.accumulator |= 1 << 7-self.bcount
        self.bcount += 1

    def writebits(self, bits, n):
        while n > 0:
            self._writebit(bits & 1 << n-1)
            n -= 1

    def flush(self):
        self.out.write(bytearray([self.accumulator]))
        self.accumulator = 0
        self.bcount = 0

class BitReader(object):
    def __init__(self, f):
        self.input = f
        self.accumulator = 0
        self.bcount = 0
        self.read = 0

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

    def _readbit(self):
        if not self.bcount:
            a = self.input.read(1)
            if a:
                self.accumulator = ord(a)
            self.bcount = 8
            self.read = len(a)
        rv = (self.accumulator & (1 << self.bcount-1)) >> self.bcount-1
        self.bcount -= 1
        return rv

    def readbits(self, n):
        v = 0
        while n > 0:
            v = (v << 1) | self._readbit()
            n -= 1
        return v

if __name__ == '__main__':
    import os
    import sys
    # Determine this module's name from it's file name and import it.
    module_name = os.path.splitext(os.path.basename(__file__))[0]
    bitio = __import__(module_name)

    with open('bitio_test.dat', 'wb') as outfile:
        with bitio.BitWriter(outfile) as writer:
            chars = '12345abcde'
            for ch in chars:
                writer.writebits(ord(ch), 7)

    with open('bitio_test.dat', 'rb') as infile:
        with bitio.BitReader(infile) as reader:
            chars = []
            while True:
                x = reader.readbits(7)
                if not reader.read:  # End-of-file?
                    break
                chars.append(chr(x))
            print(''.join(chars))


Box the compass

Avast me hearties!
There be many a land lubber that knows naught of the pirate ways and gives direction by degree!
They know not how to box the compass!

;Task description:
# Create a function that takes a heading in degrees and returns the correct 32-point compass heading.
# Use the function to print and display a table of Index, Compass point, and Degree; rather like the corresponding columns from, the first table of the wikipedia article, but use only the following 33 headings as input:
:[0.0, 16.87, 16.88, 33.75, 50.62, 50.63, 67.5, 84.37, 84.38, 101.25, 118.12, 118.13, 135.0, 151.87, 151.88, 168.75, 185.62, 185.63, 202.5, 219.37, 219.38, 236.25, 253.12, 253.13, 270.0, 286.87, 286.88, 303.75, 320.62, 320.63, 337.5, 354.37, 354.38]. (They should give the same order of points but are spread throughout the ranges of acceptance).

;Notes;
* The headings and indices can be calculated from this pseudocode:
for i in 0..32 inclusive:
    heading = i * 11.25
    case i %3:
      if 1: heading += 5.62; break
      if 2: heading -= 5.62; break
    end
    index = ( i mod 32) + 1
* The column of indices can be thought of as an enumeration of the thirty two cardinal points (see talk page)..

Solution:
majors   = 'north east south west'.split()
majors   *= 2 # no need for modulo later
quarter1 = 'N,N by E,N-NE,NE by N,NE,NE by E,E-NE,E by N'.split(',')
quarter2 = [p.replace('NE','EN') for p in quarter1]

def degrees2compasspoint(d):
    d = (d % 360) + 360/64
    majorindex, minor = divmod(d, 90.)
    majorindex = int(majorindex)
    minorindex  = int( (minor*4) // 45 )
    p1, p2 = majors[majorindex: majorindex+2]
    if p1 in {'north', 'south'}:
        q = quarter1
    else:
        q = quarter2
    return q[minorindex].replace('N', p1).replace('E', p2).capitalize()

if __name__ == '__main__':
    for i in range(33):
        d = i * 11.25
        m = i % 3
        if   m == 1: d += 5.62
        elif m == 2: d -= 5.62
        n = i % 32 + 1
        print( '%2i %-18s %7.2f°' % (n, degrees2compasspoint(d), d) )


Boyer-Moore string search

This algorithm is designed for pattern searching on certain types of devices which are backtracking-unfriendly such as Tape drives and Hard disks.

It works by first caching a segment of data from storage and match it against the pattern from the highest position backward to the lowest. If the matching fails, it will cache next segment of data and move the start point forward to skip the portion of data which will definitely fail to match. This continues until we successfully match the pattern or the pointer exceeds the data length.

Follow this link for more information about this algorithm.

To properly test this algorithm, it would be good to search for a string which contains repeated subsequences, such as alfalfa and the text being searched should not only include a match but that match should be preceded by words which partially match, such as alfredo, behalf, calfskin, halfhearted, malfunction or severalfold.

Solution:
"""
This version uses ASCII for case-sensitive matching. For Unicode you may want to match in UTF-8
bytes instead of creating a 0x10FFFF-sized table.
"""

from typing import List

ALPHABET_SIZE = 256

def alphabet_index(c: str) -> int:
    """Return the index of the given ASCII character. """
    val = ord(c)
    assert 0 <= val < ALPHABET_SIZE
    return val

def match_length(S: str, idx1: int, idx2: int) -> int:
    """Return the length of the match of the substrings of S beginning at idx1 and idx2."""
    if idx1 == idx2:
        return len(S) - idx1
    match_count = 0
    while idx1 < len(S) and idx2 < len(S) and S[idx1] == S[idx2]:
        match_count += 1
        idx1 += 1
        idx2 += 1
    return match_count

def fundamental_preprocess(S: str) -> List[int]:
    """Return Z, the Fundamental Preprocessing of S.

    Z[i] is the length of the substring beginning at i which is also a prefix of S.
    This pre-processing is done in O(n) time, where n is the length of S.
    """
    if len(S) == 0:  # Handles case of empty string
        return []
    if len(S) == 1:  # Handles case of single-character string
        return [1]
    z = [0 for x in S]
    z[0] = len(S)
    z[1] = match_length(S, 0, 1)
    for i in range(2, 1 + z[1]):  # Optimization from exercise 1-5
        z[i] = z[1] - i + 1
    # Defines lower and upper limits of z-box
    l = 0
    r = 0
    for i in range(2 + z[1], len(S)):
        if i <= r:  # i falls within existing z-box
            k = i - l
            b = z[k]
            a = r - i + 1
            if b < a:  # b ends within existing z-box
                z[i] = b
            else:  # b ends at or after the end of the z-box, we need to do an explicit match to the right of the z-box
                z[i] = a + match_length(S, a, r + 1)
                l = i
                r = i + z[i] - 1
        else:  # i does not reside within existing z-box
            z[i] = match_length(S, 0, i)
            if z[i] > 0:
                l = i
                r = i + z[i] - 1
    return z

def bad_character_table(S: str) -> List[List[int]]:
    """
    Generates R for S, which is an array indexed by the position of some character c in the
    ASCII table. At that index in R is an array of length |S|+1, specifying for each
    index i in S (plus the index after S) the next location of character c encountered when
    traversing S from right to left starting at i. This is used for a constant-time lookup
    for the bad character rule in the Boyer-Moore string search algorithm, although it has
    a much larger size than non-constant-time solutions.
    """
    if len(S) == 0:
        return [[] for a in range(ALPHABET_SIZE)]
    R = [[-1] for a in range(ALPHABET_SIZE)]
    alpha = [-1 for a in range(ALPHABET_SIZE)]
    for i, c in enumerate(S):
        alpha[alphabet_index(c)] = i
        for j, a in enumerate(alpha):
            R[j].append(a)
    return R

def good_suffix_table(S: str) -> List[int]:
    """
    Generates L for S, an array used in the implementation of the strong good suffix rule.
    L[i] = k, the largest position in S such that S[i:] (the suffix of S starting at i) matches
    a suffix of S[:k] (a substring in S ending at k). Used in Boyer-Moore, L gives an amount to
    shift P relative to T such that no instances of P in T are skipped and a suffix of P[:L[i]]
    matches the substring of T matched by a suffix of P in the previous match attempt.
    Specifically, if the mismatch took place at position i-1 in P, the shift magnitude is given
    by the equation len(P) - L[i]. In the case that L[i] = -1, the full shift table is used.
    Since only proper suffixes matter, L[0] = -1.
    """
    L = [-1 for c in S]
    N = fundamental_preprocess(S[::-1])  # S[::-1] reverses S
    N.reverse()
    for j in range(0, len(S) - 1):
        i = len(S) - N[j]
        if i != len(S):
            L[i] = j
    return L

def full_shift_table(S: str) -> List[int]:
    """
    Generates F for S, an array used in a special case of the good suffix rule in the Boyer-Moore
    string search algorithm. F[i] is the length of the longest suffix of S[i:] that is also a
    prefix of S. In the cases it is used, the shift magnitude of the pattern P relative to the
    text T is len(P) - F[i] for a mismatch occurring at i-1.
    """
    F = [0 for c in S]
    Z = fundamental_preprocess(S)
    longest = 0
    for i, zv in enumerate(reversed(Z)):
        longest = max(zv, longest) if zv == i + 1 else longest
        F[-i - 1] = longest
    return F

def string_search(P, T) -> List[int]:
    """
    Implementation of the Boyer-Moore string search algorithm. This finds all occurrences of P
    in T, and incorporates numerous ways of pre-processing the pattern to determine the optimal
    amount to shift the string and skip comparisons. In practice it runs in O(m) (and even
    sublinear) time, where m is the length of T. This implementation performs a case-sensitive
    search on ASCII characters. P must be ASCII as well.
    """
    if len(P) == 0 or len(T) == 0 or len(T) < len(P):
        return []

    matches = []

    # Preprocessing
    R = bad_character_table(P)
    L = good_suffix_table(P)
    F = full_shift_table(P)

    k = len(P) - 1      # Represents alignment of end of P relative to T
    previous_k = -1     # Represents alignment in previous phase (Galil's rule)
    while k < len(T):
        i = len(P) - 1  # Character to compare in P
        h = k           # Character to compare in T
        while i >= 0 and h > previous_k and P[i] == T[h]:  # Matches starting from end of P
            i -= 1
            h -= 1
        if i == -1 or h == previous_k:  # Match has been found (Galil's rule)
            matches.append(k - len(P) + 1)
            k += len(P) - F[1] if len(P) > 1 else 1
        else:  # No match, shift by max of bad character and good suffix rules
            char_shift = i - R[alphabet_index(T[h])][i]
            if i + 1 == len(P):  # Mismatch happened on first attempt
                suffix_shift = 1
            elif L[i + 1] == -1:  # Matched suffix does not appear anywhere in P
                suffix_shift = len(P) - F[i + 1]
            else:               # Matched suffix appears in P
                suffix_shift = len(P) - 1 - L[i + 1]
            shift = max(char_shift, suffix_shift)
            previous_k = k if shift >= i + 1 else previous_k  # Galil's rule
            k += shift
    return matches

TEXT1 = 'InhisbookseriesTheArtofComputerProgrammingpublishedbyAddisonWesleyDKnuthusesanimaginarycomputertheMIXanditsassociatedmachinecodeandassemblylanguagestoillustratetheconceptsandalgorithmsastheyarepresented'
TEXT2 = "Nearby farms grew a half acre of alfalfa on the dairy's behalf, with bales of all that alfalfa exchanged for milk."
PAT1, PAT2, PAT3 = 'put', 'and', 'alfalfa'

print("Found", PAT1, "at:", string_search(PAT1, TEXT1))
print("Found", PAT2, "at:", string_search(PAT2, TEXT1))
print("Found", PAT3, "at:", string_search(PAT3, TEXT2))


Brazilian numbers

Brazilian numbers are so called as they were first formally presented at the 1994 math Olympiad ''Olimpiada Iberoamericana de Matematica'' in Fortaleza, Brazil.

Brazilian numbers are defined as:

The set of positive integer numbers where each number '''N''' has at least one natural number '''B''' where '''1 < B < N-1''' where the representation of '''N''' in '''base B''' has all equal digits.

;E.G.:

:* '''1, 2 & 3''' can not be Brazilian; there is no base '''B''' that satisfies the condition '''1 < B < N-1'''.
:* '''4''' is not Brazilian; '''4''' in '''base 2''' is '''100'''. The digits are not all the same.
:* '''5''' is not Brazilian; '''5''' in '''base 2''' is '''101''', in '''base 3''' is '''12'''. There is no representation where the digits are the same.
:* '''6''' is not Brazilian; '''6''' in '''base 2''' is '''110''', in '''base 3''' is '''20''', in '''base 4''' is '''12'''. There is no representation where the digits are the same.
:* '''7''' ''is'' Brazilian; '''7''' in '''base 2''' is '''111'''. There is at least one representation where the digits are all the same.
:* '''8''' ''is'' Brazilian; '''8''' in '''base 3''' is '''22'''. There is at least one representation where the digits are all the same.
:* ''and so on...''

All even integers '''2P >= 8''' are Brazilian because '''2P = 2(P-1) + 2''', which is '''22''' in '''base P-1''' when '''P-1 > 2'''. That becomes true when '''P >= 4'''.
More common: for all all integers '''R''' and '''S''', where '''R > 1''' and also '''S-1 > R''', then '''R*S''' is Brazilian because '''R*S = R(S-1) + R''', which is '''RR''' in '''base S-1'''
The only problematic numbers are squares of primes, where R = S. Only 11^2 is brazilian to base 3.
All prime integers, that are brazilian, can only have the digit '''1'''. Otherwise one could factor out the digit, therefore it cannot be a prime number. Mostly in form of '''111''' to base Integer(sqrt(prime number)). Must be an odd count of '''1''' to stay odd like primes >  2

;Task:

Write a routine (function, whatever) to determine if a number is Brazilian and use the routine to show here, on this page;

:* the first '''20''' Brazilian numbers;
:* the first '''20 odd''' Brazilian numbers;
:* the first '''20 prime''' Brazilian numbers;

;See also:

:* '''OEIS:A125134 - Brazilian numbers'''
:* '''OEIS:A257521 - Odd Brazilian numbers'''
:* '''OEIS:A085104 - Prime Brazilian numbers'''

Solution:
'''Brazilian numbers'''

from itertools import count, islice

# isBrazil :: Int -> Bool
def isBrazil(n):
    '''True if n is a Brazilian number,
       in the sense of OEIS:A125134.
    '''
    return 7 <= n and (
        0 == n % 2 or any(
            map(monoDigit(n), range(2, n - 1))
        )
    )

# monoDigit :: Int -> Int -> Bool
def monoDigit(n):
    '''True if all the digits of n,
       in the given base, are the same.
    '''
    def go(base):
        def g(b, n):
            (q, d) = divmod(n, b)

            def p(qr):
                return d != qr[1] or 0 == qr[0]

            def f(qr):
                return divmod(qr[0], b)
            return d == until(p)(f)(
                (q, d)
            )[1]
        return g(base, n)
    return go

# -------------------------- TEST --------------------------
# main :: IO ()
def main():
    '''First 20 members each of:
        OEIS:A125134
        OEIS:A257521
        OEIS:A085104
    '''
    for kxs in ([
            (' ', count(1)),
            (' odd ', count(1, 2)),
            (' prime ', primes())
    ]):
        print(
            'First 20' + kxs[0] + 'Brazilians:\n' +
            showList(take(20)(filter(isBrazil, kxs[1]))) + '\n'
        )

# ------------------- GENERIC FUNCTIONS --------------------

# primes :: [Int]
def primes():
    ''' Non finite sequence of prime numbers.
    '''
    n = 2
    dct = {}
    while True:
        if n in dct:
            for p in dct[n]:
                dct.setdefault(n + p, []).append(p)
            del dct[n]
        else:
            yield n
            dct[n * n] = [n]
        n = 1 + n

# showList :: [a] -> String
def showList(xs):
    '''Stringification of a list.'''
    return '[' + ','.join(str(x) for x in xs) + ']'

# take :: Int -> [a] -> [a]
# take :: Int -> String -> String
def take(n):
    '''The prefix of xs of length n,
       or xs itself if n > length xs.
    '''
    def go(xs):
        return (
            xs[0:n]
            if isinstance(xs, (list, tuple))
            else list(islice(xs, n))
        )
    return go

# until :: (a -> Bool) -> (a -> a) -> a -> a
def until(p):
    '''The result of repeatedly applying f until p holds.
       The initial seed value is x.
    '''
    def go(f):
        def g(x):
            v = x
            while not p(v):
                v = f(v)
            return v
        return g
    return go

# MAIN ---
if __name__ == '__main__':
    main()


Break OO privacy

Show how to access private or protected members of a class in an object-oriented language from outside an instance of the class, without calling non-private or non-protected members of the class as a proxy.
The intent is to show how a debugger, serializer, or other meta-programming tool might access information that is barred by normal access methods to the object  but can nevertheless be accessed from within the language by some provided escape hatch or reflection mechanism.
The intent is specifically not to demonstrate heroic measures such as peeking and poking raw memory.

Note that cheating on your type system is almost universally regarded
as unidiomatic at best, and poor programming practice at worst.
Nonetheless, if your language intentionally maintains a double-standard for OO privacy, here's where you can show it off.

Solution:
>>> class MyClassName:
	__private = 123
	non_private = __private * 2

>>> mine = MyClassName()
>>> mine.non_private
246
>>> mine.__private
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    mine.__private
AttributeError: 'MyClassName' object has no attribute '__private'
>>> mine._MyClassName__private
123
>>>


Brilliant numbers

'''Brilliant numbers''' are a subset of semiprime numbers. Specifically, they are numbers that are the product of exactly two prime numbers '''that both have the same number of digits when expressed in base 10'''.

''Brilliant numbers are useful in cryptography and when testing prime factoring algorithms.''

;E.G.
* '''3 x 3''' (9) is a brilliant number.
* '''2 x 7''' (14) is a brilliant number.
* '''113 x 691''' (78083) is a brilliant number.
* '''2 x 31''' (62) is semiprime, but is '''not''' a brilliant number (different number of digits in the two factors).

;Task
* Find and display the first 100 brilliant numbers.
* For the orders of magnitude 1 through 6, find and show the first brilliant number greater than or equal to the order of magnitude, and, its position in the series (or the count of brilliant numbers up to that point).

;Stretch
* Continue for larger orders of magnitude.

;See also
;* Numbers Aplenty - Brilliant numbers
;* OEIS:A078972 - Brilliant numbers: semiprimes whose prime factors have the same number of decimal digits

Solution:
from primesieve.numpy import primes
from math import isqrt
import numpy as np

max_order = 9
blocks = [primes(10**n, 10**(n + 1)) for n in range(max_order)]

def smallest_brilliant(lb):
    pos = 1
    root = isqrt(lb)

    for blk in blocks:
        n = len(blk)
        if blk[-1]*blk[-1] < lb:
            pos += n*(n + 1)//2
            continue

        i = np.searchsorted(blk, root, 'left')
        i += blk[i]*blk[i] < lb

        if not i:
            return blk[0]*blk[0], pos

        p = blk[:i + 1]
        q = (lb - 1)//p
        idx = np.searchsorted(blk, q, 'right')

        sel = idx < n
        p, idx = p[sel], idx[sel]
        q = blk[idx]

        sel = q >= p
        p, q, idx = p[sel], q[sel], idx[sel]

        pos += np.sum(idx - np.arange(len(idx)))
        return np.min(p*q), pos

res = []
p = 0
for i in range(100):
    p, _ = smallest_brilliant(p + 1)
    res.append(p)

print(f'first 100 are {res}')

for i in range(max_order*2):
    thresh = 10**i
    p, pos = smallest_brilliant(thresh)
    print(f'Above 10^{i:2d}: {p:20d} at #{pos}')


Burrows–Wheeler transform

{{Wikipedia|Burrows-Wheeler_transform}}

The Burrows-Wheeler transform (BWT, also called block-sorting compression) rearranges a character string into runs of similar characters.

This is useful for compression, since it tends to be easy to compress a string that has runs of repeated characters by techniques such as move-to-front transform and run-length encoding.

More importantly, the transformation is reversible, without needing to store any additional data.

The BWT is thus a "free" method of improving the efficiency of text compression algorithms, costing only some extra computation.

Source: Burrows-Wheeler transform

Solution:
def bwt(s):
    """Apply Burrows-Wheeler transform to input string."""
    assert "\002" not in s and "\003" not in s, "Input string cannot contain STX and ETX characters"
    s = "\002" + s + "\003"  # Add start and end of text marker
    table = sorted(s[i:] + s[:i] for i in range(len(s)))  # Table of rotations of string
    last_column = [row[-1:] for row in table]  # Last characters of each row
    return "".join(last_column)  # Convert list of characters into string

def ibwt(r):
    """Apply inverse Burrows-Wheeler transform."""
    table = [""] * len(r)  # Make empty table
    for i in range(len(r)):
        table = sorted(r[i] + table[i] for i in range(len(r)))  # Add a column of r
    s = [row for row in table if row.endswith("\003")][0]  # Find the correct row (ending in ETX)
    return s.rstrip("\003").strip("\002")  # Get rid of start and end markers


CSV data manipulation

CSV spreadsheet files are suitable for storing tabular data in a relatively portable way.

The CSV format is flexible but somewhat ill-defined.

For present purposes, authors may assume that the data fields contain no commas, backslashes, or quotation marks.

;Task:
Read a CSV file, change some values and save the changes back to a file.

For this task we will use the following CSV file:

 C1,C2,C3,C4,C5
 1,5,9,13,17
 2,6,10,14,18
 3,7,11,15,19
 4,8,12,16,20

Suggestions

 Show how to add a column, headed 'SUM', of the sums of the rows.
 If possible, illustrate the use of built-in or standard functions, methods, or libraries, that handle generic CSV files.

Solution:
import fileinput

changerow, changecolumn, changevalue = 2, 4, '"Spam"'

with fileinput.input('csv_data_manipulation.csv', inplace=True) as f:
    for line in f:
        if fileinput.filelineno() == changerow:
            fields = line.rstrip().split(',')
            fields[changecolumn-1] = changevalue
            line = ','.join(fields) + '\n'
        print(line, end='')


CSV to HTML translation

Consider a simplified CSV format where all rows are separated by a newline
and all columns are separated by commas.

No commas are allowed as field data, but the data may contain
other characters and character sequences that would
normally be   ''escaped''   when converted to HTML

;Task:
Create a function that takes a string representation of the CSV data
and returns a text string of an HTML table representing the CSV data.

Use the following  data as the CSV text to convert, and show your output.
: Character,Speech
: The multitude,The messiah! Show us the messiah!
: Brians mother,Now you listen here! He's not the messiah; he's a very naughty boy! Now go away!
: The multitude,Who are you?
: Brians mother,I'm his mother; that's who!
: The multitude,Behold his mother! Behold his mother!

;Extra credit:
''Optionally'' allow special formatting for the first row of the table as if it is the tables header row
(via  preferably; CSS if you must).

Solution:
from csv import DictReader
from xml.etree import ElementTree as ET

def csv2html_robust(txt, header=True, attr=None):
    # Use DictReader because, despite what the docs say, reader() doesn't
    # return an object with .fieldnames
    # (DictReader expects an iterable that returns lines, so split on \n)
    reader = DictReader(txt.split('\n'))

    table = ET.Element("TABLE", **attr.get('TABLE', {}))
    thead_tr = ET.SubElement(
        ET.SubElement(table, "THEAD", **attr.get('THEAD', {})),
        "TR")
    tbody = ET.SubElement(table, "TBODY", **attr.get('TBODY', {}))

    if header:
        for name in reader.fieldnames:
            ET.SubElement(thead_tr, "TD").text = name

    for row in reader:
        tr_elem = ET.SubElement(tbody, "TR", **attr.get('TR', {}))

        # Use reader.fieldnames to query `row` in the correct order.
        # (`row` isn't an OrderedDict prior to Python 3.6)
        for field in reader.fieldnames:
            td_elem = ET.SubElement(tr_elem, "TD", **attr.get('TD', {}))
            td_elem.text = row[field]

    return ET.tostring(table, method='html')

htmltxt = csv2html_robust(csvtxt, True, {
    'TABLE': {'border': "1", 'summary': "csv2html extra program output"},
    'THEAD': {'bgcolor': "yellow"},
    'TBODY': {'bgcolor': "orange"}
})

print(htmltxt.decode('utf8'))


Calculating the value of e

Calculate the value of   ''e''.

(''e''   is also known as   ''Euler's number''   and   ''Napier's constant''.)

See details: Calculating the value of e

Solution:
import math
#Implementation of Brother's formula
e0 = 0
e = 2
n = 0
fact = 1
while(e-e0 > 1e-15):
	e0 = e
	n += 1
	fact *= 2*n*(2*n+1)
	e += (2.*n+2)/fact

print "Computed e = "+str(e)
print "Real e = "+str(math.e)
print "Error = "+str(math.e-e)
print "Number of iterations = "+str(n)


Calculating the value of e

Solution:
'''Calculating an approximate value for e'''

from itertools import (accumulate, chain)
from functools import (reduce)
from operator import (mul)

# eApprox :: () -> Float
def eApprox():
    '''Approximation to the value of e.'''
    return reduce(
        lambda a, x: a + 1 / x,
        scanl(mul)(1)(
            range(1, 18)
        ),
        0
    )

# TEST ----------------------------------------------------
# main :: IO ()
def main():
    '''Test'''

    print(
        eApprox()
    )

# GENERIC ABSTRACTIONS ------------------------------------

# scanl is like reduce, but returns a succession of
# intermediate values, building from the left.
# See, for example, under `scan` in the Lists chapter of
# the language-independent Bird & Wadler 1988.

# scanl :: (b -> a -> b) -> b -> [a] -> [b]
def scanl(f):
    '''scanl is like reduce, but returns a succession of
       intermediate values, building from the left.'''
    return lambda a: lambda xs: (
        accumulate(chain([a], xs), f)
    )

# MAIN ---
if __name__ == '__main__':
    main()


Calkin-Wilf sequence

The '''Calkin-Wilf sequence''' contains every nonnegative rational number exactly once.

It can be calculated recursively as follows:

        {{math|a1}}   =  {{math|1}}
 {{math|an+1}}  =  {{math|1/(2an+1-an)}} for n > 1

;Task part 1:
* Show on this page terms 1 through 20 of the Calkin-Wilf sequence.

To avoid floating point error, you may want to use a rational number data type.

It is also possible, given a non-negative rational number, to determine where it appears in the sequence without calculating the sequence. The procedure is to get the continued fraction representation of the rational and use it as the run-length encoding of the binary representation of the term number, beginning from the end of the continued fraction.
It only works if the number of terms in the continued fraction is odd- use either of the two equivalent representations to achieve this:

        {{math|[a0; a1, a2, ..., an]}}  =  {{math|[a0; a1, a2 ,..., an-1, 1]}}

;Example:
The fraction   '''9/4'''   has odd continued fraction representation      {{math|2; 3, 1}},     giving a binary representation of   '''100011''',
which means   '''9/4'''   appears as the   '''35th'''   term of the sequence.

;Task part 2:
* Find the position of the number   '''83116''''''/''''''51639'''   in the Calkin-Wilf sequence.

;See also:
* Wikipedia entry:  Calkin-Wilf tree
* [[Continued fraction]]
* [[Continued fraction/Arithmetic/Construct from rational number]]

Solution:
from fractions import Fraction
from math import floor
from itertools import islice, groupby

def cw():
    a = Fraction(1)
    while True:
        yield a
        a = 1 / (2 * floor(a) + 1 - a)

def r2cf(rational):
    num, den = rational.numerator, rational.denominator
    while den:
        num, (digit, den) = den, divmod(num, den)
        yield digit

def get_term_num(rational):
    ans, dig, pwr = 0, 1, 0
    for n in r2cf(rational):
        for _ in range(n):
            ans |= dig << pwr
            pwr += 1
        dig ^= 1
    return ans

if __name__ == '__main__':
    print('TERMS 1..20: ', ', '.join(str(x) for x in islice(cw(), 20)))
    x = Fraction(83116, 51639)
    print(f"\n{x} is the {get_term_num(x):_}'th term.")


Call a function

Demonstrate the different syntax and semantics provided for calling a function.

This may include:
:*   Calling a function that requires no arguments
:*   Calling a function with a fixed number of arguments
:*   Calling a function with optional arguments
:*   Calling a function with a variable number of arguments
:*   Calling a function with named arguments
:*   Using a function in statement context
:*   Using a function in first-class context within an expression
:*   Obtaining the return value of a function
:*   Distinguishing built-in functions and user-defined functions
:*   Distinguishing subroutines and functions
;*   Stating whether arguments are passed by value or by reference
;*   Is partial application possible and how

This task is ''not'' about defining functions.

Solution:
def no_args():
    pass
# call
no_args()

def fixed_args(x, y):
    print('x=%r, y=%r' % (x, y))
# call
fixed_args(1, 2)        # x=1, y=2

## Can also called them using the parameter names, in either order:
fixed_args(y=2, x=1)

## Can also "apply" fixed_args() to a sequence:
myargs=(1,2) # tuple
fixed_args(*myargs)

def opt_args(x=1):
    print(x)
# calls
opt_args()              # 1
opt_args(3.141)         # 3.141

def var_args(*v):
    print(v)
# calls
var_args(1, 2, 3)       # (1, 2, 3)
var_args(1, (2,3))      # (1, (2, 3))
var_args()              # ()

## Named arguments
fixed_args(y=2, x=1)    # x=1, y=2

## As a statement
if 1:
    no_args()

## First-class within an expression
assert no_args() is None

def return_something():
    return 1
x = return_something()

def is_builtin(x):
	print(x.__name__ in dir(__builtins__))
# calls
is_builtin(pow)         # True
is_builtin(is_builtin)  # False

# Very liberal function definition

def takes_anything(*args, **kwargs):
    for each in args:
        print(each)
    for key, value in sorted(kwargs.items()):
        print("%s:%s" % (key, value))
    # Passing those to another, wrapped, function:
    wrapped_fn(*args, **kwargs)
    # (Function being wrapped can have any parameter list
    # ... that doesn't have to match this prototype)

## A subroutine is merely a function that has no explicit
## return statement and will return None.

## Python uses "Call by Object Reference".
## See, for example, http://www.python-course.eu/passing_arguments.php

## For partial function application see:
##   http://rosettacode.org/wiki/Partial_function_application#Python


Canonicalize CIDR

Implement a function or program that, given a range of IPv4 addresses in CIDR notation (dotted-decimal/network-bits), will return/output the same range in canonical form.

That is, the IP address portion of the output CIDR block must not contain any set (1) bits in the host part of the address.

;Example:
Given   '''87.70.141.1/22''',    your code should output    '''87.70.140.0/22'''

;Explanation:
An Internet Protocol version 4 address is a 32-bit value, conventionally represented as a number in base 256 using dotted-decimal notation, where each base-256 digit is given in decimal and the digits are separated by periods. Logically, this 32-bit value represents two components: the leftmost (most-significant) bits determine the network portion of the address, while the rightmost (least-significant) bits determine the host portion. Classless Internet Domain Routing block notation indicates where the boundary between these two components is for a given address by adding a slash followed by the number of bits in the network portion.

In general, CIDR blocks stand in for the entire set of IP addresses sharing the same network component, so it's common to see access control lists that specify individual IP addresses using /32 to indicate that only the one address is included. Software accepting this notation as input often expects it to be entered in canonical form, in which the host bits are all zeroes. But network admins sometimes skip this step and just enter the address of a specific host on the subnet with the network size, resulting in a non-canonical entry.

The example address, 87.70.141.1/22, represents binary 0101011101000110100011 / 0100000001, with the / indicating the network/host division. To canonicalize, clear all the bits to the right of the / and convert back to dotted decimal: 0101011101000110100011 / 0000000000 - 87.70.140.0.

;More examples for testing

        36.18.154.103/12    -  36.16.0.0/12
        62.62.197.11/29     -  62.62.197.8/29
        67.137.119.181/4    -  64.0.0.0/4
        161.214.74.21/24    -  161.214.74.0/24
        184.232.176.184/18  -  184.232.128.0/18

Solution:
#!/usr/bin/env python
# canonicalize a CIDR block specification:
# make sure none of the host bits are set

import sys
from socket import inet_aton, inet_ntoa
from struct import pack, unpack

args = sys.argv[1:]
if len(args) == 0:
    args = sys.stdin.readlines()

for cidr in args:
   # IP in dotted-decimal / bits in network part
   dotted, size_str = cidr.split('/')
   size = int(size_str)

   numeric = unpack('!I', inet_aton(dotted))[0]  # IP as an integer
   binary = f'{numeric:#034b}'                   # then as a padded binary string
   prefix = binary[:size + 2]                    # just the network part
                                                 #   (34 and +2 are to account
                                                 #    for leading '0b')

   canon_binary = prefix + '0' * (32 - size)     # replace host part with all zeroes
   canon_numeric = int(canon_binary, 2)          # convert back to integer
   canon_dotted = inet_ntoa(pack('!I',
                            (canon_numeric)))    # and then to dotted-decimal
   print(f'{canon_dotted}/{size}')               # output result


Cantor set

Draw a Cantor set.

See details at this Wikipedia webpage:   Cantor set

Solution:
WIDTH = 81
HEIGHT = 5

lines=[]
def cantor(start, len, index):
    seg = len / 3
    if seg == 0:
        return None
    for it in xrange(HEIGHT-index):
        i = index + it
        for jt in xrange(seg):
            j = start + seg + jt
            pos = i * WIDTH + j
            lines[pos] = ' '
    cantor(start,           seg, index + 1)
    cantor(start + seg * 2, seg, index + 1)
    return None

lines = ['*'] * (WIDTH*HEIGHT)
cantor(0, WIDTH, 1)

for i in xrange(HEIGHT):
    beg = WIDTH * i
    print ''.join(lines[beg : beg+WIDTH])


Cantor set

Solution:
'''A Cantor set generator, and two different
   representations of its output.
'''

from itertools import (islice, chain)
from fractions import Fraction
from functools import (reduce)

# ----------------------- CANTOR SET -----------------------

# cantor :: Generator [[(Fraction, Fraction)]]
def cantor():
    '''A non-finite stream of successive Cantor
       partitions of the line, in the form of
       lists of fraction pairs.
    '''
    def go(xy):
        (x, y) = xy
        third = Fraction(y - x, 3)
        return [(x, x + third), (y - third, y)]

    return iterate(
        concatMap(go)
    )(
        [(0, 1)]
    )

# fractionLists :: [(Fraction, Fraction)] -> String
def fractionLists(xs):
    '''A fraction pair representation of a
       Cantor-partitioned line.
    '''
    def go(xy):
        return ', '.join(map(showRatio, xy))
    return ' '.join('(' + go(x) + ')' for x in xs)

# intervalBars :: [(Fraction, Fraction)] -> String
def intervalBars(w):
    '''A block diagram representation of a
       Cantor-partitioned line.
    '''
    def go(xs):
        def show(a, tpl):
            [x, y] = [int(w * r) for r in tpl]
            return (
                y,
                (' ' * (x - a)) + ('█' * (y - x))
            )
        return mapAccumL(show)(0)(xs)
    return lambda xs: ''.join(go(xs)[1])

# -------------------------- TEST --------------------------
# main :: IO ()
def main():
    '''Testing the generation of successive
       Cantor subdivisions of the line, and
       displaying them both as lines of fraction
       pairs and as graphic interval bars.
    '''
    xs = list(islice(cantor(), 4))
    w = max(xy[1].denominator for xy in xs[-1])
    print(
        '\n'.join(map(fractionLists, xs)),
        '\n'
    )
    print(
        '\n'.join(map(intervalBars(w), xs))
    )

# ------------------------ GENERIC -------------------------

# concatMap :: (a -> [b]) -> [a] -> [b]
def concatMap(f):
    '''A concatenated list over which a function has been mapped.
       The list monad can be derived by using a function f which
       wraps its output in a list,
       (using an empty list to represent computational failure).'''
    return lambda xs: list(
        chain.from_iterable(map(f, xs))
    )

# iterate :: (a -> a) -> a -> Gen [a]
def iterate(f):
    '''An infinite list of repeated
       applications of f to x.
    '''
    def go(x):
        v = x
        while True:
            yield v
            v = f(v)
    return go

# mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
def mapAccumL(f):
    '''A tuple of an accumulation and a list derived by a
       combined map and fold,
       with accumulation from left to right.
    '''
    def go(a, x):
        tpl = f(a[0], x)
        return (tpl[0], a[1] + [tpl[1]])
    return lambda acc: lambda xs: (
        reduce(go, xs, (acc, []))
    )

# showRatio :: Ratio -> String
def showRatio(r):
    '''String representation of the ratio r.'''
    d = r.denominator
    return str(r.numerator) + (
        '/' + str(d) if 1 != d else ''
    )

# MAIN ---
if __name__ == '__main__':
    main()


Cartesian product of two or more lists

Show one or more idiomatic ways of generating the Cartesian product of two arbitrary lists in your language.

Demonstrate that your function/method correctly returns:
::{1, 2} x {3, 4} = {(1, 3), (1, 4), (2, 3), (2, 4)}

and, in contrast:
::{3, 4} x {1, 2} = {(3, 1), (3, 2), (4, 1), (4, 2)}

Also demonstrate, using your function/method, that the product of an empty list with any other list is empty.
:: {1, 2} x {} = {}
:: {} x {1, 2} = {}

For extra credit, show or write a function returning the n-ary product of an arbitrary number of lists, each of arbitrary length. Your function might, for example, accept a single argument which is itself a list of lists, and return the n-ary product of those lists.

Use your n-ary Cartesian product function to show the following products:
:: {1776, 1789} x {7, 12} x {4, 14, 23} x {0, 1}
:: {1, 2, 3} x {30} x {500, 100}
:: {1, 2, 3} x {} x {500, 100}

Solution:
import itertools

def cp(lsts):
    return list(itertools.product(*lsts))

if __name__ == '__main__':
    from pprint import pprint as pp

    for lists in [[[1,2],[3,4]], [[3,4],[1,2]], [[], [1, 2]], [[1, 2], []],
                  ((1776, 1789),  (7, 12), (4, 14, 23), (0, 1)),
                  ((1, 2, 3), (30,), (500, 100)),
                  ((1, 2, 3), (), (500, 100))]:
        print(lists, '=>')
        pp(cp(lists), indent=2)


Casting out nines

Task   (in three parts):

;Part 1
Write a procedure (say \mathit{co9}(x)) which implements Casting Out Nines as described by returning the checksum for x. Demonstrate the procedure using the examples given there, or others you may consider lucky.

Note that this function does nothing more than calculate the least positive residue, modulo 9. Many of the solutions omit Part 1 for this reason. Many languages have a modulo operator, of which this is a trivial application.

With that understanding, solutions to Part 1, if given, are encouraged to follow the naive pencil-and-paper or mental arithmetic of repeated digit addition understood to be "casting out nines", or some approach other than just reducing modulo 9 using a built-in operator. Solutions for part 2 and 3 are not required to make use of the function presented in part 1.

;Part 2
Notwithstanding past Intel microcode errors, checking computer calculations like this would not be sensible. To find a computer use for your procedure:
: Consider the statement "318682 is 101558 + 217124 and squared is 101558217124" (see: [[Kaprekar numbers#Casting Out Nines (fast)]]).
: note that 318682 has the same checksum as (101558 + 217124);
: note that 101558217124 has the same checksum as (101558 + 217124) because for a Kaprekar they are made up of the same digits (sometimes with extra zeroes);
: note that this implies that for Kaprekar numbers the checksum of k equals the checksum of k^2.

Demonstrate that your procedure can be used to generate or filter a range of numbers with the property \mathit{co9}(k) = \mathit{co9}(k^2) and show that this subset is a small proportion of the range and contains all the Kaprekar in the range.

;Part 3
Considering this MathWorld page, produce a efficient algorithm based on the more mathematical treatment of Casting Out Nines, and realizing:
: \mathit{co9}(x) is the residual of x mod 9;
: the procedure can be extended to bases other than 9.

Demonstrate your algorithm by generating or filtering a range of numbers with the property k%(\mathit{Base}-1) == (k^2)%(\mathit{Base}-1) and show that this subset is a small proportion of the range and contains all the Kaprekar in the range.

;related tasks
* [[First perfect square in base N with N unique digits]]
* [[Kaprekar numbers]]

Solution:
# Casting out Nines
#
# Nigel Galloway: June 27th., 2012,
#
def CastOut(Base=10, Start=1, End=999999):
  ran = [y for y in range(Base-1) if y%(Base-1) == (y*y)%(Base-1)]
  x,y = divmod(Start, Base-1)
  while True:
    for n in ran:
      k = (Base-1)*x + n
      if k < Start:
        continue
      if k > End:
        return
      yield k
    x += 1

for V in CastOut(Base=16,Start=1,End=255):
  print(V, end=' ')


Catalan numbers/Pascal's triangle

Print out the first   '''15'''   Catalan numbers by extracting them from Pascal's triangle.

;See:
*   Catalan Numbers and the Pascal Triangle.      This method enables calculation of Catalan Numbers using only addition and subtraction.

*   Catalan's Triangle for a Number Triangle that generates Catalan Numbers using only addition.
*   Sequence A000108 on OEIS has a lot of information on Catalan Numbers.

;Related Tasks:
[[Pascal's triangle]]

Solution:
>>> n = 15
>>> t = [0] * (n + 2)
>>> t[1] = 1
>>> for i in range(1, n + 1):
	for j in range(i, 1, -1): t[j] += t[j - 1]
	t[i + 1] = t[i]
	for j in range(i + 1, 1, -1): t[j] += t[j - 1]
	print(t[i+1] - t[i], end=' ')

1 2 5 14 42 132 429 1430 4862 16796 58786 208012 742900 2674440 9694845
>>>


Catalan numbers/Pascal's triangle

Solution:
def catalan_number(n):
    nm = dm = 1
    for k in range(2, n+1):
      nm, dm = ( nm*(n+k), dm*k )
    return nm/dm

print [catalan_number(n) for n in range(1, 16)]

[1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845]


Catalan numbers/Pascal's triangle

Solution:
'''Catalan numbers from Pascal's triangle'''

from itertools import (islice)
from operator import (add)

# nCatalans :: Int -> [Int]
def nCatalans(n):
    '''The first n Catalan numbers,
       derived from Pascal's triangle.'''

    # diff :: [Int] -> Int
    def diff(xs):
        '''Difference between the first two items in the list,
           if its length is more than one.
           Otherwise, the first (only) item in the list.'''
        return (
            xs[0] - (xs[1] if 1 < len(xs) else 0)
        ) if xs else None
    return list(map(
        compose(diff)(uncurry(drop)),
        enumerate(map(fst, take(n)(
            everyOther(
                pascalTriangle()
            )
        )))
    ))

# pascalTriangle :: Gen [[Int]]
def pascalTriangle():
    '''A non-finite stream of
       Pascal's triangle rows.'''
    return iterate(nextPascal)([1])

# nextPascal :: [Int] -> [Int]
def nextPascal(xs):
    '''A row of Pascal's triangle
       derived from a preceding row.'''
    return zipWith(add)([0] + xs)(xs + [0])

# TEST ----------------------------------------------------
# main :: IO ()
def main():
    '''First 16 Catalan numbers.'''

    print(
        nCatalans(16)
    )

# GENERIC -------------------------------------------------

# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
    '''Right to left function composition.'''
    return lambda f: lambda x: g(f(x))

# drop :: Int -> [a] -> [a]
# drop :: Int -> String -> String
def drop(n):
    '''The sublist of xs beginning at
       (zero-based) index n.'''
    def go(xs):
        if isinstance(xs, list):
            return xs[n:]
        else:
            take(n)(xs)
            return xs
    return lambda xs: go(xs)

# everyOther :: Gen [a] -> Gen [a]
def everyOther(g):
    '''Every other item of a generator stream.'''
    while True:
        yield take(1)(g)
        take(1)(g)      # Consumed, not yielded.

# fst :: (a, b) -> a
def fst(tpl):
    '''First component of a pair.'''
    return tpl[0]

# iterate :: (a -> a) -> a -> Gen [a]
def iterate(f):
    '''An infinite list of repeated applications of f to x.'''
    def go(x):
        v = x
        while True:
            yield v
            v = f(v)
    return lambda x: go(x)

# take :: Int -> [a] -> [a]
# take :: Int -> String -> String
def take(n):
    '''The prefix of xs of length n,
       or xs itself if n > length xs.'''
    return lambda xs: (
        xs[0:n]
        if isinstance(xs, list)
        else list(islice(xs, n))
    )

# uncurry :: (a -> b -> c) -> ((a, b) -> c)
def uncurry(f):
    '''A function over a tuple
       derived from a curried function.'''
    return lambda xy: f(xy[0])(
        xy[1]
    )

# zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
def zipWith(f):
    '''A list constructed by zipping with a
       custom function, rather than with the
       default tuple constructor.'''
    return lambda xs: lambda ys: (
        list(map(f, xs, ys))
    )

# MAIN ---
if __name__ == '__main__':
    main()


Catamorphism

''Reduce'' is a function or method that is used to take the values in an array or a list and apply a function to successive members of the list to produce (or reduce them to), a single value.

;Task:
Show how ''reduce'' (or ''foldl'' or ''foldr'' etc), work (or would be implemented) in your language.

;See also:
* Wikipedia article:   Fold
* Wikipedia article:   Catamorphism

Solution:
>>> # Python 2.X
>>> from operator import add
>>> listoflists = [['the', 'cat'], ['sat', 'on'], ['the', 'mat']]
>>> help(reduce)
Help on built-in function reduce in module __builtin__:

reduce(...)
    reduce(function, sequence[, initial]) -> value

    Apply a function of two arguments cumulatively to the items of a sequence,
    from left to right, so as to reduce the sequence to a single value.
    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
    ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
    of the sequence in the calculation, and serves as a default when the
    sequence is empty.

>>> reduce(add, listoflists, [])
['the', 'cat', 'sat', 'on', 'the', 'mat']
>>>


Chaocipher

Description:
The Chaocipher was invented by J.F.Byrne in 1918 and, although simple by modern cryptographic standards, does not appear to have been broken until the algorithm was finally disclosed by his family in 2010.

The algorithm is described in this paper by M.Rubin in 2010 and there is a C# implementation here.

;Task:
Code the algorithm in your language and to test that it works with the plaintext 'WELLDONEISBETTERTHANWELLSAID' used in the paper itself.

Solution:
# Python3 implementation of Chaocipher
# left wheel = ciphertext wheel
# right wheel = plaintext wheel

def main():
    # letters only! makealpha(key) helps generate lalpha/ralpha.
    lalpha = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
    ralpha = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
    msg = "WELLDONEISBETTERTHANWELLSAID"

    print("L:", lalpha)
    print("R:", ralpha)
    print("I:", msg)
    print("O:", do_chao(msg, lalpha, ralpha, 1, 0), "\n")

    do_chao(msg, lalpha, ralpha, 1, 1)

def do_chao(msg, lalpha, ralpha, en=1, show=0):
    msg = correct_case(msg)
    out = ""
    if show:
        print("="*54)
        print(10*" " + "left:" + 21*" " + "right: ")
        print("="*54)
        print(lalpha, ralpha, "\n")
    for L in msg:
        if en:
            lalpha, ralpha = rotate_wheels(lalpha, ralpha, L)
            out += lalpha[0]
        else:
            ralpha, lalpha = rotate_wheels(ralpha, lalpha, L)
            out += ralpha[0]
        lalpha, ralpha = scramble_wheels(lalpha, ralpha)
        if show:
            print(lalpha, ralpha)
    return out

def makealpha(key=""):
    alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    z = set()
    key = [x.upper() for x in (key + alpha[::-1])
           if not (x.upper() in z or z.add(x.upper()))]
    return "".join(key)

def correct_case(string):
    return "".join([s.upper() for s in string if s.isalpha()])

def permu(alp, num):
    alp = alp[:num], alp[num:]
    return "".join(alp[::-1])

def rotate_wheels(lalph, ralph, key):
    newin = ralph.index(key)
    return permu(lalph, newin), permu(ralph, newin)

def scramble_wheels(lalph, ralph):
    # LEFT = cipher wheel
    # Cycle second[1] through nadir[14] forward
    lalph = list(lalph)
    lalph = "".join([*lalph[0],
                    *lalph[2:14],
                    lalph[1],
                    *lalph[14:]])

    # RIGHT = plain wheel
    # Send the zenith[0] character to the end[25],
    # cycle third[2] through nadir[14] characters forward
    ralph = list(ralph)
    ralph = "".join([*ralph[1:3],
                     *ralph[4:15],
                     ralph[3],
                     *ralph[15:],
                     ralph[0]])
    return lalph, ralph

main()


Chaocipher

Solution:
'''Chaocipher'''

from itertools import chain, cycle, islice

# chao :: String -> String -> Bool -> String -> String
def chao(l):
    '''Chaocipher encoding or decoding for the given
       left and right 'wheels'.
       A ciphertext is returned if the boolean flag
       is True, and a plaintext if the flag is False.
    '''
    def go(l, r, plain, xxs):
        if xxs:
            (src, dst) = (l, r) if plain else (r, l)
            (x, xs) = (xxs[0], xxs[1:])

            def chaoProcess(n):
                return [dst[n]] + go(
                    shifted(1)(14)(rotated(n, l)),
                    compose(shifted(2)(14))(shifted(0)(26))(
                        rotated(n, r)
                    ),
                    plain,
                    xs
                )

            return maybe('')(chaoProcess)(
                elemIndex(x)(src)
            )
        else:
            return []
    return lambda r: lambda plain: lambda xxs: concat(go(
        l, r, plain, xxs
    ))

# rotated :: Int -> [a] -> [a]
def rotated(z, s):
    '''Rotation of string s by z characters.'''
    return take(len(s))(
        drop(z)(
            cycle(s)
        )
    )

# shifted :: Int -> Int -> [a] -> [a]
def shifted(src):
    '''The string s with a set of its characters cyclically
       shifted from a source index to a destination index.
    '''
    def go(dst, s):
        (a, b) = splitAt(dst)(s)
        (x, y) = splitAt(src)(a)
        return concat([x, rotated(1, y), b])
    return lambda dst: lambda s: go(dst, s)

# TEST ----------------------------------------------------
# main :: IO ()
def main():
    '''Print the plain text, followed by
       a corresponding cipher text,
       and a decode of that cipher text.
    '''
    chaoWheels = chao(
        "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
    )(
        "PTLNBQDEOYSFAVZKGJRIHWXUMC"
    )
    plainText = "WELLDONEISBETTERTHANWELLSAID"
    cipherText = chaoWheels(False)(plainText)

    print(plainText)
    print(cipherText)
    print(
        chaoWheels(True)(cipherText)
    )

# GENERIC -------------------------------------------------

# Just :: a -> Maybe a
def Just(x):
    '''Constructor for an inhabited Maybe (option type) value.
       Wrapper containing the result of a computation.
    '''
    return {'type': 'Maybe', 'Nothing': False, 'Just': x}

# Nothing :: Maybe a
def Nothing():
    '''Constructor for an empty Maybe (option type) value.
       Empty wrapper returned where a computation is not possible.
    '''
    return {'type': 'Maybe', 'Nothing': True}

# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
    '''Right to left function composition.'''
    return lambda f: lambda x: g(f(x))

# concat :: [[a]] -> [a]
# concat :: [String] -> String
def concat(xs):
    '''The concatenation of all the elements
       in a list or iterable.
    '''
    def f(ys):
        zs = list(chain(*ys))
        return ''.join(zs) if isinstance(ys[0], str) else zs

    return (
        f(xs) if isinstance(xs, list) else (
            chain.from_iterable(xs)
        )
    ) if xs else []

# drop :: Int -> [a] -> [a]
# drop :: Int -> String -> String
def drop(n):
    '''The sublist of xs beginning at
       (zero-based) index n.
    '''
    def go(xs):
        if isinstance(xs, (list, tuple, str)):
            return xs[n:]
        else:
            take(n)(xs)
            return xs
    return lambda xs: go(xs)

# elemIndex :: Eq a => a -> [a] -> Maybe Int
def elemIndex(x):
    '''Just the index of the first element in xs
       which is equal to x,
       or Nothing if there is no such element.
    '''
    def go(xs):
        try:
            return Just(xs.index(x))
        except ValueError:
            return Nothing()
    return lambda xs: go(xs)

# maybe :: b -> (a -> b) -> Maybe a -> b
def maybe(v):
    '''Either the default value v, if m is Nothing,
       or the application of f to x,
       where m is Just(x).
    '''
    return lambda f: lambda m: v if None is m or m.get('Nothing') else (
        f(m.get('Just'))
    )

# splitAt :: Int -> [a] -> ([a], [a])
def splitAt(n):
    '''A tuple pairing the prefix of length n
       with the rest of xs.
    '''
    return lambda xs: (xs[0:n], xs[n:])

# take :: Int -> [a] -> [a]
# take :: Int -> String -> String
def take(n):
    '''The prefix of xs of length n,
       or xs itself if n > length xs.
    '''
    return lambda xs: (
        xs[0:n]
        if isinstance(xs, (list, tuple))
        else list(islice(xs, n))
    )

# MAIN ---
if __name__ == '__main__':
    main()


Chaos game

The Chaos Game is a method of generating the attractor of an iterated function system (IFS).

One of the best-known and simplest examples creates a fractal, using a polygon and an initial point selected at random.

;Task
Play the Chaos Game using the corners of an equilateral triangle as the reference points.   Add a starting point at random (preferably inside the triangle).   Then add the next point halfway between the starting point and one of the reference points.   This reference point is chosen at random.

After a sufficient number of iterations, the image of a Sierpinski Triangle should emerge.

;See also
* The Game of Chaos

Solution:
import argparse
import random
import shapely.geometry as geometry
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

def main(args):
    # Styles
    plt.style.use("ggplot")

    # Creating figure
    fig = plt.figure()
    line, = plt.plot([], [], ".")

    # Limit axes
    plt.xlim(0, 1)
    plt.ylim(0, 1)

    # Titles
    title = "Chaos Game"
    plt.title(title)
    fig.canvas.set_window_title(title)

    # Getting data
    data = get_data(args.frames)

    # Creating animation
    line_ani = animation.FuncAnimation(
        fig=fig,
        func=update_line,
        frames=args.frames,
        fargs=(data, line),
        interval=args.interval,
        repeat=False
    )

    # To save the animation install ffmpeg and uncomment
    # line_ani.save("chaos_game.gif")

    plt.show()

def get_data(n):
    """
    Get data to plot
    """
    leg = 1
    triangle = get_triangle(leg)
    cur_point = gen_point_within_poly(triangle)
    data = []
    for _ in range(n):
        data.append((cur_point.x, cur_point.y))
        cur_point = next_point(triangle, cur_point)
    return data

def get_triangle(n):
    """
    Create right triangle
    """
    ax = ay = 0.0
    a = ax, ay

    bx = 0.5  *  n
    by = 0.75 * (n ** 2)
    b = bx, by

    cx = n
    cy = 0.0
    c = cx, cy

    triangle = geometry.Polygon([a, b, c])
    return triangle

def gen_point_within_poly(poly):
    """
    Generate random point inside given polygon
    """
    minx, miny, maxx, maxy = poly.bounds
    while True:
        x = random.uniform(minx, maxx)
        y = random.uniform(miny, maxy)
        point = geometry.Point(x, y)
        if point.within(poly):
            return point

def next_point(poly, point):
    """
    Generate next point according to chaos game rules
    """
    vertices = poly.boundary.coords[:-1]  # Last point is the same as the first one
    random_vertex = geometry.Point(random.choice(vertices))
    line = geometry.linestring.LineString([point, random_vertex])
    return line.centroid

def update_line(num, data, line):
    """
    Update line with new points
    """
    new_data = zip(*data[:num]) or [(), ()]
    line.set_data(new_data)
    return line,

if __name__ == "__main__":
    arg_parser = argparse.ArgumentParser(description="Chaos Game by Suenweek (c) 2017")
    arg_parser.add_argument("-f", dest="frames", type=int, default=1000)
    arg_parser.add_argument("-i", dest="interval", type=int, default=10)

    main(arg_parser.parse_args())


Check Machin-like formulas

Machin-like formulas   are useful for efficiently computing numerical approximations for \pi

;Task:
Verify the following Machin-like formulas are correct by calculating the value of '''tan'''   (''right hand side)'' for each equation using exact arithmetic and showing they equal '''1''':

: {\pi\over4} = \arctan{1\over2} + \arctan{1\over3}
: {\pi\over4} = 2 \arctan{1\over3} + \arctan{1\over7}
: {\pi\over4} = 4 \arctan{1\over5} - \arctan{1\over239}
: {\pi\over4} = 5 \arctan{1\over7} + 2 \arctan{3\over79}
: {\pi\over4} = 5 \arctan{29\over278} + 7 \arctan{3\over79}
: {\pi\over4} = \arctan{1\over2} + \arctan{1\over5} + \arctan{1\over8}
: {\pi\over4} = 4 \arctan{1\over5} - \arctan{1\over70} + \arctan{1\over99}
: {\pi\over4} = 5 \arctan{1\over7} + 4 \arctan{1\over53} + 2 \arctan{1\over4443}
: {\pi\over4} = 6 \arctan{1\over8} + 2 \arctan{1\over57} + \arctan{1\over239}
: {\pi\over4} = 8 \arctan{1\over10} - \arctan{1\over239} - 4 \arctan{1\over515}
: {\pi\over4} = 12 \arctan{1\over18} + 8 \arctan{1\over57} - 5 \arctan{1\over239}
: {\pi\over4} = 16 \arctan{1\over21} + 3 \arctan{1\over239} + 4 \arctan{3\over1042}
: {\pi\over4} = 22 \arctan{1\over28} + 2 \arctan{1\over443} - 5 \arctan{1\over1393} - 10 \arctan{1\over11018}
: {\pi\over4} = 22 \arctan{1\over38} + 17 \arctan{7\over601} + 10 \arctan{7\over8149}
: {\pi\over4} = 44 \arctan{1\over57} + 7 \arctan{1\over239} - 12 \arctan{1\over682} + 24 \arctan{1\over12943}
: {\pi\over4} = 88 \arctan{1\over172} + 51 \arctan{1\over239} + 32 \arctan{1\over682} + 44 \arctan{1\over5357} + 68 \arctan{1\over12943}

and confirm that the following formula is ''incorrect'' by showing   '''tan'''   (''right hand side)''   is ''not''   '''1''':

: {\pi\over4} = 88 \arctan{1\over172} + 51 \arctan{1\over239} + 32 \arctan{1\over682} + 44 \arctan{1\over5357} + 68 \arctan{1\over12944}

These identities are useful in calculating the values:
: \tan(a + b) = {\tan(a) + \tan(b) \over 1 - \tan(a) \tan(b)}

: \tan\left(\arctan{a \over b}\right) = {a \over b}

: \tan(-a) = -\tan(a)

You can store the equations in any convenient data structure, but for extra credit parse them from human-readable text input.

Note: to formally prove the formula correct, it would have to be shown that ''{-3 pi \over 4} < right hand side < {5 pi \over 4}'' due to ''\tan()'' periodicity.

Solution:
import re
from fractions import Fraction
from pprint import pprint as pp

equationtext = '''\
  pi/4 = arctan(1/2) + arctan(1/3)
  pi/4 = 2*arctan(1/3) + arctan(1/7)
  pi/4 = 4*arctan(1/5) - arctan(1/239)
  pi/4 = 5*arctan(1/7) + 2*arctan(3/79)
  pi/4 = 5*arctan(29/278) + 7*arctan(3/79)
  pi/4 = arctan(1/2) + arctan(1/5) + arctan(1/8)
  pi/4 = 4*arctan(1/5) - arctan(1/70) + arctan(1/99)
  pi/4 = 5*arctan(1/7) + 4*arctan(1/53) + 2*arctan(1/4443)
  pi/4 = 6*arctan(1/8) + 2*arctan(1/57) + arctan(1/239)
  pi/4 = 8*arctan(1/10) - arctan(1/239) - 4*arctan(1/515)
  pi/4 = 12*arctan(1/18) + 8*arctan(1/57) - 5*arctan(1/239)
  pi/4 = 16*arctan(1/21) + 3*arctan(1/239) + 4*arctan(3/1042)
  pi/4 = 22*arctan(1/28) + 2*arctan(1/443) - 5*arctan(1/1393) - 10*arctan(1/11018)
  pi/4 = 22*arctan(1/38) + 17*arctan(7/601) + 10*arctan(7/8149)
  pi/4 = 44*arctan(1/57) + 7*arctan(1/239) - 12*arctan(1/682) + 24*arctan(1/12943)
  pi/4 = 88*arctan(1/172) + 51*arctan(1/239) + 32*arctan(1/682) + 44*arctan(1/5357) + 68*arctan(1/12943)
  pi/4 = 88*arctan(1/172) + 51*arctan(1/239) + 32*arctan(1/682) + 44*arctan(1/5357) + 68*arctan(1/12944)
'''

def parse_eqn(equationtext=equationtext):
    eqn_re = re.compile(r"""(?mx)
    (?P<lhs> ^ \s* pi/4 \s* = \s*)?             # LHS of equation
    (?:                                         # RHS
        \s* (?P<sign> [+-])? \s*
        (?: (?P<mult> \d+) \s* \*)?
        \s* arctan\( (?P<numer> \d+) / (?P<denom> \d+)
    )""")

    found = eqn_re.findall(equationtext)
    machins, part = [], []
    for lhs, sign, mult, numer, denom in eqn_re.findall(equationtext):
        if lhs and part:
            machins.append(part)
            part = []
        part.append( ( (-1 if sign == '-' else 1) * ( int(mult) if mult else 1),
                       Fraction(int(numer), (int(denom) if denom else 1)) ) )
    machins.append(part)
    return machins

def tans(xs):
    xslen = len(xs)
    if xslen == 1:
        return tanEval(*xs[0])
    aa, bb = xs[:xslen//2], xs[xslen//2:]
    a, b = tans(aa), tans(bb)
    return (a + b) / (1 - a * b)

def tanEval(coef, f):
    if coef == 1:
        return f
    if coef < 0:
        return -tanEval(-coef, f)
    ca = coef // 2
    cb = coef - ca
    a, b = tanEval(ca, f), tanEval(cb, f)
    return (a + b) / (1 - a * b)

if __name__ == '__main__':
    machins = parse_eqn()
    #pp(machins, width=160)
    for machin, eqn in zip(machins, equationtext.split('\n')):
        ans = tans(machin)
        print('%5s: %s' % ( ('OK' if ans == 1 else 'ERROR'), eqn))


Check input device is a terminal

Demonstrate how to check whether the input device is a terminal or not.

;Related task:
*   [[Check output device is a terminal]]

Solution:
from sys import stdin
if stdin.isatty():
    print("Input comes from tty.")
else:
    print("Input doesn't come from tty.")


Check output device is a terminal

Demonstrate how to check whether the output device is a terminal or not.

;Related task:
*   [[Check input device is a terminal]]

Solution:
from sys import stdout
if stdout.isatty():
    print 'The output device is a teletype. Or something like a teletype.'
else:
    print 'The output device isn\'t like a teletype.'


Cheryl's birthday

Albert and Bernard just became friends with Cheryl, and they want to know when her birthday is.

Cheryl gave them a list of ten possible dates:
      May 15,     May 16,     May 19
      June 17,    June 18
      July 14,    July 16
      August 14,  August 15,  August 17

Cheryl then tells Albert the   ''month''   of birth,   and Bernard the   ''day''   (of the month)   of birth.
  1)  Albert:   I don't know when Cheryl's birthday is, but I know that Bernard does not know too.
  2)  Bernard:  At first I don't know when Cheryl's birthday is, but I know now.
  3)  Albert:   Then I also know when Cheryl's birthday is.

;Task
Write a computer program to deduce, by successive elimination, Cheryl's birthday.

;Related task:
* [[Sum and Product Puzzle]]

;References
* Wikipedia article of the same name.
* Tuple Relational Calculus

Solution:
'''Cheryl's Birthday'''

from itertools import groupby
from re import split

# main :: IO ()
def main():
    '''Derivation of the date.'''

    month, day = 0, 1
    print(
        # (3 :: A "Then I also know")
        # (A's month contains only one remaining day)
        uniquePairing(month)(
            # (2 :: B "I know now")
            # (B's day is paired with only one remaining month)
            uniquePairing(day)(
                # (1 :: A "I know that Bernard does not know")
                # (A's month is not among those with unique days)
                monthsWithUniqueDays(False)([
                    # 0 :: Cheryl's list:
                    tuple(x.split()) for x in
                    split(
                        ', ',
                        'May 15, May 16, May 19, ' +
                        'June 17, June 18, ' +
                        'July 14, July 16, ' +
                        'Aug 14, Aug 15, Aug 17'
                    )
                ])
            )
        )
    )

# ------------------- QUERY FUNCTIONS --------------------

# monthsWithUniqueDays :: Bool -> [(Month, Day)] -> [(Month, Day)]
def monthsWithUniqueDays(blnInclude):
    '''The subset of months with (or without) unique days.
    '''
    def go(xs):
        month, day = 0, 1
        months = [fst(x) for x in uniquePairing(day)(xs)]
        return [
            md for md in xs
            if blnInclude or not (md[month] in months)
        ]
    return go

# uniquePairing :: DatePart -> [(Month, Day)] -> [(Month, Day)]
def uniquePairing(i):
    '''Subset of months (or days) with a unique intersection.
    '''
    def go(xs):
        def inner(md):
            dct = md[i]
            uniques = [
                k for k in dct.keys()
                if 1 == len(dct[k])
            ]
            return [tpl for tpl in xs if tpl[i] in uniques]
        return inner
    return ap(bindPairs)(go)

# bindPairs :: [(Month, Day)] ->
# ((Dict String [String], Dict String [String])
# -> [(Month, Day)]) -> [(Month, Day)]
def bindPairs(xs):
    '''List monad injection operator for lists
       of (Month, Day) pairs.
    '''
    return lambda f: f(
        (
            dictFromPairs(xs),
            dictFromPairs(
                [(b, a) for (a, b) in xs]
            )
        )
    )

# dictFromPairs :: [(Month, Day)] -> Dict Text [Text]
def dictFromPairs(xs):
    '''A dictionary derived from a list of
       month day pairs.
    '''
    return {
        k: [snd(x) for x in m] for k, m in groupby(
            sorted(xs, key=fst), key=fst
        )
    }

# ----------------------- GENERIC ------------------------

# ap :: (a -> b -> c) -> (a -> b) -> a -> c
def ap(f):
    '''Applicative instance for functions.
    '''
    def go(g):
        def fxgx(x):
            return f(x)(
                g(x)
            )
        return fxgx
    return go

# fst :: (a, b) -> a
def fst(tpl):
    '''First component of a pair.
    '''
    return tpl[0]

# snd :: (a, b) -> b
def snd(tpl):
    '''Second component of a pair.
    '''
    return tpl[1]

if __name__ == '__main__':
    main()


Chinese remainder theorem

Suppose   n_1,   n_2,   \ldots,   n_k   are positive [[integer]]s that are pairwise co-prime.

Then, for any given sequence of integers   a_1,   a_2,   \dots,   a_k,   there exists an integer   x   solving the following system of simultaneous congruences:

::: \begin{align}
  x &\equiv a_1 \pmod{n_1} \\
  x &\equiv a_2 \pmod{n_2} \\
    &{}\  \  \vdots \\
  x &\equiv a_k \pmod{n_k}
\end{align}

Furthermore, all solutions   x   of this system are congruent modulo the product,    N=n_1n_2\ldots n_k.

;Task:
Write a program to solve a system of linear congruences by applying the   Chinese Remainder Theorem.

If the system of equations cannot be solved, your program must somehow indicate this.

(It may throw an exception or return a special false value.)

Since there are infinitely many solutions, the program should return the unique solution   s   where   0 \leq s \leq n_1n_2\ldots n_k.

''Show the functionality of this program'' by printing the result such that the   n's   are   [3,5,7]   and the   a's   are   [2,3,2].

'''Algorithm''':   The following algorithm only applies if the   n_i's   are pairwise co-prime.

Suppose, as above, that a solution is required for the system of congruences:

::: x \equiv a_i \pmod{n_i} \quad\mathrm{for}\; i = 1, \ldots, k

Again, to begin, the product   N = n_1n_2 \ldots n_k   is defined.

Then a solution   x   can be found as follows:

For each   i,   the integers   n_i   and   N/n_i   are co-prime.

Using the   Extended Euclidean algorithm,   we can find integers   r_i   and   s_i   such that   r_i n_i + s_i N/n_i = 1.

Then, one solution to the system of simultaneous congruences is:

::: x = \sum_{i=1}^k a_i s_i N/n_i

and the minimal solution,

::: x \pmod{N}.

Solution:
# Python 2.7
def chinese_remainder(n, a):
    sum = 0
    prod = reduce(lambda a, b: a*b, n)

    for n_i, a_i in zip(n, a):
        p = prod / n_i
        sum += a_i * mul_inv(p, n_i) * p
    return sum % prod

def mul_inv(a, b):
    b0 = b
    x0, x1 = 0, 1
    if b == 1: return 1
    while a > 1:
        q = a / b
        a, b = b, a%b
        x0, x1 = x1 - q * x0, x0
    if x1 < 0: x1 += b0
    return x1

if __name__ == '__main__':
    n = [3, 5, 7]
    a = [2, 3, 2]
    print chinese_remainder(n, a)


Chinese remainder theorem

Solution:
'''Chinese remainder theorem'''

from operator import (add, mul)
from functools import reduce

# cnRemainder :: [Int] -> [Int] -> Either String Int
def cnRemainder(ms):
    '''Chinese remainder theorem.
       (moduli, residues) -> Either explanation or solution
    '''
    def go(ms, rs):
        mp = numericProduct(ms)
        cms = [(mp // x) for x in ms]

        def possibleSoln(invs):
            return Right(
                sum(map(
                    mul,
                    cms, map(mul, rs, invs)
                )) % mp
            )
        return bindLR(
            zipWithEither(modMultInv)(cms)(ms)
        )(possibleSoln)

    return lambda rs: go(ms, rs)

# modMultInv :: Int -> Int -> Either String Int
def modMultInv(a, b):
    '''Modular multiplicative inverse.'''
    x, y = eGcd(a, b)
    return Right(x) if 1 == (a * x + b * y) else (
        Left('no modular inverse for ' + str(a) + ' and ' + str(b))
    )

# egcd :: Int -> Int -> (Int, Int)
def eGcd(a, b):
    '''Extended greatest common divisor.'''
    def go(a, b):
        if 0 == b:
            return (1, 0)
        else:
            q, r = divmod(a, b)
            (s, t) = go(b, r)
            return (t, s - q * t)
    return go(a, b)

# TEST ----------------------------------------------------
# main :: IO ()
def main():
    '''Tests of soluble and insoluble cases.'''

    print(
        fTable(
            __doc__ + ':\n\n         (moduli, residues) -> ' + (
                'Either solution or explanation\n'
            )
        )(repr)(
            either(compose(quoted("'"))(curry(add)('No solution: ')))(
                compose(quoted(' '))(repr)
            )
        )(uncurry(cnRemainder))([
            ([10, 4, 12], [11, 12, 13]),
            ([11, 12, 13], [10, 4, 12]),
            ([10, 4, 9], [11, 22, 19]),
            ([3, 5, 7], [2, 3, 2]),
            ([2, 3, 2], [3, 5, 7])
        ])
    )

# GENERIC -------------------------------------------------

# Left :: a -> Either a b
def Left(x):
    '''Constructor for an empty Either (option type) value
       with an associated string.'''
    return {'type': 'Either', 'Right': None, 'Left': x}

# Right :: b -> Either a b
def Right(x):
    '''Constructor for a populated Either (option type) value'''
    return {'type': 'Either', 'Left': None, 'Right': x}
# any :: (a -> Bool) -> [a] -> Bool

def any_(p):
    '''True if p(x) holds for at least
       one item in xs.'''
    def go(xs):
        for x in xs:
            if p(x):
                return True
        return False
    return lambda xs: go(xs)

# bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
def bindLR(m):
    '''Either monad injection operator.
       Two computations sequentially composed,
       with any value produced by the first
       passed as an argument to the second.'''
    return lambda mf: (
        mf(m.get('Right')) if None is m.get('Left') else m
    )

# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
    '''Right to left function composition.'''
    return lambda f: lambda x: g(f(x))

# curry :: ((a, b) -> c) -> a -> b -> c
def curry(f):
    '''A curried function derived
       from an uncurried function.'''
    return lambda a: lambda b: f(a, b)

# either :: (a -> c) -> (b -> c) -> Either a b -> c
def either(fl):
    '''The application of fl to e if e is a Left value,
       or the application of fr to e if e is a Right value.'''
    return lambda fr: lambda e: fl(e['Left']) if (
        None is e['Right']
    ) else fr(e['Right'])

# fTable :: String -> (a -> String) ->
#                     (b -> String) -> (a -> b) -> [a] -> String
def fTable(s):
    '''Heading -> x display function ->
                 fx display function ->
          f -> value list -> tabular string.'''
    def go(xShow, fxShow, f, xs):
        w = max(map(compose(len)(xShow), xs))
        return s + '\n' + '\n'.join([
            xShow(x).rjust(w, ' ') + (' -> ') + fxShow(f(x))
            for x in xs
        ])
    return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
        xShow, fxShow, f, xs
    )

# numericProduct :: [Num] -> Num
def numericProduct(xs):
    '''The arithmetic product of all numbers in xs.'''
    return reduce(mul, xs, 1)

# partitionEithers :: [Either a b] -> ([a],[b])
def partitionEithers(lrs):
    '''A list of Either values partitioned into a tuple
       of two lists, with all Left elements extracted
       into the first list, and Right elements
       extracted into the second list.
    '''
    def go(a, x):
        ls, rs = a
        r = x.get('Right')
        return (ls + [x.get('Left')], rs) if None is r else (
            ls, rs + [r]
        )
    return reduce(go, lrs, ([], []))

# quoted :: Char -> String -> String
def quoted(c):
    '''A string flanked on both sides
       by a specified quote character.
    '''
    return lambda s: c + s + c

# uncurry :: (a -> b -> c) -> ((a, b) -> c)
def uncurry(f):
    '''A function over a tuple,
       derived from a curried function.'''
    return lambda xy: f(xy[0])(xy[1])

# zipWithEither :: (a -> b -> Either String  c)
#            -> [a] -> [b] -> Either String [c]
def zipWithEither(f):
    '''Either a list of results if f succeeds with every pair
       in the zip of xs and ys, or an explanatory string
       if any application of f returns no result.
    '''
    def go(xs, ys):
        ls, rs = partitionEithers(map(f, xs, ys))
        return Left(ls[0]) if ls else Right(rs)
    return lambda xs: lambda ys: go(xs, ys)

# MAIN ---
if __name__ == '__main__':
    main()


Chinese zodiac

Determine the Chinese zodiac sign and related associations for a given year.
Traditionally, the Chinese have counted years using two lists of labels, one of length 10 (the "celestial stems") and one of length 12 (the "terrestrial branches"). The labels do not really have any meaning outside their positions in the two lists; they're simply a traditional enumeration device, used much as Westerners use letters and numbers. They were historically used for months and days as well as years, and the stems are still sometimes used for school grades.

Years cycle through both lists concurrently, so that both stem and branch advance each year; if we used Roman letters for the stems and numbers for the branches, consecutive years would be labeled A1, B2, C3, etc. Since the two lists are different lengths, they cycle back to their beginning at different points: after J10 we get A11, and then after B12 we get C1. The result is a repeating 60-year pattern within which each pair of names occurs only once.

Mapping the branches to twelve traditional animal deities results in the well-known "Chinese zodiac", assigning each year to a given animal. For example, Sunday, January 22, 2023 CE (in the common Gregorian calendar) began the lunisolar Year of the Rabbit.

The celestial stems do not have a one-to-one mapping like that of the branches to animals; however, the five pairs of consecutive stems are each associated with one of the five traditional Chinese elements (Wood, Fire, Earth, Metal, and Water). Further, one of the two years within each element is assigned to yin, the other to yang.

Thus, the Chinese year beginning in 2023 CE is also the yin year of Water. Since 12 is an even number, the association between animals and yin/yang doesn't change; consecutive Years of the Rabbit will cycle through the five elements, but will always be yin.

;Task: Create a subroutine or program that will return or output the animal, yin/yang association, and element for the lunisolar year that begins in a given CE year.

You may optionally provide more information in the form of the year's numerical position within the 60-year cycle and/or its actual Chinese stem-branch name (in Han characters or Pinyin transliteration).

;Requisite information:
* The animal cycle runs in this order: Rat, Ox, Tiger, Rabbit, Dragon, Snake, Horse, Goat, Monkey, Rooster, Dog, Pig.
* The element cycle runs in this order: Wood, Fire, Earth, Metal, Water.
* Each element gets two consecutive years; a yang followed by a yin.
* The current 60-year cycle began in 1984; any multiple of 60 years from that point may be used to reckon from.

Thus, year 1 of a cycle is the year of the Wood Rat (yang), year 2 the Wood Ox (yin), and year 3 the Fire Tiger (yang). The year 2023 - which, as already noted, is the year of the Water Rabbit (yin) - is the 40th year of the current cycle.

;Information for optional task:
* The ten celestial stems are '''Jia ''' ''jia'', '''Yi ''' ''yi'', '''Bing ''' ''bing'', '''Ding ''' ''ding'', '''Wu ''' ''wu'', '''Ji ''' ''ji'', '''Geng ''' ''geng'', '''Xin ''' ''xin'', '''Ren ''' ''ren'', and '''Gui ''' ''gui''. With the ASCII version of Pinyin tones, the names are written "jia3", "yi3", "bing3", "ding1", "wu4", "ji3", "geng1", "xin1", "ren2", and "gui3".
* The twelve terrestrial branches are '''Zi ''' ''zi'', '''Chou ''' ''chou'', '''Yin ''' ''yin'', '''Mao ''' ''mao'', '''Chen ''' ''chen'', '''Si ''' ''si'', '''Wu ''' ''wu'', '''Wei ''' ''wei'', '''Shen ''' ''shen'', '''You ''' ''you'', '''Xu ''' ''xu'', '''Hai ''' ''hai''. In ASCII Pinyin, those are "zi3", "chou3", "yin2", "mao3", "chen2", "si4", "wu3", "wei4", "shen1", "you3", "xu1", and "hai4".

Therefore 1984 was '''Jia Zi ''' (''jia-zi'', or jia3-zi3).  2023 is '''Gui Mao ''' (''gui-mao'' or gui3-mao3).

Solution:
# coding: utf-8

from __future__ import print_function
from datetime import datetime

pinyin = {
  '甲': 'jiă',
  '乙': 'yĭ',
  '丙': 'bĭng',
  '丁': 'dīng',
  '戊': 'wù',
  '己': 'jĭ',
  '庚': 'gēng',
  '辛': 'xīn',
  '壬': 'rén',
  '癸': 'gŭi',

  '子': 'zĭ',
  '丑': 'chŏu',
  '寅': 'yín',
  '卯': 'măo',
  '辰': 'chén',
  '巳': 'sì',
  '午': 'wŭ',
  '未': 'wèi',
  '申': 'shēn',
  '酉': 'yŏu',
  '戌': 'xū',
  '亥': 'hài'
}

animals = ['Rat', 'Ox', 'Tiger', 'Rabbit', 'Dragon', 'Snake',
           'Horse', 'Goat', 'Monkey', 'Rooster', 'Dog', 'Pig']
elements = ['Wood', 'Fire', 'Earth', 'Metal', 'Water']

celestial = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']
terrestrial = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']
aspects = ['yang', 'yin']

def calculate(year):
    BASE = 4
    year = int(year)
    cycle_year = year - BASE
    stem_number = cycle_year % 10
    stem_han = celestial[stem_number]
    stem_pinyin = pinyin[stem_han]
    element_number = stem_number // 2
    element = elements[element_number]
    branch_number = cycle_year % 12
    branch_han = terrestrial[branch_number]
    branch_pinyin = pinyin[branch_han]
    animal = animals[branch_number]
    aspect_number = cycle_year % 2
    aspect = aspects[aspect_number]
    index = cycle_year % 60 + 1
    print("{}: {}{} ({}-{}, {} {}; {} - year {} of the cycle)"
          .format(year, stem_han, branch_han,
                  stem_pinyin, branch_pinyin, element, animal, aspect, index))

current_year = datetime.now().year
years = [1935, 1938, 1968, 1972, 1976, current_year]
for year in years:
    calculate(year)


Chinese zodiac

Solution:
'''Chinese zodiac'''

from functools import (reduce)
from datetime import datetime

# TRADITIONAL STRINGS -------------------------------------

# zodiacNames :: Dict
def zodiacNames():
    '''天干 tiangan – 10 heavenly stems
       地支 dizhi – 12 terrestrial branches
       五行 wuxing – 5 elements
       生肖 shengxiao – 12 symbolic animals
       阴阳 yinyang - dark and light
    '''
    return dict(
        zip(
            ['tian', 'di', 'wu', 'sx', 'yy'],
            map(
                lambda tpl: list(
                    zip(* [tpl[0]] + list(
                        map(
                            lambda x: x.split(),
                            tpl[1:])
                    ))
                ),
                [
                    # 天干 tiangan – 10 heavenly stems
                    ('甲乙丙丁戊己庚辛壬癸',
                     'jiă yĭ bĭng dīng wù jĭ gēng xīn rén gŭi'),

                    # 地支 dizhi – 12 terrestrial branches
                    ('子丑寅卯辰巳午未申酉戌亥',
                     'zĭ chŏu yín măo chén sì wŭ wèi shēn yŏu xū hài'),

                    # 五行 wuxing – 5 elements
                    ('木火土金水',
                     'mù huǒ tǔ jīn shuǐ',
                     'wood fire earth metal water'),

                    # 十二生肖 shengxiao – 12 symbolic animals
                    ('鼠牛虎兔龍蛇馬羊猴鸡狗豬',
                     'shǔ niú hǔ tù lóng shé mǎ yáng hóu jī gǒu zhū',
                     'rat ox tiger rabbit dragon snake horse goat ' +
                     'monkey rooster dog pig'
                     ),

                    # 阴阳 yinyang
                    ('阳阴', 'yáng yīn')
                ]
            )))

# zodiacYear :: Dict -> [[String]]
def zodiacYear(dct):
    '''A string of strings containing the
       Chinese zodiac tokens for a given year.
    '''
    def tokens(y):
        iYear = y - 4
        iStem = iYear % 10
        iBranch = iYear % 12
        (hStem, pStem) = dct['tian'][iStem]
        (hBranch, pBranch) = dct['di'][iBranch]
        yy = iYear % 2
        return [
            [str(y), '', ''],
            [
                hStem + hBranch,
                pStem + pBranch,
                str((iYear % 60) + 1) + '/60'
            ],
            list(dct['wu'][iStem // 2]),
            list(dct['sx'][iBranch]),
            list(dct['yy'][int(yy)]) + ['dark' if yy else 'light']
        ]
    return lambda year: tokens(year)

# TEST ----------------------------------------------------
# main :: IO ()
def main():
    '''Writing out wiki tables displaying Chinese zodiac
       details for a given list of years.
    '''
    print('\n'.join(
        list(map(
            zodiacTable(zodiacNames()),
            [
                1935, 1938, 1949,
                1968, 1972, 1976,
                datetime.now().year
            ]
        ))
    ))

# WIKI TABLES  --------------------------------------------

# zodiacTable :: Dict -> Int -> String
def zodiacTable(tokens):
    '''A wiki table displaying Chinese zodiac
       details for a a given year.
    '''
    return lambda y: wikiTable({
        'class': 'wikitable',
        'colwidth': '70px'
    })(transpose(zodiacYear(tokens)(y)))

# wikiTable :: Dict -> [[a]] -> String
def wikiTable(opts):
    '''List of lists rendered as a wiki table string.'''
    def colWidth():
        return 'width:' + opts['colwidth'] + '; ' if (
            'colwidth' in opts
        ) else ''

    def cellStyle():
        return opts['cell'] if 'cell' in opts else ''

    return lambda rows: '{| ' + reduce(
        lambda a, k: (
            a + k + '="' + opts[k] + '" ' if k in opts else a
        ),
        ['class', 'style'],
        ''
    ) + '\n' + '\n|-\n'.join(
        '\n'.join(
            ('|' if (0 != i and ('cell' not in opts)) else (
                '|style="' + colWidth() + cellStyle() + '"|'
            )) + (
                str(x) or ' '
            ) for x in row
        ) for i, row in enumerate(rows)
    ) + '\n|}\n\n'

# GENERIC -------------------------------------------------

# transpose :: Matrix a -> Matrix a
def transpose(m):
    '''The rows and columns of the argument transposed.
       (The matrix containers and rows can be lists or tuples).'''
    if m:
        inner = type(m[0])
        z = zip(*m)
        return (type(m))(
            map(inner, z) if tuple != inner else z
        )
    else:
        return m

# MAIN ---
if __name__ == '__main__':
    main()


Church numerals

In the Church encoding of natural numbers, the number N is encoded by a function that applies its first argument N times to its second argument.

* '''Church zero''' always returns the identity function, regardless of its first argument. In other words, the first argument is not applied to the second argument at all.
* '''Church one''' applies its first argument f just once to its second argument x, yielding '''f(x)'''
* '''Church two''' applies its first argument f twice to its second argument x, yielding '''f(f(x))'''
* and each successive Church numeral applies its first argument one additional time to its second argument, '''f(f(f(x)))''', '''f(f(f(f(x))))''' ...  The Church numeral 4, for example, returns a quadruple composition of the function supplied as its first argument.

Arithmetic operations on natural numbers can be similarly represented as functions on Church numerals.

In your language define:

* Church Zero,
* a Church successor function (a function on a Church numeral which returns the next Church numeral in the series),
* functions for Addition, Multiplication and Exponentiation over Church numerals,
* a function to convert integers to corresponding Church numerals,
* and a function to convert Church numerals to corresponding integers.

You should:

* Derive Church numerals three and four in terms of Church zero and a Church successor function.
* use Church numeral arithmetic to obtain the the sum and the product of Church 3 and Church 4,
* similarly obtain 4^3 and 3^4 in terms of Church numerals, using a Church numeral exponentiation function,
* convert each result back to an integer, and return it or print it to the console.

Solution:
'''Church numerals'''

from itertools import repeat
from functools import reduce

# ----- CHURCH ENCODINGS OF NUMERALS AND OPERATIONS ------

def churchZero():
    '''The identity function.
       No applications of any supplied f
       to its argument.
    '''
    return lambda f: identity

def churchSucc(cn):
    '''The successor of a given
       Church numeral. One additional
       application of f. Equivalent to
       the arithmetic addition of one.
    '''
    return lambda f: compose(f)(cn(f))

def churchAdd(m):
    '''The arithmetic sum of two Church numerals.'''
    return lambda n: lambda f: compose(m(f))(n(f))

def churchMult(m):
    '''The arithmetic product of two Church numerals.'''
    return lambda n: compose(m)(n)

def churchExp(m):
    '''Exponentiation of Church numerals. m^n'''
    return lambda n: n(m)

def churchFromInt(n):
    '''The Church numeral equivalent of
       a given integer.
    '''
    return lambda f: (
        foldl
        (compose)
        (identity)
        (replicate(n)(f))
    )

# OR, alternatively:
def churchFromInt_(n):
    '''The Church numeral equivalent of a given
       integer, by explicit recursion.
    '''
    if 0 == n:
        return churchZero()
    else:
        return churchSucc(churchFromInt(n - 1))

def intFromChurch(cn):
    '''The integer equivalent of a
       given Church numeral.
    '''
    return cn(succ)(0)

# ------------------------- TEST -------------------------
# main :: IO ()
def main():
    'Tests'

    cThree = churchFromInt(3)
    cFour = churchFromInt(4)

    print(list(map(intFromChurch, [
        churchAdd(cThree)(cFour),
        churchMult(cThree)(cFour),
        churchExp(cFour)(cThree),
        churchExp(cThree)(cFour),
    ])))

# ------------------ GENERIC FUNCTIONS -------------------

# compose (flip (.)) :: (a -> b) -> (b -> c) -> a -> c
def compose(f):
    '''A left to right composition of two
       functions f and g'''
    return lambda g: lambda x: g(f(x))

# foldl :: (a -> b -> a) -> a -> [b] -> a
def foldl(f):
    '''Left to right reduction of a list,
       using the binary operator f, and
       starting with an initial value a.
    '''
    def go(acc, xs):
        return reduce(lambda a, x: f(a)(x), xs, acc)
    return lambda acc: lambda xs: go(acc, xs)

# identity :: a -> a
def identity(x):
    '''The identity function.'''
    return x

# replicate :: Int -> a -> [a]
def replicate(n):
    '''A list of length n in which every
       element has the value x.
    '''
    return lambda x: repeat(x, n)

# succ :: Enum a => a -> a
def succ(x):
    '''The successor of a value.
       For numeric types, (1 +).
    '''
    return 1 + x if isinstance(x, int) else (
        chr(1 + ord(x))
    )

if __name__ == '__main__':
    main()


Circles of given radius through two points

2 circles with a given radius through 2 points in 2D space.

Given two points on a plane and a radius, usually two circles of given radius can be drawn through the points.
;Exceptions:
# r==0.0 should be treated as never describing circles (except in the case where the points are coincident).
# If the points are coincident then an infinite number of circles with the point on their circumference can be drawn, unless r==0.0 as well which then collapses the circles to a point.
# If the points form a diameter then return two identical circles ''or'' return a single circle, according to which is the most natural mechanism for the implementation language.
# If the points are too far apart then no circles can be drawn.

;Task detail:
* Write a function/subroutine/method/... that takes two points and a radius and returns the two circles through those points, ''or some indication of special cases where two, possibly equal, circles cannot be returned''.
* Show here the output for the following inputs:

      p1                p2           r
0.1234, 0.9876    0.8765, 0.2345    2.0
0.0000, 2.0000    0.0000, 0.0000    1.0
0.1234, 0.9876    0.1234, 0.9876    2.0
0.1234, 0.9876    0.8765, 0.2345    0.5
0.1234, 0.9876    0.1234, 0.9876    0.0

;Related task:
*   [[Total circles area]].

;See also:
*   Finding the Center of a Circle from 2 Points and Radius from Math forum @ Drexel

Solution:
from collections import namedtuple
from math import sqrt

Pt = namedtuple('Pt', 'x, y')
Circle = Cir = namedtuple('Circle', 'x, y, r')

def circles_from_p1p2r(p1, p2, r):
    'Following explanation at http://mathforum.org/library/drmath/view/53027.html'
    if r == 0.0:
        raise ValueError('radius of zero')
    (x1, y1), (x2, y2) = p1, p2
    if p1 == p2:
        raise ValueError('coincident points gives infinite number of Circles')
    # delta x, delta y between points
    dx, dy = x2 - x1, y2 - y1
    # dist between points
    q = sqrt(dx**2 + dy**2)
    if q > 2.0*r:
        raise ValueError('separation of points > diameter')
    # halfway point
    x3, y3 = (x1+x2)/2, (y1+y2)/2
    # distance along the mirror line
    d = sqrt(r**2-(q/2)**2)
    # One answer
    c1 = Cir(x = x3 - d*dy/q,
             y = y3 + d*dx/q,
             r = abs(r))
    # The other answer
    c2 = Cir(x = x3 + d*dy/q,
             y = y3 - d*dx/q,
             r = abs(r))
    return c1, c2

if __name__ == '__main__':
    for p1, p2, r in [(Pt(0.1234, 0.9876), Pt(0.8765, 0.2345), 2.0),
                      (Pt(0.0000, 2.0000), Pt(0.0000, 0.0000), 1.0),
                      (Pt(0.1234, 0.9876), Pt(0.1234, 0.9876), 2.0),
                      (Pt(0.1234, 0.9876), Pt(0.8765, 0.2345), 0.5),
                      (Pt(0.1234, 0.9876), Pt(0.1234, 0.9876), 0.0)]:
        print('Through points:\n  %r,\n  %r\n  and radius %f\nYou can construct the following circles:'
              % (p1, p2, r))
        try:
            print('  %r\n  %r\n' % circles_from_p1p2r(p1, p2, r))
        except ValueError as v:
            print('  ERROR: %s\n' % (v.args[0],))