Find the intersection of two lines

Solution:
'''The intersection of two lines.'''

from itertools import product

# intersection :: Line -> Line -> Either String Point
def intersection(ab):
    '''Either the point at which the lines ab and pq
       intersect, or a message string indicating that
       they are parallel and have no intersection.'''
    def delta(f):
        return lambda x: f(fst(x)) - f(snd(x))

    def prodDiff(abcd):
        [a, b, c, d] = abcd
        return (a * d) - (b * c)

    def go(pq):
        [abDX, pqDX, abDY, pqDY] = apList(
            [delta(fst), delta(snd)]
        )([ab, pq])
        determinant = prodDiff([abDX, abDY, pqDX, pqDY])

        def point():
            [abD, pqD] = map(
                lambda xy: prodDiff(
                    apList([fst, snd])([fst(xy), snd(xy)])
                ), [ab, pq]
            )
            return apList(
                [lambda abpq: prodDiff(
                    [abD, fst(abpq), pqD, snd(abpq)]) / determinant]
            )(
                [(abDX, pqDX), (abDY, pqDY)]
            )
        return Right(point()) if 0 != determinant else Left(
            '( Parallel lines - no intersection )'
        )

    return lambda pq: bindLR(go(pq))(
        lambda xs: Right((fst(xs), snd(xs)))
    )

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

    # Left(message - no intersection) or Right(point)
    # lrPoint :: Either String Point
    lrPoint = intersection(
        ((4.0, 0.0), (6.0, 10.0))
    )(
        ((0.0, 3.0), (10.0, 7.0))
    )
    print(
        lrPoint['Left'] or lrPoint['Right']
    )

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

# 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}

# apList (<*>) :: [(a -> b)] -> [a] -> [b]
def apList(fs):
    '''The application of each of a list of functions,
       to each of a list of values.
    '''
    def go(fx):
        f, x = fx
        return f(x)
    return lambda xs: [
        go(x) for x
        in product(fs, 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
    )

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

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

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


Find the last Sunday of each month

Write a program or a script that returns the last Sundays of each month of a given year. The year may be given through any simple input method in your language (command line, std in, etc).

Example of an expected output:

./last_sundays 2013
2013-01-27
2013-02-24
2013-03-31
2013-04-28
2013-05-26
2013-06-30
2013-07-28
2013-08-25
2013-09-29
2013-10-27
2013-11-24
2013-12-29

;Related tasks
* [[Day of the week]]
* [[Five weekends]]
* [[Last Friday of each month]]

Solution:
import sys
import calendar

year = 2013
if len(sys.argv) > 1:
    try:
        year = int(sys.argv[-1])
    except ValueError:
        pass

for month in range(1, 13):
    last_sunday = max(week[-1] for week in calendar.monthcalendar(year, month))
    print('{}-{}-{:2}'.format(year, calendar.month_abbr[month], last_sunday))


Find the missing permutation

ABCD
                    CABD
                    ACDB
                    DACB
                    BCDA
                    ACBD
                    ADCB
                    CDAB
                    DABC
                    BCAD
                    CADB
                    CDBA
                    CBAD
                    ABDC
                    ADBC
                    BDCA
                    DCBA
                    BACD
                    BADC
                    BDAC
                    CBDA
                    DBCA
                    DCAB

Listed above are   all-but-one   of the permutations of the symbols   '''A''',   '''B''',   '''C''',   and   '''D''',   ''except''   for one permutation that's   ''not''   listed.

;Task:
Find that missing permutation.

;Methods:
* Obvious method:
         enumerate all permutations of   '''A''',  '''B''',  '''C''',  and  '''D''',
         and then look for the missing permutation.

* alternate method:
         Hint:  if all permutations were shown above,  how many
         times would  '''A'''  appear in each position?
         What is the  ''parity''  of this number?

* another alternate method:
         Hint:  if you add up the letter values of each column,
         does a missing letter   '''A''',  '''B''',  '''C''',  and  '''D'''   from each
         column cause the total value for each column to be unique?

;Related task:
*   [[Permutations]])

Solution: ===Python: Calculate difference when compared to all permutations===


Find the missing permutation

Solution:
def missing_permutation(arr):
  "Find the missing permutation in an array of N! - 1 permutations."

  # We won't validate every precondition, but we do have some basic
  # guards.
  if len(arr) == 0: raise Exception("Need more data")
  if len(arr) == 1:
      return [arr[0][1] + arr[0][0]]

  # Now we know that for each position in the string, elements should appear
  # an even number of times (N-1 >= 2).  We can use a set to detect the element appearing
  # an odd number of times.  Detect odd occurrences by toggling admission/expulsion
  # to and from the set for each value encountered.  At the end of each pass one element
  # will remain in the set.
  missing_permutation = ''
  for pos in range(len(arr[0])):
      s = set()
      for permutation in arr:
          c = permutation[pos]
          if c in s:
            s.remove(c)
          else:
            s.add(c)
      missing_permutation += list(s)[0]
  return missing_permutation

given = '''ABCD CABD ACDB DACB BCDA ACBD ADCB CDAB DABC BCAD CADB CDBA
           CBAD ABDC ADBC BDCA DCBA BACD BADC BDAC CBDA DBCA DCAB'''.split()

print missing_permutation(given)


Find the missing permutation

Solution:
'''Find the missing permutation'''

from functools import reduce
from operator import xor

print(''.join([
    chr(i) for i in reduce(
        lambda a, s: map(
            xor,
            a,
            [ord(c) for c in list(s)]
        ), [
            'ABCD', 'CABD', 'ACDB', 'DACB',
            'BCDA', 'ACBD', 'ADCB', 'CDAB',
            'DABC', 'BCAD', 'CADB', 'CDBA',
            'CBAD', 'ABDC', 'ADBC', 'BDCA',
            'DCBA', 'BACD', 'BADC', 'BDAC',
            'CBDA', 'DBCA', 'DCAB'
        ],
        [0, 0, 0, 0]
    )
]))


First-class functions/Use numbers analogously

In [[First-class functions]], a language is showing how its manipulation of functions is similar to its manipulation of other types.

This tasks aim is to compare and contrast a language's implementation of first class functions, with its normal handling of numbers.

Write a program to create an ordered collection of a mixture of literally typed and expressions producing a real number, together with another ordered collection of their multiplicative inverses. Try and use the following pseudo-code to generate the numbers for the ordered collections:
   x  = 2.0
   xi = 0.5
   y  = 4.0
   yi = 0.25
   z  = x + y
   zi = 1.0 / ( x + y )

Create a function ''multiplier'', that given two numbers as arguments returns a function that when called with one argument, returns the result of multiplying the two arguments to the call to multiplier that created it and the argument in the call:
  new_function = multiplier(n1,n2)
  # where new_function(m) returns the result of n1 * n2 * m

Applying the multiplier of a number and its inverse from the two ordered collections of numbers in pairs, show that the result in each case is one.
'''Compare and contrast the resultant program with the corresponding entry in [[First-class functions]].''' They should be close.

To paraphrase the task description: Do what was done before, but with numbers rather than functions

Solution:
>>> # Some built in functions and their inverses
>>> from math import sin, cos, acos, asin
>>> # Add a user defined function and its inverse
>>> cube = lambda x: x * x * x
>>> croot = lambda x: x ** (1/3.0)
>>> # First class functions allow run-time creation of functions from functions
>>> # return function compose(f,g)(x) == f(g(x))
>>> compose = lambda f1, f2: ( lambda x: f1(f2(x)) )
>>> # first class functions should be able to be members of collection types
>>> funclist = [sin, cos, cube]
>>> funclisti = [asin, acos, croot]
>>> # Apply functions from lists as easily as integers
>>> [compose(inversef, f)(.5) for f, inversef in zip(funclist, funclisti)]
[0.5, 0.4999999999999999, 0.5]
>>>


First perfect square in base n with n unique digits

Find the first perfect square in a given base '''N''' that has at least '''N''' digits and
exactly '''N''' ''significant unique'' digits when expressed in base '''N'''.

E.G. In base '''10''', the first perfect square with at least '''10''' unique digits is '''1026753849''' ('''320432''').

You may use analytical methods to reduce the search space, but the code must do a search. Do not use magic numbers or just feed the code the answer to verify it is correct.

;Task

* Find and display here, on this page, the first perfect square in base '''N''', with '''N''' significant unique digits when expressed in base '''N''', for each of base '''2''' through '''12'''. Display each number in the base '''N''' for which it was calculated.

* (optional) Do the same for bases '''13''' through '''16'''.

* (stretch goal) Continue on for bases '''17''' - '''??''' (Big Integer math)

;See also:

;* OEIS A260182: smallest square that is pandigital in base n.

;Related task

;* [[Casting out nines]]

Solution:
'''Perfect squares using every digit in a given base.'''

from itertools import count, dropwhile, repeat
from math import ceil, sqrt
from time import time

# allDigitSquare :: Int -> Int -> Int
def allDigitSquare(base, above):
    '''The lowest perfect square which
       requires all digits in the given base.
    '''
    bools = list(repeat(True, base))
    return next(
        dropwhile(
            missingDigitsAtBase(base, bools),
            count(
                max(
                    above,
                    ceil(sqrt(int(
                        '10' + '0123456789abcdef'[2:base],
                        base
                    )))
                )
            )
        )
    )

# missingDigitsAtBase :: Int -> [Bool] -> Int -> Bool
def missingDigitsAtBase(base, bools):
    '''Fusion of representing the square of integer N at a
       given base with checking whether all digits of
       that base contribute to N^2.
       Clears the bool at a digit position to False when used.
       True if any positions remain uncleared (unused).
    '''
    def go(x):
        xs = bools.copy()
        while x:
            xs[x % base] = False
            x //= base
        return any(xs)
    return lambda n: go(n * n)

# digit :: Int -> Char
def digit(n):
    '''Digit character for given integer.'''
    return '0123456789abcdef'[n]

# ------------------------- TEST -------------------------
# main :: IO ()
def main():
    '''Smallest perfect squares using all digits in bases 2-16'''

    start = time()

    print(main.__doc__ + ':\n\nBase      Root    Square')
    q = 0
    for b in enumFromTo(2)(16):
        q = allDigitSquare(b, q)
        print(
            str(b).rjust(2, ' ') + ' -> ' +
            showIntAtBase(b)(digit)(q)('').rjust(8, ' ') +
            ' -> ' +
            showIntAtBase(b)(digit)(q * q)('')
        )

    print(
        '\nc. ' + str(ceil(time() - start)) + ' seconds.'
    )

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

# enumFromTo :: (Int, Int) -> [Int]
def enumFromTo(m):
    '''Integer enumeration from m to n.'''
    return lambda n: list(range(m, 1 + n))

# showIntAtBase :: Int -> (Int -> String) -> Int ->
# String -> String
def showIntAtBase(base):
    '''String representation of an integer in a given base,
       using a supplied function for the string representation
       of digits.
    '''
    def wrap(toChr, n, rs):
        def go(nd, r):
            n, d = nd
            r_ = toChr(d) + r
            return go(divmod(n, base), r_) if 0 != n else r_
        return 'unsupported base' if 1 >= base else (
            'negative number' if 0 > n else (
                go(divmod(n, base), rs))
        )
    return lambda toChr: lambda n: lambda rs: (
        wrap(toChr, n, rs)
    )

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


First power of 2 that has leading decimal digits of 12

Solution:
from math import log, modf, floor

def p(l, n, pwr=2):
    l = int(abs(l))
    digitcount = floor(log(l, 10))
    log10pwr = log(pwr, 10)
    raised, found = -1, 0
    while found < n:
        raised += 1
        firstdigits = floor(10**(modf(log10pwr * raised)[0] + digitcount))
        if firstdigits == l:
            found += 1
    return raised

if __name__ == '__main__':
    for l, n in [(12, 1), (12, 2), (123, 45), (123, 12345), (123, 678910)]:
        print(f"p({l}, {n}) =", p(l, n))


Fivenum

Many big data or scientific programs use boxplots to show distributions of data.   In addition, sometimes saving large arrays for boxplots can be impractical and use extreme amounts of RAM.   It can be useful to save large arrays as arrays with five numbers to save memory.

For example, the   '''R'''   programming language implements Tukey's five-number summary as the '''fivenum''' function.

;Task:
Given an array of numbers, compute the five-number summary.

;Note:
While these five numbers can be used to draw a boxplot,   statistical packages will typically need extra data.

Moreover, while there is a consensus about the "box" of the boxplot,   there are variations among statistical packages for the whiskers.

Solution:
from __future__ import division
import math
import sys

def fivenum(array):
    n = len(array)
    if n == 0:
        print("you entered an empty array.")
        sys.exit()
    x = sorted(array)

    n4 = math.floor((n+3.0)/2.0)/2.0
    d = [1, n4, (n+1)/2, n+1-n4, n]
    sum_array = []

    for e in range(5):
        floor = int(math.floor(d[e] - 1))
        ceil = int(math.ceil(d[e] - 1))
        sum_array.append(0.5 * (x[floor] + x[ceil]))

    return sum_array

x = [0.14082834, 0.09748790, 1.73131507, 0.87636009, -1.95059594, 0.73438555, -0.03035726, 1.46675970,
-0.74621349, -0.72588772, 0.63905160, 0.61501527, -0.98983780, -1.00447874, -0.62759469, 0.66206163,
1.04312009, -0.10305385, 0.75775634, 0.32566578]

y = fivenum(x)
print(y)


Fixed length records

Fixed length read/write

Before terminals, computers commonly used punch card readers or paper tape input.

A common format before these devices were superseded by terminal technology was based on the Hollerith code, Hollerith code.

These input devices handled 80 columns per card and had a limited character set, encoded by punching holes in one or more rows of the card for each column.

These devices assumed/demanded a fixed line width of 80 characters, newlines were not required (and could not even be encoded in some systems).

;Task:
Write a program to read 80 column fixed length records (no newline terminators (but newline characters allowed in the data)) and then write out the reverse of each line as fixed length 80 column records.

Samples here use printable characters, but that is not a given with fixed length data.  Filenames used are sample.txt, infile.dat, outfile.dat.

'''Note:''' There are no newlines, inputs and outputs are fixed at 80 columns, no more, no less, space padded.  Fixed length data is 8 bit complete.  NUL bytes of zero are allowed.

These fixed length formats are still in wide use on mainframes, with JCL and with COBOL (which commonly use EBCDIC encoding and not ASCII).  Most of the large players in day to day financial transactions know all about fixed length records and the expression ''logical record length''.

;Sample data:
To create the sample input file, use an editor that supports fixed length records or use a conversion utility.  For instance, most GNU/Linux versions of '''dd''' support blocking and unblocking records with a conversion byte size.

Line 1...1.........2.........3.........4.........5.........6.........7.........8
Line 2
Line 3
Line 4

Line 6
Line 7
     Indented line 8............................................................
Line 9                                                                 RT MARGIN
prompt$ dd if=sample.txt of=infile.dat cbs=80 conv=block will create a fixed length record file of 80 bytes given newline delimited text input.

prompt$ dd if=infile.dat cbs=80 conv=unblock will display a file with 80 byte logical record lengths to standard out as standard text with newlines.

;Bonus round:
Forth systems often include BLOCK words.  A block is 1024 bytes.  Source code is stored as 16 lines of 64 characters each (again, no newline character or sequence to mark the end of a line).

Write a program to convert a block file to text (using newlines). Trailing spaces should be excluded from the output.

Also demonstrate how to convert from a normal text file to block form. All lines either truncated or padded to 64 characters with no newline terminators. The last block filled to be exactly 1024 characters by adding blanks if needed. Assume a full range of 8 bit byte values for each character.

The COBOL example uses forth.txt and forth.blk filenames.

Solution:
infile = open('infile.dat', 'rb')
outfile = open('outfile.dat', 'wb')

while True:
    onerecord = infile.read(80)
    if len(onerecord) < 80:
        break
    onerecordreversed = bytes(reversed(onerecord))
    outfile.write(onerecordreversed)

infile.close()
outfile.close()


Flatten a list

Write a function to flatten the nesting in an arbitrary list of values.

Your program should work on the equivalent of this list:
   [[1], 2, [[3, 4], 5], [[[]]], [[[6]]], 7, 8, []]
Where the correct result would be the list:
    [1, 2, 3, 4, 5, 6, 7, 8]

;Related task:
*   [[Tree traversal]]

Solution:
>>> def flatten(itr):
>>>    for x in itr:
>>>        try:
>>>            yield from flatten(x)
>>>        except:
>>>            yield x

>>> lst = [[1], 2, [[3,4], 5], [[[]]], [[[6]]], 7, 8, []]

>>> list(flatten(lst))
[1, 2, 3, 4, 5, 6, 7, 8]

>>> tuple(flatten(lst))
(1, 2, 3, 4, 5, 6, 7, 8)

>>>for i in flatten(lst):
>>>    print(i)
1
2
3
4
5
6
7
8


Flatten a list

Solution:
'''Flatten a list'''

from functools import (reduce)
from itertools import (chain)

def flatten(xs):
    '''A flat list of atomic values derived
       from a nested list.
    '''
    return reduce(
        lambda a, x: a + list(until(every(notList))(
            concatMap(pureList)
        )([x])),
        xs, []
    )

# TEST ----------------------------------------------------
def main():
    '''From nested list to flattened list'''

    print(main.__doc__ + ':\n\n')
    xs = [[1], 2, [[3, 4], 5], [[[]]], [[[6]]], 7, 8, []]
    print(
        repr(xs) + ' -> ' + repr(flatten(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))
    )

# every :: (a -> Bool) -> [a] -> Bool
def every(p):
    '''True if p(x) holds for every x in xs'''
    def go(p, xs):
        return all(map(p, xs))
    return lambda xs: go(p, xs)

# notList :: a -> Bool
def notList(x):
    '''True if the value x is not a list.'''
    return not isinstance(x, list)

# pureList :: a -> [b]
def pureList(x):
    '''x if x is a list, othewise [x]'''
    return x if isinstance(x, list) else [x]

# 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, x):
        v = x
        while not p(v):
            v = f(v)
        return v
    return lambda f: lambda x: go(f, x)

if __name__ == '__main__':
    main()


Flipping bits game

The game:
Given an   '''NxN'''   square array of zeroes or ones in an initial configuration,   and a target configuration of zeroes and ones.

The game is to transform one to the other in as few moves as possible by inverting whole numbered rows or whole lettered
columns at once   (as one move).

In an inversion.   any  '''1'''  becomes  '''0''',   and any  '''0'''  becomes  '''1'''  for that whole row or column.

;Task:
Create a program to score for the Flipping bits game.
# The game should create an original random target configuration and a starting configuration.
# Ensure that the starting position is ''never'' the target position.
# The target position must be guaranteed as reachable from the starting position.   (One possible way to do this is to generate the start position by legal flips from a random target position.   The flips will always be reversible back to the target from the given start position).
# The number of moves taken so far should be shown.

Show an example of a short game here, on this page, for a   '''3x3'''   array of bits.

Solution:
"""
Given a %i by %i sqare array of zeroes or ones in an initial
configuration, and a target configuration of zeroes and ones
The task is to transform one to the other in as few moves as
possible by inverting whole numbered rows or whole lettered
columns at once.
In an inversion any 1 becomes 0 and any 0 becomes 1 for that
whole row or column.

"""

from random import randrange
from copy import deepcopy
from string import ascii_lowercase

try:    # 2to3 fix
    input = raw_input
except:
    pass

N = 3   # N x N Square arrray

board  = [[0]* N for i in range(N)]

def setbits(board, count=1):
    for i in range(count):
        board[randrange(N)][randrange(N)] ^= 1

def shuffle(board, count=1):
    for i in range(count):
        if randrange(0, 2):
            fliprow(randrange(N))
        else:
            flipcol(randrange(N))

def pr(board, comment=''):
    print(str(comment))
    print('     ' + ' '.join(ascii_lowercase[i] for i in range(N)))
    print('  ' + '\n  '.join(' '.join(['%2s' % j] + [str(i) for i in line])
                             for j, line in enumerate(board, 1)))

def init(board):
    setbits(board, count=randrange(N)+1)
    target = deepcopy(board)
    while board == target:
        shuffle(board, count=2 * N)
    prompt = '  X, T, or 1-%i / %s-%s to flip: ' % (N, ascii_lowercase[0],
                                                    ascii_lowercase[N-1])
    return target, prompt

def fliprow(i):
    board[i-1][:] = [x ^ 1 for x in board[i-1] ]

def flipcol(i):
    for row in board:
        row[i] ^= 1

if __name__ == '__main__':
    print(__doc__ % (N, N))
    target, prompt = init(board)
    pr(target, 'Target configuration is:')
    print('')
    turns = 0
    while board != target:
        turns += 1
        pr(board, '%i:' % turns)
        ans = input(prompt).strip()
        if (len(ans) == 1
            and ans in ascii_lowercase and ascii_lowercase.index(ans) < N):
            flipcol(ascii_lowercase.index(ans))
        elif ans and all(ch in '0123456789' for ch in ans) and 1 <= int(ans) <= N:
            fliprow(int(ans))
        elif ans == 'T':
            pr(target, 'Target configuration is:')
            turns -= 1
        elif ans == 'X':
            break
        else:
            print("  I don't understand %r... Try again. "
                  "(X to exit or T to show target)\n" % ans[:9])
            turns -= 1
    else:
        print('\nWell done!\nBye.')


Floyd's triangle

Floyd's triangle   lists the natural numbers in a right triangle aligned to the left where
* the first row is   '''1'''     (unity)
* successive rows start towards the left with the next number followed by successive naturals listing one more number than the line above.

The first few lines of a Floyd triangle looks like this:

 1
 2  3
 4  5  6
 7  8  9 10
11 12 13 14 15

;Task:
:# Write a program to generate and display here the first   n   lines of a Floyd triangle. (Use   n=5   and   n=14   rows).
:# Ensure that when displayed in a mono-space font, the numbers line up in vertical columns as shown and that only one space separates numbers of the last row.

Solution:
>>> def floyd(rowcount=5):
	rows = [[1]]
	while len(rows) < rowcount:
		n = rows[-1][-1] + 1
		rows.append(list(range(n, n + len(rows[-1]) + 1)))
	return rows

>>> floyd()
[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10], [11, 12, 13, 14, 15]]
>>> def pfloyd(rows=[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]):
	colspace = [len(str(n)) for n in rows[-1]]
	for row in rows:
		print( ' '.join('%*i' % space_n for space_n in zip(colspace, row)))

>>> pfloyd()
1
2 3
4 5 6
7 8 9 10
>>> pfloyd(floyd(5))
 1
 2  3
 4  5  6
 7  8  9 10
11 12 13 14 15
>>> pfloyd(floyd(14))
 1
 2  3
 4  5  6
 7  8  9 10
11 12 13 14 15
16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44  45
46 47 48 49 50 51 52 53  54  55
56 57 58 59 60 61 62 63  64  65  66
67 68 69 70 71 72 73 74  75  76  77  78
79 80 81 82 83 84 85 86  87  88  89  90  91
92 93 94 95 96 97 98 99 100 101 102 103 104 105
>>>


Floyd's triangle

Solution:
'''Floyd triangle in terms of iterate(f)(x)'''

from itertools import islice

# floyd :: Int -> [[Int]]
def floyd(n):
    '''n rows of a Floyd triangle.'''
    return take(n)(iterate(nextFloyd)([1]))

# nextFloyd :: [Int] -> [Int]
def nextFloyd(xs):
    '''A Floyd triangle row derived from
       the preceding row.'''
    n = succ(len(xs))
    return [1] if n < 2 else (
        enumFromTo(succ(n * pred(n) // 2))(
            n * succ(n) // 2
        )
    )

# showFloyd :: [[Int]] -> String
def showFloyd(xs):
    '''A stringification of Floyd triangle rows.'''
    return unlines(str(x) for x in xs)

# main :: IO ()
def main():
    '''Test'''
    print(showFloyd(
        floyd(5)
    ))

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

# enumFromTo :: (Int, Int) -> [Int]
def enumFromTo(m):
    '''Integer enumeration from m to n.'''
    return lambda n: list(range(m, 1 + n))

# 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)

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

# 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))
    )

# 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))
    )

# unlines :: [String] -> String
def unlines(xs):
    '''A single string derived by the intercalation
       of a list of strings with the newline character.'''
    return '\n'.join(xs)

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


Four bit adder

"''Simulate''" a four-bit adder.

This design can be realized using four 1-bit full adders.
Each of these 1-bit full adders can be built with two gate. ;

Finally a half adder can be made using an   ''xor''   gate and an   ''and''   gate.

The   ''xor''   gate can be made using two   ''not''s,   two   ''and''s   and one   ''or''.

'''Not''',   '''or'''   and   '''and''',   the only allowed "gates" for the task, can be "imitated" by using the bitwise operators of your language.

If there is not a ''bit type'' in your language, to be sure that the   ''not''   does not "invert" all the other bits of the basic type   (e.g. a byte)   we are not interested in,   you can use an extra   ''nand''   (''and''   then   ''not'')   with the constant   '''1'''   on one input.

Instead of optimizing and reducing the number of gates used for the final 4-bit adder,   build it in the most straightforward way,   ''connecting'' the other "constructive blocks",   in turn made of "simpler" and "smaller" ones.

{|
|+Schematics of the "constructive blocks"
!(Xor gate with ANDs, ORs and NOTs)
!   (A half adder)
!          (A full adder)
!                (A 4-bit adder)
|-
|Xor gate done with ands, ors and nots
|A half adder
|A full adder
|A 4-bit adder
|}

Solutions should try to be as descriptive as possible, making it as easy as possible to identify "connections" between higher-order "blocks".

It is not mandatory to replicate the syntax of higher-order blocks in the atomic "gate" blocks, i.e. basic "gate" operations can be performed as usual bitwise operations, or they can be "wrapped" in a ''block'' in order to expose the same syntax of higher-order blocks, at implementers' choice.

To test the implementation, show the sum of two four-bit numbers (in binary).

Solution:
def xor(a, b): return (a and not b) or (b and not a)

def ha(a, b): return xor(a, b), a and b     # sum, carry

def fa(a, b, ci):
    s0, c0 = ha(ci, a)
    s1, c1 = ha(s0, b)
    return s1, c0 or c1     # sum, carry

def fa4(a, b):
    width = 4
    ci = [None] * width
    co = [None] * width
    s  = [None] * width
    for i in range(width):
        s[i], co[i] = fa(a[i], b[i], co[i-1] if i else 0)
    return s, co[-1]

def int2bus(n, width=4):
    return [int(c) for c in "{0:0{1}b}".format(n, width)[::-1]]

def bus2int(b):
    return sum(1 << i for i, bit in enumerate(b) if bit)

def test_fa4():
    width = 4
    tot = [None] * (width + 1)
    for a in range(2**width):
        for b in range(2**width):
            tot[:width], tot[width] = fa4(int2bus(a), int2bus(b))
            assert a + b == bus2int(tot), "totals don't match: %i + %i != %s" % (a, b, tot)

if __name__ == '__main__':
   test_fa4()


Four is magic

Write a subroutine, function, whatever it may be called in your language, that takes an integer number and returns an English text sequence starting with the English cardinal representation of that integer, the word 'is' and then the English cardinal representation of the count of characters that made up the first word, followed by a comma.

Continue the sequence by using the previous count word as the first word of the next phrase, append 'is' and the cardinal count of the letters in ''that'' word.

Continue until you reach four. Since four has four characters, finish by adding the words 'four is magic' and a period. All integers will eventually wind up at four.

For instance, suppose your are given the integer '''3'''. Convert '''3''' to '''Three''', add ''' is ''', then the cardinal character count of three, or '''five''', with a comma to separate if from the next phrase. Continue the sequence '''five is four,''' (five has four letters), and finally, '''four is magic.'''

      '''Three is five, five is four, four is magic.'''

For reference, here are outputs for 0 through 9.

      Zero is four, four is magic.
      One is three, three is five, five is four, four is magic.
      Two is three, three is five, five is four, four is magic.
      Three is five, five is four, four is magic.
      Four is magic.
      Five is four, four is magic.
      Six is three, three is five, five is four, four is magic.
      Seven is five, five is four, four is magic.
      Eight is five, five is four, four is magic.
      Nine is four, four is magic.

;Some task guidelines:
:* You may assume the input will only contain integer numbers.
:* Cardinal numbers between 20 and 100 may use either hyphens or spaces as word separators but they must use a word separator. ('''23''' is '''twenty three''' or '''twenty-three''' not '''twentythree'''.)
:* Cardinal number conversions should follow the  English short scale. (billion is 1e9, trillion is 1e12, etc.)
:* Cardinal numbers should not include commas. ('''20140''' is '''twenty thousand one hundred forty''' not '''twenty thousand, one hundred forty'''.)
:* When converted to a string, '''100''' should be '''one hundred''', not '''a hundred''' or '''hundred''', '''1000''' should be '''one thousand''', not '''a thousand''' or '''thousand'''.
:* When converted to a string, there should be no '''and''' in the cardinal string. '''130''' should be '''one hundred thirty''' not '''one hundred and thirty'''.
:* When counting characters, count ''all'' of the characters in the cardinal number including spaces and hyphens. '''One hundred fifty-one''' should be '''21''' not '''18'''.
:* The output should follow the format "N is K, K is M, M is ... four is magic." (unless the input is 4, in which case the output should simply be "four is magic.")
:* The output can either be the return value from the function, or be displayed from within the function.
:* You are encouraged, though not mandated to use proper sentence capitalization.
:* You may optionally support negative numbers. '''-7''' is '''negative seven'''.
:* Show the output here for a small representative sample of values, at least 5 but no more than 25. You are free to choose which which numbers to use for output demonstration.

You can choose to use a library, (module, external routine, whatever) to do the cardinal conversions as long as the code is easily and freely available to the public.

If you roll your own, make the routine accept at minimum any integer from 0 up to 999999. If you use a pre-made library, support at least up to unsigned 64 bit integers. (or the largest integer supported in your language if it is less.)

Four is magic is a popular code-golf task. '''This is not code golf.''' Write legible, idiomatic and well formatted code.

;Related tasks:
:*   [[Four is the number of_letters in the ...]]
:*   [[Look-and-say sequence]]
:*   [[Number names]]
:*   [[Self-describing numbers]]
:*   [[Summarize and say sequence]]
:*   [[Spelling of ordinal numbers]]
:*   [[De Bruijn sequences]]

Solution:
import random
from collections import OrderedDict

numbers = {  # taken from https://en.wikipedia.org/wiki/Names_of_large_numbers#cite_ref-a_14-3
    1: 'one',
    2: 'two',
    3: 'three',
    4: 'four',
    5: 'five',
    6: 'six',
    7: 'seven',
    8: 'eight',
    9: 'nine',
    10: 'ten',
    11: 'eleven',
    12: 'twelve',
    13: 'thirteen',
    14: 'fourteen',
    15: 'fifteen',
    16: 'sixteen',
    17: 'seventeen',
    18: 'eighteen',
    19: 'nineteen',
    20: 'twenty',
    30: 'thirty',
    40: 'forty',
    50: 'fifty',
    60: 'sixty',
    70: 'seventy',
    80: 'eighty',
    90: 'ninety',
    100: 'hundred',
    1000: 'thousand',
    10 ** 6: 'million',
    10 ** 9: 'billion',
    10 ** 12: 'trillion',
    10 ** 15: 'quadrillion',
    10 ** 18: 'quintillion',
    10 ** 21: 'sextillion',
    10 ** 24: 'septillion',
    10 ** 27: 'octillion',
    10 ** 30: 'nonillion',
    10 ** 33: 'decillion',
    10 ** 36: 'undecillion',
    10 ** 39: 'duodecillion',
    10 ** 42: 'tredecillion',
    10 ** 45: 'quattuordecillion',
    10 ** 48: 'quinquadecillion',
    10 ** 51: 'sedecillion',
    10 ** 54: 'septendecillion',
    10 ** 57: 'octodecillion',
    10 ** 60: 'novendecillion',
    10 ** 63: 'vigintillion',
    10 ** 66: 'unvigintillion',
    10 ** 69: 'duovigintillion',
    10 ** 72: 'tresvigintillion',
    10 ** 75: 'quattuorvigintillion',
    10 ** 78: 'quinquavigintillion',
    10 ** 81: 'sesvigintillion',
    10 ** 84: 'septemvigintillion',
    10 ** 87: 'octovigintillion',
    10 ** 90: 'novemvigintillion',
    10 ** 93: 'trigintillion',
    10 ** 96: 'untrigintillion',
    10 ** 99: 'duotrigintillion',
    10 ** 102: 'trestrigintillion',
    10 ** 105: 'quattuortrigintillion',
    10 ** 108: 'quinquatrigintillion',
    10 ** 111: 'sestrigintillion',
    10 ** 114: 'septentrigintillion',
    10 ** 117: 'octotrigintillion',
    10 ** 120: 'noventrigintillion',
    10 ** 123: 'quadragintillion',
    10 ** 153: 'quinquagintillion',
    10 ** 183: 'sexagintillion',
    10 ** 213: 'septuagintillion',
    10 ** 243: 'octogintillion',
    10 ** 273: 'nonagintillion',
    10 ** 303: 'centillion',
    10 ** 306: 'uncentillion',
    10 ** 309: 'duocentillion',
    10 ** 312: 'trescentillion',
    10 ** 333: 'decicentillion',
    10 ** 336: 'undecicentillion',
    10 ** 363: 'viginticentillion',
    10 ** 366: 'unviginticentillion',
    10 ** 393: 'trigintacentillion',
    10 ** 423: 'quadragintacentillion',
    10 ** 453: 'quinquagintacentillion',
    10 ** 483: 'sexagintacentillion',
    10 ** 513: 'septuagintacentillion',
    10 ** 543: 'octogintacentillion',
    10 ** 573: 'nonagintacentillion',
    10 ** 603: 'ducentillion',
    10 ** 903: 'trecentillion',
    10 ** 1203: 'quadringentillion',
    10 ** 1503: 'quingentillion',
    10 ** 1803: 'sescentillion',
    10 ** 2103: 'septingentillion',
    10 ** 2403: 'octingentillion',
    10 ** 2703: 'nongentillion',
    10 ** 3003: 'millinillion'
}
numbers = OrderedDict(sorted(numbers.items(), key=lambda t: t[0], reverse=True))

def string_representation(i: int) -> str:
    """
    Return the english string representation of an integer
    """
    if i == 0:
        return 'zero'

    words = ['negative'] if i < 0 else []
    working_copy = abs(i)

    for key, value in numbers.items():
        if key <= working_copy:
            times = int(working_copy / key)

            if key >= 100:
                words.append(string_representation(times))

            words.append(value)
            working_copy -= times * key

        if working_copy == 0:
            break

    return ' '.join(words)

def next_phrase(i: int):
    """
    Generate all the phrases
    """
    while not i == 4:  # Generate phrases until four is reached
        str_i = string_representation(i)
        len_i = len(str_i)

        yield str_i, 'is', string_representation(len_i)

        i = len_i

    # the last phrase
    yield string_representation(i), 'is', 'magic'

def magic(i: int) -> str:
    phrases = []

    for phrase in next_phrase(i):
        phrases.append(' '.join(phrase))

    return f'{", ".join(phrases)}.'.capitalize()

if __name__ == '__main__':

    for j in (random.randint(0, 10 ** 3) for i in range(5)):
        print(j, ':\n', magic(j), '\n')

    for j in (random.randint(-10 ** 24, 10 ** 24) for i in range(2)):
        print(j, ':\n', magic(j), '\n')


Four is the number of letters in the ...

The      '''Four is ...'''      sequence is based on the counting of the number of
letters in the words of the (never-ending) sentence:
   Four is the number of letters in the first word of this sentence, two in the second,
   three in the third, six in the fourth, two in the fifth, seven in the sixth, ***

;Definitions and directives:
:*   English is to be used in spelling numbers.
:*   '''Letters'''   are defined as the upper- and lowercase letters in the Latin alphabet   ('''A-->Z'''   and   '''a-->z''').
:*   Commas are not counted,   nor are hyphens (dashes or minus signs).
:*   '''twenty-three'''   has eleven letters.
:*   '''twenty-three'''   is considered one word   (which is hyphenated).
:*   no   ''' ''and'' '''   words are to be used when spelling a (English) word for a number.
:*   The American version of numbers will be used here in this task   (as opposed to the British version).
          '''2,000,000,000'''   is two billion,   ''not''   two milliard.

;Task:
:*   Write a driver (invoking routine) and a function (subroutine/routine***) that returns the sequence (for any positive integer) of the number of letters in the first   '''N'''    words in the never-ending sentence.   For instance, the portion of the never-ending sentence shown above (2nd sentence of this task's preamble),   the sequence would be:
          '''4  2  3  6  2  7'''
:*   Only construct as much as is needed for the never-ending sentence.
:*   Write a driver (invoking routine) to show the number of letters in the   Nth   word,   ''as well as''   showing the   Nth   word itself.
:*   After each test case, show the total number of characters   (including blanks, commas, and punctuation)   of the sentence that was constructed.
:*   Show all output here.

;Test cases:
  Display the first  201  numbers in the sequence   (and the total number of characters in the sentence).
  Display the number of letters  (and the word itself)  of the       1,000th  word.
  Display the number of letters  (and the word itself)  of the      10,000th  word.
  Display the number of letters  (and the word itself)  of the     100,000th  word.
  Display the number of letters  (and the word itself)  of the   1,000,000th  word.
  Display the number of letters  (and the word itself)  of the  10,000,000th  word  (optional).

;Related tasks:
:*   [[Four is magic]]
:*   [[Look-and-say sequence]]
:*   [[Number names]]
:*   [[Self-describing numbers]]
:*   [[Self-referential sequence]]
:*   [[Spelling of ordinal numbers]]

;Also see:
:*   See the OEIS sequence  A72425  "Four is the number of letters...".
:*   See the OEIS sequence  A72424  "Five's the number of letters..."

Solution:
# Python implementation of Rosetta Code Task
# http://rosettacode.org/wiki/Four_is_the_number_of_letters_in_the_...
# Uses inflect
# https://pypi.org/project/inflect/

import inflect

def count_letters(word):
    """
    count letters ignore , or -, or space
    """
    count = 0
    for letter in word:
        if letter != ',' and letter !='-' and letter !=' ':
            count += 1

    return count

def split_with_spaces(sentence):
    """
    Takes string with partial sentence and returns
    list of words with spaces included.

    Leading space is attached to first word.
    Later spaces attached to prior word.
    """
    sentence_list = []
    curr_word = ""
    for c in sentence:
        if c == " " and curr_word != "":
            # append space to end of non-empty words
            # assumed no more than 1 consecutive space.
            sentence_list.append(curr_word+" ")
            curr_word = ""
        else:
            curr_word += c

    # add trailing word that does not end with a space

    if len(curr_word) > 0:
        sentence_list.append(curr_word)

    return sentence_list

def my_num_to_words(p, my_number):
    """
    Front end to inflect's number_to_words

    Get's rid of ands and commas in large numbers.
    """

    number_string_list = p.number_to_words(my_number, wantlist=True, andword='')

    number_string = number_string_list[0]

    for i in range(1,len(number_string_list)):
        number_string += " " + number_string_list[i]

    return number_string

def build_sentence(p, max_words):
    """

    Builds at most max_words of the task following the pattern:

    Four is the number of letters in the first word of this sentence, two in the second,
    three in the third, six in the fourth, two in the fifth, seven in the sixth,

    """

    # start with first part of sentence up first comma as a list

    sentence_list = split_with_spaces("Four is the number of letters in the first word of this sentence,")

    num_words = 13

    # which word number we are doing next
    # two/second is first one in loop

    word_number = 2

    # loop until sentance is at least as long as needs be

    while num_words < max_words:
        # Build something like
        # ,two in the second

        # get second or whatever we are on

        ordinal_string = my_num_to_words(p, p.ordinal(word_number))

        # get two or whatever the length is of the word_number word

        word_number_string = my_num_to_words(p, count_letters(sentence_list[word_number - 1]))

        # sentence addition

        new_string = " "+word_number_string+" in the "+ordinal_string+","

        new_list = split_with_spaces(new_string)

        sentence_list += new_list

        # add new word count

        num_words += len(new_list)

        # increment word number

        word_number += 1

    return sentence_list, num_words

def word_and_counts(word_num):
    """

    Print's lines like this:

    Word     1000 is "in", with 2 letters.  Length of sentence so far: 6279

    """

    sentence_list, num_words = build_sentence(p, word_num)

    word_str = sentence_list[word_num - 1].strip(' ,')

    num_letters = len(word_str)

    num_characters = 0

    for word in sentence_list:
       num_characters += len(word)

    print('Word {0:8d} is "{1}", with {2} letters.  Length of the sentence so far: {3}  '.format(word_num,word_str,num_letters,num_characters))

p = inflect.engine()

sentence_list, num_words = build_sentence(p, 201)

print(" ")
print("The lengths of the first 201 words are:")
print(" ")

print('{0:3d}:  '.format(1),end='')

total_characters = 0

for word_index in range(201):

    word_length = count_letters(sentence_list[word_index])

    total_characters += len(sentence_list[word_index])

    print('{0:2d}'.format(word_length),end='')
    if (word_index+1) % 20 == 0:
        # newline every 20
        print(" ")
        print('{0:3d}:  '.format(word_index + 2),end='')
    else:
        print(" ",end='')

print(" ")
print(" ")
print("Length of the sentence so far: "+str(total_characters))
print(" ")

"""

Expected output this part:

Word     1000 is "in", with 2 letters.  Length of the sentence so far: 6279
Word    10000 is "in", with 2 letters.  Length of the sentence so far: 64140
Word   100000 is "one", with 3 letters.  Length of the sentence so far: 659474
Word  1000000 is "the", with 3 letters.  Length of the sentence so far: 7113621
Word 10000000 is "thousand", with 8 letters.  Length of the sentence so far: 70995756

"""

word_and_counts(1000)
word_and_counts(10000)
word_and_counts(100000)
word_and_counts(1000000)
word_and_counts(10000000)


Functional coverage tree

Functional coverage is a measure of how much a particular function of a system
has been verified as correct. It is used heavily in tracking the completeness
of the verification of complex System on Chip (SoC) integrated circuits, where
it can also be used to track how well the functional ''requirements'' of the
system have been verified.

This task uses a sub-set of the calculations sometimes used in tracking
functional coverage but uses a more familiar(?) scenario.

;Task Description:
The head of the clean-up crews for "The Men in a very dark shade of grey when
viewed at night" has been tasked with managing the cleansing of two properties
after an incident involving aliens.

She arranges the task hierarchically with a manager for the crews working on
each house who return with a breakdown of how they will report on progress in
each house.

The overall hierarchy of (sub)tasks is as follows,
cleaning
    house1
        bedrooms
        bathrooms
            bathroom1
            bathroom2
            outside lavatory
        attic
        kitchen
        living rooms
            lounge
            dining room
            conservatory
            playroom
        basement
        garage
        garden
    house2
        upstairs
            bedrooms
                suite 1
                suite 2
                bedroom 3
                bedroom 4
            bathroom
            toilet
            attics
        groundfloor
            kitchen
            living rooms
                lounge
                dining room
                conservatory
                playroom
            wet room & toilet
            garage
            garden
            hot tub suite
        basement
            cellars
            wine cellar
            cinema

The head of cleanup knows that her managers will report fractional completion of leaf tasks (tasks with no child tasks of their own), and she knows that she will want to modify the weight of values of completion as she sees fit.

Some time into the cleaning, and some coverage reports have come in and she thinks see needs to weight the big house2 60-40 with respect to coverage from house1 She prefers a tabular view of her data where missing weights are assumed to be 1.0 and missing coverage 0.0.
NAME_HIERARCHY                  |WEIGHT  |COVERAGE  |
cleaning                        |        |          |
    house1                      |40      |          |
        bedrooms                |        |0.25      |
        bathrooms               |        |          |
            bathroom1           |        |0.5       |
            bathroom2           |        |          |
            outside_lavatory    |        |1         |
        attic                   |        |0.75      |
        kitchen                 |        |0.1       |
        living_rooms            |        |          |
            lounge              |        |          |
            dining_room         |        |          |
            conservatory        |        |          |
            playroom            |        |1         |
        basement                |        |          |
        garage                  |        |          |
        garden                  |        |0.8       |
    house2                      |60      |          |
        upstairs                |        |          |
            bedrooms            |        |          |
                suite_1         |        |          |
                suite_2         |        |          |
                bedroom_3       |        |          |
                bedroom_4       |        |          |
            bathroom            |        |          |
            toilet              |        |          |
            attics              |        |0.6       |
        groundfloor             |        |          |
            kitchen             |        |          |
            living_rooms        |        |          |
                lounge          |        |          |
                dining_room     |        |          |
                conservatory    |        |          |
                playroom        |        |          |
            wet_room_&_toilet   |        |          |
            garage              |        |          |
            garden              |        |0.9       |
            hot_tub_suite       |        |1         |
        basement                |        |          |
            cellars             |        |1         |
            wine_cellar         |        |1         |
            cinema              |        |0.75      |

;Calculation:
The coverage of a node in the tree is calculated as the weighted average of the coverage of its children evaluated bottom-upwards in the tree.

'''The task is to''' calculate the overall coverage of the cleaning task and display the coverage at all levels of the hierarchy on this page, in a manner that visually shows the hierarchy, weights and coverage of all nodes.

;Extra Credit:
After calculating the coverage for all nodes, one can also calculate the additional/delta top level coverage that would occur if any (sub)task were to be fully covered from its current fractional coverage. This is done by multiplying the extra coverage that could be gained 1-coverage for any node, by the product of the `powers` of its parent nodes from the top down to the node.
The power of a direct child of any parent is given by the power of the parent multiplied by the weight of the child divided by the sum of the weights of all the direct children.

The pseudo code would be:

    method delta_calculation(this, power):
        sum_of_weights = sum(node.weight for node in children)
        this.delta  = (1 - this.coverage) * power
        for node in self.children:
            node.delta_calculation(power * node.weight / sum_of_weights)
        return this.delta

Followed by a call to:

    top.delta_calculation(power=1)

'''Note:''' to aid in getting the data into your program you might want to use an alternative, more functional description of the starting data given on the discussion page.

Solution:
from itertools import zip_longest

fc2 = '''\
cleaning,,
    house1,40,
        bedrooms,,.25
        bathrooms,,
            bathroom1,,.5
            bathroom2,,
            outside_lavatory,,1
        attic,,.75
        kitchen,,.1
        living_rooms,,
            lounge,,
            dining_room,,
            conservatory,,
            playroom,,1
        basement,,
        garage,,
        garden,,.8
    house2,60,
        upstairs,,
            bedrooms,,
                suite_1,,
                suite_2,,
                bedroom_3,,
                bedroom_4,,
            bathroom,,
            toilet,,
            attics,,.6
        groundfloor,,
            kitchen,,
            living_rooms,,
                lounge,,
                dining_room,,
                conservatory,,
                playroom,,
            wet_room_&_toilet,,
            garage,,
            garden,,.9
            hot_tub_suite,,1
        basement,,
            cellars,,1
            wine_cellar,,1
            cinema,,.75

'''

NAME, WT, COV = 0, 1, 2

def right_type(txt):
    try:
        return float(txt)
    except ValueError:
        return txt

def commas_to_list(the_list, lines, start_indent=0):
    '''
    Output format is a nest of lists and tuples
    lists are for coverage leaves without children items in the list are name, weight, coverage
    tuples are 2-tuples for nodes with children. The first element is a list representing the
    name, weight, coverage of the node (some to be calculated); the second element is a list of
    child elements which may be 2-tuples or lists as above.

    the_list is modified in-place
    lines must be a generator of successive lines of input like fc2
    '''
    for n, line in lines:
        indent = 0
        while line.startswith(' ' * (4 * indent)):
            indent += 1
        indent -= 1
        fields = [right_type(f) for f in line.strip().split(',')]
        if indent == start_indent:
            the_list.append(fields)
        elif indent > start_indent:
            lst = [fields]
            sub = commas_to_list(lst, lines, indent)
            the_list[-1] = (the_list[-1], lst)
            if sub not in (None, ['']) :
                the_list.append(sub)
        else:
            return fields if fields else None
    return None

def pptreefields(lst, indent=0, widths=['%-32s', '%-8g', '%-10g']):
    '''
    Pretty prints the format described from function commas_to_list as a table with
    names in the first column suitably indented and all columns having a fixed
    minimum column width.
    '''
    lhs = ' ' * (4 * indent)
    for item in lst:
        if type(item) != tuple:
            name, *rest = item
            print(widths[0] % (lhs + name), end='|')
            for width, item in zip_longest(widths[1:len(rest)], rest, fillvalue=widths[-1]):
                if type(item) == str:
                    width = width[:-1] + 's'
                print(width % item, end='|')
            print()
        else:
            item, children = item
            name, *rest = item
            print(widths[0] % (lhs + name), end='|')
            for width, item in zip_longest(widths[1:len(rest)], rest, fillvalue=widths[-1]):
                if type(item) == str:
                    width = width[:-1] + 's'
                print(width % item, end='|')
            print()
            pptreefields(children, indent+1)

def default_field(node_list):
    node_list[WT] = node_list[WT] if node_list[WT] else 1.0
    node_list[COV] = node_list[COV] if node_list[COV] else 0.0

def depth_first(tree, visitor=default_field):
    for item in tree:
        if type(item) == tuple:
            item, children = item
            depth_first(children, visitor)
        visitor(item)

def covercalc(tree):
    '''
    Depth first weighted average of coverage
    '''
    sum_covwt, sum_wt = 0, 0
    for item in tree:
        if type(item) == tuple:
            item, children = item
            item[COV] = covercalc(children)
        sum_wt  += item[WT]
        sum_covwt += item[COV] * item[WT]
    cov = sum_covwt / sum_wt
    return cov

if __name__ == '__main__':
    lstc = []
    commas_to_list(lstc, ((n, ln) for n, ln in enumerate(fc2.split('\n'))))
    #pp(lstc, width=1, indent=4, compact=1)

    #print('\n\nEXPANDED DEFAULTS\n')
    depth_first(lstc)
    #pptreefields(['NAME_HIERARCHY WEIGHT COVERAGE'.split()] + lstc)

    print('\n\nTOP COVERAGE = %f\n' % covercalc(lstc))
    depth_first(lstc)
    pptreefields(['NAME_HIERARCHY WEIGHT COVERAGE'.split()] + lstc)


Functional coverage tree

Solution:
'''Functional coverage tree'''

from itertools import chain, product
from functools import reduce

# main :: IO ()
def main():
    '''Tabular outline serialisation of a parse tree
       decorated with computations of:
       1. Weighted coverage of each tree node.
       2. Each node's share of the total project's
          remaining work.
    '''
    columnWidths = [31, 9, 9, 9]
    delimiter = '|'

    reportLines = REPORT.splitlines()
    columnTitles = init(columnNames(delimiter)(reportLines[0]))

    # ------ SERIALISATION OF DECORATED PARSE TREE -------
    print(titleLine(delimiter)(columnWidths)(
        columnTitles + ['share of residue']
    ))
    print(indentedLinesFromTree('    ', tabulation(columnWidths))(

        # -------- TWO COMPUTATIONS BY TRAVERSAL ---------
        withResidueShares(1.0)(
            foldTree(weightedCoverage)(

                # --- TREE FROM PARSE OF OUTLINE TEXT ----
                fmapTree(
                    recordFromKeysDefaultsDelimiterAndLine(
                        columnTitles
                    )(
                        [str, float, float])([
                            '?', 1.0, 0.0
                        ])(delimiter)
                )(
                    forestFromIndentLevels(
                        indentLevelsFromLines(
                            reportLines[1:]
                        )
                    )[0]
                )
            )
        )
    ))

# ---- WEIGHTED COVERAGE, AND SHARE OF TOTAL RESIDUE -----

# weightedCoverage :: Tree Dict ->
# [Tree Dict] -> Tree Dict
def weightedCoverage(x):
    '''The weighted coverage of a tree node,
       as a function of the weighted averages
       of its children.
    '''
    def go(xs):
        cws = [
            (r['coverage'], r['weight']) for r
            in [root(x) for x in xs]
        ]
        totalWeight = reduce(lambda a, x: a + x[1], cws, 0)
        return Node(dict(
            x, **{
                'coverage': round(reduce(
                    lambda a, cw: a + (cw[0] * cw[1]),
                    cws, x['coverage']
                ) / (totalWeight if 0 < totalWeight else 1), 5)
            }
        ))(xs)
    return go

# withResidueShares :: Float -> Tree Dict -> Tree Dict
def withResidueShares(shareOfTotal):
    '''A Tree of dictionaries additionally decorated with each
       node's proportion of the total project's outstanding work.
    '''
    def go(fraction, node):
        [nodeRoot, nodeNest] = ap([root, nest])([node])
        weights = [root(x)['weight'] for x in nodeNest]
        siblingsTotal = sum(weights)
        return Node(
            insertDict('residual_share')(
                round(fraction * (1 - nodeRoot['coverage']), 5)
            )(nodeRoot)
        )(
            map(
                go,
                [fraction * (w / siblingsTotal) for w in weights],
                nodeNest
            )
        )
    return lambda tree: go(shareOfTotal, tree)

# ------------------ OUTLINE TABULATION ------------------

# tabulation :: [Int] -> String -> Dict -> String
def tabulation(columnWidths):
    '''Indented string representation of a node
       in a functional coverage tree.
    '''
    return lambda indent, dct: '| '.join(map(
        lambda k, w: (
            (indent if 10 < w else '') + str(dct.get(k, ''))
        ).ljust(w, ' '),
        dct.keys(),
        columnWidths
    ))

# titleLine :: String -> [Int] -> [String] -> String
def titleLine(delimiter):
    '''A string consisting of a spaced and delimited
       series of upper-case column titles.
    '''
    return lambda columnWidths: lambda ks: (
        delimiter + ' '
    ).join(map(
        lambda k, w: k.ljust(w, ' '),
        [k.upper() for k in ks],
        columnWidths
    ))

# ------------ GENERIC AND REUSABLE FUNCTIONS ------------

# Node :: a -> [Tree a] -> Tree a
def Node(v):
    '''Constructor for a Tree node which connects a
       value of some kind to a list of zero or
       more child trees.
    '''
    return lambda xs: {'type': 'Tree', 'root': v, 'nest': xs}

# ap (<*>) :: [(a -> b)] -> [a] -> [b]
def ap(fs):
    '''The application of each of a list of functions,
       to each of a list of values.
    '''
    def go(xs):
        return [
            f(x) for (f, x)
            in product(fs, xs)
        ]
    return go

# columnNames :: String -> String -> [String]
def columnNames(delimiter):
    '''A list of lower-case keys derived from
       a header line and a delimiter character.
    '''
    return compose(
        fmapList(compose(toLower, strip)),
        splitOn(delimiter)
    )

# compose :: ((a -> a), ...) -> (a -> a)
def compose(*fs):
    '''Composition, from right to left,
       of a series of functions.
    '''
    return lambda x: reduce(
        lambda a, f: f(a),
        fs[::-1], x
    )

# 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).
    '''
    def go(xs):
        return chain.from_iterable(map(f, xs))
    return go

# div :: Int -> Int -> Int
def div(x):
    '''Integer division.'''
    return lambda y: x // y

# first :: (a -> b) -> ((a, c) -> (b, c))
def first(f):
    '''A simple function lifted to a function over a tuple,
       with f applied only the first of two values.
    '''
    return lambda xy: (f(xy[0]), xy[1])

# flip :: (a -> b -> c) -> b -> a -> c
def flip(f):
    '''The (curried or uncurried) function f with its
       arguments reversed.
    '''
    return lambda a: lambda b: f(b)(a)

# fmapList :: (a -> b) -> [a] -> [b]
def fmapList(f):
    '''fmap over a list.
       f lifted to a function over a list.
    '''
    return lambda xs: [f(x) for x in xs]

# fmapTree :: (a -> b) -> Tree a -> Tree b
def fmapTree(f):
    '''A new tree holding the results of
       an application of f to each root in
       the existing tree.
    '''
    def go(x):
        return Node(
            f(x['root'])
        )([go(v) for v in x['nest']])
    return go

# foldTree :: (a -> [b] -> b) -> Tree a -> b
def foldTree(f):
    '''The catamorphism on trees. A summary
       value defined by a depth-first fold.
    '''
    def go(node):
        return f(root(node))([
            go(x) for x in nest(node)
        ])
    return go

# forestFromIndentLevels :: [(Int, a)] -> [Tree a]
def forestFromIndentLevels(tuples):
    '''A list of trees derived from a list of values paired
       with integers giving their levels of indentation.
    '''
    def go(xs):
        if xs:
            intIndent, v = xs[0]
            firstTreeLines, rest = span(
                lambda x: intIndent < x[0]
            )(xs[1:])
            return [Node(v)(go(firstTreeLines))] + go(rest)
        else:
            return []
    return go(tuples)

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

# indentLevelsFromLines :: [String] -> [(Int, String)]
def indentLevelsFromLines(xs):
    '''Each input line stripped of leading
       white space, and tupled with a preceding integer
       giving its level of indentation from 0 upwards.
    '''
    indentTextPairs = list(map(
        compose(first(len), span(isSpace)),
        xs
    ))
    indentUnit = min(concatMap(
        lambda x: [x[0]] if x[0] else []
    )(indentTextPairs))
    return list(map(
        first(flip(div)(indentUnit)),
        indentTextPairs
    ))

# indentedLinesFromTree :: String -> (String -> a -> String) ->
# [Tree a] -> String
def indentedLinesFromTree(strTab, f):
    '''An indented line rendering of a tree, in which
       the function f stringifies a root value.
    '''
    def go(indent):
        return lambda node: [f(indent, node['root'])] + list(
            concatMap(
                go(strTab + indent)
            )(node['nest'])
        )
    return lambda tree: '\n'.join(go('')(tree))

# init :: [a] -> [a]
def init(xs):
    '''A list containing all the elements
       of xs except the last.
    '''
    return xs[:-1]

# insertDict :: String -> a -> Dict -> Dict
def insertDict(k):
    '''A new dictionary updated with a (k, v) pair.'''
    def go(v, dct):
        return dict(dct, **{k: v})
    return lambda v: lambda dct: go(v, dct)

# isSpace :: Char -> Bool
# isSpace :: String -> Bool
def isSpace(s):
    '''True if s is not empty, and
       contains only white space.
    '''
    return s.isspace()

# lt (<) :: Ord a => a -> a -> Bool
def lt(x):
    '''True if x < y.'''
    return lambda y: (x < y)

# nest :: Tree a -> [Tree a]
def nest(t):
    '''Accessor function for children of tree node.'''
    return t['nest'] if 'nest' in t else None

# recordFromKeysDefaultsAndLine :: String ->
# { name :: String, weight :: Float, completion :: Float }
def recordFromKeysDefaultsDelimiterAndLine(columnTitles):
    '''A dictionary of key-value pairs, derived from a
       delimited string, together with ordered lists of
       key-names, types, default values, and a delimiter.
    '''
    return lambda ts: lambda vs: lambda delim: lambda s: dict(
        map(
            lambda k, t, v, x: (k, t(x) if x else v),
            columnTitles, ts, vs,
            map(strip, splitOn(delim)(s))
        )
    )

# root :: Tree a -> a
def root(t):
    '''Accessor function for data of tree node.'''
    return t['root'] if 'root' in t else None

# strip :: String -> String
def strip(s):
    '''A copy of s without any leading or trailling
       white space.
    '''
    return s.strip()

# span :: (a -> Bool) -> [a] -> ([a], [a])
def span(p):
    '''The longest (possibly empty) prefix of xs
       that contains only elements satisfying p,
       tupled with the remainder of xs.
       span p xs is equivalent to (takeWhile p xs, dropWhile p xs).
    '''
    def match(ab):
        b = ab[1]
        return not b or not p(b[0])

    def f(ab):
        a, b = ab
        return a + [b[0]], b[1:]

    def go(xs):
        return until(match)(f)(([], xs))
    return go

# splitOn :: String -> String -> [String]
def splitOn(pat):
    '''A list of the strings delimited by
       instances of a given pattern in s.
    '''
    return lambda xs: (
        xs.split(pat) if isinstance(xs, str) else None
    )

# toLower :: String -> String
def toLower(s):
    '''String in lower case.'''
    return s.lower()

# 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__':
    REPORT = '''NAME_HIERARCHY                  |WEIGHT  |COVERAGE  |
    cleaning                        |        |          |
        house1                      |40      |          |
            bedrooms                |        |0.25      |
            bathrooms               |        |          |
                bathroom1           |        |0.5       |
                bathroom2           |        |          |
                outside_lavatory    |        |1         |
            attic                   |        |0.75      |
            kitchen                 |        |0.1       |
            living_rooms            |        |          |
                lounge              |        |          |
                dining_room         |        |          |
                conservatory        |        |          |
                playroom            |        |1         |
            basement                |        |          |
            garage                  |        |          |
            garden                  |        |0.8       |
        house2                      |60      |          |
            upstairs                |        |          |
                bedrooms            |        |          |
                    suite_1         |        |          |
                    suite_2         |        |          |
                    bedroom_3       |        |          |
                    bedroom_4       |        |          |
                bathroom            |        |          |
                toilet              |        |          |
                attics              |        |0.6       |
            groundfloor             |        |          |
                kitchen             |        |          |
                living_rooms        |        |          |
                    lounge          |        |          |
                    dining_room     |        |          |
                    conservatory    |        |          |
                    playroom        |        |          |
                wet_room_&_toilet   |        |          |
                garage              |        |          |
                garden              |        |0.9       |
                hot_tub_suite       |        |1         |
            basement                |        |          |
                cellars             |        |1         |
                wine_cellar         |        |1         |
                cinema              |        |0.75      |'''
    main()


Fusc sequence

Definitions:
The   '''fusc'''   integer sequence is defined as:
::*   fusc(0) = 0
::*   fusc(1) = 1
::*   for '''n'''>1,   the   '''n'''th   term is defined as:
::::*   if   '''n'''   is       even;     fusc(n) = fusc(n/2)
::::*   if   '''n'''   is   odd;     fusc(n) = fusc((n-1)/2)   +   fusc((n+1)/2)

Note that MathWorld's definition starts with unity, not zero.   This task will be using the OEIS' version   (above).

;An observation:
:::::*   fusc(A) = fusc(B)

where   '''A'''   is some non-negative integer expressed in binary,   and
where   '''B'''   is the binary value of   '''A'''   reversed.

Fusc numbers are also known as:
::*   fusc function   (named by Dijkstra, 1982)
::*   Stern's Diatomic series   (although it starts with unity, not zero)
::*   Stern-Brocot sequence   (although it starts with unity, not zero)

;Task:
::*   show the first   '''61'''   fusc numbers (starting at zero) in a horizontal format.
::*   show the fusc number (and its index) whose length is greater than any previous fusc number length.
::::*   (the length is the number of decimal digits when the fusc number is expressed in base ten.)
::*   show all numbers with commas   (if appropriate).
::*   show all output here.

;Related task:
::*   RosettaCode Stern-Brocot sequence

;Also see:
::*   the MathWorld entry:   Stern's Diatomic Series.
::*   the OEIS      entry:   A2487.

Solution:
from collections import deque
from itertools import islice, count

def fusc():
    q = deque([1])
    yield 0
    yield 1

    while True:
        x = q.popleft()
        q.append(x)
        yield x

        x += q[0]
        q.append(x)
        yield x

def longest_fusc():
    sofar = 0
    for i, f in zip(count(), fusc()):
        if f >= sofar:
            yield(i, f)
            sofar = 10 * sofar or 10

print('First 61:')
print(list(islice(fusc(), 61)))

print('\nLength records:')
for i, f in islice(longest_fusc(), 6):
    print(f'fusc({i}) = {f}')


Gapful numbers

Numbers   (positive integers expressed in base ten)   that are (evenly) divisible by the number formed by the
first and last digit are known as   '''gapful numbers'''.

''Evenly divisible''   means divisible with   no   remainder.

All   one-   and two-digit   numbers have this property and are trivially excluded.   Only
numbers    >=  '''100'''   will be considered for this Rosetta Code task.

;Example:
'''187'''   is a   '''gapful'''   number because it is evenly divisible by the
number   '''17'''   which is formed by the first and last decimal digits
of    '''187'''.

About   7.46%   of positive integers are   ''gapful''.

;Task:
:*   Generate and show all sets of numbers (below) on one line (horizontally) with a title,   here on this page
:*   Show the first   '''30'''   gapful numbers
:*   Show the first   '''15'''   gapful numbers    >=           '''1,000,000'''
:*   Show the first   '''10'''   gapful numbers    >=                               '''1,000,000,000'''

;Related tasks:
:*   Harshad or Niven series.
:*   palindromic gapful numbers.
:*   largest number divisible by its digits.

;Also see:
:*   The OEIS entry:   A108343 gapful numbers.
:*   numbersaplenty gapful numbers

Solution:
from itertools import islice, count
for start, n in [(100, 30), (1_000_000, 15), (1_000_000_000, 10)]:
    print(f"\nFirst {n} gapful numbers from {start:_}")
    print(list(islice(( x for x in count(start)
                        if (x % (int(str(x)[0]) * 10 + (x % 10)) == 0) )
                      , n)))


Gauss-Jordan matrix inversion

Invert matrix   '''A'''   using Gauss-Jordan method.

'''A'''   being an   '''n''' x '''n'''   matrix.

Solution:
import numpy as np
from numpy.linalg import inv
a = np.array([[1., 2., 3.], [4., 1., 6.],[ 7., 8., 9.]])
ainv = inv(a)

print(a)
print(ainv)


Gaussian elimination

Solve   '''Ax=b'''   using Gaussian elimination then backwards substitution.

'''A'''   being an   '''n''' by '''n'''   matrix.

Also,   '''x''' and '''b'''   are   '''n''' by '''1'''   vectors.

To improve accuracy, please use partial pivoting and scaling.

;See also:
:*   the Wikipedia entry:   Gaussian elimination

Solution:
# The 'gauss' function takes two matrices, 'a' and 'b', with 'a' square, and it return the determinant of 'a' and a matrix 'x' such that a*x = b.
# If 'b' is the identity, then 'x' is the inverse of 'a'.

import copy
from fractions import Fraction

def gauss(a, b):
    a = copy.deepcopy(a)
    b = copy.deepcopy(b)
    n = len(a)
    p = len(b[0])
    det = 1
    for i in range(n - 1):
        k = i
        for j in range(i + 1, n):
            if abs(a[j][i]) > abs(a[k][i]):
                k = j
        if k != i:
            a[i], a[k] = a[k], a[i]
            b[i], b[k] = b[k], b[i]
            det = -det

        for j in range(i + 1, n):
            t = a[j][i]/a[i][i]
            for k in range(i + 1, n):
                a[j][k] -= t*a[i][k]
            for k in range(p):
                b[j][k] -= t*b[i][k]

    for i in range(n - 1, -1, -1):
        for j in range(i + 1, n):
            t = a[i][j]
            for k in range(p):
                b[i][k] -= t*b[j][k]
        t = 1/a[i][i]
        det *= a[i][i]
        for j in range(p):
            b[i][j] *= t
    return det, b

def zeromat(p, q):
    return [[0]*q for i in range(p)]

def matmul(a, b):
    n, p = len(a), len(a[0])
    p1, q = len(b), len(b[0])
    if p != p1:
        raise ValueError("Incompatible dimensions")
    c = zeromat(n, q)
    for i in range(n):
        for j in range(q):
                c[i][j] = sum(a[i][k]*b[k][j] for k in range(p))
    return c

def mapmat(f, a):
    return [list(map(f, v)) for v in a]

def ratmat(a):
    return mapmat(Fraction, a)

# As an example, compute the determinant and inverse of 3x3 magic square

a = [[2, 9, 4], [7, 5, 3], [6, 1, 8]]
b = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
det, c = gauss(a, b)

det
-360.0

c
[[-0.10277777777777776, 0.18888888888888888, -0.019444444444444438],
[0.10555555555555554, 0.02222222222222223, -0.061111111111111116],
[0.0638888888888889, -0.14444444444444446, 0.14722222222222223]]

# Check product
matmul(a, c)
[[1.0, 0.0, 0.0], [5.551115123125783e-17, 1.0, 0.0],
[1.1102230246251565e-16, -2.220446049250313e-16, 1.0]]

# Same with fractions, so the result is exact

det, c = gauss(ratmat(a), ratmat(b))

det
Fraction(-360, 1)

c
[[Fraction(-37, 360), Fraction(17, 90), Fraction(-7, 360)],
[Fraction(19, 180), Fraction(1, 45), Fraction(-11, 180)],
[Fraction(23, 360), Fraction(-13, 90), Fraction(53, 360)]]

matmul(a, c)
[[Fraction(1, 1), Fraction(0, 1), Fraction(0, 1)],
[Fraction(0, 1), Fraction(1, 1), Fraction(0, 1)],
[Fraction(0, 1), Fraction(0, 1), Fraction(1, 1)]]


Generate Chess960 starting position

Bobby Fischer.  Unlike other variants of the game, Chess960 does not require a different material, but instead relies on a random initial position, with a few constraints:

* as in the standard chess game, all eight white pawns must be placed on the second rank.
* White pieces must stand on the first rank as in the standard game, in random column order but with the two following constraints:
** the bishops must be placed on opposite color squares (i.e. they must be an odd number of spaces apart or there must be an even number of spaces between them)
** the King must be between two rooks (with any number of other pieces between them all)
* Black pawns and pieces must be placed respectively on the seventh and eighth ranks, mirroring the white pawns and pieces, just as in the standard game.  (That is, their positions are not independently randomized.)

With those constraints there are '''960''' possible starting positions, thus the name of the variant.

;Task:
The purpose of this task is to write a program that can randomly generate any one of the 960 Chess960 initial positions. You will show the result as the first rank displayed with Chess symbols in Unicode:  or with the letters '''K'''ing '''Q'''ueen '''R'''ook '''B'''ishop k'''N'''ight.

Solution:
from random import choice

def random960():
    start = ['R', 'K', 'R']         # Subsequent order unchanged by insertions.
    #
    for piece in ['Q', 'N', 'N']:
        start.insert(choice(range(len(start)+1)), piece)
    #
    bishpos = choice(range(len(start)+1))
    start.insert(bishpos, 'B')
    start.insert(choice(range(bishpos + 1, len(start) + 1, 2)), 'B')
    return start
    return ''.join(start).upper()

print(random960())


Generate random chess position

Generate a random chess position in FEN format.

The position does not have to be realistic or even balanced,  but it must comply to the following rules:
:* there is one and only one king of each color  (one black king and one white king);
:* the kings must not be placed on adjacent squares;
:* there can not be any pawn in the promotion square  (no white pawn in the eighth rank, and no black pawn in the first rank);
:* including the kings, up to 32 pieces of either color can be placed.
:* There is no requirement for material balance between sides.
:* The picking of pieces does not have to comply to a regular chess set --- there can be five knights, twenty rooks, whatever ... as long as the total number of pieces do not exceed thirty-two.
:* it is white's turn.
:* It's assumed that both sides have lost castling rights and that there is no possibility for   ''en passant''   (the FEN should thus end in w - - 0 1).

No requirement is made regarding the probability distribution of your method, but your program should be able to span a reasonably representative sample of all possible positions.  For instance, programs that would always generate positions with say five pieces on the board, or with kings on a corner, would not be considered truly random.

Solution:
import random

board = [[" " for x in range(8)] for y in range(8)]
piece_list = ["R", "N", "B", "Q", "P"]

def place_kings(brd):
	while True:
		rank_white, file_white, rank_black, file_black = random.randint(0,7), random.randint(0,7), random.randint(0,7), random.randint(0,7)
		diff_list = [abs(rank_white - rank_black),  abs(file_white - file_black)]
		if sum(diff_list) > 2 or set(diff_list) == set([0, 2]):
			brd[rank_white][file_white], brd[rank_black][file_black] = "K", "k"
			break

def populate_board(brd, wp, bp):
	for x in range(2):
		if x == 0:
			piece_amount = wp
			pieces = piece_list
		else:
			piece_amount = bp
			pieces = [s.lower() for s in piece_list]
		while piece_amount != 0:
			piece_rank, piece_file = random.randint(0, 7), random.randint(0, 7)
			piece = random.choice(pieces)
			if brd[piece_rank][piece_file] == " " and pawn_on_promotion_square(piece, piece_rank) == False:
				brd[piece_rank][piece_file] = piece
				piece_amount -= 1

def fen_from_board(brd):
	fen = ""
	for x in brd:
		n = 0
		for y in x:
			if y == " ":
				n += 1
			else:
				if n != 0:
					fen += str(n)
				fen += y
				n = 0
		if n != 0:
			fen += str(n)
		fen += "/" if fen.count("/") < 7 else ""
	fen += " w - - 0 1\n"
	return fen

def pawn_on_promotion_square(pc, pr):
	if pc == "P" and pr == 0:
		return True
	elif pc == "p" and pr == 7:
		return True
	return False

def start():
	piece_amount_white, piece_amount_black = random.randint(0, 15), random.randint(0, 15)
	place_kings(board)
	populate_board(board, piece_amount_white, piece_amount_black)
	print(fen_from_board(board))
	for x in board:
		print(x)

#entry point
start()


Generator/Exponential

A generator is an executable entity (like a function or procedure) that contains code that yields a sequence of values, one at a time, so that each time you call the generator, the next value in the sequence is provided.

Generators are often built on top of coroutines or objects so that the internal state of the object is handled "naturally".

Generators are often used in situations where a sequence is potentially infinite, and where it is possible to construct the next value of the sequence with only minimal state.

;Task:
* Create a function that returns a generation of the m'th powers of the positive integers starting from zero, in order, and without obvious or simple upper limit. (Any upper limit to the generator should not be stated in the source but should be down to factors such as the languages natural integer size limit or computational time/size).
* Use it to create a generator of:
:::*   Squares.
:::*   Cubes.
* Create a new generator that filters all cubes from the generator of squares.
* Drop the first 20 values from this last generator of filtered results, and then show the next 10 values.

Note that this task ''requires'' the use of generators in the calculation of the result.

;Also see:
* Generator

Solution: In Python, any function that contains a yield statement becomes a generator. The standard libraries itertools module provides the following functions used in the solution: [http://docs.python.org/library/itertools.html#itertools.count count], that will count up from zero; and [http://docs.python.org/library/itertools.html#itertools.islice islice], which will take a slice from an iterator/generator.


Generator/Exponential

Solution:
from itertools import islice, count

def powers(m):
    for n in count():
        yield n ** m

def filtered(s1, s2):
    v, f = next(s1), next(s2)
    while True:
        if v > f:
            f = next(s2)
            continue
        elif v < f:
            yield v
        v = next(s1)

squares, cubes = powers(2), powers(3)
f = filtered(squares, cubes)
print(list(islice(f, 20, 30)))


Generator/Exponential

Solution:
'''Exponentials as generators'''

from itertools import count, islice

# powers :: Gen [Int]
def powers(n):
    '''A non-finite succession of integers,
       starting at zero,
       raised to the nth power.'''

    def f(x):
        return pow(x, n)

    return map(f, count(0))

# main :: IO ()
def main():
    '''Taking the difference between two derived generators.'''
    print(
        take(10)(
            drop(20)(
                differenceGen(powers(2))(
                    powers(3)
                )
            )
        )
    )

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

# differenceGen :: Gen [a] -> Gen [a] -> Gen [a]
def differenceGen(ga):
    '''All values of ga except any
       already seen in gb.'''
    def go(a, b):
        stream = zip(a, b)
        bs = set([])
        while True:
            xy = next(stream, None)
            if None is not xy:
                x, y = xy
                bs.add(y)
                if x not in bs:
                    yield x
            else:
                return
    return lambda gb: go(ga, gb)

# 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)

# 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))
    )

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


Get system command output

Task
Execute a system command and get its output into the program. The output may be stored in any kind of collection (array, list, etc.).

;Related task
*  Execute a system command

Solution:
>>> import subprocess
>>> returned_text = subprocess.check_output("dir", shell=True, universal_newlines=True)
>>> type(returned_text)
<class 'str'>
>>> print(returned_text)
 Volume in drive C is Windows
 Volume Serial Number is 44X7-73CE

 Directory of C:\Python33

04/07/2013  06:40    <DIR>          .
04/07/2013  06:40    <DIR>          ..
27/05/2013  07:10    <DIR>          DLLs
27/05/2013  07:10    <DIR>          Doc
27/05/2013  07:10    <DIR>          include
27/05/2013  07:10    <DIR>          Lib
27/05/2013  07:10    <DIR>          libs
16/05/2013  00:15            33,326 LICENSE.txt
15/05/2013  22:49           214,554 NEWS.txt
16/05/2013  00:03            26,624 python.exe
16/05/2013  00:03            27,136 pythonw.exe
15/05/2013  22:49             6,701 README.txt
27/05/2013  07:10    <DIR>          tcl
27/05/2013  07:10    <DIR>          Tools
16/05/2013  00:02            43,008 w9xpopen.exe
               6 File(s)        351,349 bytes
               9 Dir(s)  46,326,947,840 bytes free

>>> # Ref: https://docs.python.org/3/library/subprocess.html


Giuga numbers

Definition
A '''Giuga number''' is a composite number '''n''' which is such that each of its distinct prime factors
'''f''' divide (n/f - 1) exactly.

All known Giuga numbers are even though it is not known for certain that there are no odd examples.

;Example
30 is a Giuga number because its distinct prime factors are 2, 3 and 5 and:
* 30/2 - 1 = 14 is divisible by 2
* 30/3 - 1 = 9 is divisible by 3
* 30/5 - 1 = 5 is divisible by 5

;Task
Determine and show here the first four Giuga numbers.

;Stretch
Determine the fifth Giuga number and any more you have the patience for.

;References

* Wikipedia: Giuga number
* OEIS:A007850 - Giuga numbers

Solution:
#!/usr/bin/python

from math import sqrt

def isGiuga(m):
    n = m
    f = 2
    l = sqrt(n)
    while True:
        if n % f == 0:
            if ((m / f) - 1) % f != 0:
                return False
            n /= f
            if f > n:
                return True
        else:
            f += 1
            if f > l:
                return False

if __name__ == '__main__':
    n = 3
    c = 0
    print("The first 4 Giuga numbers are: ")
    while c < 4:
        if isGiuga(n):
            c += 1
            print(n)
        n += 1


Globally replace text in several files

Replace every occurring instance of a piece of text in a group of text files with another one.

For this task we want to replace the text   "'''Goodbye London!'''"   with   "'''Hello New York!'''"   for a list of files.

Solution:
import fileinput

for line in fileinput.input(inplace=True):
    print(line.replace('Goodbye London!', 'Hello New York!'), end='')


Graph colouring

A Graph is a collection of nodes
(or vertices), connected by edges (or not).
Nodes directly connected by edges are called neighbours.

In our representation of graphs, nodes are numbered and edges are represented
by the two node numbers connected by the edge separated by a dash.
Edges define the nodes being connected. Only unconnected nodes ''need'' a separate
description.

For example,
0-1 1-2 2-0 3
Describes the following graph. Note that node 3 has no neighbours

;Example graph:

+---+
| 3 |
+---+

  +-------------------+
  |                   |
+---+     +---+     +---+
| 0 | --- | 1 | --- | 2 |
+---+     +---+     +---+

A useful internal datastructure for a graph and for later graph algorithms is
as a mapping between each node and the set/list of its neighbours.

In the above example:
0 maps-to 1 and 2
1 maps to 2 and 0
2 maps-to 1 and 0
3 maps-to

;Graph colouring task:
Colour the vertices of a given graph so that no edge is between verticies of
the same colour.

* Integers may be used to denote different colours.
* Algorithm should do better than just assigning each vertex a separate colour. The idea is to minimise the number of colours used, although no algorithm short of exhaustive search for the minimum is known at present, (and exhaustive search is '''not''' a requirement).
* Show for each edge, the colours assigned on each vertex.
* Show the total number of nodes, edges, and colours used for each graph.

;Use the following graphs:
;Ex1:

        0-1 1-2 2-0 3

+---+
| 3 |
+---+

  +-------------------+
  |                   |
+---+     +---+     +---+
| 0 | --- | 1 | --- | 2 |
+---+     +---+     +---+

;Ex2:
The wp articles left-side graph

    1-6 1-7 1-8 2-5 2-7 2-8 3-5 3-6 3-8 4-5 4-6 4-7

  +----------------------------------+
  |                                  |
  |                      +---+       |
  |    +-----------------| 3 | ------+----+
  |    |                 +---+       |    |
  |    |                   |         |    |
  |    |                   |         |    |
  |    |                   |         |    |
  |  +---+     +---+     +---+     +---+  |
  |  | 8 | --- | 1 | --- | 6 | --- | 4 |  |
  |  +---+     +---+     +---+     +---+  |
  |    |         |                   |    |
  |    |         |                   |    |
  |    |         |                   |    |
  |    |       +---+     +---+     +---+  |
  +----+------ | 7 | --- | 2 | --- | 5 | -+
       |       +---+     +---+     +---+
       |                   |
       +-------------------+

;Ex3:
The wp articles right-side graph which is the same graph as Ex2, but with
different node orderings and namings.

    1-4 1-6 1-8 3-2 3-6 3-8 5-2 5-4 5-8 7-2 7-4 7-6

  +----------------------------------+
  |                                  |
  |                      +---+       |
  |    +-----------------| 5 | ------+----+
  |    |                 +---+       |    |
  |    |                   |         |    |
  |    |                   |         |    |
  |    |                   |         |    |
  |  +---+     +---+     +---+     +---+  |
  |  | 8 | --- | 1 | --- | 4 | --- | 7 |  |
  |  +---+     +---+     +---+     +---+  |
  |    |         |                   |    |
  |    |         |                   |    |
  |    |         |                   |    |
  |    |       +---+     +---+     +---+  |
  +----+------ | 6 | --- | 3 | --- | 2 | -+
       |       +---+     +---+     +---+
       |                   |
       +-------------------+

;Ex4:
This is the same graph, node naming, and edge order as Ex2 except some of the edges x-y are flipped to y-x.
This might alter the node order used in the greedy algorithm leading to differing numbers of colours.

    1-6 7-1 8-1 5-2 2-7 2-8 3-5 6-3 3-8 4-5 4-6 4-7

                      +-------------------------------------------------+
                      |                                                 |
                      |                                                 |
  +-------------------+---------+                                       |
  |                   |         |                                       |
+---+     +---+     +---+     +---+     +---+     +---+     +---+     +---+
| 4 | --- | 5 | --- | 2 | --- | 7 | --- | 1 | --- | 6 | --- | 3 | --- | 8 |
+---+     +---+     +---+     +---+     +---+     +---+     +---+     +---+
  |         |                             |         |         |         |
  +---------+-----------------------------+---------+         |         |
            |                             |                   |         |
            |                             |                   |         |
            +-----------------------------+-------------------+         |
                                          |                             |
                                          |                             |
                                          +-----------------------------+

;References:
* Greedy coloring Wikipedia.
* Graph Coloring : Greedy Algorithm & Welsh Powell Algorithm by  Priyank Jain.

Solution:
import re
from collections import defaultdict
from itertools import count

connection_re = r"""
    (?: (?P<N1>\d+) - (?P<N2>\d+) | (?P<N>\d+) (?!\s*-))
    """

class Graph:

    def __init__(self, name, connections):
        self.name = name
        self.connections = connections
        g = self.graph = defaultdict(list)  # maps vertex to direct connections

        matches = re.finditer(connection_re, connections,
                              re.MULTILINE | re.VERBOSE)
        for match in matches:
            n1, n2, n = match.groups()
            if n:
                g[n] += []
            else:
                g[n1].append(n2)    # Each the neighbour of the other
                g[n2].append(n1)

    def greedy_colour(self, order=None):
        "Greedy colourisation algo."
        if order is None:
            order = self.graph      # Choose something
        colour = self.colour = {}
        neighbours = self.graph
        for node in order:
            used_neighbour_colours = (colour[nbr] for nbr in neighbours[node]
                                      if nbr in colour)
            colour[node] = first_avail_int(used_neighbour_colours)
        self.pp_colours()
        return colour

    def pp_colours(self):
        print(f"\n{self.name}")
        c = self.colour
        e = canonical_edges = set()
        for n1, neighbours in sorted(self.graph.items()):
            if neighbours:
                for n2 in neighbours:
                    edge = tuple(sorted([n1, n2]))
                    if edge not in canonical_edges:
                        print(f"       {n1}-{n2}: Colour: {c[n1]}, {c[n2]}")
                        canonical_edges.add(edge)
            else:
                print(f"         {n1}: Colour: {c[n1]}")
        lc = len(set(c.values()))
        print(f"    #Nodes: {len(c)}\n    #Edges: {len(e)}\n  #Colours: {lc}")

def first_avail_int(data):
    "return lowest int 0... not in data"
    d = set(data)
    for i in count():
        if i not in d:
            return i

if __name__ == '__main__':
    for name, connections in [
            ('Ex1', "0-1 1-2 2-0 3"),
            ('Ex2', "1-6 1-7 1-8 2-5 2-7 2-8 3-5 3-6 3-8 4-5 4-6 4-7"),
            ('Ex3', "1-4 1-6 1-8 3-2 3-6 3-8 5-2 5-4 5-8 7-2 7-4 7-6"),
            ('Ex4', "1-6 7-1 8-1 5-2 2-7 2-8 3-5 6-3 3-8 4-5 4-6 4-7"),
            ]:
        g = Graph(name, connections)
        g.greedy_colour()


Gray code

Karnaugh maps in order from left to right or top to bottom.
Create functions to encode a number to and decode a number from Gray code.

Display the normal binary representations, Gray code representations, and decoded Gray code values for all 5-bit binary numbers (0-31 inclusive, leading 0's not necessary).

There are many possible Gray codes. The following encodes what is called "binary reflected Gray code."

Encoding (MSB is bit 0, b is binary, g is Gray code):

if b[i-1] = 1
   g[i] = not b[i]
else
   g[i] = b[i]

Or:

g = b xor (b logically right shifted 1 time)

Decoding (MSB is bit 0, b is binary, g is Gray code):

b[0] = g[0]

for other bits:
b[i] = g[i] xor b[i-1]

;Reference
* Converting Between Gray and Binary Codes. It includes step-by-step animations.

Solution:
def gray_encode(n):
    return n ^ n >> 1

def gray_decode(n):
    m = n >> 1
    while m:
        n ^= m
        m >>= 1
    return n

if __name__ == '__main__':
    print("DEC,   BIN =>  GRAY => DEC")
    for i in range(32):
        gray = gray_encode(i)
        dec = gray_decode(gray)
        print(f" {i:>2d}, {i:>05b} => {gray:>05b} => {dec:>2d}")


Greatest subsequential sum

Given a sequence of integers, find a continuous subsequence which maximizes the sum of its elements, that is, the elements of no other single subsequence add up to a value larger than this one.

An empty subsequence is considered to have the sum of   '''0''';   thus if all elements are negative, the result must be the empty sequence.

Solution:
f = maxsumit
assert f([]) == []
assert f([-1]) == []
assert f([0])  == []
assert f([1])       == [1]
assert f([1, 0])    == [1]
assert f([0, 1])    == [0, 1]
assert f([0, 1, 0]) == [0, 1]
assert f([2])         == [2]
assert f([2, -1])     == [2]
assert f([-1, 2])     == [2]
assert f([-1, 2, -1]) == [2]
assert f([2, -1, 3])         == [2, -1, 3]
assert f([2, -1, 3, -1])     == [2, -1, 3]
assert f([-1, 2, -1, 3])     == [2, -1, 3]
assert f([-1, 2, -1, 3, -1]) == [2, -1, 3]
assert f([-1, 1, 2, -5, -6]) == [1,2]


Greatest subsequential sum

Solution:
'''Greatest subsequential sum'''

from functools import (reduce)

# maxSubseq :: [Int] -> [Int] -> (Int, [Int])
def maxSubseq(xs):
    '''Subsequence of xs with the maximum sum'''
    def go(ab, x):
        (m1, m2) = ab[0]
        hi = max((0, []), (m1 + x, m2 + [x]))
        return (hi, max(ab[1], hi))
    return reduce(go, xs, ((0, []), (0, [])))[1]

# TEST -----------------------------------------------------------
print(
    maxSubseq(
        [-1, -2, 3, 5, 6, -2, -1, 4, -4, 2, -1]
    )
)