Weird numbers

In number theory, a perfect either).

In other words, the sum of the proper divisors of the number (divisors including 1 but not itself) is greater than the number itself (the number is ''abundant''), but no subset of those divisors sums to the number itself (the number is not ''semiperfect'').

For example:

* '''12''' is ''not'' a weird number.
** It is abundant; its proper divisors '''1, 2, 3, 4, 6''' sum to '''16''' (which ''is'' > 12),
** but it ''is'' semiperfect, e.g.:     '''6 + 4 + 2 == 12'''.
* '''70''' ''is'' a weird number.
** It is abundant; its proper divisors '''1, 2, 5, 7, 10, 14, 35''' sum to '''74''' (which ''is'' > 70),
** and there is no subset of proper divisors that sum to '''70'''.

;Task:
Find and display, here on this page, the first '''25''' weird numbers.

;Related tasks:
:* Abundant, deficient and perfect number classifications
:* Proper divisors

;See also:
:* OEIS: A006037 weird numbers
:* Wikipedia: weird number
:* [http://mathworld.wolfram.com/WeirdNumber.html MathWorld: weird number]

Solution:
#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"
#include "string.h"

struct int_a {
    int *ptr;
    size_t size;
};

struct int_a divisors(int n) {
    int *divs, *divs2, *out;
    int i, j, c1 = 0, c2 = 0;
    struct int_a array;

    divs = malloc(n * sizeof(int) / 2);
    divs2 = malloc(n * sizeof(int) / 2);
    divs[c1++] = 1;

    for (i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            j = n / i;
            divs[c1++] = i;
            if (i != j) {
                divs2[c2++] = j;
            }
        }
    }

    out = malloc((c1 + c2) * sizeof(int));
    for (int i = 0; i < c2; i++) {
        out[i] = divs2[i];
    }
    for (int i = 0; i < c1; i++) {
        out[c2 + i] = divs[c1 - i - 1];
    }
    array.ptr = out;
    array.size = c1 + c2;

    free(divs);
    free(divs2);
    return array;
}

bool abundant(int n, struct int_a divs) {
    int sum = 0;
    int i;
    for (i = 0; i < divs.size; i++) {
        sum += divs.ptr[i];
    }
    return sum > n;
}

bool semiperfect(int n, struct int_a divs) {
    if (divs.size > 0) {
        int h = *divs.ptr;
        int *t = divs.ptr + 1;

        struct int_a ta;
        ta.ptr = t;
        ta.size = divs.size - 1;

        if (n < h) {
            return semiperfect(n, ta);
        } else {
            return n == h
                || semiperfect(n - h, ta)
                || semiperfect(n, ta);
        }
    } else {
        return false;
    }
}

bool *sieve(int limit) {
    bool *w = calloc(limit, sizeof(bool));
    struct int_a divs;
    int i, j;

    for (i = 2; i < limit; i += 2) {
        if (w[i]) continue;
        divs = divisors(i);
        if (!abundant(i, divs)) {
            w[i] = true;
        } else if (semiperfect(i, divs)) {
            for (j = i; j < limit; j += i) {
                w[j] = true;
            }
        }
    }

    free(divs.ptr);
    return w;
}

int main() {
    bool *w = sieve(17000);
    int count = 0;
    int max = 25;
    int n;

    printf("The first 25 weird numbers:\n");
    for (n = 2; count < max; n += 2) {
        if (!w[n]) {
            printf("%d ", n);
            count++;
        }
    }
    printf("\n");

    free(w);
    return 0;
}


Weird numbers

Solution:
(() => {
    'use strict';

    // main :: IO ()
    const main = () =>
        take(25, weirds());

    // weirds :: Gen [Int]
    function* weirds() {
        let
            x = 1,
            i = 1;
        while (true) {
            x = until(isWeird, succ, x)
            console.log(i.toString() + ' -> ' + x)
            yield x;
            x = 1 + x;
            i = 1 + i;
        }
    }

    // isWeird :: Int -> Bool
    const isWeird = n => {
        const
            ds = descProperDivisors(n),
            d = sum(ds) - n;
        return 0 < d && !hasSum(d, ds)
    };

    // hasSum :: Int -> [Int] -> Bool
    const hasSum = (n, xs) => {
        const go = (n, xs) =>
            0 < xs.length ? (() => {
                const
                    h = xs[0],
                    t = xs.slice(1);
                return n < h ? (
                    go(n, t)
                ) : (
                    n == h || hasSum(n - h, t) || hasSum(n, t)
                );
            })() : false;
        return go(n, xs);
    };

    // descProperDivisors :: Int -> [Int]
    const descProperDivisors = n => {
        const
            rRoot = Math.sqrt(n),
            intRoot = Math.floor(rRoot),
            blnPerfect = rRoot === intRoot,
            lows = enumFromThenTo(intRoot, intRoot - 1, 1)
            .filter(x => (n % x) === 0);
        return (
            reverse(lows)
            .slice(1)
            .map(x => n / x)
        ).concat((blnPerfect ? tail : id)(lows))
    };

    // GENERIC FUNCTIONS ----------------------------

    // enumFromThenTo :: Int -> Int -> Int -> [Int]
    const enumFromThenTo = (x1, x2, y) => {
        const d = x2 - x1;
        return Array.from({
            length: Math.floor(y - x2) / d + 2
        }, (_, i) => x1 + (d * i));
    };

    // id :: a -> a
    const id = x => x;

    // reverse :: [a] -> [a]
    const reverse = xs =>
        'string' !== typeof xs ? (
            xs.slice(0).reverse()
        ) : xs.split('').reverse().join('');

    // succ :: Enum a => a -> a
    const succ = x => 1 + x;

    // sum :: [Num] -> Num
    const sum = xs => xs.reduce((a, x) => a + x, 0);

    // tail :: [a] -> [a]
    const tail = xs => 0 < xs.length ? xs.slice(1) : [];

    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = (n, xs) =>
        'GeneratorFunction' !== xs.constructor.constructor.name ? (
            xs.slice(0, n)
        ) : [].concat.apply([], Array.from({
            length: n
        }, () => {
            const x = xs.next();
            return x.done ? [] : [x.value];
        }));

    // until :: (a -> Bool) -> (a -> a) -> a -> a
    const until = (p, f, x) => {
        let v = x;
        while (!p(v)) v = f(v);
        return v;
    };

    // MAIN ---
    return main();
})();


Weird numbers

Solution:
===Functional===
The first 50 seem to take c. 300 ms


Weird numbers

Solution:
'''Weird numbers'''

from itertools import chain, count, islice, repeat
from functools import reduce
from math import sqrt
from time import time

# weirds :: Gen [Int]
def weirds():
    '''Non-finite stream of weird numbers.
       (Abundant, but not semi-perfect)
       OEIS: A006037
    '''
    def go(n):
        ds = descPropDivs(n)
        d = sum(ds) - n
        return [n] if 0 < d and not hasSum(d, ds) else []
    return concatMap(go)(count(1))

# hasSum :: Int -> [Int] -> Bool
def hasSum(n, xs):
    '''Does any subset of xs sum to n ?
       (Assuming xs to be sorted in descending
       order of magnitude)'''
    def go(n, xs):
        if xs:
            h, t = xs[0], xs[1:]
            if n < h:  # Head too big. Forget it. Tail ?
                return go(n, t)
            else:
                # The head IS the target ?
                # Or the tail contains a sum for the
                # DIFFERENCE between the head and the target ?
                # Or the tail contains some OTHER sum for the target ?
                return n == h or go(n - h, t) or go(n, t)
        else:
            return False
    return go(n, xs)

# descPropDivs :: Int -> [Int]
def descPropDivs(n):
    '''Descending positive divisors of n,
       excluding n itself.'''
    root = sqrt(n)
    intRoot = int(root)
    blnSqr = root == intRoot
    lows = [x for x in range(1, 1 + intRoot) if 0 == n % x]
    return [
        n // x for x in (
            lows[1:-1] if blnSqr else lows[1:]
        )
    ] + list(reversed(lows))

# --------------------------TEST---------------------------

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

    start = time()
    n = 50
    xs = take(n)(weirds())

    print(
        (tabulated('First ' + str(n) + ' weird numbers:\n')(
            lambda i: str(1 + i)
        )(str)(5)(
            index(xs)
        )(range(0, n)))
    )
    print(
        '\nApprox computation time: ' +
        str(int(1000 * (time() - start))) + ' ms'
    )

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

# chunksOf :: Int -> [a] -> [[a]]
def chunksOf(n):
    '''A series of lists of length n,
       subdividing the contents of xs.
       Where the length of xs is not evenly divible,
       the final list will be shorter than n.'''
    return lambda xs: reduce(
        lambda a, i: a + [xs[i:n + i]],
        range(0, len(xs), n), []
    ) if 0 < n else []

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

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

# index (!!) :: [a] -> Int -> a
def index(xs):
    '''Item at given (zero-based) index.'''
    return lambda n: None if 0 > n else (
        xs[n] if (
            hasattr(xs, "__getitem__")
        ) else next(islice(xs, n, None))
    )

# paddedMatrix :: a -> [[a]] -> [[a]]
def paddedMatrix(v):
    ''''A list of rows padded to equal length
        (where needed) with instances of the value v.'''
    def go(rows):
        return paddedRows(
            len(max(rows, key=len))
        )(v)(rows)
    return lambda rows: go(rows) if rows else []

# paddedRows :: Int -> a -> [[a]] -[[a]]
def paddedRows(n):
    '''A list of rows padded (but never truncated)
       to length n with copies of value v.'''
    def go(v, xs):
        def pad(x):
            d = n - len(x)
            return (x + list(repeat(v, d))) if 0 < d else x
        return list(map(pad, xs))
    return lambda v: lambda xs: go(v, xs) if xs else []

# showColumns :: Int -> [String] -> String
def showColumns(n):
    '''A column-wrapped string
       derived from a list of rows.'''
    def go(xs):
        def fit(col):
            w = len(max(col, key=len))

            def pad(x):
                return x.ljust(4 + w, ' ')
            return ''.join(map(pad, col))

        q, r = divmod(len(xs), n)
        return unlines(map(
            fit,
            transpose(paddedMatrix('')(
                chunksOf(q + int(bool(r)))(
                    xs
                )
            ))
        ))
    return lambda xs: go(xs)

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

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

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

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

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

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

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


Word frequency

[[Category:Text processing]]

;Task:
Given a text file and an integer   '''n''',   print/display the   '''n'''   most
common words in the file   (and the number of their occurrences)   in decreasing frequency.

For the purposes of this task:
*   A word is a sequence of one or more contiguous letters.
*   You are free to define what a   ''letter''   is.
*   Underscores, accented letters, apostrophes, hyphens, and other special characters can be handled at your discretion.
*   You may treat a compound word like   '''well-dressed'''   as either one word or two.
*   The word   '''it's'''   could also be one or two words as you see fit.
*   You may also choose not to support non US-ASCII characters.
*   Assume words will not span multiple lines.
*   Don't worry about normalization of word spelling differences.
*   Treat   '''color'''   and   '''colour'''   as two distinct words.
*   Uppercase letters are considered equivalent to their lowercase counterparts.
*   Words of equal frequency can be listed in any order.
*   Feel free to explicitly state the thoughts behind the program decisions.

Show example output using [http://www.gutenberg.org/files/135/135-0.txt Les Misérables from Project Gutenberg] as the text file input and display the top   '''10'''   most used words.

;History:
This task was originally taken from programming pearls from [https://doi.org/10.1145/5948.315654 Communications of the ACM June 1986 Volume 29 Number 6]
where this problem is solved by Donald Knuth using literate programming and then critiqued by Doug McIlroy,
demonstrating solving the problem in a 6 line Unix shell script (provided as an example below).

;References:
*[http://franklinchen.com/blog/2011/12/08/revisiting-knuth-and-mcilroys-word-count-programs/ McIlroy's program]

Solution:
#include
#include
#include

typedef struct word_count_tag {
    const char* word;
    size_t count;
} word_count;

int compare_word_count(const void* p1, const void* p2) {
    const word_count* w1 = p1;
    const word_count* w2 = p2;
    if (w1->count > w2->count)
        return -1;
    if (w1->count < w2->count)
        return 1;
    return 0;
}

bool get_top_words(const char* filename, size_t count) {
    GError* error = NULL;
    GMappedFile* mapped_file = g_mapped_file_new(filename, FALSE, &error);
    if (mapped_file == NULL) {
        fprintf(stderr, "%s\n", error->message);
        g_error_free(error);
        return false;
    }
    const char* text = g_mapped_file_get_contents(mapped_file);
    if (text == NULL) {
        fprintf(stderr, "File %s is empty\n", filename);
        g_mapped_file_unref(mapped_file);
        return false;
    }
    gsize file_size = g_mapped_file_get_length(mapped_file);
    // Store word counts in a hash table
    GHashTable* ht = g_hash_table_new_full(g_str_hash, g_str_equal,
                                           g_free, g_free);
    GRegex* regex = g_regex_new("\\w+", 0, 0, NULL);
    GMatchInfo* match_info;
    g_regex_match_full(regex, text, file_size, 0, 0, &match_info, NULL);
    while (g_match_info_matches(match_info)) {
        char* word = g_match_info_fetch(match_info, 0);
        char* lower = g_utf8_strdown(word, -1);
        g_free(word);
        size_t* count = g_hash_table_lookup(ht, lower);
        if (count != NULL) {
            ++*count;
            g_free(lower);
        } else {
            count = g_new(size_t, 1);
            *count = 1;
            g_hash_table_insert(ht, lower, count);
        }
        g_match_info_next(match_info, NULL);
    }
    g_match_info_free(match_info);
    g_regex_unref(regex);
    g_mapped_file_unref(mapped_file);

    // Sort words in decreasing order of frequency
    size_t size = g_hash_table_size(ht);
    word_count* words = g_new(word_count, size);
    GHashTableIter iter;
    gpointer key, value;
    g_hash_table_iter_init(&iter, ht);
    for (size_t i = 0; g_hash_table_iter_next(&iter, &key, &value); ++i) {
        words[i].word = key;
        words[i].count = *(size_t*)value;
    }
    qsort(words, size, sizeof(word_count), compare_word_count);

    // Print the most common words
    if (count > size)
        count = size;
    printf("Top %lu words\n", count);
    printf("Rank\tCount\tWord\n");
    for (size_t i = 0; i < count; ++i)
        printf("%lu\t%lu\t%s\n", i + 1, words[i].count, words[i].word);
    g_free(words);
    g_hash_table_destroy(ht);
    return true;
}

int main(int argc, char** argv) {
    if (argc != 2) {
        fprintf(stderr, "usage: %s file\n", argv[0]);
        return EXIT_FAILURE;
    }
    if (!get_top_words(argv[1], 10))
        return EXIT_FAILURE;
    return EXIT_SUCCESS;
}


Word frequency

Solution:
import collections
import re
import string
import sys

def main():
  counter = collections.Counter(re.findall(r"\w+",open(sys.argv[1]).read().lower()))
  print counter.most_common(int(sys.argv[2]))

if __name__ == "__main__":
  main()


Word search

A word search puzzle typically consists of a grid of letters in which words are hidden.

There are many varieties of word search puzzles. For the task at hand we will use a rectangular grid in which the words may be placed horizontally, vertically, or diagonally. The words may also be spelled backwards.

The words may overlap but are not allowed to zigzag, or wrap around.

;Task
Create a 10 by 10 word search and fill it using words from the [http://www.puzzlers.org/pub/wordlists/unixdict.txt unixdict]. Use only words that are longer than 2, and contain no non-alphabetic characters.

The cells not used by the hidden words should contain the message: ''Rosetta Code'', read from left to right, top to bottom. These letters should be somewhat evenly distributed over the grid, not clumped together. The message should be in upper case, the hidden words in lower case. All cells should either contain letters from the hidden words or from the message.

Pack a minimum of 25 words into the grid.

Print the resulting grid and the solutions.

;Example

     0  1  2  3  4  5  6  7  8  9

0    n  a  y  r  y  R  e  l  m  f
1    y  O  r  e  t  s  g  n  a  g
2    t  n  e  d  i  S  k  y  h  E
3    n  o  t  n  c  p  c  w  t  T
4    a  l  s  u  u  n  T  m  a  x
5    r  o  k  p  a  r  i  s  h  h
6    a  A  c  f  p  a  e  a  c  C
7    u  b  u  t  t  t  O  l  u  n
8    g  y  h  w  a  D  h  p  m  u
9    m  i  r  p  E  h  o  g  a  n

parish     (3,5)(8,5)   gangster   (9,1)(2,1)
paucity    (4,6)(4,0)   guaranty   (0,8)(0,1)
prim       (3,9)(0,9)   huckster   (2,8)(2,1)
plasm      (7,8)(7,4)   fancy      (3,6)(7,2)
hogan      (5,9)(9,9)   nolo       (1,2)(1,5)
under      (3,4)(3,0)   chatham    (8,6)(8,0)
ate        (4,8)(6,6)   nun        (9,7)(9,9)
butt       (1,7)(4,7)   hawk       (9,5)(6,2)
why        (3,8)(1,8)   ryan       (3,0)(0,0)
fay        (9,0)(7,2)   much       (8,8)(8,5)
tar        (5,7)(5,5)   elm        (6,0)(8,0)
max        (7,4)(9,4)   pup        (5,3)(3,5)
mph        (8,8)(6,8)

Solution:
import re
from random import shuffle, randint

dirs = [[1, 0], [0, 1], [1, 1], [1, -1], [-1, 0], [0, -1], [-1, -1], [-1, 1]]
n_rows = 10
n_cols = 10
grid_size = n_rows * n_cols
min_words = 25

class Grid:
    def __init__(self):
        self.num_attempts = 0
        self.cells = [['' for _ in range(n_cols)] for _ in range(n_rows)]
        self.solutions = []

def read_words(filename):
    max_len = max(n_rows, n_cols)

    words = []
    with open(filename, "r") as file:
        for line in file:
            s = line.strip().lower()
            if re.match(r'^[a-z]{3,' + re.escape(str(max_len)) + r'}$', s) is not None:
                words.append(s)

    return words

def place_message(grid, msg):
    msg = re.sub(r'[^A-Z]', "", msg.upper())

    message_len = len(msg)
    if 0 < message_len < grid_size:
        gap_size = grid_size // message_len

        for i in range(0, message_len):
            pos = i * gap_size + randint(0, gap_size)
            grid.cells[pos // n_cols][pos % n_cols] = msg[i]

        return message_len

    return 0

def try_location(grid, word, direction, pos):
    r = pos // n_cols
    c = pos % n_cols
    length = len(word)

    # check bounds
    if (dirs[direction][0] == 1 and (length + c) > n_cols) or \
       (dirs[direction][0] == -1 and (length - 1) > c) or \
       (dirs[direction][1] == 1 and (length + r) > n_rows) or \
       (dirs[direction][1] == -1 and (length - 1) > r):
        return 0

    rr = r
    cc = c
    i = 0
    overlaps = 0

    # check cells
    while i < length:
        if grid.cells[rr][cc] != '' and grid.cells[rr][cc] != word[i]:
            return 0
        cc += dirs[direction][0]
        rr += dirs[direction][1]
        i += 1

    rr = r
    cc = c
    i = 0
    # place
    while i < length:
        if grid.cells[rr][cc] == word[i]:
            overlaps += 1
        else:
            grid.cells[rr][cc] = word[i]

        if i < length - 1:
            cc += dirs[direction][0]
            rr += dirs[direction][1]

        i += 1

    letters_placed = length - overlaps
    if letters_placed > 0:
        grid.solutions.append("{0:<10} ({1},{2})({3},{4})".format(word, c, r, cc, rr))

    return letters_placed

def try_place_word(grid, word):
    rand_dir = randint(0, len(dirs))
    rand_pos = randint(0, grid_size)

    for direction in range(0, len(dirs)):
        direction = (direction + rand_dir) % len(dirs)

        for pos in range(0, grid_size):
            pos = (pos + rand_pos) % grid_size

            letters_placed = try_location(grid, word, direction, pos)
            if letters_placed > 0:
                return letters_placed

    return 0

def create_word_search(words):
    grid = None
    num_attempts = 0

    while num_attempts < 100:
        num_attempts += 1
        shuffle(words)

        grid = Grid()
        message_len = place_message(grid, "Rosetta Code")
        target = grid_size - message_len

        cells_filled = 0
        for word in words:
            cells_filled += try_place_word(grid, word)
            if cells_filled == target:
                if len(grid.solutions) >= min_words:
                    grid.num_attempts = num_attempts
                    return grid
                else:
                    break # grid is full but we didn't pack enough words, start over

    return grid

def print_result(grid):
    if grid is None or grid.num_attempts == 0:
        print("No grid to display")
        return

    size = len(grid.solutions)

    print("Attempts: {0}".format(grid.num_attempts))
    print("Number of words: {0}".format(size))

    print("\n     0  1  2  3  4  5  6  7  8  9\n")
    for r in range(0, n_rows):
        print("{0}   ".format(r), end='')
        for c in range(0, n_cols):
            print(" %c " % grid.cells[r][c], end='')
        print()
    print()

    for i in range(0, size - 1, 2):
        print("{0}   {1}".format(grid.solutions[i], grid.solutions[i+1]))

    if size % 2 == 1:
        print(grid.solutions[size - 1])

if __name__ == "__main__":
    print_result(create_word_search(read_words("unixdict.txt")))


Word wrap

[[Category:Text processing]]

Even today, with proportional fonts and complex layouts, there are still cases where you need to wrap text at a specified column.

;Basic task:
The basic task is to wrap a paragraph of text in a simple way in your language.

If there is a way to do this that is built-in, trivial, or provided in a standard library, show that.  Otherwise implement the [http://en.wikipedia.org/wiki/Word_wrap#Minimum_length minimum length greedy algorithm from Wikipedia.]

Show your routine working on a sample of text at two different wrap columns.

;Extra credit:
Wrap text using a more sophisticated algorithm such as the Knuth and Plass TeX algorithm.
If your language provides this, you get easy extra credit,
but you ''must reference documentation'' indicating that the algorithm
is something better than a simple minimum length algorithm.

If you have both basic and extra credit solutions, show an example where
the two algorithms give different results.

Solution:
#include
#include
#include
#include

/* nonsensical hyphens to make greedy wrapping method look bad */
const char *string = "In olden times when wishing still helped one, there lived a king "
    "whose daughters were all beautiful, but the youngest was so beautiful "
    "that the sun itself, which has seen so much, was astonished whenever "
    "it shone-in-her-face.  Close-by-the-king's castle lay a great dark "
    "forest, and under an old lime-tree in the forest was a well, and when "
    "the day was very warm, the king's child went out into the forest and "
    "sat down by the side of the cool-fountain, and when she was bored she "
    "took a golden ball, and threw it up on high and caught it, and this "
    "ball was her favorite plaything.";

/*  Each but the last of wrapped lines comes with some penalty as the square
    of the diff between line length and desired line length.  If the line
    is longer than desired length, the penalty is multiplied by 100.  This
    pretty much prohibits the wrapping routine from going over right margin.
    If is ok to exceed the margin just a little, something like 20 or 40 will
    do.

    Knuth uses a per-paragraph penalty for line-breaking in TeX, which is--
    unlike what I have here--probably bug-free.
*/

#define PENALTY_LONG    100
#define PENALTY_SHORT   1

typedef struct word_t {
    const char *s;
    int len;
} *word;

word make_word_list(const char *s, int *n)
{
    int max_n = 0;
    word words = 0;

    *n = 0;
    while (1) {
        while (*s && isspace(*s)) s++;
        if (!*s) break;

        if (*n >= max_n) {
            if (!(max_n *= 2)) max_n = 2;
            words = realloc(words, max_n * sizeof(*words));
        }
        words[*n].s = s;
        while (*s && !isspace(*s)) s++;
        words[*n].len = s - words[*n].s;
        (*n) ++;
    }

    return words;
}

int greedy_wrap(word words, int count, int cols, int *breaks)
{
    int score = 0, line, i, j, d;

    i = j = line = 0;
    while (1) {
        if (i == count) {
            breaks[j++] = i;
            break;
        }

        if (!line) {
            line = words[i++].len;
            continue;
        }

        if (line + words[i].len < cols) {
            line += words[i++].len + 1;
            continue;
        }

        breaks[j++] = i;
        if (i < count) {
            d = cols - line;
            if (d > 0)  score += PENALTY_SHORT * d * d;
            else if (d < 0) score += PENALTY_LONG * d * d;
        }

        line = 0;
    }
    breaks[j++] = 0;

    return score;
}

/* tries to make right margin more even; pretty sure there's an off-by-one bug
    here somewhere */
int balanced_wrap(word words, int count, int cols, int *breaks)
{
    int *best = malloc(sizeof(int) * (count + 1));

    /* do a greedy wrap to have some baseline score to work with, else
       we'll end up with O(2^N) behavior */
    int best_score = greedy_wrap(words, count, cols, breaks);

    void test_wrap(int line_no, int start, int score) {
        int line = 0, current_score = -1, d;

        while (start <= count) {
            if (line) line ++;
            line += words[start++].len;
            d = cols - line;
            if (start < count || d < 0) {
                if (d > 0)
                    current_score = score + PENALTY_SHORT * d * d;
                else
                    current_score = score + PENALTY_LONG * d * d;
            } else {
                current_score = score;
            }

            if (current_score >= best_score) {
                if (d <= 0) return;
                continue;
            }

            best[line_no] = start;
            test_wrap(line_no + 1, start, current_score);
        }
        if (current_score >= 0 && current_score < best_score) {
            best_score = current_score;
            memcpy(breaks, best, sizeof(int) * (line_no));
        }
    }
    test_wrap(0, 0, 0);
    free(best);

    return best_score;
}

void show_wrap(word list, int count, int *breaks)
{
    int i, j;
    for (i = j = 0; i < count && breaks[i]; i++) {
        while (j < breaks[i]) {
            printf("%.*s", list[j].len, list[j].s);
            if (j < breaks[i] - 1)
                putchar(' ');
            j++;
        }
        if (breaks[i]) putchar('\n');
    }
}

int main(void)
{
    int len, score, cols;
    word list = make_word_list(string, &len);
    int *breaks = malloc(sizeof(int) * (len + 1));

    cols = 80;
    score = greedy_wrap(list, len, cols, breaks);
    printf("\n== greedy wrap at %d (score %d) ==\n\n", cols, score);
    show_wrap(list, len, breaks);

    score = balanced_wrap(list, len, cols, breaks);
    printf("\n== balanced wrap at %d (score %d) ==\n\n", cols, score);
    show_wrap(list, len, breaks);

    cols = 32;
    score = greedy_wrap(list, len, cols, breaks);
    printf("\n== greedy wrap at %d (score %d) ==\n\n", cols, score);
    show_wrap(list, len, breaks);

    score = balanced_wrap(list, len, cols, breaks);
    printf("\n== balanced wrap at %d (score %d) ==\n\n", cols, score);
    show_wrap(list, len, breaks);

    return 0;
}


Word wrap

Solution:
function wrap (text, limit) {
  if (text.length > limit) {
    // find the last space within limit
    var edge = text.slice(0, limit).lastIndexOf(' ');
    if (edge > 0) {
      var line = text.slice(0, edge);
      var remainder = text.slice(edge + 1);
      return line + '\n' + wrap(remainder, limit);
    }
  }
  return text;
}


Word wrap

Solution:
>>> import textwrap
>>> help(textwrap.fill)
Help on function fill in module textwrap:

fill(text, width=70, **kwargs)
    Fill a single paragraph of text, returning a new string.

    Reformat the single paragraph in 'text' to fit in lines of no more
    than 'width' columns, and return a new string containing the entire
    wrapped paragraph.  As with wrap(), tabs are expanded and other
    whitespace characters converted to space.  See TextWrapper class for
    available keyword args to customize wrapping behaviour.

>>> txt = '''\
Reformat the single paragraph in 'text' to fit in lines of no more
than 'width' columns, and return a new string containing the entire
wrapped paragraph.  As with wrap(), tabs are expanded and other
whitespace characters converted to space.  See TextWrapper class for
available keyword args to customize wrapping behaviour.'''
>>> print(textwrap.fill(txt, width=75))
Reformat the single paragraph in 'text' to fit in lines of no more than
'width' columns, and return a new string containing the entire wrapped
paragraph.  As with wrap(), tabs are expanded and other whitespace
characters converted to space.  See TextWrapper class for available keyword
args to customize wrapping behaviour.
>>> print(textwrap.fill(txt, width=45))
Reformat the single paragraph in 'text' to
fit in lines of no more than 'width' columns,
and return a new string containing the entire
wrapped paragraph.  As with wrap(), tabs are
expanded and other whitespace characters
converted to space.  See TextWrapper class
for available keyword args to customize
wrapping behaviour.
>>> print(textwrap.fill(txt, width=85))
Reformat the single paragraph in 'text' to fit in lines of no more than 'width'
columns, and return a new string containing the entire wrapped paragraph.  As with
wrap(), tabs are expanded and other whitespace characters converted to space.  See
TextWrapper class for available keyword args to customize wrapping behaviour.
>>>


World Cup group stage

It's World Cup season (or at least it was when this page was created)!

The World Cup is an international football/soccer tournament that happens every 4 years.   Countries put their international teams together in the years between tournaments and qualify for the tournament based on their performance in other international games.   Once a team has qualified they are put into a group with 3 other teams.

For the first part of the World Cup tournament the teams play in "group stage" games where each of the four teams in a group plays all three other teams once.   The results of these games determine which teams will move on to the "knockout stage" which is a standard single-elimination tournament.   The two teams from each group with the most standings points move on to the knockout stage.

Each game can result in a win for one team and a loss for the other team or it can result in a draw/tie for each team.
:::*   A win is worth three points.
:::*   A draw/tie is worth one point.
:::*   A loss is worth zero points.

;Task:
:*   Generate all possible outcome combinations for the six group stage games.   With three possible outcomes for each game there should be 36 = 729 of them.
:*   Calculate the standings points for each team with each combination of outcomes.
:*   Show a histogram (graphical,   ASCII art, or straight counts--whichever is easiest/most fun) of the standings points for all four teams over all possible outcomes.

Don't worry about tiebreakers as they can get complicated.   We are basically looking to answer the question "if a team gets x standings points, where can they expect to end up in the group standings?".

''Hint: there should be no possible way to end up in second place with less than two points as well as no way to end up in first with less than three.   Oddly enough, there is no way to get 8 points at all.''

Solution:
#include
#include
#include
#include

// to supply to qsort
int compare(const void *a, const void *b) {
    int int_a = *((int *)a);
    int int_b = *((int *)b);
    return (int_a > int_b) - (int_a < int_b);
}

char results[7];
bool next_result() {
    char *ptr = results + 5;
    int num = 0;
    size_t i;

    // check if the space has been examined
    if (strcmp(results, "222222") == 0) {
        return false;
    }

    // translate the base 3 string back to a base 10 integer
    for (i = 0; results[i] != 0; i++) {
        int d = results[i] - '0';
        num = 3 * num + d;
    }

    // to the next value to process
    num++;

    // write the base 3 string (fixed width)
    while (num > 0) {
        int rem = num % 3;
        num /= 3;
        *ptr-- = rem + '0';
    }
    // zero fill the remainder
    while (ptr > results) {
        *ptr-- = '0';
    }

    return true;
}

char *games[6] = { "12", "13", "14", "23", "24", "34" };
char *places[4] = { "1st", "2nd", "3rd", "4th" };
int main() {
    int points[4][10];
    size_t i, j;

    strcpy(results, "000000");
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 10; j++) {
            points[i][j] = 0;
        }
    }

    do {
        int records[] = { 0, 0, 0, 0 };

        for (i = 0; i < 6; i++) {
            switch (results[i]) {
            case '2':
                records[games[i][0] - '1'] += 3;
                break;
            case '1':
                records[games[i][0] - '1']++;
                records[games[i][1] - '1']++;
                break;
            case '0':
                records[games[i][1] - '1'] += 3;
                break;
            default:
                break;
            }
        }

        qsort(records, 4, sizeof(int), compare);
        for (i = 0; i < 4; i++) {
            points[i][records[i]]++;
        }
    } while (next_result());

    printf("POINTS       0    1    2    3    4    5    6    7    8    9\n");
    printf("-----------------------------------------------------------\n");
    for (i = 0; i < 4; i++) {
        printf("%s place", places[i]);
        for (j = 0; j < 10; j++) {
            printf("%5d", points[3 - i][j]);
        }
        printf("\n");
    }

    return 0;
}


World Cup group stage

Solution:
from itertools import product, combinations, izip

scoring = [0, 1, 3]
histo = [[0] * 10 for _ in xrange(4)]

for results in product(range(3), repeat=6):
    s = [0] * 4
    for r, g in izip(results, combinations(range(4), 2)):
        s[g[0]] += scoring[r]
        s[g[1]] += scoring[2 - r]

    for h, v in izip(histo, sorted(s)):
        h[v] += 1

for x in reversed(histo):
    print x


Write float arrays to a text file

;Task:
Write two equal-sized numerical arrays 'x' and 'y' to
a two-column text file named 'filename'.

The first column of the file contains values from an 'x'-array with a
given 'xprecision', the second -- values from 'y'-array with 'yprecision'.

For example, considering:
    x = {1, 2, 3, 1e11};
    y = {1, 1.4142135623730951, 1.7320508075688772, 316227.76601683791};
                                                           /* sqrt(x) */
    xprecision = 3;
    yprecision = 5;

The file should look like:
    1    1
    2    1.4142
    3    1.7321
    1e+011   3.1623e+005

This task is intended as a subtask for [[Measure relative performance of sorting algorithms implementations]].

Solution:
#include
#include

int main(int argc, char **argv) {

   float x[4] = {1,2,3,1e11}, y[4];
   int i = 0;
   FILE *filePtr;

   filePtr = fopen("floatArray","w");

   for (i = 0; i < 4; i++) {
      y[i] = sqrt(x[i]);
      fprintf(filePtr, "%.3g\t%.5g\n", x[i], y[i]);
   }

   return 0;
}


Write float arrays to a text file

Solution:
>>> import math
>>> x = [1, 2, 3, 1e11]
>>> y = map(math.sqrt, x)
>>> y
[1.0, 1.4142135623730951, 1.7320508075688772, 316227.76601683791]
>>> writedat("sqrt.dat", x, y)
>>> # check
...
>>> for line in open('sqrt.dat'):
...   print line,
...
1       1
2       1.4142
3       1.7321
1e+011  3.1623e+005


Write float arrays to a text file

Solution:
def writedat(filename, x, y, xprecision=3, yprecision=5):
    with open(filename,'w') as f:
        for a, b in zip(x, y):
            print("%.*g\t%.*g" % (xprecision, a, yprecision, b), file=f)
            #or, using the new-style formatting:
            #print("{1:.{0}g}\t{3:.{2}g}".format(xprecision, a, yprecision, b), file=f)


Write language name in 3D ASCII

;Task:
Write/display a language's name in '''3D''' ASCII.

(We can leave the definition of "3D ASCII" fuzzy,
so long as the result is interesting or amusing,
not a cheap hack to satisfy the task.)

;Related tasks:
* draw a sphere
* draw a cuboid
* draw a rotating cube
* draw a Deathstar

Solution:
#include
const char*s = "  _____\n /____/\\\n/  ___\\/\n\\  \\/__/\n \\____/";
int main(){ puts(s); return 0; }


Write language name in 3D ASCII

Solution:
py = '''\
 ####   #   #  #####  #   #   ###   #   #
 #   #   # #     #    #   #  #   #  ##  #
 ####     #      #    #####  #   #  # # #
 #        #      #    #   #  #   #  #  ##
 #        #      #    #   #   ###   #   #'''

lines = py.replace('#', '<<<').replace(' ','X') \
        .replace('X', '   ').replace('\n', ' Y') \
        .replace('< ', '<>').split('Y')

for i, l in enumerate(lines):
    print('  ' * (len(lines) - i) + l)


Write to Windows event log

;Task:
Write script status to the Windows Event Log

Solution:
#include
#include

int main(int argC,char* argV[])
{
	char str[1000];

	if(argC!=5)
		printf("Usage : %s < Followed by level, id, source string and description>",argV[0]);
	else{
		sprintf(str,"EventCreate /t %s /id %s /l APPLICATION /so %s /d \"%s\"",argV[1],argV[2],argV[3],argV[4]);
		system(str);
	}

	return 0;
}


Write to Windows event log

Solution:
import win32api
import win32con
import win32evtlog
import win32security
import win32evtlogutil

ph = win32api.GetCurrentProcess()
th = win32security.OpenProcessToken(ph, win32con.TOKEN_READ)
my_sid = win32security.GetTokenInformation(th, win32security.TokenUser)[0]

applicationName = "My Application"
eventID = 1
category = 5	# Shell
myType = win32evtlog.EVENTLOG_WARNING_TYPE
descr = ["A warning", "An even more dire warning"]
data = "Application\0Data".encode("ascii")

win32evtlogutil.ReportEvent(applicationName, eventID, eventCategory=category,
	eventType=myType, strings=descr, data=data, sid=my_sid)


Yellowstone sequence

[[Category:Prime Numbers]]

The '''Yellowstone sequence''', also called the '''Yellowstone permutation''', is defined as:

For n <= 3,

    a(n) = n

For n >= 4,

    a(n) = the smallest number not already in sequence such that a(n) is relatively prime to a(n-1) and
           is not relatively prime to a(n-2).

The sequence is a permutation of the natural numbers, and gets its name from what its authors felt was a spiking, geyser like appearance of a plot of the sequence.

;Example:
a(4) is 4 because 4 is the smallest number following 1, 2, 3 in the sequence that is relatively prime to the entry before it (3), and is not relatively prime to the number two entries before it (2).

;Task
: Find and show as output the first  '''30'''  Yellowstone numbers.

;Extra
:  Demonstrate how to plot, with x = n and y coordinate a(n), the first 100 Yellowstone numbers.

;Related tasks:
:*   [https://rosettacode.org/wiki/Greatest_common_divisor Greatest common divisor].
:*   [https://rosettacode.org/wiki/Plot_coordinate_pairs Plot coordinate pairs].

;See also:
:*   The OEIS entry:   [https://oeis.org/A098550 A098550 The Yellowstone permutation].
:*   Applegate et al, 2015: The Yellowstone Permutation [https://arxiv.org/abs/1501.01669].

Solution:
#include
#include
#include

typedef struct lnode_t {
    struct lnode_t *prev;
    struct lnode_t *next;
    int v;
} Lnode;

Lnode *make_list_node(int v) {
    Lnode *node = malloc(sizeof(Lnode));
    if (node == NULL) {
        return NULL;
    }
    node->v = v;
    node->prev = NULL;
    node->next = NULL;
    return node;
}

void free_lnode(Lnode *node) {
    if (node == NULL) {
        return;
    }

    node->v = 0;
    node->prev = NULL;
    free_lnode(node->next);
    node->next = NULL;
}

typedef struct list_t {
    Lnode *front;
    Lnode *back;
    size_t len;
} List;

List *make_list() {
    List *list = malloc(sizeof(List));
    if (list == NULL) {
        return NULL;
    }
    list->front = NULL;
    list->back = NULL;
    list->len = 0;
    return list;
}

void free_list(List *list) {
    if (list == NULL) {
        return;
    }
    list->len = 0;
    list->back = NULL;
    free_lnode(list->front);
    list->front = NULL;
}

void list_insert(List *list, int v) {
    Lnode *node;

    if (list == NULL) {
        return;
    }

    node = make_list_node(v);
    if (list->front == NULL) {
        list->front = node;
        list->back = node;
        list->len = 1;
    } else {
        node->prev = list->back;
        list->back->next = node;
        list->back = node;
        list->len++;
    }
}

void list_print(List *list) {
    Lnode *it;

    if (list == NULL) {
        return;
    }

    for (it = list->front; it != NULL; it = it->next) {
        printf("%d ", it->v);
    }
}

int list_get(List *list, int idx) {
    Lnode *it = NULL;

    if (list != NULL && list->front != NULL) {
        int i;
        if (idx < 0) {
            it = list->back;
            i = -1;
            while (it != NULL && i > idx) {
                it = it->prev;
                i--;
            }
        } else {
            it = list->front;
            i = 0;
            while (it != NULL && i < idx) {
                it = it->next;
                i++;
            }
        }
    }

    if (it == NULL) {
        return INT_MIN;
    }
    return it->v;
}

///////////////////////////////////////

typedef struct mnode_t {
    int k;
    bool v;
    struct mnode_t *next;
} Mnode;

Mnode *make_map_node(int k, bool v) {
    Mnode *node = malloc(sizeof(Mnode));
    if (node == NULL) {
        return node;
    }
    node->k = k;
    node->v = v;
    node->next = NULL;
    return node;
}

void free_mnode(Mnode *node) {
    if (node == NULL) {
        return;
    }
    node->k = 0;
    node->v = false;
    free_mnode(node->next);
    node->next = NULL;
}

typedef struct map_t {
    Mnode *front;
} Map;

Map *make_map() {
    Map *map = malloc(sizeof(Map));
    if (map == NULL) {
        return NULL;
    }
    map->front = NULL;
    return map;
}

void free_map(Map *map) {
    if (map == NULL) {
        return;
    }
    free_mnode(map->front);
    map->front = NULL;
}

void map_insert(Map *map, int k, bool v) {
    if (map == NULL) {
        return;
    }
    if (map->front == NULL) {
        map->front = make_map_node(k, v);
    } else {
        Mnode *it = map->front;
        while (it->next != NULL) {
            it = it->next;
        }
        it->next = make_map_node(k, v);
    }
}

bool map_get(Map *map, int k) {
    if (map != NULL) {
        Mnode *it = map->front;
        while (it != NULL && it->k != k) {
            it = it->next;
        }
        if (it != NULL) {
            return it->v;
        }
    }
    return false;
}

///////////////////////////////////////

int gcd(int u, int v) {
    if (u < 0) u = -u;
    if (v < 0) v = -v;
    if (v) {
        while ((u %= v) && (v %= u));
    }
    return u + v;
}

List *yellow(size_t n) {
    List *a;
    Map *b;
    int i;

    a = make_list();
    list_insert(a, 1);
    list_insert(a, 2);
    list_insert(a, 3);

    b = make_map();
    map_insert(b, 1, true);
    map_insert(b, 2, true);
    map_insert(b, 3, true);

    i = 4;

    while (n > a->len) {
        if (!map_get(b, i) && gcd(i, list_get(a, -1)) == 1 && gcd(i, list_get(a, -2)) > 1) {
            list_insert(a, i);
            map_insert(b, i, true);
            i = 4;
        }
        i++;
    }

    free_map(b);
    return a;
}

int main() {
    List *a = yellow(30);
    list_print(a);
    free_list(a);
    putc('\n', stdout);
    return 0;
}


Yellowstone sequence

Solution:
(() => {
    'use strict';

    // yellowstone :: Generator [Int]
    function* yellowstone() {
        // A non finite stream of terms in the
        // Yellowstone permutation of the natural numbers.
        // OEIS A098550
        const nextWindow = ([p2, p1, rest]) => {
            const [rp2, rp1] = [p2, p1].map(
                relativelyPrime
            );
            const go = xxs => {
                const [x, xs] = Array.from(
                    uncons(xxs).Just
                );
                return rp1(x) && !rp2(x) ? (
                    Tuple(x)(xs)
                ) : secondArrow(cons(x))(
                    go(xs)
                );
            };
            return [p1, ...Array.from(go(rest))];
        };
        const A098550 = fmapGen(x => x[1])(
            iterate(nextWindow)(
                [2, 3, enumFrom(4)]
            )
        );
        yield 1
        yield 2
        while (true)(
            yield A098550.next().value
        )
    };

    // relativelyPrime :: Int -> Int -> Bool
    const relativelyPrime = a =>
        // True if a is relatively prime to b.
        b => 1 === gcd(a)(b);

    // ------------------------TEST------------------------
    const main = () => console.log(
        take(30)(
            yellowstone()
        )
    );

    // -----------------GENERIC FUNCTIONS------------------

    // Just :: a -> Maybe a
    const Just = x => ({
        type: 'Maybe',
        Nothing: false,
        Just: x
    });

    // Nothing :: Maybe a
    const Nothing = () => ({
        type: 'Maybe',
        Nothing: true,
    });

    // Tuple (,) :: a -> b -> (a, b)
    const Tuple = a =>
        b => ({
            type: 'Tuple',
            '0': a,
            '1': b,
            length: 2
        });

    // abs :: Num -> Num
    const abs =
        // Absolute value of a given number - without the sign.
        Math.abs;

    // cons :: a -> [a] -> [a]
    const cons = x =>
        xs => Array.isArray(xs) ? (
            [x].concat(xs)
        ) : 'GeneratorFunction' !== xs
        .constructor.constructor.name ? (
            x + xs
        ) : ( // cons(x)(Generator)
            function*() {
                yield x;
                let nxt = xs.next()
                while (!nxt.done) {
                    yield nxt.value;
                    nxt = xs.next();
                }
            }
        )();

    // enumFrom :: Enum a => a -> [a]
    function* enumFrom(x) {
        // A non-finite succession of enumerable
        // values, starting with the value x.
        let v = x;
        while (true) {
            yield v;
            v = 1 + v;
        }
    }

    // fmapGen <$> :: (a -> b) -> Gen [a] -> Gen [b]
    const fmapGen = f =>
        function*(gen) {
            let v = take(1)(gen);
            while (0 < v.length) {
                yield(f(v[0]))
                v = take(1)(gen)
            }
        };

    // gcd :: Int -> Int -> Int
    const gcd = x => y => {
        const
            _gcd = (a, b) => (0 === b ? a : _gcd(b, a % b)),
            abs = Math.abs;
        return _gcd(abs(x), abs(y));
    };

    // iterate :: (a -> a) -> a -> Gen [a]
    const iterate = f =>
        function*(x) {
            let v = x;
            while (true) {
                yield(v);
                v = f(v);
            }
        };

    // length :: [a] -> Int
    const length = xs =>
        // Returns Infinity over objects without finite
        // length. This enables zip and zipWith to choose
        // the shorter argument when one is non-finite,
        // like cycle, repeat etc
        (Array.isArray(xs) || 'string' === typeof xs) ? (
            xs.length
        ) : Infinity;

    // secondArrow :: (a -> b) -> ((c, a) -> (c, b))
    const secondArrow = f => xy =>
        // A function over a simple value lifted
        // to a function over a tuple.
        // f (a, b) -> (a, f(b))
        Tuple(xy[0])(
            f(xy[1])
        );

    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = n =>
        // The first n elements of a list,
        // string of characters, or stream.
        xs => 'GeneratorFunction' !== xs
        .constructor.constructor.name ? (
            xs.slice(0, n)
        ) : [].concat.apply([], Array.from({
            length: n
        }, () => {
            const x = xs.next();
            return x.done ? [] : [x.value];
        }));

    // uncons :: [a] -> Maybe (a, [a])
    const uncons = xs => {
        // Just a tuple of the head of xs and its tail,
        // Or Nothing if xs is an empty list.
        const lng = length(xs);
        return (0 < lng) ? (
            Infinity > lng ? (
                Just(Tuple(xs[0])(xs.slice(1))) // Finite list
            ) : (() => {
                const nxt = take(1)(xs);
                return 0 < nxt.length ? (
                    Just(Tuple(nxt[0])(xs))
                ) : Nothing();
            })() // Lazy generator
        ) : Nothing();
    };

    // MAIN ---
    return main();
})();


Yellowstone sequence

Solution:
'''Yellowstone permutation OEIS A098550'''

from itertools import chain, count, islice
from operator import itemgetter
from math import gcd

from matplotlib import pyplot

# yellowstone :: [Int]
def yellowstone():
    '''A non-finite stream of terms from
       the Yellowstone permutation.
       OEIS A098550.
    '''
    # relativelyPrime :: Int -> Int -> Bool
    def relativelyPrime(a):
        return lambda b: 1 == gcd(a, b)

    # nextWindow :: (Int, Int, [Int]) -> (Int, Int, [Int])
    def nextWindow(triple):
        p2, p1, rest = triple
        [rp2, rp1] = map(relativelyPrime, [p2, p1])

        # match :: [Int] -> (Int, [Int])
        def match(xxs):
            x, xs = uncons(xxs)['Just']
            return (x, xs) if rp1(x) and not rp2(x) else (
                second(cons(x))(
                    match(xs)
                )
            )
        n, residue = match(rest)
        return (p1, n, residue)

    return chain(
        range(1, 3),
        map(
            itemgetter(1),
            iterate(nextWindow)(
                (2, 3, count(4))
            )
        )
    )

# TEST ----------------------------------------------------
# main :: IO ()
def main():
    '''Terms of the Yellowstone permutation.'''

    print(showList(
        take(30)(yellowstone())
    ))
    pyplot.plot(
        take(100)(yellowstone())
    )
    pyplot.xlabel(main.__doc__)
    pyplot.show()

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

# cons :: a -> [a] -> [a]
def cons(x):
    '''Construction of a list from x as head,
       and xs as tail.
    '''
    return lambda xs: [x] + xs if (
        isinstance(xs, list)
    ) else x + xs if (
        isinstance(xs, str)
    ) else chain([x], xs)

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

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

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

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

# uncons :: [a] -> Maybe (a, [a])
def uncons(xs):
    '''The deconstruction of a non-empty list
       (or generator stream) into two parts:
       a head value, and the remaining values.
    '''
    if isinstance(xs, list):
        return Just((xs[0], xs[1:])) if xs else Nothing()
    else:
        nxt = take(1)(xs)
        return Just((nxt[0], xs)) if nxt else Nothing()

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


Zeckendorf number representation

Just as numbers can be represented in a positional notation as sums of multiples of the powers of ten (decimal) or two (binary); all the positive integers can be represented as the sum of one or zero times the distinct members of the Fibonacci series.

Recall that the first six distinct Fibonacci numbers are:  1, 2, 3, 5, 8, 13.

The decimal number eleven can be written as 0*13 + 1*8 + 0*5 + 1*3 + 0*2 + 0*1 or 010100 in positional notation where the columns represent multiplication by a particular member of the sequence. Leading zeroes are dropped so that 11 decimal becomes 10100.

10100 is not the only way to make 11 from the Fibonacci numbers however;  0*13 + 1*8 + 0*5 + 0*3 + 1*2 + 1*1 or 010011 would also represent decimal 11. For a true Zeckendorf number there is the added restriction that ''no two consecutive Fibonacci numbers can be used'' which leads to the former unique solution.

;Task:
Generate and show here a table of the Zeckendorf number representations of the decimal numbers zero to twenty, in order.

The intention in this task to find the Zeckendorf form of an arbitrary integer.  The Zeckendorf form can be iterated by some bit twiddling rather than calculating each value separately but leave that to another separate task.

;Also see:
*   [http://oeis.org/A014417 OEIS A014417]   for the the sequence of required results.
*   [http://www.youtube.com/watch?v=kQZmZRE0cQY&list=UUoxcjq-8xIDTYp3uz647V5A&index=3&feature=plcp Brown's Criterion - Numberphile]

;Related task:
*   [[Fibonacci sequence]]

Solution:
#include

typedef unsigned long long u64;

#define FIB_INVALID (~(u64)0)

u64 fib[] = {
	1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597,
	2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418,
	317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465,
	14930352, 24157817, 39088169, 63245986, 102334155, 165580141,
	267914296, 433494437, 701408733, 1134903170, 1836311903,
	2971215073ULL, 4807526976ULL, 7778742049ULL, 12586269025ULL,
	20365011074ULL, 32951280099ULL, 53316291173ULL, 86267571272ULL,
	139583862445ULL, 225851433717ULL, 365435296162ULL, 591286729879ULL,
	956722026041ULL, 1548008755920ULL, 2504730781961ULL, 4052739537881ULL,
	6557470319842ULL, 10610209857723ULL, 17167680177565ULL,

	27777890035288ULL // this 65-th one is for range check
};

u64 fibbinary(u64 n)
{
	if (n >= fib[64]) return FIB_INVALID;

	u64 ret = 0;
	int i;
	for (i = 64; i--; )
		if (n >= fib[i]) {
			ret |= 1ULL << i;
			n -= fib[i];
		}

	return ret;
}

void bprint(u64 n, int width)
{
	if (width > 64) width = 64;

	u64 b;
	for (b = 1ULL << (width - 1); b; b >>= 1)
		putchar(b == 1 && !n
			? '0'
			: b > n	? ' '
				: b & n ? '1' : '0');
	putchar('\n');
}

int main(void)
{
	int i;

	for (i = 0; i <= 20; i++)
		printf("%2d:", i), bprint(fibbinary(i), 8);

	return 0;
}


Zeckendorf number representation

Solution:
(() => {
    'use strict';

    const main = () =>
        unlines(
            map(n => concat(zeckendorf(n)),
                enumFromTo(0, 20)
            )
        );

    // zeckendorf :: Int -> String
    const zeckendorf = n => {
        const go = (n, x) =>
            n < x ? (
                Tuple(n, '0')
            ) : Tuple(n - x, '1')
        return 0 < n ? (
            snd(mapAccumL(
                go, n,
                reverse(fibUntil(n))
            ))
        ) : ['0'];
    };

    // fibUntil :: Int -> [Int]
    const fibUntil = n =>
        cons(1, takeWhile(x => n >= x,
            map(snd, iterateUntil(
                tpl => n <= fst(tpl),
                tpl => {
                    const x = snd(tpl);
                    return Tuple(x, x + fst(tpl));
                },
                Tuple(1, 2)
            ))));

    // GENERIC FUNCTIONS ----------------------------

    // Tuple (,) :: a -> b -> (a, b)
    const Tuple = (a, b) => ({
        type: 'Tuple',
        '0': a,
        '1': b,
        length: 2
    });

    // concat :: [[a]] -> [a]
    // concat :: [String] -> String
    const concat = xs =>
        0 < xs.length ? (() => {
            const unit = 'string' !== typeof xs[0] ? (
                []
            ) : '';
            return unit.concat.apply(unit, xs);
        })() : [];

    // cons :: a -> [a] -> [a]
    const cons = (x, xs) =>
        Array.isArray(xs) ? (
            [x].concat(xs)
        ) : (x + xs);

    // enumFromTo :: Int -> Int -> [Int]
    const enumFromTo = (m, n) =>
        m <= n ? iterateUntil(
            x => n <= x,
            x => 1 + x,
            m
        ) : [];

    // fst :: (a, b) -> a
    const fst = tpl => tpl[0];

    // iterateUntil :: (a -> Bool) -> (a -> a) -> a -> [a]
    const iterateUntil = (p, f, x) => {
        const vs = [x];
        let h = x;
        while (!p(h))(h = f(h), vs.push(h));
        return vs;
    };

    // map :: (a -> b) -> [a] -> [b]
    const map = (f, xs) => xs.map(f);

    // 'The mapAccumL function behaves like a combination of map and foldl;
    // it applies a function to each element of a list, passing an accumulating
    // parameter from left to right, and returning a final value of this
    // accumulator together with the new list.' (See Hoogle)

    // mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
    const mapAccumL = (f, acc, xs) =>
        xs.reduce((a, x, i) => {
            const pair = f(a[0], x, i);
            return Tuple(pair[0], a[1].concat(pair[1]));
        }, Tuple(acc, []));

    // reverse :: [a] -> [a]
    const reverse = xs =>
        'string' !== typeof xs ? (
            xs.slice(0).reverse()
        ) : xs.split('').reverse().join('');

    // snd :: (a, b) -> b
    const snd = tpl => tpl[1];

    // tail :: [a] -> [a]
    const tail = xs => 0 < xs.length ? xs.slice(1) : [];

    // takeWhile :: (a -> Bool) -> [a] -> [a]
    // takeWhile :: (Char -> Bool) -> String -> String
    const takeWhile = (p, xs) => {
        const lng = xs.length;
        return 0 < lng ? xs.slice(
            0,
            until(
                i => i === lng || !p(xs[i]),
                i => 1 + i,
                0
            )
        ) : [];
    };

    // unlines :: [String] -> String
    const unlines = xs => xs.join('\n');

    // until :: (a -> Bool) -> (a -> a) -> a -> a
    const until = (p, f, x) => {
        let v = x;
        while (!p(v)) v = f(v);
        return v;
    };

    // MAIN ---
    return main();
})();


Zeckendorf number representation

Solution:
def fib():
    memo = [1, 2]
    while True:
        memo.append(sum(memo))
        yield memo.pop(0)

def sequence_down_from_n(n, seq_generator):
    seq = []
    for s in seq_generator():
        seq.append(s)
        if s >= n: break
    return seq[::-1]

def zeckendorf(n):
    if n == 0: return [0]
    seq = sequence_down_from_n(n, fib)
    digits, nleft = [], n
    for s in seq:
        if s <= nleft:
            digits.append(1)
            nleft -= s
        else:
            digits.append(0)
    assert nleft == 0, 'Check all of n is accounted for'
    assert sum(x*y for x,y in zip(digits, seq)) == n, 'Assert digits are correct'
    while digits[0] == 0:
        # Remove any zeroes padding L.H.S.
        digits.pop(0)
    return digits

n = 20
print('Fibonacci digit multipliers: %r' % sequence_down_from_n(n, fib))
for i in range(n + 1):
    print('%3i: %8s' % (i, ''.join(str(d) for d in zeckendorf(i))))


Zero to the zero power

[[Category:Simple]]
Some computer programming languages are not exactly consistent   (with other computer programming languages)
when   ''raising zero to the zeroth power'':     00

;Task:
Show the results of raising   zero   to the   zeroth   power.

If your computer language objects to      '''0**0'''      or      '''0^0'''      at compile time,   you may also try something like:
            x = 0
            y = 0
            z = x**y
            say  'z='  z

'''Show the result here.'''
And of course use any symbols or notation that is supported in your computer programming language for exponentiation.

;See also:
* The Wiki entry: Zero to the power of zero.
* The Wiki entry: Zero to the power of zero: History.
* The MathWorld™ entry: [http://mathworld.wolfram.com/ExponentLaws.html exponent laws].
** Also, in the above MathWorld™ entry, see formula ('''9'''): x^0=1.
* The OEIS entry: [https://oeis.org/wiki/The_special_case_of_zero_to_the_zeroth_power The special case of zero to the zeroth power]

Solution:
#include
#include
#include

int main()
{
	printf("0 ^ 0 = %f\n", pow(0,0));
        double complex c = cpow(0,0);
	printf("0+0i ^ 0+0i = %f+%fi\n", creal(c), cimag(c));
	return 0;
}


Zero to the zero power

Solution:
from decimal import Decimal
from fractions import Fraction
from itertools import product

zeroes = [0, 0.0, 0j, Decimal(0), Fraction(0, 1), -0.0, -0.0j, Decimal(-0.0)]
for i, j in product(zeroes, repeat=2):
    try:
        ans = i**j
    except:
        ans = ''
    print(f'{i!r:>15} ** {j!r:<15} = {ans!r}')


Zhang-Suen thinning algorithm

Solution:
#include
#include

char** imageMatrix;

char blankPixel,imagePixel;

typedef struct{
	int row,col;
}pixel;

int getBlackNeighbours(int row,int col){

	int i,j,sum = 0;

	for(i=-1;i<=1;i++){
		for(j=-1;j<=1;j++){
			if(i!=0 || j!=0)
				sum+= (imageMatrix[row+i][col+j]==imagePixel);
		}
	}

	return sum;
}

int getBWTransitions(int row,int col){
	return 	((imageMatrix[row-1][col]==blankPixel && imageMatrix[row-1][col+1]==imagePixel)
			+(imageMatrix[row-1][col+1]==blankPixel && imageMatrix[row][col+1]==imagePixel)
			+(imageMatrix[row][col+1]==blankPixel && imageMatrix[row+1][col+1]==imagePixel)
			+(imageMatrix[row+1][col+1]==blankPixel && imageMatrix[row+1][col]==imagePixel)
			+(imageMatrix[row+1][col]==blankPixel && imageMatrix[row+1][col-1]==imagePixel)
			+(imageMatrix[row+1][col-1]==blankPixel && imageMatrix[row][col-1]==imagePixel)
			+(imageMatrix[row][col-1]==blankPixel && imageMatrix[row-1][col-1]==imagePixel)
			+(imageMatrix[row-1][col-1]==blankPixel && imageMatrix[row-1][col]==imagePixel));
}

int zhangSuenTest1(int row,int col){
	int neighbours = getBlackNeighbours(row,col);

	return ((neighbours>=2 && neighbours<=6)
		&& (getBWTransitions(row,col)==1)
		&& (imageMatrix[row-1][col]==blankPixel||imageMatrix[row][col+1]==blankPixel||imageMatrix[row+1][col]==blankPixel)
		&& (imageMatrix[row][col+1]==blankPixel||imageMatrix[row+1][col]==blankPixel||imageMatrix[row][col-1]==blankPixel));
}

int zhangSuenTest2(int row,int col){
	int neighbours = getBlackNeighbours(row,col);

	return ((neighbours>=2 && neighbours<=6)
		&& (getBWTransitions(row,col)==1)
		&& (imageMatrix[row-1][col]==blankPixel||imageMatrix[row][col+1]==blankPixel||imageMatrix[row][col-1]==blankPixel)
		&& (imageMatrix[row-1][col]==blankPixel||imageMatrix[row+1][col]==blankPixel||imageMatrix[row][col+1]==blankPixel));
}

void zhangSuen(char* inputFile, char* outputFile){

	int startRow = 1,startCol = 1,endRow,endCol,i,j,count,rows,cols,processed;

	pixel* markers;

	FILE* inputP = fopen(inputFile,"r");

	fscanf(inputP,"%d%d",&rows,&cols);

	fscanf(inputP,"%d%d",&blankPixel,&imagePixel);

	blankPixel<=9?blankPixel+='0':blankPixel;
	imagePixel<=9?imagePixel+='0':imagePixel;

	printf("\nPrinting original image :\n");

	imageMatrix = (char**)malloc(rows*sizeof(char*));

	for(i=0;i0);

		for(i=0;i0);

		for(i=0;i

Contents of input file : zhImage.txt

10 32
0 1
00000000000000000000000000000000
01111111110000000111111110000000
01110001111000001111001111000000
01110000111000001110000111000000
01110001111000001110000000000000
01111111110000001110000000000000
01110111100000001110000111000000
01110011110011101111001111011100
01110001111011100111111110011100
00000000000000000000000000000000

Console interaction :

Enter full path of input image file : zhImage.txt
Enter full path of output image file : out.txt

Printing original image :

00000000000000000000000000000000
01111111110000000111111110000000
01110001111000001111001111000000
01110000111000001110000111000000
01110001111000001110000000000000
01111111110000001110000000000000
01110111100000001110000111000000
01110011110011101111001111011100
01110001111011100111111110011100
00000000000000000000000000000000

Printing image after applying Zhang Suen Thinning Algorithm :

00000000000000000000000000000000
00111111100000000011111100000000
00100000100000000110000000000000
01000000100000000100000000000000
01000000100000001000000000000000
01111110100000001000000000000000
00000001000000000100000000000000
00000000100001000110000110001000
00000000010000000001111000000000
00000000000000000000000000000000

Image also written to : out.txt

Contents of out.txt :

00000000000000000000000000000000
00111111100000000011111100000000
00100000100000000110000000000000
01000000100000000100000000000000
01000000100000001000000000000000
01111110100000001000000000000000
00000001000000000100000000000000
00000000100001000110000110001000
00000000010000000001111000000000
00000000000000000000000000000000


Zhang-Suen thinning algorithm

Solution:
function Point(x, y) {
    this.x = x;
    this.y = y;
}
var ZhangSuen = (function () {
    function ZhangSuen() {
    }
    ZhangSuen.image =
    ["                                                          ",
     " #################                   #############        ",
     " ##################               ################        ",
     " ###################            ##################        ",
     " ########     #######          ###################        ",
     "   ######     #######         #######       ######        ",
     "   ######     #######        #######                      ",
     "   #################         #######                      ",
     "   ################          #######                      ",
     "   #################         #######                      ",
     "   ######     #######        #######                      ",
     "   ######     #######        #######                      ",
     "   ######     #######         #######       ######        ",
     " ########     #######          ###################        ",
     " ########     ####### ######    ################## ###### ",
     " ########     ####### ######      ################ ###### ",
     " ########     ####### ######         ############# ###### ",
     "                                                          "];

    ZhangSuen.nbrs = [[0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1]];

    ZhangSuen.nbrGroups = [[[0, 2, 4], [2, 4, 6]], [[0, 2, 6], [0, 4, 6]]];

    ZhangSuen.toWhite = new Array();
    ;
    ZhangSuen.main = function (args) {
        ZhangSuen.grid = new Array(ZhangSuen.image.length);
        for (var r = 0; r < ZhangSuen.image.length; r++)
            ZhangSuen.grid[r] = (ZhangSuen.image[r]).split('');
        ZhangSuen.thinImage();
    };
    ZhangSuen.thinImage = function () {
        var firstStep = false;
        var hasChanged;
        do {
            hasChanged = false;
            firstStep = !firstStep;
            for (var r = 1; r < ZhangSuen.grid.length - 1; r++) {
                for (var c = 1; c < ZhangSuen.grid[0].length - 1; c++) {
                    if (ZhangSuen.grid[r][c] !== '#')
                        continue;
                    var nn = ZhangSuen.numNeighbors(r, c);
                    if (nn < 2 || nn > 6)
                        continue;
                    if (ZhangSuen.numTransitions(r, c) !== 1)
                        continue;
                    if (!ZhangSuen.atLeastOneIsWhite(r, c, firstStep ? 0 : 1))
                        continue;
                    ZhangSuen.toWhite.push(new Point(c, r));
                    hasChanged = true;
                }
            }
            for (let i = 0; i < ZhangSuen.toWhite.length; i++) {
                var p = ZhangSuen.toWhite[i];
                ZhangSuen.grid[p.y][p.x] = ' ';
            }
            ZhangSuen.toWhite = new Array();
        } while ((firstStep || hasChanged));
        ZhangSuen.printResult();
    };
    ZhangSuen.numNeighbors = function (r, c) {
        var count = 0;
        for (var i = 0; i < ZhangSuen.nbrs.length - 1; i++)
            if (ZhangSuen.grid[r + ZhangSuen.nbrs[i][1]][c + ZhangSuen.nbrs[i][0]] === '#')
                count++;
        return count;
    };
    ZhangSuen.numTransitions = function (r, c) {
        var count = 0;
        for (var i = 0; i < ZhangSuen.nbrs.length - 1; i++)
            if (ZhangSuen.grid[r + ZhangSuen.nbrs[i][1]][c + ZhangSuen.nbrs[i][0]] === ' ') {
                if (ZhangSuen.grid[r + ZhangSuen.nbrs[i + 1][1]][c + ZhangSuen.nbrs[i + 1][0]] === '#')
                    count++;
            }
        return count;
    };
    ZhangSuen.atLeastOneIsWhite = function (r, c, step) {
        var count = 0;
        var group = ZhangSuen.nbrGroups[step];
        for (var i = 0; i < 2; i++)
            for (var j = 0; j < group[i].length; j++) {
                var nbr = ZhangSuen.nbrs[group[i][j]];
                if (ZhangSuen.grid[r + nbr[1]][c + nbr[0]] === ' ') {
                    count++;
                    break;
                }
            }
        return count > 1;
    };
    ZhangSuen.printResult = function () {
        for (var i = 0; i < ZhangSuen.grid.length; i++) {
            var row = ZhangSuen.grid[i];
            console.log(row.join(''));
        }
    };
    return ZhangSuen;
}());
ZhangSuen.main(null);


Zhang-Suen thinning algorithm

Solution:
# -*- coding: utf-8 -*-

# Example from [http://nayefreza.wordpress.com/2013/05/11/zhang-suen-thinning-algorithm-java-implementation/ this blog post].
beforeTxt = '''\
1100111
1100111
1100111
1100111
1100110
1100110
1100110
1100110
1100110
1100110
1100110
1100110
1111110
0000000\
'''

# Thanks to [http://www.network-science.de/ascii/ this site] and vim for these next two examples
smallrc01 = '''\
00000000000000000000000000000000
01111111110000000111111110000000
01110001111000001111001111000000
01110000111000001110000111000000
01110001111000001110000000000000
01111111110000001110000000000000
01110111100000001110000111000000
01110011110011101111001111011100
01110001111011100111111110011100
00000000000000000000000000000000\
'''

rc01 = '''\
00000000000000000000000000000000000000000000000000000000000
01111111111111111100000000000000000001111111111111000000000
01111111111111111110000000000000001111111111111111000000000
01111111111111111111000000000000111111111111111111000000000
01111111100000111111100000000001111111111111111111000000000
00011111100000111111100000000011111110000000111111000000000
00011111100000111111100000000111111100000000000000000000000
00011111111111111111000000000111111100000000000000000000000
00011111111111111110000000000111111100000000000000000000000
00011111111111111111000000000111111100000000000000000000000
00011111100000111111100000000111111100000000000000000000000
00011111100000111111100000000111111100000000000000000000000
00011111100000111111100000000011111110000000111111000000000
01111111100000111111100000000001111111111111111111000000000
01111111100000111111101111110000111111111111111111011111100
01111111100000111111101111110000001111111111111111011111100
01111111100000111111101111110000000001111111111111011111100
00000000000000000000000000000000000000000000000000000000000\
'''

def intarray(binstring):
    '''Change a 2D matrix of 01 chars into a list of lists of ints'''
    return [[1 if ch == '1' else 0 for ch in line]
            for line in binstring.strip().split()]

def chararray(intmatrix):
    '''Change a 2d list of lists of 1/0 ints into lines of 1/0 chars'''
    return '\n'.join(''.join(str(p) for p in row) for row in intmatrix)

def toTxt(intmatrix):
    '''Change a 2d list of lists of 1/0 ints into lines of '#' and '.' chars'''
    return '\n'.join(''.join(('#' if p else '.') for p in row) for row in intmatrix)

def neighbours(x, y, image):
    '''Return 8-neighbours of point p1 of picture, in order'''
    i = image
    x1, y1, x_1, y_1 = x+1, y-1, x-1, y+1
    #print ((x,y))
    return [i[y1][x],  i[y1][x1],   i[y][x1],  i[y_1][x1],  # P2,P3,P4,P5
            i[y_1][x], i[y_1][x_1], i[y][x_1], i[y1][x_1]]  # P6,P7,P8,P9

def transitions(neighbours):
    n = neighbours + neighbours[0:1]    # P2, ... P9, P2
    return sum((n1, n2) == (0, 1) for n1, n2 in zip(n, n[1:]))

def zhangSuen(image):
    changing1 = changing2 = [(-1, -1)]
    while changing1 or changing2:
        # Step 1
        changing1 = []
        for y in range(1, len(image) - 1):
            for x in range(1, len(image[0]) - 1):
                P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, image)
                if (image[y][x] == 1 and    # (Condition 0)
                    P4 * P6 * P8 == 0 and   # Condition 4
                    P2 * P4 * P6 == 0 and   # Condition 3
                    transitions(n) == 1 and # Condition 2
                    2 <= sum(n) <= 6):      # Condition 1
                    changing1.append((x,y))
        for x, y in changing1: image[y][x] = 0
        # Step 2
        changing2 = []
        for y in range(1, len(image) - 1):
            for x in range(1, len(image[0]) - 1):
                P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, image)
                if (image[y][x] == 1 and    # (Condition 0)
                    P2 * P6 * P8 == 0 and   # Condition 4
                    P2 * P4 * P8 == 0 and   # Condition 3
                    transitions(n) == 1 and # Condition 2
                    2 <= sum(n) <= 6):      # Condition 1
                    changing2.append((x,y))
        for x, y in changing2: image[y][x] = 0
        #print changing1
        #print changing2
    return image

if __name__ == '__main__':
    for picture in (beforeTxt, smallrc01, rc01):
        image = intarray(picture)
        print('\nFrom:\n%s' % toTxt(image))
        after = zhangSuen(image)
        print('\nTo thinned:\n%s' % toTxt(after))