Esthetic numbers

An '''esthetic number''' is a positive integer where every adjacent digit differs from its neighbour by 1.

;E.G.

:* '''12''' is an esthetic number. One and two differ by 1.

:* '''5654''' is an esthetic number. Each digit is exactly 1 away from its neighbour.

:* '''890''' is '''not''' an esthetic number. Nine and zero differ by 9.

These examples are nominally in base 10 but the concept extends easily to numbers in other bases. Traditionally, single digit numbers ''are'' included in esthetic numbers; zero may or may not be. For our purposes, for this task, do not include zero (0) as an esthetic number. Do not include numbers with leading zeros.

Esthetic numbers are also sometimes referred to as stepping numbers.

;Task

:* Write a routine (function, procedure, whatever) to find esthetic numbers in a given base.

:* Use that routine to find esthetic numbers in bases '''2''' through '''16''' and display, here on this page, the esthectic numbers from index '''(base x 4)''' through index '''(base x 6)''', inclusive. (E.G. for base 2: 8th through 12th, for base 6: 24th through 36th, etc.)

:* Find and display, here on this page, the '''base 10''' esthetic numbers with a magnitude between '''1000''' and '''9999'''.

:* Stretch: Find and display, here on this page, the '''base 10''' esthetic numbers with a magnitude between '''1.0e8''' and '''1.3e8'''.

;Related task:
*   numbers with equal rises and falls

;See also:
:;*OEIS A033075 - Positive numbers n such that all pairs of consecutive decimal digits differ by 1
:;*Numbers Aplenty - Esthetic numbers
:;*Geeks for Geeks - Stepping numbers

Solution:
from collections import deque
from itertools import dropwhile, islice, takewhile
from textwrap import wrap
from typing import Iterable, Iterator

Digits = str  # Alias for the return type of to_digits()

def esthetic_nums(base: int) -> Iterator[int]:
    """Generate the esthetic number sequence for a given base

    >>> list(islice(esthetic_nums(base=10), 20))
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 21, 23, 32, 34, 43, 45, 54, 56, 65]
    """
    queue: deque[tuple[int, int]] = deque()
    queue.extendleft((d, d) for d in range(1, base))
    while True:
        num, lsd = queue.pop()
        yield num
        new_lsds = (d for d in (lsd - 1, lsd + 1) if 0 <= d < base)
        num *= base  # Shift num left one digit
        queue.extendleft((num + d, d) for d in new_lsds)

def to_digits(num: int, base: int) -> Digits:
    """Return a representation of an integer as digits in a given base

    >>> to_digits(0x3def84f0ce, base=16)
    '3def84f0ce'
    """
    digits: list[str] = []
    while num:
        num, d = divmod(num, base)
        digits.append("0123456789abcdef"[d])
    return "".join(reversed(digits)) if digits else "0"

def pprint_it(it: Iterable[str], indent: int = 4, width: int = 80) -> None:
    """Pretty print an iterable which returns strings

    >>> pprint_it(map(str, range(20)), indent=0, width=40)
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
    12, 13, 14, 15, 16, 17, 18, 19
    <BLANKLINE>
    """
    joined = ", ".join(it)
    lines = wrap(joined, width=width - indent)
    for line in lines:
        print(f"{indent*' '}{line}")
    print()

def task_2() -> None:
    nums: Iterator[int]
    for base in range(2, 16 + 1):
        start, stop = 4 * base, 6 * base
        nums = esthetic_nums(base)
        nums = islice(nums, start - 1, stop)  # start and stop are 1-based indices
        print(
            f"Base-{base} esthetic numbers from "
            f"index {start} through index {stop} inclusive:\n"
        )
        pprint_it(to_digits(num, base) for num in nums)

def task_3(lower: int, upper: int, base: int = 10) -> None:
    nums: Iterator[int] = esthetic_nums(base)
    nums = dropwhile(lambda num: num < lower, nums)
    nums = takewhile(lambda num: num <= upper, nums)
    print(
        f"Base-{base} esthetic numbers with "
        f"magnitude between {lower:,} and {upper:,}:\n"
    )
    pprint_it(to_digits(num, base) for num in nums)

if __name__ == "__main__":
    print("======\nTask 2\n======\n")
    task_2()

    print("======\nTask 3\n======\n")
    task_3(1_000, 9_999)

    print("======\nTask 4\n======\n")
    task_3(100_000_000, 130_000_000)


Esthetic numbers

Solution:
'''Esthetic numbers'''

from functools import reduce
from itertools import (
    accumulate, chain, count, dropwhile,
    islice, product, takewhile
)
from operator import add
from string import digits, ascii_lowercase
from textwrap import wrap

# estheticNumbersInBase :: Int -> [Int]
def estheticNumbersInBase(b):
    '''Infinite stream of numbers which are
       esthetic in a given base.
    '''
    return concatMap(
        compose(
            lambda deltas: concatMap(
                lambda headDigit: concatMap(
                    compose(
                        fromBaseDigits(b),
                        scanl(add)(headDigit)
                    )
                )(deltas)
            )(range(1, b)),
            replicateList([-1, 1])
        )
    )(count(0))

# ------------------------ TESTS -------------------------
def main():
    '''Specified tests'''
    def samples(b):
        i, j = b * 4, b * 6
        return '\n'.join([
            f'Esthetics [{i}..{j}] for base {b}:',
            unlines(wrap(
                unwords([
                    showInBase(b)(n) for n in compose(
                        drop(i - 1), take(j)
                    )(
                        estheticNumbersInBase(b)
                    )
                ]), 60
            ))
        ])

    def takeInRange(a, b):
        return compose(
            dropWhile(lambda x: x < a),
            takeWhile(lambda x: x <= b)
        )

    print(
        '\n\n'.join([
            samples(b) for b in range(2, 1 + 16)
        ])
    )
    for (lo, hi) in [(1000, 9999), (100_000_000, 130_000_000)]:
        print(f'\nBase 10 Esthetics in range [{lo}..{hi}]:')
        print(
            unlines(wrap(
                unwords(
                    str(x) for x in takeInRange(lo, hi)(
                        estheticNumbersInBase(10)
                    )
                ), 60
            ))
        )

# ------------------- BASES AND DIGITS -------------------

# fromBaseDigits :: Int -> [Int] -> [Int]
def fromBaseDigits(b):
    '''An empty list if any digits are out of range for
       the base. Otherwise a list containing an integer.
    '''
    def go(digitList):
        maybeNum = reduce(
            lambda r, d: None if r is None or (
                0 > d or d >= b
            ) else r * b + d,
            digitList, 0
        )
        return [] if None is maybeNum else [maybeNum]
    return go

# toBaseDigits :: Int -> Int -> [Int]
def toBaseDigits(b):
    '''A list of the digits of n in base b.
    '''
    def f(x):
        return None if 0 == x else (
            divmod(x, b)[::-1]
        )
    return lambda n: list(reversed(unfoldr(f)(n)))

# showInBase :: Int -> Int -> String
def showInBase(b):
    '''String representation of n in base b.
    '''
    charSet = digits + ascii_lowercase
    return lambda n: ''.join([
        charSet[i] for i in toBaseDigits(b)(n)
    ])

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

# compose :: ((a -> a), ...) -> (a -> a)
def compose(*fs):
    '''Composition, from right to left,
       of a series of functions.
    '''
    def go(f, g):
        def fg(x):
            return f(g(x))
        return fg
    return reduce(go, fs, lambda x: 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

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

# dropWhile :: (a -> Bool) -> [a] -> [a]
# dropWhile :: (Char -> Bool) -> String -> String
def dropWhile(p):
    '''The suffix remainining after takeWhile p xs.
    '''
    return lambda xs: list(
        dropwhile(p, xs)
    )

# replicateList :: [a] -> Int -> [[a]]
def replicateList(xs):
    '''All distinct lists of length n that
       consist of elements drawn from xs.
    '''
    def rep(n):
        def go(x):
            return [[]] if 1 > x else [
                ([a] + b) for (a, b) in product(
                    xs, go(x - 1)
                )
            ]
        return go(n)
    return rep

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

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

# takeWhile :: (a -> Bool) -> [a] -> [a]
# takeWhile :: (Char -> Bool) -> String -> String
def takeWhile(p):
    '''The longest (possibly empty) prefix of xs
       in which all elements satisfy p.
    '''
    return lambda xs: list(
        takewhile(p, xs)
    )

# unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
def unfoldr(f):
    '''Dual to reduce or foldr.
       Where catamorphism reduces a list to a summary value,
       the anamorphic unfoldr builds a list from a seed value.
       As long as f returns (a, b) a is prepended to the list,
       and the residual b is used as the argument for the next
       application of f.
       When f returns None, the completed list is returned.
    '''
    def go(v):
        xr = v, v
        xs = []
        while True:
            xr = f(xr[1])
            if None is not xr:
                xs.append(xr[0])
            else:
                return xs
    return go

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

# unwords :: [String] -> String
def unwords(xs):
    '''A space-separated string derived
       from a list of words.
    '''
    return ' '.join(xs)

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


Euclid-Mullin sequence

Definition
The Euclid-Mullin sequence is an infinite sequence of distinct prime numbers, in which each element is the least prime factor of one plus the product of all earlier elements.

The first element is usually assumed to be 2. So the second element is : (2) + 1 = 3 and the third element is : (2 x 3) + 1 = 7 as this is prime.

Although intermingled with smaller elements, the sequence can produce very large elements quite quickly and only the first 51 have been computed at the time of writing.

;Task
Compute and show here the first '''16''' elements of the sequence or, if your language does not support arbitrary precision arithmetic, as many as you can.

;Stretch goal
Compute the next '''11''' elements of the sequence.

;Reference
OEIS sequence A000945

Solution:
""" Rosetta code task: Euclid-Mullin_sequence """

from primePy import primes

def euclid_mullin():
    """ generate Euclid-Mullin sequence """
    total = 1
    while True:
        next_iter = primes.factor(total + 1)
        total *= next_iter
        yield next_iter

GEN = euclid_mullin()
print('First 16 Euclid-Mullin numbers:', ', '.join(str(next(GEN)) for _ in range(16)))


Euler's identity

{{Wikipedia|Euler's_identity}}

In mathematics, ''Euler's identity'' is the equality:

                ei\pi + 1 = 0

where

    e is Euler's number, the base of natural logarithms,
    ''i'' is the imaginary unit, which satisfies ''i''2 = -1, and
    \pi is pi, the ratio of the circumference of a circle to its diameter.

Euler's identity is often cited as an example of deep mathematical beauty. Three of the basic arithmetic operations occur exactly once each: addition, multiplication, and exponentiation. The identity also links five fundamental mathematical constants:

    The number 0.
    The number 1.
    The number \pi (\pi = 3.14159+),
    The number e (e = 2.71828+), which occurs widely in mathematical analysis.
    The number ''i'', the imaginary unit of the complex numbers.

;Task
Show in your language that Euler's identity is true. As much as possible and practical, mimic the Euler's identity equation.

Most languages are limited to IEEE 754 floating point calculations so will have some error in the calculation.

If that is the case, or there is some other limitation, show
that ei\pi + 1 is ''approximately'' equal to zero and
show the amount of error in the calculation.

If your language is capable of symbolic calculations, show
that ei\pi + 1 is ''exactly'' equal to zero for bonus kudos points.

Solution:
>>> import math
>>> math.e ** (math.pi * 1j) + 1
1.2246467991473532e-16j


Euler's sum of powers conjecture

There is a conjecture in mathematics that held for over two hundred years before it was disproved by the finding of a counterexample in 1966 by Lander and Parkin.

This conjecture is called Euler's sum of powers conjecture and can be stated as such:

:At least k positive kth powers are required to sum to a kth power, except for the trivial case of one kth power: yk = yk.

In 1966, Leon J. Lander and Thomas R. Parkin used a brute-force search on a CDC 6600 computer restricting numbers to those less than 250.

The task consists in writing a program to search for an integer solution of x_0^5 + x_1^5 + x_2^5 + x_3^5 = y^5 where all x_i and y are distinct integers between 0 and 250 (exclusive). Show an answer here.

Related tasks are:
* [[Pythagorean quadruples]].
* [[Pythagorean triples]].

Solution:
def eulers_sum_of_powers():
    max_n = 250
    pow_5 = [n**5 for n in range(max_n)]
    pow5_to_n = {n**5: n for n in range(max_n)}
    for x0 in range(1, max_n):
        for x1 in range(1, x0):
            for x2 in range(1, x1):
                for x3 in range(1, x2):
                    pow_5_sum = sum(pow_5[i] for i in (x0, x1, x2, x3))
                    if pow_5_sum in pow5_to_n:
                        y = pow5_to_n[pow_5_sum]
                        return (x0, x1, x2, x3, y)

print("%i**5 + %i**5 + %i**5 + %i**5 == %i**5" % eulers_sum_of_powers())


Euler's sum of powers conjecture

Solution:
from itertools import combinations

def eulers_sum_of_powers():
    max_n = 250
    pow_5 = [n**5 for n in range(max_n)]
    pow5_to_n = {n**5: n for n in range(max_n)}
    for x0, x1, x2, x3 in combinations(range(1, max_n), 4):
        pow_5_sum = sum(pow_5[i] for i in (x0, x1, x2, x3))
        if pow_5_sum in pow5_to_n:
            y = pow5_to_n[pow_5_sum]
            return (x0, x1, x2, x3, y)

print("%i**5 + %i**5 + %i**5 + %i**5 == %i**5" % eulers_sum_of_powers())


Euler's sum of powers conjecture

Solution:
'''Euler's sum of powers conjecture'''

from itertools import (chain, takewhile)

# main :: IO ()
def main():
    '''Search for counter-example'''

    xs = enumFromTo(1)(249)

    powerMap = {x**5: x for x in xs}
    sumMap = {
        x**5 + y**5: (x, y)
        for x in xs[1:]
        for y in xs if x > y
    }

    # isExample :: (Int, Int) -> Bool
    def isExample(ps):
        p, s = ps
        return p - s in sumMap

    # display :: (Int, Int) -> String
    def display(ps):
        p, s = ps
        a, b = sumMap[p - s]
        c, d = sumMap[s]
        return '^5 + '.join([str(n) for n in [a, b, c, d]]) + (
            '^5 = ' + str(powerMap[p]) + '^5'
        )

    print(__doc__ + ' – counter-example:\n')
    print(
        maybe('No counter-example found.')(display)(
            find(isExample)(
                bind(powerMap.keys())(
                    lambda p: bind(
                        takewhile(
                            lambda x: p > x,
                            sumMap.keys()
                        )
                    )(lambda s: [(p, s)])
                )
            )
        )
    )

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

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

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

# bind (>>=) :: [a] -> (a -> [b]) -> [b]
def bind(xs):
    '''List monad injection operator.
       Two computations sequentially composed,
       with any value produced by the first
       passed as an argument to the second.
    '''
    def go(f):
        return chain.from_iterable(map(f, xs))
    return go

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

# find :: (a -> Bool) -> [a] -> Maybe a
def find(p):
    '''Just the first element in the list that matches p,
       or Nothing if no elements match.
    '''
    def go(xs):
        try:
            return Just(next(x for x in xs if p(x)))
        except StopIteration:
            return Nothing()
    return go

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

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


Even or odd

Test whether an integer is even or odd.

There is more than one way to solve this task:

* Use the even and odd predicates, if the language provides them.
* Check the least significant digit. With binary integers, ''i iff ''i'' is even, or equals 1 iff ''i'' is odd.
* Divide ''i'' by 2. The remainder equals 0 iff ''i'' is even. The remainder equals +1 or -1 iff ''i'' is odd.
* Use modular congruences:
** ''i''  0 (mod 2) iff ''i'' is even.
** ''i''  1 (mod 2) iff ''i'' is odd.

Solution:
>>> def is_odd(i): return bool(i & 1)

>>> def is_even(i): return not is_odd(i)

>>> [(j, is_odd(j)) for j in range(10)]
[(0, False), (1, True), (2, False), (3, True), (4, False), (5, True), (6, False), (7, True), (8, False), (9, True)]
>>> [(j, is_even(j)) for j in range(10)]
[(0, True), (1, False), (2, True), (3, False), (4, True), (5, False), (6, True), (7, False), (8, True), (9, False)]
>>>


Evolutionary algorithm

Starting with:
* The target string: "METHINKS IT IS LIKE A WEASEL".
* An array of random characters chosen from the set of upper-case letters together with the space, and of the same length as the target string. (Call it the parent).
* A fitness function that computes the 'closeness' of its argument to the target string.
* A mutate function that given a string and a mutation rate returns a copy of the string, with some characters probably mutated.
* While the parent is not yet the target:
:* copy the parent C times, each time allowing some random probability that another character might be substituted using mutate.
:* Assess the fitness of the parent and all the copies to the target and make the most fit string the new parent, discarding the others.
:* repeat until the parent converges, (hopefully), to the target.

;See also:
*   Wikipedia entry:   Weasel algorithm.
*   Wikipedia entry:   Evolutionary algorithm.

Note: to aid comparison, try and ensure the variables and functions mentioned in the task description appear in solutions

A cursory examination of a few of the solutions reveals that the instructions have not been followed rigorously in some solutions. Specifically,
* While the parent is not yet the target:
:* copy the parent C times, each time allowing some random probability that another character might be substituted using mutate.

Note that some of the the solutions given retain characters in the mutated string that are ''correct'' in the target string. However, the instruction above does not state to retain any of the characters while performing the mutation. Although some may believe to do so is implied from the use of "converges"

 (:* repeat until the parent converges, (hopefully), to the target.

Strictly speaking, the new parent should be selected from the new pool of mutations, and then the new parent used to generate the next set of mutations with parent characters getting retained only by ''not'' being mutated. It then becomes possible that the new set of mutations has no member that is fitter than the parent!

As illustration of this error, the code for 8th has the following remark.

 Create a new string based on the TOS, '''changing randomly any characters which
 don't already match the target''':

''NOTE:'' this has been changed, the 8th version is completely random now

Clearly, this algo will be applying the mutation function only to the parent characters that don't match to the target characters!

To ensure that the new parent is never less fit than the prior parent, both the parent and all of the latest mutations are subjected to the fitness test to select the next parent.

Solution:
from string import letters
from random import choice, random

target  = list("METHINKS IT IS LIKE A WEASEL")
charset = letters + ' '
parent  = [choice(charset) for _ in range(len(target))]
minmutaterate  = .09
C = range(100)

perfectfitness = float(len(target))

def fitness(trial):
    'Sum of matching chars by position'
    return sum(t==h for t,h in zip(trial, target))

def mutaterate():
    'Less mutation the closer the fit of the parent'
    return 1-((perfectfitness - fitness(parent)) / perfectfitness * (1 - minmutaterate))

def mutate(parent, rate):
    return [(ch if random() <= rate else choice(charset)) for ch in parent]

def que():
    '(from the favourite saying of Manuel in Fawlty Towers)'
    print ("#%-4i, fitness: %4.1f%%, '%s'" %
           (iterations, fitness(parent)*100./perfectfitness, ''.join(parent)))

def mate(a, b):
    place = 0
    if choice(xrange(10)) < 7:
        place = choice(xrange(len(target)))
    else:
        return a, b

    return a, b, a[:place] + b[place:], b[:place] + a[place:]

iterations = 0
center = len(C)/2
while parent != target:
    rate = mutaterate()
    iterations += 1
    if iterations % 100 == 0: que()
    copies = [ mutate(parent, rate) for _ in C ]  + [parent]
    parent1 = max(copies[:center], key=fitness)
    parent2 = max(copies[center:], key=fitness)
    parent = max(mate(parent1, parent2), key=fitness)
que()


Executable library

The general idea behind an executable library is to create a library
that when used as a library does one thing;
but has the ability to be run directly via command line.
Thus the API comes with a CLI in the very same source code file.

'''Task detail'''

* Create a library/module/dll/shared object/... for a programming language that contains a function/method called hailstone that is a function taking a positive integer and returns the [[Hailstone sequence]] for that number.

* The library, when executed directly should satisfy the remaining requirements of the [[Hailstone sequence]] task:
:: 2.  Use the routine to show that the hailstone sequence for the number 27 has 112 elements starting with 27, 82, 41, 124 and ending with 8, 4, 2, 1
:: 3.  Show the number less than 100,000 which has the longest hailstone sequence together with that sequence's length.

* Create a second executable to calculate the following:
** Use the library's hailstone function, in the standard manner, (or document how this use deviates from standard use of a library), together with extra code in this executable, to find the hailstone length returned most often for 1 <= n < 100,000.

* Explain any extra setup/run steps needed to complete the task.

'''Notes:'''
* It is assumed that for a language that overwhelmingly ships in a compiled form, such as C, the library must also be an executable and the compiled user of that library is to do so without changing the compiled library. I.e. the compile tool-chain is assumed ''not'' to be present in the runtime environment.
* Interpreters are present in the runtime environment.

Solution:
from collections import Counter

def function_length_frequency(func, hrange):
    return Counter(len(func(n)) for n in hrange).most_common()

if __name__ == '__main__':
    from executable_hailstone_library import hailstone

    upto = 100000
    hlen, freq = function_length_frequency(hailstone, range(1, upto))[0]
    print("The length of hailstone sequence that is most common for\n"
          "hailstone(n) where 1<=n<%i, is %i. It occurs %i times."
          % (upto, hlen, freq))


Execute Computer/Zero

Computer/zero Assembly}}

;Task:
Create a [[Computer/zero Assembly emulator. You may consider this webpage as a reference implementation. Output the results of the sample programs "2+2" and "7*8" found there.

:*   The virtual machine "bytecode" needs to be able to modify itself (or at least act as though it can) while the virtual machine is running, to be consistent with the reference implementation.
:*   For output, it is sufficient to have the implementation of the STP opcode return the accumulator to your actual language, and then use your standard printing routines to output it.

;Bonus Points: Run all 5 sample programs at the aforementioned website and output their results.

Solution:
"""Computer/zero Assembly emulator. Requires Python >= 3.7"""

import re

from typing import Dict
from typing import Iterable
from typing import List
from typing import NamedTuple
from typing import Optional
from typing import Tuple

NOP = 0b000
LDA = 0b001
STA = 0b010
ADD = 0b011
SUB = 0b100
BRZ = 0b101
JMP = 0b110
STP = 0b111

OPCODES = {
    "NOP": NOP,
    "LDA": LDA,
    "STA": STA,
    "ADD": ADD,
    "SUB": SUB,
    "BRZ": BRZ,
    "JMP": JMP,
    "STP": STP,
}

RE_INSTRUCTION = re.compile(
    r"\s*"
    r"(?:(?P<label>\w+):)?"
    r"\s*"
    rf"(?P<opcode>{'|'.join(OPCODES)})?"
    r"\s*"
    r"(?P<argument>\w+)?"
    r"\s*"
    r"(?:;(?P<comment>[\w\s]+))?"
)

class AssemblySyntaxError(Exception):
    pass

class Instruction(NamedTuple):
    label: Optional[str]
    opcode: Optional[str]
    argument: Optional[str]
    comment: Optional[str]

def parse(assembly: str) -> Tuple[List[Instruction], Dict[str, int]]:
    instructions: List[Instruction] = []
    labels: Dict[str, int] = {}
    linenum: int = 0

    for line in assembly.split("\n"):
        match = RE_INSTRUCTION.match(line)

        if not match:
            raise AssemblySyntaxError(f"{line}: {linenum}")

        instructions.append(Instruction(**match.groupdict()))
        label = match.group(1)
        if label:
            labels[label] = linenum

        linenum += 1

    return instructions, labels

def compile(instructions: List[Instruction], labels: Dict[str, int]) -> Iterable[int]:
    for instruction in instructions:
        if instruction.argument is None:
            argument = 0
        elif instruction.argument.isnumeric():
            argument = int(instruction.argument)
        else:
            argument = labels[instruction.argument]

        if instruction.opcode:
            yield OPCODES[instruction.opcode] << 5 | argument
        else:
            yield argument

def run(bytecode: bytes) -> int:
    accumulator = 0
    program_counter = 0
    memory = list(bytecode)[:32] + [0 for _ in range(32 - len(bytecode))]

    while program_counter < 32:
        operation = memory[program_counter] >> 5
        argument = memory[program_counter] & 0b11111
        program_counter += 1

        if operation == NOP:
            continue
        elif operation == LDA:
            accumulator = memory[argument]
        elif operation == STA:
            memory[argument] = accumulator
        elif operation == ADD:
            accumulator = (accumulator + memory[argument]) % 256
        elif operation == SUB:
            accumulator = (accumulator - memory[argument]) % 256
        elif operation == BRZ:
            if accumulator == 0:
                program_counter = argument
        elif operation == JMP:
            program_counter = argument
        elif operation == STP:
            break
        else:
            raise Exception(f"error: {operation} {argument}")

    return accumulator

SAMPLES = [
    """\
            LDA   x
            ADD   y       ; accumulator = x + y
            STP
    x:            2
    y:            2
    """,
    """\
    loop:   LDA   prodt
            ADD   x
            STA   prodt
            LDA   y
            SUB   one
            STA   y
            BRZ   done
            JMP   loop
    done:   LDA   prodt   ; to display it
            STP
    x:            8
    y:            7
    prodt:        0
    one:          1
    """,
    """\
    loop:   LDA   n
            STA   temp
            ADD   m
            STA   n
            LDA   temp
            STA   m
            LDA   count
            SUB   one
            BRZ   done
            STA   count
            JMP   loop
    done:   LDA   n       ; to display it
            STP
    m:            1
    n:            1
    temp:         0
    count:        8       ; valid range: 1-11
    one:          1
    """,
    """\
    start:  LDA   load
            ADD   car     ; head of list
            STA   ldcar
            ADD   one
            STA   ldcdr   ; next CONS cell
    ldcar:  NOP
            STA   value
    ldcdr:  NOP
            BRZ   done    ; 0 stands for NIL
            STA   car
            JMP   start
    done:   LDA   value   ; CAR of last CONS
            STP
    load:   LDA   0
    value:        0
    car:          28
    one:          1
                        ; order of CONS cells
                        ; in memory
                        ; does not matter
                6
                0       ; 0 stands for NIL
                2       ; (CADR ls)
                26      ; (CDDR ls) -- etc.
                5
                20
                3
                30
                1       ; value of (CAR ls)
                22      ; points to (CDR ls)
                4
                24
    """,
    """\
    p:            0       ; NOP in first round
    c:            0
    start:  STP           ; wait for p's move
    pmove:  NOP
            LDA   pmove
            SUB   cmove
            BRZ   same
            LDA   pmove
            STA   cmove   ; tit for tat
            BRZ   cdeft
            LDA   c       ; p defected, c did not
            ADD   three
            STA   c
            JMP   start
    cdeft:  LDA   p
            ADD   three
            STA   p
            JMP   start
    same:   LDA   pmove
            STA   cmove   ; tit for tat
            LDA   p
            ADD   one
            ADD   pmove
            STA   p
            LDA   c
            ADD   one
            ADD   pmove
            STA   c
            JMP   start
    cmove:        0       ; co-operate initially
    one:          1
    three:        3
    """,
    """\
    LDA  3
    SUB  4
    STP  0
         0
         255
    """,
    """\
    LDA  3
    SUB  4
    STP  0
         0
         1
    """,
    """\
    LDA  3
    ADD  4
    STP  0
         1
         255
    """,
]

def main() -> None:
    for sample in SAMPLES:
        instructions, labels = parse(sample)
        bytecode = bytes(compile(instructions, labels))
        result = run(bytecode)
        print(result)

if __name__ == "__main__":
    main()


Execute SNUSP

SNUSP}}'''RCSNUSP''' is a set of [[SNUSP compilers and interpreters written for Rosetta Code in a variety of languages. Below are links to each of the versions of RCSNUSP.

An implementation need only properly implement the Core SNUSP instructions ('$', '\', '/', '+', '-', '<', '>', ',', '.', '!', and '?'). Modular SNUSP ('#', '@') and Bloated SNUSP (':', ';', '%', and '&') are also allowed, but not required. Any extra characters that you implement should be noted in the description of your implementation. Any cell size is allowed, EOF support is optional, as is whether you have bounded or unbounded memory.

Solution:
#!/usr/bin/env python3

HW = r'''
/++++!/===========?\>++.>+.+++++++..+++\
\+++\ | /+>+++++++>/ /++++++++++<<.++>./
$+++/ | \+++++++++>\ \+++++.>.+++.-----\
      \==-<<<<+>+++/ /=.>.+>.--------.-/'''

def snusp(store, code):
    ds = bytearray(store)  # data store
    dp = 0                 # data pointer
    cs = code.splitlines() # 2 dimensional code store
    ipr, ipc = 0, 0        # instruction pointers in row and column
    for r, row in enumerate(cs):
        try:
            ipc = row.index('$')
            ipr = r
            break
        except ValueError:
            pass
    rt, dn, lt, up = range(4)
    id = rt  # instruction direction.  starting direction is always rt
    def step():
        nonlocal ipr, ipc
        if id&1:
            ipr += 1 - (id&2)
        else:
            ipc += 1 - (id&2)
    while ipr >= 0 and ipr < len(cs) and ipc >= 0 and ipc < len(cs[ipr]):
        op = cs[ipr][ipc]
        if op == '>':
            dp += 1
        elif op == '<':
            dp -= 1
        elif op == '+':
            ds[dp] += 1
        elif op == '-':
            ds[dp] -= 1
        elif op == '.':
            print(chr(ds[dp]), end='')
        elif op == ',':
            ds[dp] = input()
        elif op == '/':
            id = ~id
        elif op == '\\':
            id ^= 1
        elif op == '!':
            step()
        elif op == '?':
            if not ds[dp]:
                step()
        step()

if __name__ == '__main__':
    snusp(5, HW)


Exponentiation order

This task will demonstrate the order of exponentiation   ('''xy''')    when there are multiple exponents.

(Many programming languages,   especially those with extended-precision integer arithmetic,   usually support one of  **, ^, |  or some such for exponentiation.)

;Task requirements
Show the result of a language's evaluation of multiple exponentiation (either as an integer or floating point).

If your language's exponentiation operator is not one of the usual ones, please comment on how to recognize it.

Using whatever operator or syntax your language supports (if any), show the results in three lines (with identification):

::::*   5**3**2
::::*   (5**3)**2
::::*   5**(3**2)

If there are other methods (or formats) of multiple exponentiations, show them as well.

;See also:
* MathWorld entry:   exponentiation

;Related tasks:
*   exponentiation operator
*   arbitrary-precision integers (included)
*   [[Exponentiation with infix operators in (or operating on) the base]]

Solution:
>>> 5**3**2
1953125
>>> (5**3)**2
15625
>>> 5**(3**2)
1953125
>>> # The following is not normally done
>>> try: from functools import reduce # Py3K
except: pass

>>> reduce(pow, (5, 3, 2))
15625
>>>


Exponentiation with infix operators in (or operating on) the base

(Many programming languages,   especially those with extended-precision integer arithmetic,   usually
support one of  **, ^, |  or some such for exponentiation.)

Some languages treat/honor infix operators when performing exponentiation   (raising
numbers to some power by the language's exponentiation operator,   if the computer
programming language has one).

Other programming languages may make use of the   '''POW'''   or some other BIF
  ('''B'''uilt-'''I'''n '''F'''function),   or some other library service.

If your language's exponentiation operator is not one of the usual ones, please comment on how to recognize it.

This task will deal with the case where there is some form of an   ''infix operator''   operating
in   (or operating on)   the base.

;Example:
A negative five raised to the 3rd power could be specified as:
    -5  ** 3          or as
   -(5) ** 3          or as
   (-5) ** 3          or as something else

(Not all computer programming languages have an exponential operator and/or support these syntax expression(s).

;Task:
:*   compute and display exponentiation with a possible infix operator, whether specified and/or implied/inferred.
:*   Raise the following numbers   (integer or real):
:::*   -5     and
:::*   +5
:*   to the following powers:
:::*   2nd     and
:::*   3rd
:*   using the following expressions   (if applicable in your language):
:::*   -x**p
:::*   -(x)**p
:::*   (-x)**p
:::*   -(x**p)
:*   Show here (on this page) the four (or more) types of symbolic expressions for each number and power.

Try to present the results in the same format/manner as the other programming entries to make any differences apparent.

The variables may be of any type(s) that is/are applicable in your language.

;Related tasks:
*   [[Exponentiation order]]
*   [[Exponentiation operator]]
*   [[Arbitrary-precision integers (included)]]
*   [[Parsing/RPN to infix conversion]]
*   [[Operator precedence]]

;References:
* Wikipedia: Order of operations in Programming languages

Solution:
from itertools import product

xx = '-5 +5'.split()
pp = '2 3'.split()
texts = '-x**p -(x)**p (-x)**p -(x**p)'.split()

print('Integer variable exponentiation')
for x, p in product(xx, pp):
    print(f'  x,p = {x:2},{p}; ', end=' ')
    x, p = int(x), int(p)
    print('; '.join(f"{t} =={eval(t):4}" for t in texts))

print('\nBonus integer literal exponentiation')
X, P = 'xp'
xx.insert(0, ' 5')
texts.insert(0, 'x**p')
for x, p in product(xx, pp):
    texts2 = [t.replace(X, x).replace(P, p) for t in texts]
    print(' ', '; '.join(f"{t2} =={eval(t2):4}" for t2 in texts2))


Extend your language

{{Control Structures}}Some programming languages allow you to extend the language. While this can be done to a certain degree in most languages (e.g. by using macros), other languages go much further. Most notably in the Forth and Lisp families, programming per se is done by extending the language without any formal distinction between built-in and user-defined elements.

If your language supports it, show how to introduce a new flow control mechanism. A practical and useful example is a four-way branch:

Occasionally, code must be written that depends on ''two'' conditions, resulting in up to four branches (depending on whether both, only the first, only the second, or none of the conditions are "true"). In a C-like language this could look like the following:

   if (condition1isTrue) {
      if (condition2isTrue)
         bothConditionsAreTrue();
      else
         firstConditionIsTrue();
   }
   else if (condition2isTrue)
      secondConditionIsTrue();
   else
      noConditionIsTrue();

Besides being rather cluttered, the statement(s) for 'condition2isTrue' must be written down twice. If 'condition2isTrue' were a lengthy and involved expression, it would be quite unreadable, and the code generated by the compiler might be unnecessarily large.

This can be improved by introducing a new keyword '''if2'''. It is similar to '''if''', but takes two conditional statements instead of one, and up to three 'else' statements. One proposal (in pseudo-C syntax) might be:

   if2 (condition1isTrue) (condition2isTrue)
      bothConditionsAreTrue();
   else1
      firstConditionIsTrue();
   else2
      secondConditionIsTrue();
   else
      noConditionIsTrue();

Pick the syntax which suits your language. The keywords 'else1' and 'else2' are just examples. The new conditional expression should look, nest and behave analogously to the language's built-in 'if' statement.

Solution:
a, b = 1, 0

if (c1 := a == 1) and (c2 := b == 3):
  print('a = 1 and b = 3')
elif c1:
  print('a = 1 and b <> 3')
elif c2:
  print('a <> 1 and b = 3')
else:
  print('a <> 1 and b <> 3')


Extreme floating point values

The IEEE floating point specification defines certain 'extreme' floating point values such as minus zero, -0.0, a value distinct from plus zero; not a number, NaN; and plus and minus infinity.

The task is to use expressions involving other 'normal' floating point values in your language to calculate these, (and maybe other), extreme floating point values in your language and assign them to variables.

Print the values of these variables if possible; and show some arithmetic with these values and variables.

If your language can directly enter these extreme floating point values then show it.

;See also:
*   What Every Computer Scientist Should Know About Floating-Point Arithmetic

;Related tasks:
*   [[Infinity]]
*   [[Detect division by zero]]
*   [[Literals/Floating point]]

Solution:
>>> # Extreme values from expressions
>>> inf = 1e234 * 1e234
>>> _inf = 1e234 * -1e234
>>> _zero = 1 / _inf
>>> nan = inf + _inf
>>> inf, _inf, _zero, nan
(inf, -inf, -0.0, nan)
>>> # Print
>>> for value in (inf, _inf, _zero, nan): print (value)

inf
-inf
-0.0
nan
>>> # Extreme values from other means
>>> float('nan')
nan
>>> float('inf')
inf
>>> float('-inf')
-inf
>>> -0.
-0.0
>>> # Some arithmetic
>>> nan == nan
False
>>> nan is nan
True
>>> 0. == -0.
True
>>> 0. is -0.
False
>>> inf + _inf
nan
>>> 0.0 * nan
nan
>>> nan * 0.0
nan
>>> 0.0 * inf
nan
>>> inf * 0.0
nan


FASTA format

In FASTA.

A FASTA file can contain several strings, each identified by a name marked by a > (greater than) character at the beginning of the line.

;Task:
Write a program that reads a FASTA file such as:

>Rosetta_Example_1
THERECANBENOSPACE
>Rosetta_Example_2
THERECANBESEVERAL
LINESBUTTHEYALLMUST
BECONCATENATED

Solution:
import io

FASTA='''\
>Rosetta_Example_1
THERECANBENOSPACE
>Rosetta_Example_2
THERECANBESEVERAL
LINESBUTTHEYALLMUST
BECONCATENATED'''

infile = io.StringIO(FASTA)

def fasta_parse(infile):
    key = ''
    for line in infile:
        if line.startswith('>'):
            if key:
                yield key, val
            key, val = line[1:].rstrip().split()[0], ''
        elif key:
            val += line.rstrip()
    if key:
        yield key, val

print('\n'.join('%s: %s' % keyval for keyval in fasta_parse(infile)))


Faces from a mesh

A mesh defining a surface has uniquely numbered vertices, and named,
simple-polygonal faces described usually by an ordered list of edge numbers
going around the face,

For example:
External image of two faces
Rough textual version without edges:

      1
                        17
 7   A
             B

       11
                  23

* A is the triangle (1, 11, 7), or equally (7, 11, 1), going anti-clockwise, or
any of all the rotations of those ordered vertices.
      1

 7   A

       11

* B is the four-sided face (1, 17, 23, 11), or equally (23, 17, 1, 11) or any
of their rotations.
1
                  17

       B

 11
            23

Let's call the above the '''perimeter format''' as it traces around the perimeter.

;A second format:
A separate algorithm returns polygonal faces consisting of a face name and an unordered
set of edge definitions for each face.
* A single edge is described by the vertex numbers at its two ends, always in
ascending order.
* All edges for the face are given, but in an undefined order.

For example face A could be described by the edges (1, 11), (7, 11), and (1, 7)
(The  order of each vertex number in an edge is ascending, but the order in
which the edges are stated is arbitrary).

Similarly face B could be described by the edges (11, 23), (1, 17), (17, 23),
and (1, 11) in arbitrary order of the edges.

Let's call this second format the '''edge format'''.

;Task:
'''1.''' Write a routine to check if two perimeter formatted faces have the same perimeter.  Use it to check if the following pairs of perimeters are the same:
 Q: (8, 1, 3)
 R: (1, 3, 8)

 U: (18, 8, 14, 10, 12, 17, 19)
 V: (8, 14, 10, 12, 17, 19, 18)

'''2.''' Write a routine and use it to transform the following faces from edge to perimeter format.
 E: {(1, 11), (7, 11), (1, 7)}
 F: {(11, 23), (1, 17), (17, 23), (1, 11)}
 G: {(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)}
 H: {(1, 3), (9, 11), (3, 11), (1, 11)}

Show your output here.

Solution:
def perim_equal(p1, p2):
    # Cheap tests first
    if len(p1) != len(p2) or set(p1) != set(p2):
        return False
    if any(p2 == (p1[n:] + p1[:n]) for n in range(len(p1))):
        return True
    p2 = p2[::-1] # not inplace
    return any(p2 == (p1[n:] + p1[:n]) for n in range(len(p1)))

def edge_to_periphery(e):
    edges = sorted(e)
    p = list(edges.pop(0)) if edges else []
    last = p[-1] if p else None
    while edges:
        for n, (i, j) in enumerate(edges):
            if i == last:
                p.append(j)
                last = j
                edges.pop(n)
                break
            elif j == last:
                p.append(i)
                last = i
                edges.pop(n)
                break
        else:
            #raise ValueError(f'Invalid edge format: {e}')
            return ">>>Error! Invalid edge format<<<"
    return p[:-1]

if __name__ == '__main__':
    print('Perimeter format equality checks:')
    for eq_check in [
            { 'Q': (8, 1, 3),
              'R': (1, 3, 8)},
            { 'U': (18, 8, 14, 10, 12, 17, 19),
              'V': (8, 14, 10, 12, 17, 19, 18)} ]:
        (n1, p1), (n2, p2) = eq_check.items()
        eq = '==' if perim_equal(p1, p2) else '!='
        print(' ', n1, eq, n2)

    print('\nEdge to perimeter format translations:')
    edge_d = {
     'E': {(1, 11), (7, 11), (1, 7)},
     'F': {(11, 23), (1, 17), (17, 23), (1, 11)},
     'G': {(8, 14), (17, 19), (10, 12), (10, 14), (12, 17), (8, 18), (18, 19)},
     'H': {(1, 3), (9, 11), (3, 11), (1, 11)}
            }
    for name, edges in edge_d.items():
        print(f"  {name}: {edges}\n     -> {edge_to_periphery(edges)}")


Factorial base numbers indexing permutations of a collection

You need a random arrangement of a deck of cards, you are sick of lame ways of doing this. This task is a super-cool way of doing this using factorial base numbers.
The first 25 factorial base numbers in increasing order are: 0.0.0, 0.0.1, 0.1.0, 0.1.1, 0.2.0, 0.2.1, 1.0.0, 1.0.1, 1.1.0, 1.1.1,1.2.0, 1.2.1, 2.0.0, 2.0.1, 2.1.0, 2.1.1, 2.2.0, 2.2.1, 3.0.0, 3.0.1, 3.1.0, 3.1.1, 3.2.0, 3.2.1, 1.0.0.0
Observe that the least significant digit is base 2 the next base 3, in general an n-digit factorial base number has digits n..1 in base n+1..2.

I want to produce a 1 to 1 mapping between these numbers and permutations:-
        0.0.0 -> 0123
        0.0.1 -> 0132
        0.1.0 -> 0213
        0.1.1 -> 0231
        0.2.0 -> 0312
        0.2.1 -> 0321
        1.0.0 -> 1023
        1.0.1 -> 1032
        1.1.0 -> 1203
        1.1.1 -> 1230
        1.2.0 -> 1302
        1.2.1 -> 1320
        2.0.0 -> 2013
        2.0.1 -> 2031
        2.1.0 -> 2103
        2.1.1 -> 2130
        2.2.0 -> 2301
        2.2.1 -> 2310
        3.0.0 -> 3012
        3.0.1 -> 3021
        3.1.0 -> 3102
        3.1.1 -> 3120
        3.2.0 -> 3201
        3.2.1 -> 3210

The following psudo-code will do this:
Starting with m=0 and O, an array of elements to be permutated, for each digit g starting with the most significant digit in the factorial base number.

If g is greater than zero, rotate the elements from m to m+g in O (see example)
Increment m and repeat the first step using the next most significant digit until the factorial base number is exhausted.
For example: using the factorial base number 2.0.1 and O = 0 1 2 3 where place 0 in both is the most significant (left-most) digit/element.

Step 1: m=0 g=2; Rotate places 0 through 2. 0 1 2 3 becomes 2 0 1 3
Step 2: m=1 g=0; No action.
Step 3: m=2 g=1; Rotate places 2 through 3. 2 0 1 3 becomes 2 0 3 1

Let me work 2.0.1 and 0123
     step 1 n=0 g=2 O=2013
     step 2 n=1 g=0 so no action
     step 3 n=2 g=1 O=2031

The task:

  First use your function to recreate the above table.
  Secondly use your function to generate all permutaions of 11 digits, perhaps count them don't display them, compare this method with
     methods in rc's permutations task.
  Thirdly here following are two ramdom 51 digit factorial base numbers I prepared earlier:
    39.49.7.47.29.30.2.12.10.3.29.37.33.17.12.31.29.34.17.25.2.4.25.4.1.14.20.6.21.18.1.1.1.4.0.5.15.12.4.3.10.10.9.1.6.5.5.3.0.0.0
    51.48.16.22.3.0.19.34.29.1.36.30.12.32.12.29.30.26.14.21.8.12.1.3.10.4.7.17.6.21.8.12.15.15.13.15.7.3.12.11.9.5.5.6.6.3.4.0.3.2.1
    use your function to crate the corresponding permutation of the following shoe of cards:
       AKQJ1098765432AKQJ1098765432AKQJ1098765432AKQJ1098765432
  Finally create your own 51 digit factorial base number and produce the corresponding permutation of the above shoe

Solution:
"""

http://rosettacode.org/wiki/Factorial_base_numbers_indexing_permutations_of_a_collection

https://en.wikipedia.org/wiki/Factorial_number_system

"""

import math

def apply_perm(omega,fbn):
    """

    omega contains a list which will be permuted (scrambled)
    based on fbm.

    fbm is a list which represents a factorial base number.

    This function just translates the pseudo code in the
    Rosetta Code task.

    """
    for m in range(len(fbn)):
        g = fbn[m]
        if g > 0:
            # do rotation
            # save last number
            new_first = omega[m+g]
            # move numbers right
            omega[m+1:m+g+1] = omega[m:m+g]
            # put last number first
            omega[m] = new_first

    return omega

def int_to_fbn(i):
    """

    convert integer i to factorial based number

    """
    current = i
    divisor = 2
    new_fbn = []
    while current > 0:
        remainder = current % divisor
        current = current // divisor
        new_fbn.append(remainder)
        divisor += 1

    return list(reversed(new_fbn))

def leading_zeros(l,n):
   """

   If list l has less than n elements returns l with enough 0 elements
   in front of the list to make it length n.

   """
   if len(l) < n:
       return(([0] * (n - len(l))) + l)
   else:
       return l

def get_fbn(n):
    """

    Return the n! + 1 first Factorial Based Numbers starting with zero.

    """
    max = math.factorial(n)

    for i in range(max):
        # from Wikipedia article
        current = i
        divisor = 1
        new_fbn = int_to_fbn(i)
        yield leading_zeros(new_fbn,n-1)

def print_write(f, line):
    """

    prints to console and
    output file f

    """
    print(line)
    f.write(str(line)+'\n')

def dot_format(l):
    """
    Take a list l that is a factorial based number
    and returns it in dot format.

    i.e. [0, 2, 1] becomes 0.2.1
    """
    # empty list
    if len(l) < 1:
        return ""
    # start with just first element no dot
    dot_string = str(l[0])
    # add rest if any with dots
    for e in l[1:]:
        dot_string += "."+str(e)

    return dot_string

def str_format(l):
    """
    Take a list l and returns a string
    of those elements converted to strings.
    """
    if len(l) < 1:
        return ""

    new_string = ""

    for e in l:
        new_string += str(e)

    return new_string

with open("output.html", "w", encoding="utf-8") as f:
    f.write("\n")

    # first print list

    omega=[0,1,2,3]

    four_list = get_fbn(4)

    for l in four_list:
        print_write(f,dot_format(l)+' -> '+str_format(apply_perm(omega[:],l)))

    print_write(f," ")

    # now generate this output:
    #
    # Permutations generated = 39916800
    # compared to 11! which  = 39916800

    num_permutations = 0

    for p in get_fbn(11):
        num_permutations += 1
        if num_permutations % 1000000 == 0:
            print_write(f,"permutations so far = "+str(num_permutations))

    print_write(f," ")
    print_write(f,"Permutations generated = "+str(num_permutations))
    print_write(f,"compared to 11! which  = "+str(math.factorial(11)))

    print_write(f," ")

    """

    u"\u2660" - spade

    u"\u2665" - heart

    u"\u2666" - diamond

    u"\u2663" - club

    """

    shoe = []

    for suit in [u"\u2660",u"\u2665",u"\u2666",u"\u2663"]:
        for value in ['A','K','Q','J','10','9','8','7','6','5','4','3','2']:
            shoe.append(value+suit)

    print_write(f,str_format(shoe))

    p1 = [39,49,7,47,29,30,2,12,10,3,29,37,33,17,12,31,29,34,17,25,2,4,25,4,1,14,20,6,21,18,1,1,1,4,0,5,15,12,4,3,10,10,9,1,6,5,5,3,0,0,0]

    p2 = [51,48,16,22,3,0,19,34,29,1,36,30,12,32,12,29,30,26,14,21,8,12,1,3,10,4,7,17,6,21,8,12,15,15,13,15,7,3,12,11,9,5,5,6,6,3,4,0,3,2,1]

    print_write(f," ")
    print_write(f,dot_format(p1))
    print_write(f," ")
    print_write(f,str_format(apply_perm(shoe[:],p1)))

    print_write(f," ")
    print_write(f,dot_format(p2))
    print_write(f," ")
    print_write(f,str_format(apply_perm(shoe[:],p2)))

    # generate random 51 digit factorial based number

    import random

    max = math.factorial(52)

    random_int = random.randint(0, max-1)

    myperm = leading_zeros(int_to_fbn(random_int),51)

    print(len(myperm))

    print_write(f," ")
    print_write(f,dot_format(myperm))
    print_write(f," ")
    print_write(f,str_format(apply_perm(shoe[:],myperm)))

    f.write("\n")


Factorions

Definition:
A factorion is a natural number that equals the sum of the factorials of its digits.

;Example:
'''145'''   is a factorion in base '''10''' because:

 1! + 4! + 5!   =   1 + 24 + 120   =   145

It can be shown (see talk page) that no factorion in base '''10''' can exceed   '''1,499,999'''.

;Task:
Write a program in your language to demonstrate, by calculating and printing out the factorions, that:
:*   There are   '''3'''   factorions in base   '''9'''
:*   There are   '''4'''   factorions in base '''10'''
:*   There are   '''5'''   factorions in base '''11'''
:*   There are   '''2'''   factorions in base '''12'''     (up to the same upper bound as for base '''10''')

;See also:
:* '''Wikipedia article'''
:* '''OEIS:A014080 - Factorions in base 10'''
:* '''OEIS:A193163 - Factorions in base n'''

Solution:
fact = [1] # cache factorials from 0 to 11
for n in range(1, 12):
    fact.append(fact[n-1] * n)

for b in range(9, 12+1):
    print(f"The factorions for base {b} are:")
    for i in range(1, 1500000):
        fact_sum = 0
        j = i
        while j > 0:
            d = j % b
            fact_sum += fact[d]
            j = j//b
        if fact_sum == i:
            print(i, end=" ")
    print("\n")


Fairshare between two and more

The [[Thue-Morse]] sequence is a sequence of ones and zeros that if two people
take turns in the given order, the first persons turn for every '0' in the
sequence, the second for every '1'; then this is shown to give a fairer, more
equitable sharing of resources. (Football penalty shoot-outs for example, might
not favour the team that goes first as much if the penalty takers take turns
according to the Thue-Morse sequence and took 2^n penalties)

The Thue-Morse sequence of ones-and-zeroes can be generated by:
:''"When counting in binary, the digit sum modulo 2 is the Thue-Morse sequence"''

;Sharing fairly between two or more:
Use this method:
:''When counting base '''b''', the digit sum modulo '''b''' is the Thue-Morse sequence of fairer sharing between '''b''' people.''

;Task
Counting from zero;   using a function/method/routine to express an integer count in base '''b''',
sum the digits modulo '''b''' to produce the next member of the Thue-Morse fairshare series for '''b''' people.

Show the first 25 terms of the fairshare sequence:
:*   For two people:
:*   For three people
:*   For five people
:*   For eleven people

;Related tasks:
:*   [[Non-decimal radices/Convert]]
:*   [[Thue-Morse]]

;See also:
:*   A010060, A053838, A053840: The On-Line Encyclopedia of Integer Sequences(r) (OEIS(r))

Solution:
from itertools import count, islice

def _basechange_int(num, b):
    """
    Return list of ints representing positive num in base b

    >>> b = 3
    >>> print(b, [_basechange_int(num, b) for num in range(11)])
    3 [[0], [1], [2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2], [1, 0, 0], [1, 0, 1]]
    >>>
    """
    if num == 0:
        return [0]
    result = []
    while num != 0:
        num, d = divmod(num, b)
        result.append(d)
    return result[::-1]

def fairshare(b=2):
    for i in count():
        yield sum(_basechange_int(i, b)) % b

if __name__ == '__main__':
    for b in (2, 3, 5, 11):
        print(f"{b:>2}: {str(list(islice(fairshare(b), 25)))[1:-1]}")


Farey sequence

The   Farey sequence   ''' ''F''n'''   of order   '''n'''   is the sequence of completely reduced fractions between   '''0'''   and   '''1'''   which, when in lowest terms, have denominators less than or equal to   '''n''',   arranged in order of increasing size.

The   ''Farey sequence''   is sometimes incorrectly called a   ''Farey series''.

Each Farey sequence:
:::*   starts with the value   '''0'''   (zero),   denoted by the fraction      \frac{0}{1}
:::*   ends with the value   '''1'''   (unity),   denoted by the fraction    \frac{1}{1}.

The Farey sequences of orders   '''1'''   to   '''5'''   are:

:::: {\bf\it{F}}_1 = \frac{0}{1}, \frac{1}{1}
:
:::: {\bf\it{F}}_2 = \frac{0}{1}, \frac{1}{2}, \frac{1}{1}
:
:::: {\bf\it{F}}_3 = \frac{0}{1}, \frac{1}{3}, \frac{1}{2}, \frac{2}{3}, \frac{1}{1}
:
:::: {\bf\it{F}}_4 = \frac{0}{1}, \frac{1}{4}, \frac{1}{3}, \frac{1}{2}, \frac{2}{3}, \frac{3}{4}, \frac{1}{1}
:
:::: {\bf\it{F}}_5 = \frac{0}{1}, \frac{1}{5}, \frac{1}{4}, \frac{1}{3}, \frac{2}{5}, \frac{1}{2}, \frac{3}{5}, \frac{2}{3}, \frac{3}{4}, \frac{4}{5}, \frac{1}{1}

;Task
*   Compute and show the Farey sequence for orders   '''1'''   through   '''11'''   (inclusive).
*   Compute and display the   ''number''   of fractions in the Farey sequence for order   '''100'''   through   '''1,000'''   (inclusive)   by hundreds.
*   Show the fractions as    '''n/d'''    (using the solidus [or slash] to separate the numerator from the denominator).

The length   (the number of fractions)   of a Farey sequence asymptotically approaches:

:::::::::::  3 x n2   /   \pi2

;See also:
*    OEIS sequence           A006842 numerators of Farey series of order 1, 2, ***
*    OEIS sequence           A006843 denominators of Farey series of order 1, 2, ***
*    OEIS sequence           A005728 number of fractions in Farey series of order n
*   MathWorld entry          Farey sequence
*   Wikipedia   entry   Farey sequence

Solution:
from fractions import Fraction

class Fr(Fraction):
    def __repr__(self):
        return '(%s/%s)' % (self.numerator, self.denominator)

def farey(n, length=False):
    if not length:
        return [Fr(0, 1)] + sorted({Fr(m, k) for k in range(1, n+1) for m in range(1, k+1)})
    else:
        #return 1         +    len({Fr(m, k) for k in range(1, n+1) for m in range(1, k+1)})
        return  (n*(n+3))//2 - sum(farey(n//k, True) for k in range(2, n+1))

if __name__ == '__main__':
    print('Farey sequence for order 1 through 11 (inclusive):')
    for n in range(1, 12):
        print(farey(n))
    print('Number of fractions in the Farey sequence for order 100 through 1,000 (inclusive) by hundreds:')
    print([farey(i, length=True) for i in range(100, 1001, 100)])


Farey sequence

Solution:
'''Farey sequence'''

from itertools import (chain, count, islice)
from math import gcd

# farey :: Int -> [Ratio Int]
def farey(n):
    '''Farey sequence of order n.'''
    return sorted(
        nubBy(on(eq)(fromRatio))(
            bind(enumFromTo(1)(n))(
                lambda k: bind(enumFromTo(0)(k))(
                    lambda m: [ratio(m)(k)]
                )
            )
        ),
        key=fromRatio
    ) + [ratio(1)(1)]

# fareyLength :: Int -> Int
def fareyLength(n):
    '''Number of terms in a Farey sequence
       of order n.'''
    def go(x):
        return (x * (x + 3)) // 2 - sum(
            go(x // k) for k in enumFromTo(2)(x)
        )
    return go(n)

# showFarey :: [Ratio Int] -> String
def showFarey(xs):
    '''Stringification of a Farey sequence.'''
    return '(' + ', '.join(map(showRatio, xs)) + ')'

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

    print(
        fTable(
            'Farey sequence for orders 1-11 (inclusive):\n'
        )(str)(showFarey)(
            farey
        )(enumFromTo(1)(11))
    )
    print(
        fTable(
            '\n\nNumber of fractions in the Farey sequence ' +
            'for order 100 through 1,000 (inclusive) by hundreds:\n'
        )(str)(str)(
            fareyLength
        )(enumFromThenTo(100)(200)(1000))
    )

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

# bind(>>=) :: [a] -> (a -> [b]) -> [b]
def bind(xs):
    '''List monad injection operator.
       Two computations sequentially composed,
       with any value produced by the first
       passed as an argument to the second.'''
    return lambda f: list(
        chain.from_iterable(
            map(f, xs)
        )
    )

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

# enumFromThenTo :: Int -> Int -> Int -> [Int]
def enumFromThenTo(m):
    '''Integer values enumerated from m to n
       with a step defined by nxt-m.
    '''
    def go(nxt, n):
        d = nxt - m
        return islice(count(0), m, d + n, d)
    return lambda nxt: lambda n: (
        list(go(nxt, n))
    )

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

# eq (==) :: Eq a => a -> a -> Bool
def eq(a):
    '''Simple equality of a and b.'''
    return lambda b: a == b

# fromRatio :: Ratio Int -> Float
def fromRatio(r):
    '''A floating point value derived from a
       a rational value.
    '''
    return r.get('numerator') / r.get('denominator')

# nubBy :: (a -> a -> Bool) -> [a] -> [a]
def nubBy(p):
    '''A sublist of xs from which all duplicates,
       (as defined by the equality predicate p)
       are excluded.
    '''
    def go(xs):
        if not xs:
            return []
        x = xs[0]
        return [x] + go(
            list(filter(
                lambda y: not p(x)(y),
                xs[1:]
            ))
        )
    return lambda xs: go(xs)

# on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
def on(f):
    '''A function returning the value of applying
      the binary f to g(a) g(b)
    '''
    return lambda g: lambda a: lambda b: f(g(a))(g(b))

# ratio :: Int -> Int -> Ratio Int
def ratio(n):
    '''Rational value constructed
       from a numerator and a denominator.
    '''
    def go(n, d):
        g = gcd(n, d)
        return {
            'type': 'Ratio',
            'numerator': n // g, 'denominator': d // g
        }
    return lambda d: go(n * signum(d), abs(d))

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

# signum :: Num -> Num
def signum(n):
    '''The sign of n.'''
    return -1 if 0 > n else (1 if 0 < n else 0)

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

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

if __name__ == '__main__':
    main()


Fast Fourier transform

Calculate the   FFT   (Fast Fourier Transform)   of an input sequence.

The most general case allows for complex numbers at the input
and results in a sequence of equal length, again of complex numbers.
If you need to restrict yourself to real numbers, the output should
be the magnitude   (i.e.:   sqrt(re2 + im2))   of the complex result.

The classic version is the recursive Cooley-Tukey FFT. Wikipedia has pseudo-code for that.
Further optimizations are possible but not required.

Solution:
from cmath import exp, pi

def fft(x):
    N = len(x)
    if N <= 1: return x
    even = fft(x[0::2])
    odd =  fft(x[1::2])
    T= [exp(-2j*pi*k/N)*odd[k] for k in range(N//2)]
    return [even[k] + T[k] for k in range(N//2)] + \
           [even[k] - T[k] for k in range(N//2)]

print( ' '.join("%5.3f" % abs(f)
                for f in fft([1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0])) )


Feigenbaum constant calculation

Calculate the Feigenbaum constant.

;See:
:*   Details in the Wikipedia article:   Feigenbaum constant.

Solution:
max_it = 13
max_it_j = 10
a1 = 1.0
a2 = 0.0
d1 = 3.2
a = 0.0

print " i       d"
for i in range(2, max_it + 1):
    a = a1 + (a1 - a2) / d1
    for j in range(1, max_it_j + 1):
        x = 0.0
        y = 0.0
        for k in range(1, (1 << i) + 1):
            y = 1.0 - 2.0 * y * x
            x = a - x * x
        a = a - x / y
    d = (a1 - a2) / (a - a1)
    print("{0:2d}    {1:.8f}".format(i, d))
    d1 = d
    a2 = a1
    a1 = a


Fibonacci n-step number sequences

These number series are an expansion of the ordinary [[Fibonacci sequence]] where:
# For n = 2 we have the Fibonacci sequence; with initial values [1, 1] and F_k^2 = F_{k-1}^2 + F_{k-2}^2
# For n = 3 we have the tribonacci sequence; with initial values [1, 1, 2] and F_k^3 = F_{k-1}^3 + F_{k-2}^3 + F_{k-3}^3
# For n = 4 we have the tetranacci sequence; with initial values [1, 1, 2, 4] and F_k^4 = F_{k-1}^4 + F_{k-2}^4 + F_{k-3}^4 + F_{k-4}^4...
# For general n>2 we have the Fibonacci n-step sequence - F_k^n; with initial values of the first n values of the (n-1)'th Fibonacci n-step sequence F_k^{n-1}; and k'th value of this n'th sequence being F_k^n = \sum_{i=1}^{(n)} {F_{k-i}^{(n)}}

For small values of n, Greek numeric prefixes are sometimes used to individually name each series.

:::: {| style="text-align: left;" border="4" cellpadding="2" cellspacing="2"
|+ Fibonacci n-step sequences
|- style="background-color: rgb(255, 204, 255);"
! n !! Series name !! Values
|-
|  2 ||  fibonacci || 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 ...
|-
|  3 || tribonacci || 1 1 2 4 7 13 24 44 81 149 274 504 927 1705 3136 ...
|-
|  4 || tetranacci || 1 1 2 4 8 15 29 56 108 208 401 773 1490 2872 5536 ...
|-
|  5 || pentanacci || 1 1 2 4 8 16 31 61 120 236 464 912 1793 3525 6930 ...
|-
|  6 ||  hexanacci || 1 1 2 4 8 16 32 63 125 248 492 976 1936 3840 7617 ...
|-
|  7 || heptanacci || 1 1 2 4 8 16 32 64 127 253 504 1004 2000 3984 7936 ...
|-
|  8 ||  octonacci || 1 1 2 4 8 16 32 64 128 255 509 1016 2028 4048 8080 ...
|-
|  9 ||  nonanacci || 1 1 2 4 8 16 32 64 128 256 511 1021 2040 4076 8144 ...
|-
| 10 ||  decanacci || 1 1 2 4 8 16 32 64 128 256 512 1023 2045 4088 8172 ...
|}

Allied sequences can be generated where the initial values are changed:
: '''The Lucas series''' sums the two preceding values like the fibonacci series for n=2 but uses [2, 1] as its initial values.

;Task:
# Write a function to generate Fibonacci n-step number sequences given its initial values and assuming the number of initial values determines how many previous values are summed to make the next number of the series.
# Use this to print and show here at least the first ten members of the Fibo/tribo/tetra-nacci and Lucas sequences.

;Related tasks:
*   [[Fibonacci sequence]]
*   Wolfram Mathworld
*   [[Hofstadter Q sequence]]
*   [[Leonardo numbers]]

;Also see:
*   Lucas Numbers - Numberphile (Video)
*   Tribonacci Numbers (and the Rauzy Fractal) - Numberphile (Video)
*   Wikipedia, Lucas number
*   MathWorld, Fibonacci Number
*   Some identities for r-Fibonacci numbers
*   OEIS Fibonacci numbers
*   OEIS Lucas numbers

Solution:
>>> class Fiblike():
	def __init__(self, start):
		self.addnum = len(start)
		self.memo = start[:]
	def __call__(self, n):
		try:
			return self.memo[n]
		except IndexError:
			ans = sum(self(i) for i in range(n-self.addnum, n))
			self.memo.append(ans)
			return ans

>>> fibo = Fiblike([1,1])
>>> [fibo(i) for i in range(10)]
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>>> lucas = Fiblike([2,1])
>>> [lucas(i) for i in range(10)]
[2, 1, 3, 4, 7, 11, 18, 29, 47, 76]
>>> for n, name in zip(range(2,11), 'fibo tribo tetra penta hexa hepta octo nona deca'.split()) :
	fibber = Fiblike([1] + [2**i for i in range(n-1)])
	print('n=%2i, %5snacci -> %s ...' % (n, name, ' '.join(str(fibber(i)) for i in range(15))))

n= 2,  fibonacci -> 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 ...
n= 3, tribonacci -> 1 1 2 4 7 13 24 44 81 149 274 504 927 1705 3136 ...
n= 4, tetranacci -> 1 1 2 4 8 15 29 56 108 208 401 773 1490 2872 5536 ...
n= 5, pentanacci -> 1 1 2 4 8 16 31 61 120 236 464 912 1793 3525 6930 ...
n= 6,  hexanacci -> 1 1 2 4 8 16 32 63 125 248 492 976 1936 3840 7617 ...
n= 7, heptanacci -> 1 1 2 4 8 16 32 64 127 253 504 1004 2000 3984 7936 ...
n= 8,  octonacci -> 1 1 2 4 8 16 32 64 128 255 509 1016 2028 4048 8080 ...
n= 9,  nonanacci -> 1 1 2 4 8 16 32 64 128 256 511 1021 2040 4076 8144 ...
n=10,  decanacci -> 1 1 2 4 8 16 32 64 128 256 512 1023 2045 4088 8172 ...
>>>


Fibonacci n-step number sequences

Solution:
'''Fibonacci n-step number sequences'''

from itertools import chain, count, islice

# A000032 :: () -> [Int]
def A000032():
    '''Non finite sequence of Lucas numbers.
    '''
    return unfoldr(recurrence(2))([2, 1])

# nStepFibonacci :: Int -> [Int]
def nStepFibonacci(n):
    '''Non-finite series of N-step Fibonacci numbers,
       defined by a recurrence relation.
    '''
    return unfoldr(recurrence(n))(
        take(n)(
            chain(
                [1],
                (2 ** i for i in count(0))
            )
        )
    )

# recurrence :: Int -> [Int] -> Int
def recurrence(n):
    '''Recurrence relation in Fibonacci and related series.
    '''
    def go(xs):
        h, *t = xs
        return h, t + [sum(take(n)(xs))]
    return go

# ------------------------- TEST -------------------------
# main :: IO ()
def main():
    '''First 15 terms each n-step Fibonacci(n) series
       where n is drawn from [2..8]
    '''
    labels = "fibo tribo tetra penta hexa hepta octo nona deca"
    table = list(
        chain(
            [['lucas:'] + [
                str(x) for x in take(15)(A000032())]
             ],
            map(
                lambda k, n: list(
                    chain(
                        [k + 'nacci:'],
                        (
                            str(x) for x
                            in take(15)(nStepFibonacci(n))
                        )
                    )
                ),
                labels.split(),
                count(2)
            )
        )
    )
    print('Recurrence relation series:\n')
    print(
        spacedTable(table)
    )

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

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

# unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
def unfoldr(f):
    '''Generic anamorphism.
       A lazy (generator) list unfolded from a seed value by
       repeated application of f until no residue remains.
       Dual to fold/reduce.
       f returns either None, or just (value, residue).
       For a strict output value, wrap in list().
    '''
    def go(x):
        valueResidue = f(x)
        while None is not valueResidue:
            yield valueResidue[0]
            valueResidue = f(valueResidue[1])
    return go

# ---------------------- FORMATTING ----------------------

# spacedTable :: [[String]] -> String
def spacedTable(rows):
    columnWidths = [
        max([len(x) for x in col])
        for col in zip(*rows)
    ]
    return '\n'.join([
        ' '.join(
            map(
                lambda x, w: x.rjust(w, ' '),
                row, columnWidths
            )
        )
        for row in rows
    ])

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


Fibonacci word

The   Fibonacci Word   may be created in a manner analogous to the   Fibonacci Sequence    as described here:

     Define   F_Word1   as   '''1'''
     Define   F_Word2   as   '''0'''
     Form     F_Word3   as   F_Word2     concatenated with   F_Word1    i.e.:   '''01'''
     Form     F_Wordn   as   F_Wordn-1   concatenated with   F_wordn-2

;Task:
Perform the above steps for     n = 37.

You may display the first few but not the larger values of   n.
{Doing so will get the task's author into trouble with them what be (again!).}

Instead, create a table for   F_Words   '''1'''   to   '''37'''   which shows:
::*   The number of characters in the word
::*   The word's [[Entropy]]

;Related tasks:
*   Fibonacci word/fractal
*   [[Entropy]]
*   [[Entropy/Narcissist]]

Solution:
>>> import math
>>> from collections import Counter
>>>
>>> def entropy(s):
...     p, lns = Counter(s), float(len(s))
...     return -sum( count/lns * math.log(count/lns, 2) for count in p.values())
...
>>>
>>> def fibword(nmax=37):
...     fwords = ['1', '0']
...     print('%-3s %10s %-10s %s' % tuple('N Length Entropy Fibword'.split()))
...     def pr(n, fwords):
...         while len(fwords) < n:
...             fwords += [''.join(fwords[-2:][::-1])]
...         v = fwords[n-1]
...         print('%3i %10i %10.7g %s' % (n, len(v), entropy(v), v if len(v) < 20 else '<too long>'))
...     for n in range(1, nmax+1): pr(n, fwords)
...
>>> fibword()
N       Length Entropy    Fibword
  1          1         -0 1
  2          1         -0 0
  3          2          1 01
  4          3  0.9182958 010
  5          5  0.9709506 01001
  6          8   0.954434 01001010
  7         13  0.9612366 0100101001001
  8         21  0.9587119 <too long>
  9         34  0.9596869 <too long>
 10         55   0.959316 <too long>
 11         89  0.9594579 <too long>
 12        144  0.9594038 <too long>
 13        233  0.9594244 <too long>
 14        377  0.9594165 <too long>
 15        610  0.9594196 <too long>
 16        987  0.9594184 <too long>
 17       1597  0.9594188 <too long>
 18       2584  0.9594187 <too long>
 19       4181  0.9594187 <too long>
 20       6765  0.9594187 <too long>
 21      10946  0.9594187 <too long>
 22      17711  0.9594187 <too long>
 23      28657  0.9594187 <too long>
 24      46368  0.9594187 <too long>
 25      75025  0.9594187 <too long>
 26     121393  0.9594187 <too long>
 27     196418  0.9594187 <too long>
 28     317811  0.9594187 <too long>
 29     514229  0.9594187 <too long>
 30     832040  0.9594187 <too long>
 31    1346269  0.9594187 <too long>
 32    2178309  0.9594187 <too long>
 33    3524578  0.9594187 <too long>
 34    5702887  0.9594187 <too long>
 35    9227465  0.9594187 <too long>
 36   14930352  0.9594187 <too long>
 37   24157817  0.9594187 <too long>
>>>


File extension is in extensions list

Checking if a file is in a certain category of file formats with known extensions (e.g. archive files, or image files) is a common problem in practice, and may be approached differently from extracting and outputting an arbitrary extension ''(see e.g. FileNameExtensionFilter in Java)''.

It also requires less assumptions about the format of an extension, because the calling code can decide what extensions are valid.

For these reasons, this task exists in addition to the [[Extract file extension]] task.

;Related tasks:
* [[Extract file extension]]
* [[String matching]]

Solution:
'''Check for a specific set of file extensions'''

# extensionFound :: [Extension] -> FileName -> Maybe Extension
def extensionFound(xs):
    '''Nothing if no matching extension is found,
       or Just the extension (drawn from xs, and
       a suffix of the filename, immediately following
       a dot character).
    '''
    return lambda fn: find(fn.lower().endswith)(
        ['.' + x.lower() for x in xs]
    )

# TEST ----------------------------------------------------
# main :: IO ()
def main():
    '''Check filenames for a particular set of extensions.'''

    # checkExtension :: FileName -> Maybe Extension
    def checkExtension(fn):
        return extensionFound([
            'zip', 'rar', '7z', 'gz', 'archive', 'A##', 'tar.bz2'
        ])(fn)

    print(
        fTable(__doc__ + ':\n')(str)(str)(
            compose(fromMaybe('n/a'))(checkExtension)
        )([
            'MyData.a##',
            'MyData.tar.Gz',
            'MyData.gzip',
            'MyData.7z.backup',
            'MyData...',
            'MyData',
            'MyData_v1.0.tar.bz2',
            'MyData_v1.0.bz2'
        ])
    )

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

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

# Nothing :: Maybe a
def Nothing():
    '''Constructor for an empty Maybe (option type) value.'''
    return {'type': 'Maybe', 'Nothing': True}

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

# find :: (a -> Bool) -> [a] -> Maybe a
def find(p):
    '''Just the first element in the list that matches p,
       or Nothing if no elements match.
    '''
    def go(xs):
        for x in xs:
            if p(x):
                return Just(x)
        return Nothing()
    return lambda xs: go(xs)

# fromMaybe :: a -> Maybe a -> a
def fromMaybe(x):
    '''The default value x if mb is Nothing,
       or the value contained in mb.
    '''
    return lambda mb: x if (
        mb.get('Nothing')
    ) else mb.get('Just')

# DISPLAY -------------------------------------------------

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

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


File size distribution

Beginning from the current directory, or optionally from a directory specified as a command-line argument, determine how many files there are of various sizes in a directory hierarchy.

My suggestion is to sort by logarithmn of file size, since a few bytes here or there, or even a factor of two or three, may not be that significant.

Don't forget that empty files may exist, to serve as a marker.

Is your file system predominantly devoted to a large number of smaller files, or a smaller number of huge files?

Solution:
import sys, os
from collections import Counter

def dodir(path):
    global h

    for name in os.listdir(path):
        p = os.path.join(path, name)

        if os.path.islink(p):
            pass
        elif os.path.isfile(p):
            h[os.stat(p).st_size] += 1
        elif os.path.isdir(p):
            dodir(p)
        else:
            pass

def main(arg):
    global h
    h = Counter()
    for dir in arg:
        dodir(dir)

    s = n = 0
    for k, v in sorted(h.items()):
        print("Size %d -> %d file(s)" % (k, v))
        n += v
        s += k * v
    print("Total %d bytes for %d files" % (s, n))

main(sys.argv[1:])


Find Chess960 starting position identifier

Starting Position Identifier number ("SP-ID"), and generate the corresponding position.

;Task:
This task is to go the other way: given a starting array of pieces (provided in any form that suits your implementation, whether string or list or array, of letters or Unicode chess symbols or enum values, etc.), derive its unique SP-ID. For example, given the starting array '''QNRBBNKR''' (or '''''' or ''''''), which we assume is given as seen from White's side of the board from left to right, your (sub)program should return 105; given the starting lineup of standard chess, it should return 518.

You may assume the input is a valid Chess960 position; detecting invalid input (including illegal characters or starting arrays with the bishops on the same color square or the king not between the two rooks) is optional.

;Algorithm:

The derivation is the inverse of the algorithm given at Wikipedia, and goes like this (we'll use the standard chess setup as an example).

1. Ignoring the Queen and Bishops, find the positions of the Knights within the remaining five spaces (in the standard array they're in the second and fourth positions), and then find the index number of that combination. There's a table at the above Wikipedia article, but it's just the possible positions sorted left to right and numbered 0 to 9: 0='''NN---''', 1='''N-N--''', 2='''N--N-''', 3='''N---N''', 4='''-NN--''', etc; our pair is combination number 5. Call this number N. '''N=5'''

2. Still ignoring the Bishops, find the position of the Queen in the remaining 6 spaces; number them 0..5 from left to right and call the index of the Queen's position Q. In our example, '''Q=2'''.

3. Finally, find the positions of the two bishops within their respective sets of four like-colored squares. It's important to note here that the board in chess is placed such that the leftmost position on the home row is on a dark square and the rightmost a light. So if we number the squares of each color 0..3 from left to right, the dark bishop in the standard position is on square 1 ('''D=1'''), and the light bishop is on square 2 ('''L=2''').

4. Then the position number is given by '''4(4(6N + Q)+D)+L''', which reduces to '''96N + 16Q + 4D + L'''. In our example, that's 96x5 + 16x2 + 4x1 + 2 = 480 + 32 + 4 + 2 = 518.

Note that an earlier iteration of this page contained an incorrect description of the algorithm which would give the same SP-ID for both of the following two positions.

    RQNBBKRN = 601
    RNQBBKRN = 617

Solution:
# optional, but task function depends on it as written
def validate_position(candidate: str):
    assert (
        len(candidate) == 8
    ), f"candidate position has invalide len = {len(candidate)}"

    valid_pieces = {"R": 2, "N": 2, "B": 2, "Q": 1, "K": 1}
    assert {
        piece for piece in candidate
    } == valid_pieces.keys(), f"candidate position contains invalid pieces"
    for piece_type in valid_pieces.keys():
        assert (
            candidate.count(piece_type) == valid_pieces[piece_type]
        ), f"piece type '{piece_type}' has invalid count"

    bishops_pos = [index for index,
                   value in enumerate(candidate) if value == "B"]
    assert (
        bishops_pos[0] % 2 != bishops_pos[1] % 2
    ), f"candidate position has both bishops in the same color"

    assert [piece for piece in candidate if piece in "RK"] == [
        "R",
        "K",
        "R",
    ], "candidate position has K outside of RR"

def calc_position(start_pos: str):
    try:
        validate_position(start_pos)
    except AssertionError:
        raise AssertionError
    # step 1
    subset_step1 = [piece for piece in start_pos if piece not in "QB"]
    nights_positions = [
        index for index, value in enumerate(subset_step1) if value == "N"
    ]
    nights_table = {
        (0, 1): 0,
        (0, 2): 1,
        (0, 3): 2,
        (0, 4): 3,
        (1, 2): 4,
        (1, 3): 5,
        (1, 4): 6,
        (2, 3): 7,
        (2, 4): 8,
        (3, 4): 9,
    }
    N = nights_table.get(tuple(nights_positions))

    # step 2
    subset_step2 = [piece for piece in start_pos if piece != "B"]
    Q = subset_step2.index("Q")

    # step 3
    dark_squares = [
        piece for index, piece in enumerate(start_pos) if index in range(0, 9, 2)
    ]
    light_squares = [
        piece for index, piece in enumerate(start_pos) if index in range(1, 9, 2)
    ]
    D = dark_squares.index("B")
    L = light_squares.index("B")

    return 4 * (4 * (6*N + Q) + D) + L

if __name__ == '__main__':
    for example in ["QNRBBNKR", "RNBQKBNR", "RQNBBKRN", "RNQBBKRN"]:
        print(f'Position: {example}; Chess960 PID= {calc_position(example)}')


Find duplicate files

In a large directory structure it is easy to inadvertently leave unnecessary copies of files around, which can use considerable disk space and create confusion.

;Task:
Create a program which, given a minimum size and a folder/directory, will find all files of at least ''size'' bytes with duplicate contents under the directory and output or show the sets of duplicate files in order of decreasing size.

The program may be command-line or graphical, and duplicate content may be determined by direct comparison or by calculating a hash of the data.

Specify which filesystems or operating systems your program works with if it has any filesystem- or OS-specific requirements.

Identify hard links (filenames referencing the same content) in the output if applicable for the filesystem.

For extra points, detect when whole directory sub-trees are identical, or optionally remove or link identical files.

Solution:
from __future__ import print_function
import os
import hashlib
import datetime

def FindDuplicateFiles(pth, minSize = 0, hashName = "md5"):
    knownFiles = {}

    #Analyse files
    for root, dirs, files in os.walk(pth):
        for fina in files:
            fullFina = os.path.join(root, fina)
            isSymLink = os.path.islink(fullFina)
            if isSymLink:
                continue # Skip symlinks
            si = os.path.getsize(fullFina)
            if si < minSize:
                continue
            if si not in knownFiles:
                knownFiles[si] = {}
            h = hashlib.new(hashName)
            h.update(open(fullFina, "rb").read())
            hashed = h.digest()
            if hashed in knownFiles[si]:
                fileRec = knownFiles[si][hashed]
                fileRec.append(fullFina)
            else:
                knownFiles[si][hashed] = [fullFina]

    #Print result
    sizeList = list(knownFiles.keys())
    sizeList.sort(reverse=True)
    for si in sizeList:
        filesAtThisSize = knownFiles[si]
        for hashVal in filesAtThisSize:
            if len(filesAtThisSize[hashVal]) < 2:
                continue
            fullFinaLi = filesAtThisSize[hashVal]
            print ("=======Duplicate=======")
            for fullFina in fullFinaLi:
                st = os.stat(fullFina)
                isHardLink = st.st_nlink > 1
                infoStr = []
                if isHardLink:
                    infoStr.append("(Hard linked)")
                fmtModTime = datetime.datetime.utcfromtimestamp(st.st_mtime).strftime('%Y-%m-%dT%H:%M:%SZ')
                print (fmtModTime, si, os.path.relpath(fullFina, pth), " ".join(infoStr))

if __name__=="__main__":

    FindDuplicateFiles('/home/tim/Dropbox', 1024*1024)


Find if a point is within a triangle

Find if a point is within a triangle.

;Task:

::*   Assume points are on a plane defined by (x, y) real number coordinates.

::*   Given a point P(x, y) and a triangle formed by points A, B, and C, determine if P is within triangle ABC.

::*   You may use any algorithm.

::*   Bonus: explain why the algorithm you chose works.

;Related tasks:
*   [[Determine_if_two_triangles_overlap]]

;Also see:
:* Discussion of several methods. [[http://totologic.blogspot.com/2014/01/accurate-point-in-triangle-test.html]]
:* Determine if a point is in a polygon [[https://en.wikipedia.org/wiki/Point_in_polygon]]
:* Triangle based coordinate systems [[https://en.wikipedia.org/wiki/Barycentric_coordinate_system]]
:* Wolfram entry [[https://mathworld.wolfram.com/TriangleInterior.html]]

Solution:
""" find if point is in a triangle """

from sympy.geometry import Point, Triangle

def sign(pt1, pt2, pt3):
    """ which side of plane cut by line (pt2, pt3) is pt1 on? """
    return (pt1.x - pt3.x) * (pt2.y - pt3.y) - (pt2.x - pt3.x) * (pt1.y - pt3.y)

def iswithin(point, pt1, pt2, pt3):
    """
    Determine if point is within triangle formed by points p1, p2, p3.
    If so, the point will be on the same side of each of the half planes
    defined by vectors p1p2, p2p3, and p3p1. zval is positive if outside,
    negative if inside such a plane. All should be positive or all negative
    if point is within the triangle.
    """
    zval1 = sign(point, pt1, pt2)
    zval2 = sign(point, pt2, pt3)
    zval3 = sign(point, pt3, pt1)
    notanyneg = zval1 >= 0 and zval2 >= 0 and zval3 >= 0
    notanypos = zval1 <= 0 and zval2 <= 0 and zval3 <= 0
    return notanyneg or notanypos

if __name__ == "__main__":
    POINTS = [Point(0, 0)]
    TRI = Triangle(Point(1.5, 2.4), Point(5.1, -3.1), Point(-3.8, 0.5))
    for pnt in POINTS:
        a, b, c = TRI.vertices
        isornot = "is" if iswithin(pnt, a, b, c) else "is not"
        print("Point", pnt, isornot, "within the triangle", TRI)


Find limit of recursion

{{selection|Short Circuit|Console Program Basics}}

;Task:
Find the limit of recursion.

Solution:
def recurseDeeper(counter):
    try:
        print(counter)
        recurseDeeper(counter + 1)
    except RecursionError:
        print("RecursionError at depth", counter)
        recurseDeeper(counter + 1)


Find palindromic numbers in both binary and ternary bases

*   Find and show (in decimal) the first six numbers (non-negative integers) that are   palindromes   in   ''both'':
:::*   base 2
:::*   base 3
*   Display   '''0'''   (zero) as the first number found, even though some other definitions ignore it.
*   Optionally, show the decimal number found in its binary and ternary form.
*   Show all output here.

It's permissible to assume the first two numbers and simply list them.

;See also
*   Sequence A60792,   numbers that are palindromic in bases 2 and 3 on ''The On-Line Encyclopedia of Integer Sequences''.

Solution:
from itertools import islice

digits = "0123456789abcdefghijklmnopqrstuvwxyz"

def baseN(num,b):
  if num == 0: return "0"
  result = ""
  while num != 0:
    num, d = divmod(num, b)
    result += digits[d]
  return result[::-1] # reverse

def pal2(num):
    if num == 0 or num == 1: return True
    based = bin(num)[2:]
    return based == based[::-1]

def pal_23():
    yield 0
    yield 1
    n = 1
    while True:
        n += 1
        b = baseN(n, 3)
        revb = b[::-1]
        #if len(b) > 12: break
        for trial in ('{0}{1}'.format(b, revb), '{0}0{1}'.format(b, revb),
                      '{0}1{1}'.format(b, revb), '{0}2{1}'.format(b, revb)):
            t = int(trial, 3)
            if pal2(t):
                yield t

for pal23 in islice(pal_23(), 6):
    print(pal23, baseN(pal23, 3), baseN(pal23, 2))


Solution:
'''Numbers with palindromic digit strings in both binary and ternary'''

from itertools import (islice)

# palinBoth :: Generator [Int]
def palinBoth():
    '''Non finite stream of dually palindromic integers.'''
    yield 0, '0', '0'
    ibt = 1, '1', '1'

    yield ibt
    while True:
        ibt = until(isBoth)(psucc)(psucc(ibt))
        yield int(ibt[2], 3), ibt[1], ibt[2]

# isBoth :: (Int, String, String) -> Bool
def isBoth(ibt):
    '''True if the binary string is palindromic (as
       the ternary string is already known to be).
    '''
    b = ibt[1]
    return b == b[::-1]

# psucc :: (Int, String, String) -> (Int, String, String)
def psucc(ibt):
    '''The next triple of index, binary
       and (palindromic) ternary string
    '''
    d = 1 + ibt[0]
    s = showBase3(d)
    pal = s + '1' + s[::-1]
    return d, bin(int(pal, 3))[2:], pal

# showBase3 :: Int -> String
def showBase3(n):
    '''Ternary digit string for integer n.'''
    return showIntAtBase(3)(
        lambda i: '012'[i]
    )(n)('')

# ------------------------- TEST -------------------------
def main():
    '''Integers with palindromic digits in
       both binary and ternary bases.
    '''

    xs = take(6)(palinBoth())
    d, b, t = xs[-1]
    bw = len(b)
    tw = len(t)

    print(
        fTable(
            label('rjust')(('Decimal', len(str(d)))) +
            ''.join(map(
                label('center'),
                [('Binary', bw), ('Ternary', tw)]
            )) + '\n'
        )(compose(str)(fst))(
            lambda p: p[1].center(bw, ' ') +
            '    ' + p[2].center(tw, ' ')
        )(identity)(xs)
    )

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

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

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

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

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

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

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

# ---------------------- FORMATTING ----------------------

# label :: Method String -> (String, Int)
def label(k):
    '''Stringification, using the named justification
       method (ljust|centre|rjust) of the label,
       and the specified amount of white space.
    '''
    def go(sw):
        s, w = sw
        return getattr(s, k)(w, ' ') + '    '
    return go

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

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


Find the intersection of a line with a plane

Finding the intersection of an infinite ray with a plane in 3D is an important topic in collision detection.

;Task:
Find the point of intersection for the infinite ray with direction   (0, -1, -1)   passing through position   (0, 0, 10)   with the infinite plane with a normal vector of   (0, 0, 1)   and which passes through [0, 0, 5].

Solution:
#!/bin/python
from __future__ import print_function
import numpy as np

def LinePlaneCollision(planeNormal, planePoint, rayDirection, rayPoint, epsilon=1e-6):

	ndotu = planeNormal.dot(rayDirection)
	if abs(ndotu) < epsilon:
		raise RuntimeError("no intersection or line is within plane")

	w = rayPoint - planePoint
	si = -planeNormal.dot(w) / ndotu
	Psi = w + si * rayDirection + planePoint
	return Psi

if __name__=="__main__":
	#Define plane
	planeNormal = np.array([0, 0, 1])
	planePoint = np.array([0, 0, 5]) #Any point on the plane

	#Define ray
	rayDirection = np.array([0, -1, -1])
	rayPoint = np.array([0, 0, 10]) #Any point along the ray

	Psi = LinePlaneCollision(planeNormal, planePoint, rayDirection, rayPoint)
	print ("intersection at", Psi)


Find the intersection of two lines

Finding the intersection of two lines that are in the same plane is an important topic in collision detection.[http://mathworld.wolfram.com/Line-LineIntersection.html]

;Task:
Find the point of intersection of two lines in 2D.

The 1st     line passes though    (4,0)    and    (6,10) .
The 2nd line passes though    (0,3)    and    (10,7) .

Solution:
def line_intersect(Ax1, Ay1, Ax2, Ay2, Bx1, By1, Bx2, By2):
    """ returns a (x, y) tuple or None if there is no intersection """
    d = (By2 - By1) * (Ax2 - Ax1) - (Bx2 - Bx1) * (Ay2 - Ay1)
    if d:
        uA = ((Bx2 - Bx1) * (Ay1 - By1) - (By2 - By1) * (Ax1 - Bx1)) / d
        uB = ((Ax2 - Ax1) * (Ay1 - By1) - (Ay2 - Ay1) * (Ax1 - Bx1)) / d
    else:
        return
    if not(0 <= uA <= 1 and 0 <= uB <= 1):
        return
    x = Ax1 + uA * (Ax2 - Ax1)
    y = Ay1 + uA * (Ay2 - Ay1)

    return x, y

if __name__ == '__main__':
    (a, b), (c, d) = (4, 0), (6, 10)  # try (4, 0), (6, 4)
    (e, f), (g, h) = (0, 3), (10, 7)  # for non intersecting test
    pt = line_intersect(a, b, c, d, e, f, g, h)
    print(pt)