Password generator

Solution:
String.prototype.shuffle = function() {
  return this.split('').sort(() => Math.random() - .5).join('');
}

function createPwd(opts = {}) {
  let len    = opts.len || 5,                       // password length
      num    = opts.num || 1,                       // number of outputs
      noSims = opts.noSims == false ? false : true, // exclude similar?
      out = [],
      cur, i;

  let chars = [
    'abcdefghijkmnopqrstuvwxyz'.split(''),
    'ABCDEFGHJKLMNPQRTUVWXY'.split(''),
    '346789'.split(''),
    '!"#$%&()*+,-./:;<=>?@[]^_{|}'.split('')
  ];

  if (!noSims) {
    chars[0].push('l');
    chars[1] = chars[1].concat('IOSZ'.split(''));
    chars[2] = chars[2].concat('1250'.split(''));
  }

  if (len < 4) {
    console.log('Password length changed to 4 (minimum)');
    len = 4;
  }

  while (out.length < num) {
    cur = '';
    // basic requirement
    for (i = 0; i < 4; i++)
      cur += chars[i][Math.floor(Math.random() * chars[i].length)];

    while (cur.length < len) {
      let rnd = Math.floor(Math.random() * chars.length);
      cur += chars[rnd][Math.floor(Math.random() * chars[rnd].length)];
    }
    out.push(cur);
  }

  for (i = 0; i < out.length; i++) out[i] = out[i].shuffle();

  if (out.length == 1) return out[0];
  return out;
}

// testing
console.log( createPwd() );
console.log( createPwd( {len: 20}) );
console.log( createPwd( {len: 20, num: 2}) );
console.log( createPwd( {len: 20, num: 2, noSims: false}) );


Password generator

Create a password generation program which will generate passwords containing random ASCII characters from the following groups:
          lower-case letters:  a ──► z
          upper-case letters:  A ──► Z
                      digits:  0 ──► 9
  other printable characters:  !"#$%&'()*+,-./:;<=>?@[]^_{|}~
  (the above character list excludes white-space, backslash and grave)

The generated password(s) must include   ''at least one''   (of each of the four groups):
    lower-case letter,
    upper-case letter,
    digit  (numeral),   and
    one  "other"  character.

The user must be able to specify the password length and the number of passwords to generate.

The passwords should be displayed or written to a file, one per line.

The randomness should be from a system source or library.

The program should implement a help option or button which should describe the program and options when invoked.

You may also allow the user to specify a seed value, and give the option of excluding visually similar characters.

For example:            Il1     O0     5S     2Z            where the characters are:
::::*   capital eye, lowercase ell, the digit one
::::*   capital oh, the digit zero
::::*   the digit five, capital ess
::::*   the digit two, capital zee

Solution:
import random

lowercase = 'abcdefghijklmnopqrstuvwxyz' # same as string.ascii_lowercase
uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' # same as string.ascii_uppercase
digits = '0123456789'                    # same as string.digits
punctuation = '!"#$%&\'()*+,-./:;<=>?@[]^_{|}~' # like string.punctuation but without backslash \ nor grave `

allowed = lowercase + uppercase + digits + punctuation

visually_similar = 'Il1O05S2Z'

def new_password(length:int, readable=True) -> str:
    if length < 4:
        print("password length={} is too short,".format(length),
            "minimum length=4")
        return ''
    choice = random.SystemRandom().choice
    while True:
        password_chars = [
            choice(lowercase),
            choice(uppercase),
            choice(digits),
            choice(punctuation)
            ] + random.sample(allowed, length-4)
        if (not readable or
                all(c not in visually_similar for c in password_chars)):
            random.SystemRandom().shuffle(password_chars)
            return ''.join(password_chars)

def password_generator(length, qty=1, readable=True):
    for i in range(qty):
        print(new_password(length, readable))


Pathological floating point problems

Most programmers are familiar with the inexactness of floating point calculations in a binary processor.

The classic example being:

0.1 + 0.2 =  0.30000000000000004

In many situations the amount of error in such calculations is very small and can be overlooked or eliminated with rounding.

There are pathological problems however, where seemingly simple, straight-forward calculations are extremely sensitive to even tiny amounts of imprecision.

This task's purpose is to show how your language deals with such classes of problems.

'''A sequence that seems to converge to a wrong limit.'''

Consider the sequence:
::::::   v1 =  2
::::::   v2 = -4
::::::   vn = 111   -   1130   /   vn-1   +   3000  /   (vn-1 * vn-2)

As   '''n'''   grows larger, the series should converge to   '''6'''   but small amounts of error will cause it to approach   '''100'''.

;Task 1:
Display the values of the sequence where   n =   3, 4, 5, 6, 7, 8, 20, 30, 50 & 100   to at least '''16''' decimal places.

    n = 3     18.5
    n = 4      9.378378
    n = 5      7.801153
    n = 6      7.154414
    n = 7      6.806785
    n = 8      6.5926328
    n = 20     6.0435521101892689
    n = 30     6.006786093031205758530554
    n = 50     6.0001758466271871889456140207471954695237
    n = 100    6.000000019319477929104086803403585715024350675436952458072592750856521767230266

;Task 2:
'''The Chaotic Bank Society'''   is offering a new investment account to their customers.

You first deposit   $e - 1   where   e   is   2.7182818...   the base of natural logarithms.

After each year, your account balance will be multiplied by the number of years that have passed, and $1 in service charges will be removed.

So ...
::* after 1 year, your balance will be multiplied by 1 and $1 will be removed for service charges.
::* after 2 years your balance will be doubled and $1 removed.
::* after 3 years your balance will be tripled and $1 removed.
::*  ...
::* after 10 years, multiplied by 10 and $1 removed,  and so on.

What will your balance be after   25   years?
    Starting balance: $e-1
    Balance = (Balance * year) - 1 for 25 years
    Balance after 25 years: $0.0399387296732302

;Task 3, extra credit:
'''Siegfried Rump's example.'''   Consider the following function, designed by Siegfried Rump in 1988.
::::::   f(a,b) = 333.75b6 + a2( 11a2b2 - b6 - 121b4 - 2 ) + 5.5b8 + a/(2b)
::::::  compute    f(a,b)    where    a=77617.0    and    b=33096.0
::::::   f(77617.0, 33096.0)   =   -0.827396059946821

Demonstrate how to solve at least one of the first two problems, or both, and the third if you're feeling particularly jaunty.

;See also;
*   [https://perso.ens-lyon.fr/jean-michel.muller/chapitre1.pdf Floating-Point Arithmetic]   Section 1.3.2 Difficult problems.

Solution:
#include
#include

void firstCase(){
	mpf_t a,b,c;

	mpf_inits(a,b,c,NULL);

	mpf_set_str(a,"0.1",10);
	mpf_set_str(b,"0.2",10);
	mpf_add(c,a,b);

	gmp_printf("\n0.1 + 0.2 = %.*Ff",20,c);
}

void pathologicalSeries(){
	int n;
	mpf_t v1, v2, vn, a1, a2, a3, t2, t3, prod;

	mpf_inits(v1,v2,vn, a1, a2, a3, t2, t3, prod,NULL);

	mpf_set_str(v1,"2",10);
	mpf_set_str(v2,"-4",10);
	mpf_set_str(a1,"111",10);
	mpf_set_str(a2,"1130",10);
	mpf_set_str(a3,"3000",10);

	for(n=3;n<=100;n++){
		mpf_div(t2,a2,v2);
		mpf_mul(prod,v1,v2);
		mpf_div(t3,a3,prod);
		mpf_add(vn,a1,t3);
		mpf_sub(vn,vn,t2);

		if((n>=3&&n<=8) || n==20 || n==30 || n==50 || n==100){
			gmp_printf("\nv_%d : %.*Ff",n,(n==3)?1:(n>=4&&n<=7)?6:(n==8)?7:(n==20)?16:(n==30)?24:(n==50)?40:78,vn);
		}

		mpf_set(v1,v2);
		mpf_set(v2,vn);
	}
}

void healthySeries(){
	int n;

	mpf_t num,denom,result;
	mpq_t v1, v2, vn, a1, a2, a3, t2, t3, prod;

	mpf_inits(num,denom,result,NULL);
	mpq_inits(v1,v2,vn, a1, a2, a3, t2, t3, prod,NULL);

	mpq_set_str(v1,"2",10);
	mpq_set_str(v2,"-4",10);
	mpq_set_str(a1,"111",10);
	mpq_set_str(a2,"1130",10);
	mpq_set_str(a3,"3000",10);

	for(n=3;n<=100;n++){
		mpq_div(t2,a2,v2);
		mpq_mul(prod,v1,v2);
		mpq_div(t3,a3,prod);
		mpq_add(vn,a1,t3);
		mpq_sub(vn,vn,t2);

		if((n>=3&&n<=8) || n==20 || n==30 || n==50 || n==100){
			mpf_set_z(num,mpq_numref(vn));
			mpf_set_z(denom,mpq_denref(vn));
			mpf_div(result,num,denom);

			gmp_printf("\nv_%d : %.*Ff",n,(n==3)?1:(n>=4&&n<=7)?6:(n==8)?7:(n==20)?16:(n==30)?24:(n==50)?40:78,result);
		}

		mpq_set(v1,v2);
		mpq_set(v2,vn);
	}
}

int main()
{
	mpz_t rangeProd;

	firstCase();

	printf("\n\nPathological Series : ");

	pathologicalSeries();

	printf("\n\nNow a bit healthier : ");

	healthySeries();

	return 0;
}


Pathological floating point problems

Solution:
from fractions import Fraction

def muller_seq(n:int) -> float:
    seq = [Fraction(0), Fraction(2), Fraction(-4)]
    for i in range(3, n+1):
        next_value = (111 - 1130/seq[i-1]
            + 3000/(seq[i-1]*seq[i-2]))
        seq.append(next_value)
    return float(seq[n])

for n in [3, 4, 5, 6, 7, 8, 20, 30, 50, 100]:
    print("{:4d} -> {}".format(n, muller_seq(n)))


Peaceful chess queen armies

In chess, a queen attacks positions from where it is, in straight lines up-down and left-right as well as on both its diagonals. It attacks only pieces ''not'' of its own colour.

⇖
⇑
⇗

⇐
⇐
♛
⇒
⇒

⇙
⇓
⇘

⇙

⇓

⇘

⇓

The goal of Peaceful chess queen armies is to arrange m black queens and m white queens on an n-by-n square grid, (the board), so that ''no queen attacks another of a different colour''.

;Task:
# Create a routine to represent two-colour queens on a 2-D board. (Alternating black/white background colours, Unicode chess pieces and other embellishments are not necessary, but may be used at your discretion).
# Create a routine to generate at least one solution to placing m equal numbers of black and white queens on an n square board.
# Display here results for the m=4, n=5 case.

;References:
* [http://www.mathopt.org/Optima-Issues/optima62.pdf Peaceably Coexisting Armies of Queens] (Pdf) by Robert A. Bosch. Optima, the Mathematical Programming Socity newsletter, issue 62.
* [https://oeis.org/A250000 A250000] OEIS

Solution:
#include
#include
#include
#include

enum Piece {
    Empty,
    Black,
    White,
};

typedef struct Position_t {
    int x, y;
} Position;

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

struct Node_t {
    Position pos;
    struct Node_t *next;
};

void releaseNode(struct Node_t *head) {
    if (head == NULL) return;

    releaseNode(head->next);
    head->next = NULL;

    free(head);
}

typedef struct List_t {
    struct Node_t *head;
    struct Node_t *tail;
    size_t length;
} List;

List makeList() {
    return (List) { NULL, NULL, 0 };
}

void releaseList(List *lst) {
    if (lst == NULL) return;

    releaseNode(lst->head);
    lst->head = NULL;
    lst->tail = NULL;
}

void addNode(List *lst, Position pos) {
    struct Node_t *newNode;

    if (lst == NULL) {
        exit(EXIT_FAILURE);
    }

    newNode = malloc(sizeof(struct Node_t));
    if (newNode == NULL) {
        exit(EXIT_FAILURE);
    }

    newNode->next = NULL;
    newNode->pos = pos;

    if (lst->head == NULL) {
        lst->head = lst->tail = newNode;
    } else {
        lst->tail->next = newNode;
        lst->tail = newNode;
    }

    lst->length++;
}

void removeAt(List *lst, size_t pos) {
    if (lst == NULL) return;

    if (pos == 0) {
        struct Node_t *temp = lst->head;

        if (lst->tail == lst->head) {
            lst->tail = NULL;
        }

        lst->head = lst->head->next;
        temp->next = NULL;

        free(temp);
        lst->length--;
    } else {
        struct Node_t *temp = lst->head;
        struct Node_t *rem;
        size_t i = pos;

        while (i-- > 1) {
            temp = temp->next;
        }

        rem = temp->next;
        if (rem == lst->tail) {
            lst->tail = temp;
        }

        temp->next = rem->next;

        rem->next = NULL;
        free(rem);

        lst->length--;
    }
}

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

bool isAttacking(Position queen, Position pos) {
    return queen.x == pos.x
        || queen.y == pos.y
        || abs(queen.x - pos.x) == abs(queen.y - pos.y);
}

bool place(int m, int n, List *pBlackQueens, List *pWhiteQueens) {
    struct Node_t *queenNode;
    bool placingBlack = true;
    int i, j;

    if (pBlackQueens == NULL || pWhiteQueens == NULL) {
        exit(EXIT_FAILURE);
    }

    if (m == 0) return true;
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            Position pos = { i, j };

            queenNode = pBlackQueens->head;
            while (queenNode != NULL) {
                if ((queenNode->pos.x == pos.x && queenNode->pos.y == pos.y) || !placingBlack && isAttacking(queenNode->pos, pos)) {
                    goto inner;
                }
                queenNode = queenNode->next;
            }

            queenNode = pWhiteQueens->head;
            while (queenNode != NULL) {
                if ((queenNode->pos.x == pos.x && queenNode->pos.y == pos.y) || placingBlack && isAttacking(queenNode->pos, pos)) {
                    goto inner;
                }
                queenNode = queenNode->next;
            }

            if (placingBlack) {
                addNode(pBlackQueens, pos);
                placingBlack = false;
            } else {
                addNode(pWhiteQueens, pos);
                if (place(m - 1, n, pBlackQueens, pWhiteQueens)) {
                    return true;
                }
                removeAt(pBlackQueens, pBlackQueens->length - 1);
                removeAt(pWhiteQueens, pWhiteQueens->length - 1);
                placingBlack = true;
            }

        inner: {}
        }
    }
    if (!placingBlack) {
        removeAt(pBlackQueens, pBlackQueens->length - 1);
    }
    return false;
}

void printBoard(int n, List *pBlackQueens, List *pWhiteQueens) {
    size_t length = n * n;
    struct Node_t *queenNode;
    char *board;
    size_t i, j, k;

    if (pBlackQueens == NULL || pWhiteQueens == NULL) {
        exit(EXIT_FAILURE);
    }

    board = calloc(length, sizeof(char));
    if (board == NULL) {
        exit(EXIT_FAILURE);
    }

    queenNode = pBlackQueens->head;
    while (queenNode != NULL) {
        board[queenNode->pos.x * n + queenNode->pos.y] = Black;
        queenNode = queenNode->next;
    }

    queenNode = pWhiteQueens->head;
    while (queenNode != NULL) {
        board[queenNode->pos.x * n + queenNode->pos.y] = White;
        queenNode = queenNode->next;
    }

    for (i = 0; i < length; i++) {
        if (i != 0 && i % n == 0) {
            printf("\n");
        }
        switch (board[i]) {
        case Black:
            printf("B ");
            break;
        case White:
            printf("W ");
            break;
        default:
            j = i / n;
            k = i - j * n;
            if (j % 2 == k % 2) {
                printf("  ");
            } else {
                printf("# ");
            }
            break;
        }
    }

    printf("\n\n");
}

void test(int n, int q) {
    List blackQueens = makeList();
    List whiteQueens = makeList();

    printf("%d black and %d white queens on a %d x %d board:\n", q, q, n, n);
    if (place(q, n, &blackQueens, &whiteQueens)) {
        printBoard(n, &blackQueens, &whiteQueens);
    } else {
        printf("No solution exists.\n\n");
    }

    releaseList(&blackQueens);
    releaseList(&whiteQueens);
}

int main() {
    test(2, 1);

    test(3, 1);
    test(3, 2);

    test(4, 1);
    test(4, 2);
    test(4, 3);

    test(5, 1);
    test(5, 2);
    test(5, 3);
    test(5, 4);
    test(5, 5);

    test(6, 1);
    test(6, 2);
    test(6, 3);
    test(6, 4);
    test(6, 5);
    test(6, 6);

    test(7, 1);
    test(7, 2);
    test(7, 3);
    test(7, 4);
    test(7, 5);
    test(7, 6);
    test(7, 7);

    return EXIT_SUCCESS;
}


Peaceful chess queen armies

Solution:
from itertools import combinations, product, count
from functools import lru_cache, reduce

_bbullet, _wbullet = '\u2022\u25E6'
_or = set.__or__

def place(m, n):
    "Place m black and white queens, peacefully, on an n-by-n board"
    board = set(product(range(n), repeat=2))  # (x, y) tuples
    placements = {frozenset(c) for c in combinations(board, m)}
    for blacks in placements:
        black_attacks = reduce(_or,
                               (queen_attacks_from(pos, n) for pos in blacks),
                               set())
        for whites in {frozenset(c)     # Never on blsck attacking squares
                       for c in combinations(board - black_attacks, m)}:
            if not black_attacks & whites:
                return blacks, whites
    return set(), set()

@lru_cache(maxsize=None)
def queen_attacks_from(pos, n):
    x0, y0 = pos
    a = set([pos])    # Its position
    a.update((x, y0) for x in range(n))    # Its row
    a.update((x0, y) for y in range(n))    # Its column
    # Diagonals
    for x1 in range(n):
        # l-to-r diag
        y1 = y0 -x0 +x1
        if 0 <= y1 < n:
            a.add((x1, y1))
        # r-to-l diag
        y1 = y0 +x0 -x1
        if 0 <= y1 < n:
            a.add((x1, y1))
    return a

def pboard(black_white, n):
    "Print board"
    if black_white is None:
        blk, wht = set(), set()
    else:
        blk, wht = black_white
    print(f"## {len(blk)} black and {len(wht)} white queens "
          f"on a {n}-by-{n} board:", end='')
    for x, y in product(range(n), repeat=2):
        if y == 0:
            print()
        xy = (x, y)
        ch = ('?' if xy in blk and xy in wht
              else 'B' if xy in blk
              else 'W' if xy in wht
              else _bbullet if (x + y)%2 else _wbullet)
        print('%s' % ch, end='')
    print()

if __name__ == '__main__':
    n=2
    for n in range(2, 7):
        print()
        for m in count(1):
            ans = place(m, n)
            if ans[0]:
                pboard(ans, n)
            else:
                print (f"# Can't place {m} queens on a {n}-by-{n} board")
                break
    #
    print('\n')
    m, n = 5, 7
    ans = place(m, n)
    pboard(ans, n)


Pentagram

right

A pentagram is a star polygon, consisting of a central pentagon of which each side forms the base of an isosceles triangle. The vertex of each triangle, a point of the star, is 36 degrees.

;Task:
Draw (or print) a regular pentagram, in any orientation. Use a different color (or token) for stroke and fill, and background. For the fill it should be assumed that all points inside the triangles and the pentagon are inside the pentagram.

;See also
* [http://proofsfromthebook.com/2013/08/04/angle-sum-of-a-pentagram/ Angle sum of a pentagram]

Solution:
#include
#include
#include

#define pi M_PI

int main(){

	char colourNames[][14] = { "BLACK", "BLUE", "GREEN", "CYAN", "RED", "MAGENTA", "BROWN", "LIGHTGRAY", "DARKGRAY",
              "LIGHTBLUE", "LIGHTGREEN", "LIGHTCYAN", "LIGHTRED", "LIGHTMAGENTA", "YELLOW", "WHITE" };

	int stroke=0,fill=0,back=0,i;

	double centerX = 300,centerY = 300,coreSide,armLength,pentaLength;

	printf("Enter core pentagon side length : ");
	scanf("%lf",&coreSide);

	printf("Enter pentagram arm length : ");
	scanf("%lf",&armLength);

	printf("Available colours are :\n");

	for(i=0;i<16;i++){
		printf("%d. %s\t",i+1,colourNames[i]);
		if((i+1) % 3 == 0){
			printf("\n");
		}
	}

	while(stroke==fill && fill==back){
		printf("\nEnter three diffrenet options for stroke, fill and background : ");
		scanf("%d%d%d",&stroke,&fill,&back);
	}

	pentaLength = coreSide/(2 * tan(pi/5)) + sqrt(armLength*armLength - coreSide*coreSide/4);

	initwindow(2*centerX,2*centerY,"Pentagram");

	setcolor(stroke-1);

	setfillstyle(SOLID_FILL,back-1);

	bar(0,0,2*centerX,2*centerY);

	floodfill(centerX,centerY,back-1);

	setfillstyle(SOLID_FILL,fill-1);

	for(i=0;i<5;i++){
		line(centerX + coreSide*cos(i*2*pi/5)/(2*sin(pi/5)),centerY + coreSide*sin(i*2*pi/5)/(2*sin(pi/5)),centerX + coreSide*cos((i+1)*2*pi/5)/(2*sin(pi/5)),centerY + coreSide*sin((i+1)*2*pi/5)/(2*sin(pi/5)));
		line(centerX + coreSide*cos(i*2*pi/5)/(2*sin(pi/5)),centerY + coreSide*sin(i*2*pi/5)/(2*sin(pi/5)),centerX + pentaLength*cos(i*2*pi/5 + pi/5),centerY + pentaLength*sin(i*2*pi/5 + pi/5));
		line(centerX + coreSide*cos((i+1)*2*pi/5)/(2*sin(pi/5)),centerY + coreSide*sin((i+1)*2*pi/5)/(2*sin(pi/5)),centerX + pentaLength*cos(i*2*pi/5 + pi/5),centerY + pentaLength*sin(i*2*pi/5 + pi/5));

		floodfill(centerX + coreSide*cos(i*2*pi/5 + pi/10)/(2*sin(pi/5)),centerY + coreSide*sin(i*2*pi/5 + pi/10)/(2*sin(pi/5)),stroke-1);
	}

	floodfill(centerX,centerY,stroke-1);

	getch();

	closegraph();
}


Pentagram

Solution:
import turtle

turtle.bgcolor("green")
t = turtle.Turtle()
t.color("red", "blue")
t.begin_fill()
for i in range(0, 5):
    t.forward(200)
    t.right(144)
t.end_fill()


Pentomino tiling

A pentomino is a polyomino that consists of 5 squares. There are 12 pentomino shapes,
if you don't count rotations and reflections. Most pentominoes can form their own mirror image through
rotation, but some of them have to be flipped over.

        I
        I     L       N                                                 Y
 FF     I     L      NN     PP     TTT              V       W     X    YY      ZZ
FF      I     L      N      PP      T     U U       V      WW    XXX    Y      Z
 F      I     LL     N      P       T     UUU     VVV     WW      X     Y     ZZ

A Pentomino tiling is an example of an exact cover problem and can take on many forms.
A traditional tiling presents an 8 by 8 grid, where 4 cells are left uncovered. The other cells are covered
by the 12 pentomino shapes, without overlaps, with every shape only used once.

The 4 uncovered cells should be chosen at random. Note that not all configurations are solvable.

;Task
Create an 8 by 8 tiling and print the result.

;Example

F I I I I I L N
F F F L L L L N
W F - X Z Z N N
W W X X X Z N V
T W W X - Z Z V
T T T P P V V V
T Y - P P U U U
Y Y Y Y P U - U

;Related tasks
* Free polyominoes enumeration

Solution:
from itertools import product

minos = (((197123, 7, 6), (1797, 6, 7), (1287, 6, 7), (196867, 7, 6)),
        ((263937, 6, 6), (197126, 6, 6), (393731, 6, 6), (67332, 6, 6)),
        ((16843011, 7, 5), (2063, 5, 7), (3841, 5, 7), (271, 5, 7), (3848, 5, 7), (50463234, 7, 5), (50397441, 7, 5), (33686019, 7, 5)),
        ((131843, 7, 6), (1798, 6, 7), (775, 6, 7), (1795, 6, 7), (1543, 6, 7), (197377, 7, 6), (197378, 7, 6), (66307, 7, 6)),
        ((132865, 6, 6), (131846, 6, 6), (198146, 6, 6), (132611, 6, 6), (393986, 6, 6), (263938, 6, 6), (67330, 6, 6), (132868, 6, 6)),
        ((1039, 5, 7), (33751554, 7, 5), (16843521, 7, 5), (16974081, 7, 5), (33686274, 7, 5), (3842, 5, 7), (3844, 5, 7), (527, 5, 7)),
        ((1804, 5, 7), (33751297, 7, 5), (33686273, 7, 5), (16974338, 7, 5), (16843522, 7, 5), (782, 5, 7), (3079, 5, 7), (3587, 5, 7)),
        ((263683, 6, 6), (198148, 6, 6), (66310, 6, 6), (393985, 6, 6)),
        ((67329, 6, 6), (131591, 6, 6), (459266, 6, 6), (263940, 6, 6)),
        ((459780, 6, 6), (459009, 6, 6), (263175, 6, 6), (65799, 6, 6)),
        ((4311810305, 8, 4), (31, 4, 8)),
        ((132866, 6, 6),))

boxchar_double_width = ' ╶╺╵└┕╹┖┗╴─╼┘┴┶┚┸┺╸╾━┙┵┷┛┹┻╷┌┍│├┝╿┞┡┐┬┮┤┼┾┦╀╄┑┭┯┥┽┿┩╃╇╻┎┏╽┟┢┃┠┣┒┰┲┧╁╆┨╂╊┓┱┳┪╅╈┫╉╋'
boxchar_single_width = [c + ' ─━'[i%3] for i, c in enumerate(boxchar_double_width)]

# choose drawing alphabet based on terminal font
patterns = boxchar_single_width

tiles = []
for row in reversed(minos):
    tiles.append([])
    for n, x, y in row:
        for shift in (b*8 + a for a, b in product(range(x), range(y))):
            tiles[-1].append(n << shift)

def img(seq):
    b = [[0]*10 for _ in range(10)]

    for i, s in enumerate(seq):
        for j, k in product(range(8), range(8)):
            if s & (1<<(j*8 + k)):
                b[j + 1][k + 1] = i + 1

    idices = [[0]*9 for _ in range(9)]
    for i, j in product(range(9), range(9)):
        n = (b[i+1][j+1], b[i][j+1], b[i][j], b[i+1][j], b[i+1][j+1])
        idices[i][j] = sum((a != b)*(1 + (not a or not b))*3**i for i, (a,b) in enumerate(zip(n, n[1:])))

    return '\n'.join(''.join(patterns[i] for i in row) for row in idices)

def tile(board=0, seq=tuple(), tiles=tiles):
    if not tiles:
        yield img(seq)
        return

    for c in tiles[0]:
        b = board | c

        tnext = [] # not using list comprehension ...
        for t in tiles[1:]:
            tnext.append(tuple(n for n in t if not n&b))
            if not tnext[-1]: break # because early break is faster
        else:
            yield from tile(b, seq + (c,), tnext)

for x in tile():
    print(x)


Perfect shuffle

A perfect shuffle (or [https://en.wikipedia.org/wiki/Faro_shuffle faro/weave shuffle]) means splitting a deck of cards into equal halves, and perfectly interleaving them - so that you end up with the first card from the left half, followed by the first card from the right half, and so on:

::: 7♠ 8♠ 9♠ J♠ Q♠ K♠→7♠  8♠  9♠  J♠  Q♠  K♠→7♠ J♠ 8♠ Q♠ 9♠ K♠

When you repeatedly perform perfect shuffles on an even-sized deck of unique cards, it will at some point arrive back at its original order. How many shuffles this takes, depends solely on the number of cards in the deck - for example for a deck of eight cards it takes three shuffles:

::::: {| style="border-spacing:0.5em 0;border-collapse:separate;margin:0 1em;text-align:right"
|-
| ''original:'' ||
1
2
3
4
5
6
7
8
|-
| ''after 1st shuffle:'' ||
1
5
2
6
3
7
4
8
|-
| ''after 2nd shuffle:'' ||
1
3
5
7
2
4
6
8
|-
| ''after 3rd shuffle:'' ||
1
2
3
4
5
6
7
8
|}

'''''The Task'''''

# Write a function that can perform a perfect shuffle on an even-sized list of values.
# Call this function repeatedly to count how many shuffles are needed to get a deck back to its original order, for each of the deck sizes listed under "Test Cases" below.
#* You can use a list of numbers (or anything else that's convenient) to represent a deck; just make sure that all "cards" are unique within each deck.
#* Print out the resulting shuffle counts, to demonstrate that your program passes the test-cases.
'''''Test Cases'''''

::::: {| class="wikitable"
|-
! input ''(deck size)'' !! output ''(number of shuffles required)''
|-
| 8 || 3
|-
| 24 || 11
|-
| 52 || 8
|-
| 100 || 30
|-
| 1020 || 1018
|-
| 1024 || 10
|-
| 10000 || 300
|}

Solution:
/* ===> INCLUDES <============================================================*/
#include
#include
#include

/* ===> CONSTANTS <===========================================================*/
#define N_DECKS 7
const int kDecks[N_DECKS] = { 8, 24, 52, 100, 1020, 1024, 10000 };

/* ===> FUNCTION PROTOTYPES <=================================================*/
int CreateDeck( int **deck, int nCards );
void InitDeck( int *deck, int nCards );
int DuplicateDeck( int **dest, const int *orig, int nCards );
int InitedDeck( int *deck, int nCards );
int ShuffleDeck( int *deck, int nCards );
void FreeDeck( int **deck );

/* ===> FUNCTION DEFINITIONS <================================================*/

int main() {
    int i, nCards, nShuffles;
    int *deck = NULL;

    for( i=0; i


Perfect shuffle

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

    // shuffleCycleLength :: Int -> Int
    const shuffleCycleLength = deckSize =>
        firstCycle(shuffle, range(1, deckSize))
        .all.length;

    // shuffle :: [a] -> [a]
    const shuffle = xs =>
        concat(zip.apply(null, splitAt(div(length(xs), 2), xs)));

    // firstycle :: Eq a => (a -> a) -> a -> [a]
    const firstCycle = (f, x) =>
        until(
            m => EqArray(x, m.current),
            m => {
                const fx = f(m.current);
                return {
                    current: fx,
                    all: m.all.concat([fx])
                };
            }, {
                current: f(x),
                all: [x]
            }
        );

    // Two arrays equal ?
    // EqArray :: [a] -> [b] -> Bool
    const EqArray = (xs, ys) => {
        const [nx, ny] = [xs.length, ys.length];
        return nx === ny ? (
            nx > 0 ? (
                xs[0] === ys[0] && EqArray(xs.slice(1), ys.slice(1))
            ) : true
        ) : false;
    };

    // GENERIC FUNCTIONS

    // zip :: [a] -> [b] -> [(a,b)]
    const zip = (xs, ys) =>
        xs.slice(0, Math.min(xs.length, ys.length))
        .map((x, i) => [x, ys[i]]);

    // concat :: [[a]] -> [a]
    const concat = xs => [].concat.apply([], xs);

    // splitAt :: Int -> [a] -> ([a],[a])
    const splitAt = (n, xs) => [xs.slice(0, n), xs.slice(n)];

    // div :: Num -> Num -> Int
    const div = (x, y) => Math.floor(x / y);

    // until :: (a -> Bool) -> (a -> a) -> a -> a
    const until = (p, f, x) => {
        const go = x => p(x) ? x : go(f(x));
        return go(x);
    }

    // range :: Int -> Int -> [Int]
    const range = (m, n) =>
        Array.from({
            length: Math.floor(n - m) + 1
        }, (_, i) => m + i);

    // length :: [a] -> Int
    // length :: Text -> Int
    const length = xs => xs.length;

    // maximumBy :: (a -> a -> Ordering) -> [a] -> a
    const maximumBy = (f, xs) =>
        xs.reduce((a, x) => a === undefined ? x : (
            f(x, a) > 0 ? x : a
        ), undefined);

    // transpose :: [[a]] -> [[a]]
    const transpose = xs =>
        xs[0].map((_, iCol) => xs.map((row) => row[iCol]));

    // show :: a -> String
    const show = x => JSON.stringify(x, null, 2);

    // replicateS :: Int -> String -> String
    const replicateS = (n, s) => {
        let v = s,
            o = '';
        if (n < 1) return o;
        while (n > 1) {
            if (n & 1) o = o.concat(v);
            n >>= 1;
            v = v.concat(v);
        }
        return o.concat(v);
    };

    // justifyRight :: Int -> Char -> Text -> Text
    const justifyRight = (n, cFiller, strText) =>
        n > strText.length ? (
            (replicateS(n, cFiller) + strText)
            .slice(-n)
        ) : strText;

    // TEST
    return transpose(transpose([
                ['Deck', 'Shuffles']
            ].concat(
                [8, 24, 52, 100, 1020, 1024, 10000]
                .map(n => [n.toString(), shuffleCycleLength(n)
                    .toString()
                ])))
            .map(col => { // Right-justified number columns
                const width = length(
                    maximumBy((a, b) => length(a) - length(b), col)
                ) + 2;

                return col.map(x => justifyRight(width, ' ', x));
            }))
        .map(row => row.join(''))
        .join('\n');
})();


Perfect shuffle

Solution:
"""
Brute force solution for the Perfect Shuffle problem.
See http://oeis.org/A002326 for possible improvements
"""
from functools import partial
from itertools import chain
from operator import eq
from typing import (Callable,
                    Iterable,
                    Iterator,
                    List,
                    TypeVar)

T = TypeVar('T')

def main():
    print("Deck length | Shuffles ")
    for length in (8, 24, 52, 100, 1020, 1024, 10000):
        deck = list(range(length))
        shuffles_needed = spin_number(deck, shuffle)
        print(f"{length:<11} | {shuffles_needed}")

def shuffle(deck: List[T]) -> List[T]:
    """[1, 2, 3, 4] -> [1, 3, 2, 4]"""
    half = len(deck) // 2
    return list(chain.from_iterable(zip(deck[:half], deck[half:])))

def spin_number(source: T,
                function: Callable[[T], T]) -> int:
    """
    Applies given function to the source
    until the result becomes equal to it,
    returns the number of calls
    """
    is_equal_source = partial(eq, source)
    spins = repeat_call(function, source)
    return next_index(is_equal_source,
                      spins,
                      start=1)

def repeat_call(function: Callable[[T], T],
                value: T) -> Iterator[T]:
    """(f, x) -> f(x), f(f(x)), f(f(f(x))), ..."""
    while True:
        value = function(value)
        yield value

def next_index(predicate: Callable[[T], bool],
               iterable: Iterable[T],
               start: int = 0) -> int:
    """
    Returns index of the first element of the iterable
    satisfying given condition
    """
    for index, item in enumerate(iterable, start=start):
        if predicate(item):
            return index

if __name__ == "__main__":
    main()


Perfect totient numbers

Generate and show here, the first twenty [https://en.wikipedia.org/wiki/Perfect_totient_number Perfect totient numbers].

;Related task:
::*   [[Totient function]]

;Also see:
::*   the OEIS      entry for   [http://oeis.org/A082897 perfect totient numbers].
::*   mrob            [https://mrob.com/pub/seq/a082897.html list of the first 54]

Solution:
#include
#include

long totient(long n){
	long tot = n,i;

	for(i=2;i*i<=n;i+=2){
		if(n%i==0){
			while(n%i==0)
				n/=i;
			tot-=tot/i;
		}

		if(i==2)
			i=1;
	}

	if(n>1)
		tot-=tot/n;

	return tot;
}

long* perfectTotients(long n){
	long *ptList = (long*)malloc(n*sizeof(long)), m,count=0,sum,tot;

	for(m=1;count",argV[0]);
	else{
		n = atoi(argV[1]);

		ptList = perfectTotients(n);

		printf("The first %d perfect Totient numbers are : \n[",n);

		for(i=0;i
Output for multiple runs, a is the default executable file name produced by GCC

C:\rossetaCode>a 10
The first 10 perfect Totient numbers are :
[ 3, 9, 15, 27, 39, 81, 111, 183, 243, 255]
C:\rossetaCode>a 20
The first 20 perfect Totient numbers are :
[ 3, 9, 15, 27, 39, 81, 111, 183, 243, 255, 327, 363, 471, 729, 2187, 2199, 3063, 4359, 4375, 5571]
C:\rossetaCode>a 30
The first 30 perfect Totient numbers are :
[ 3, 9, 15, 27, 39, 81, 111, 183, 243, 255, 327, 363, 471, 729, 2187, 2199, 3063, 4359, 4375, 5571, 6561, 8751, 15723, 19683, 36759, 46791, 59049, 65535, 140103, 177147]
C:\rossetaCode>a 40
The first 40 perfect Totient numbers are :
[ 3, 9, 15, 27, 39, 81, 111, 183, 243, 255, 327, 363, 471, 729, 2187, 2199, 3063, 4359, 4375, 5571, 6561, 8751, 15723, 19683, 36759, 46791, 59049, 65535, 140103, 177147, 208191, 441027, 531441, 1594323, 4190263, 4782969, 9056583, 14348907, 43046721, 57395631]


Perfect totient numbers

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

    // main :: IO ()
    const main = () =>
        showLog(
            take(20, perfectTotients())
        );

    // perfectTotients :: Generator [Int]
    function* perfectTotients() {
        const
            phi = memoized(
                n => length(
                    filter(
                        k => 1 === gcd(n, k),
                        enumFromTo(1, n)
                    )
                )
            ),
            imperfect = n => n !== sum(
                tail(iterateUntil(
                    x => 1 === x,
                    phi,
                    n
                ))
            );
        let ys = dropWhileGen(imperfect, enumFrom(1))
        while (true) {
            yield ys.next().value - 1;
            ys = dropWhileGen(imperfect, ys)
        }
    }

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

    // abs :: Num -> Num
    const abs = Math.abs;

    // dropWhileGen :: (a -> Bool) -> Gen [a] -> [a]
    const dropWhileGen = (p, xs) => {
        let
            nxt = xs.next(),
            v = nxt.value;
        while (!nxt.done && p(v)) {
            nxt = xs.next();
            v = nxt.value;
        }
        return xs;
    };

    // enumFrom :: Int -> [Int]
    function* enumFrom(x) {
        let v = x;
        while (true) {
            yield v;
            v = 1 + v;
        }
    }

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

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

    // 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));
    };

    // 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;
    };

    // 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

    // length :: [a] -> Int
    const length = xs =>
        (Array.isArray(xs) || 'string' === typeof xs) ? (
            xs.length
        ) : Infinity;

    // memoized :: (a -> b) -> (a -> b)
    const memoized = f => {
        const dctMemo = {};
        return x => {
            const v = dctMemo[x];
            return undefined !== v ? v : (dctMemo[x] = f(x));
        };
    };

    // showLog :: a -> IO ()
    const showLog = (...args) =>
        console.log(
            args
            .map(JSON.stringify)
            .join(' -> ')
        );

    // 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];
        }));

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


Perfect totient numbers

Solution:
from math import gcd
from functools import lru_cache
from itertools import islice, count

@lru_cache(maxsize=None)
def  φ(n):
    return sum(1 for k in range(1, n + 1) if gcd(n, k) == 1)

def perfect_totient():
    for n0 in count(1):
        parts, n = 0, n0
        while n != 1:
            n = φ(n)
            parts += n
        if parts == n0:
            yield n0

if __name__ == '__main__':
    print(list(islice(perfect_totient(), 20)))


Periodic table

;Task:
Display the row and column in the periodic table of the given atomic number.

;The periodic table:
Let us consider the following periodic table representation.

     __________________________________________________________________________
    |   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18 |
    |                                                                          |
    |1  H                                                                   He |
    |                                                                          |
    |2  Li  Be                                          B   C   N   O   F   Ne |
    |                                                                          |
    |3  Na  Mg                                          Al  Si  P   S   Cl  Ar |
    |                                                                          |
    |4  K   Ca  Sc  Ti  V   Cr  Mn  Fe  Co  Ni  Cu  Zn  Ga  Ge  As  Se  Br  Kr |
    |                                                                          |
    |5  Rb  Sr  Y   Zr  Nb  Mo  Tc  Ru  Rh  Pd  Ag  Cd  In  Sn  Sb  Te  I   Xe |
    |                                                                          |
    |6  Cs  Ba  *   Hf  Ta  W   Re  Os  Ir  Pt  Au  Hg  Tl  Pb  Bi  Po  At  Rn |
    |                                                                          |
    |7  Fr  Ra  °   Rf  Db  Sg  Bh  Hs  Mt  Ds  Rg  Cn  Nh  Fl  Mc  Lv  Ts  Og |
    |__________________________________________________________________________|
    |                                                                          |
    |                                                                          |
    |8  Lantanoidi* La  Ce  Pr  Nd  Pm  Sm  Eu  Gd  Tb  Dy  Ho  Er  Tm  Yb  Lu |
    |                                                                          |
    |9   Aktinoidi° Ak  Th  Pa  U   Np  Pu  Am  Cm  Bk  Cf  Es  Fm  Md  No  Lr |
    |__________________________________________________________________________|

;Example test cases;

*   1 -> 1 1
*   2 -> 1 18
*   29 -> 4 11
*   42 -> 5 6
*   57 -> 8 4
*   58 -> 8 5
*   72 -> 6 4
*   89 -> 9 4

;Details;

The representation of the periodic table may be represented in various way. The one presented in this challenge does have the following property : Lantanides and Aktinoides are all in a dedicated row, hence there is no element that is placed at 6, 3 nor 7, 3.

You may take a look at the atomic number repartitions [https://en.wikipedia.org/wiki/Periodic_table#/media/File:Simple_Periodic_Table_Chart-blocks.svg here].

The atomic number is at least 1, at most 118.

;See also:
*   [https://en.wikipedia.org/wiki/Periodic_table the periodic table]
*   [https://twitter.com/CompSciFact/status/1537447575573233666 This task was an idea from CompSciFact]
*   [https://ascii.periodni.com/index.html The periodic table in ascii] that was used as template

Solution:
#include

LIB_GADGET_START

/* prototypes */
GD_VIDEO put_chemical_cell( GD_VIDEO table, MT_CELL * E, DS_ARRAY E_data );
MT_CELL* load_chem_elements( MT_CELL * E, DS_ARRAY * E_data );
int select_box_chemical_elem( RDS(MT_CELL, Elements) );
void put_information(RDS( MT_CELL, elem), int i);

Main

   GD_VIDEO table;
   /* las dimensiones del terminal son muy importantes
      para desplegar la tabla */
   Resize_terminal(42,135);
   Init_video( &table );

   Gpm_Connect conn;

   if ( ! Init_mouse(&conn)){
        Msg_red("No se puede conectar al servidor del ratón\n");
        Stop(1);
   }
   Enable_raw_mode();
   Hide_cursor;

   /* I declare a multitype array "Elements", and load the file that will populate this array. */
   New multitype Elements;
   Elements = load_chem_elements( pSDS(Elements) );
   Throw( load_fail );

  /* I create a "Button" object with which the execution will end. */
   New objects Btn_exit;
   Btn_exit = New_object_mouse( SMD(&Btn_exit), BUTTOM, "  Terminar  ", 6,44, 15, 0);

  /* Fill the space on the screen with the table of chemical elements. */
   table = put_chemical_cell( table, SDS(Elements) );

  /* I print the screen and place the mouse object. */
   Refresh(table);
   Put object Btn_exit;

  /* I wait for a mouse event. */
   int c;
   Waiting_some_clic(c)
   {
       if( select_box_chemical_elem(SDS(Elements)) ){
           Waiting_some_clic(c) break;
       }
       if (Object_mouse( Btn_exit)) break;

       Refresh(table);
       Put object Btn_exit;
   }

   Free object Btn_exit;
   Free multitype Elements;

   Exception( load_fail ){
      Msg_red("No es un archivo matriciable");
   }

   Free video table;
   Disable_raw_mode();
   Close_mouse();
   Show_cursor;

   At SIZE_TERM_ROWS,0;
   Prnl;
End

void put_information(RDS(MT_CELL, elem), int i)
{
    At 2,19;
    Box_solid(11,64,67,17);
    Color(15,17);
    At 4,22; Print "Elemento (%s) = %s", (char*)$s-elem[i,5],(char*)$s-elem[i,6];
    if (Cell_type(elem,i,7) == double_TYPE ){
        At 5,22; Print "Peso atómico  = %f", $d-elem[i,7];
    }else{
        At 5,22; Print "Peso atómico  = (%ld)", $l-elem[i,7];
    }
    At 6,22; Print "Posición      = (%ld, %ld)",$l-elem[i,0]+ ($l-elem[i,0]>=8 ? 0:1),$l-elem[i,1]+1;
    At 8,22; Print "1ª energía de";
    if (Cell_type(elem,i,12) == double_TYPE ){
        At 9,22; Print "ionización (kJ/mol) = %.*f",2,$d-elem[i,12];
    }else{
        At 9,22; Print "ionización (kJ/mol) = ---";
    }
    if (Cell_type(elem,i,13) == double_TYPE ){
        At 10,22; Print "Electronegatividad  = %.*f",2,$d-elem[i,13];
    }else{
        At 10,22; Print "Electronegatividad  = ---";
    }
    At 4,56; Print "Conf. electrónica:";
    At 5,56; Print "       %s", (char*)$s-elem[i,14];
    At 7,56; Print "Estados de oxidación:";
    if ( Cell_type(elem,i,15) == string_TYPE ){
        At 8,56; Print "       %s", (char*)$s-elem[i,15];
    }else{
       /* Strangely, when the file loader detects a "+n", it treats it as a string,
          but when it detects a "-n", it treats it as a "long".
          I must review that. */
        At 8,56; Print "       %ld", $l-elem[i,15];
    }
    At 10,56; Print "Número Atómico: %ld",$l-elem[i,4];
    Reset_color;
}

int select_box_chemical_elem( RDS(MT_CELL, elem) )
{
   int i;
   Iterator up i [0:1:Rows(elem)]{
       if ( Is_range_box( $l-elem[i,8], $l-elem[i,9], $l-elem[i,10], $l-elem[i,11]) ){
           Gotoxy( $l-elem[i,8], $l-elem[i,9] );
           Color_fore( 15 ); Color_back( 0 );
           Box( 4,5, DOUB_ALL );

           Gotoxy( $l-elem[i,8]+1, $l-elem[i,9]+2); Print "%ld",$l-elem[i,4];
           Gotoxy( $l-elem[i,8]+2, $l-elem[i,9]+2); Print "%s",(char*)$s-elem[i,5];
           Flush_out;
           Reset_color;
           put_information(SDS(elem),i);
           return 1;
       }
   }
   return 0;
}

GD_VIDEO put_chemical_cell(GD_VIDEO table, MT_CELL * elem, DS_ARRAY elem_data)
{
   int i;

   /* put each cell */
   Iterator up i [0:1:Rows(elem)]{
       long rx = 2+($l-elem[i,0]*4);
       long cx = 3+($l-elem[i,1]*7);
       long offr = rx+3;
       long offc = cx+6;

       Gotoxy(table, rx, cx);

       Color_fore(table, $l-elem[i,2]);
       Color_back(table,$l-elem[i,3]);

       Box(table, 4,5, SING_ALL );

       char Atnum[50], Elem[50];
       sprintf(Atnum,"\x1b[3m%ld\x1b[23m",$l-elem[i,4]);
       sprintf(Elem, "\x1b[1m%s\x1b[22m",(char*)$s-elem[i,5]);

       Outvid(table,rx+1, cx+2, Atnum);
       Outvid(table,rx+2, cx+2, Elem);

       Reset_text(table);
       /* Update positions of each cell to be detected by the mouse. */
       $l-elem[i,8] = rx;
       $l-elem[i,9] = cx;
       $l-elem[i,10] = offr;
       $l-elem[i,11] = offc;

   }
   /* put rows and cols */
   Iterator up i [ 1: 1: 19 ]{
       Gotoxy(table, 31, 5+(i-1)*7);
       char num[5]; sprintf( num, "%d",i );
       Outvid(table, num );
   }
   Iterator up i [ 1: 1: 8 ]{
       Gotoxy(table, 3+(i-1)*4, 130);
       char num[5]; sprintf( num, "%d",i );
       Outvid(table, num );
   }
   Outvid( table, 35,116, "8");
   Outvid( table, 39,116, "9");

   /* others */
   Color_fore(table, 15);
   Color_back(table, 0);
   Outvid(table,35,2,"Lantánidos ->");
   Outvid(table,39,2,"Actínidos  ->");
   Reset_text(table);
   return table;
}

MT_CELL* load_chem_elements( MT_CELL * E, DS_ARRAY * E_data )
{
   F_STAT dataFile = Stat_file("chem_table.txt");
   if( dataFile.is_matrix ){
       /*
          Set the ranges to read from the file.
          You can choose the portion of the file that you want to upload.
       */
       Range ptr E [0:1:dataFile.total_lines-1, 0:1:dataFile.max_tokens_per_line-1];
       E = Load_matrix_mt( SDS(E), "chem_table.txt", dataFile, DET_LONG);
   }else{
       Is_ok=0;
   }
   return E;
}


Periodic table

Solution:
def perta(atomic) -> (int, int):

    NOBLES = 2, 10, 18, 36, 54, 86, 118
    INTERTWINED = 0, 0, 0, 0, 0, 57, 89
    INTERTWINING_SIZE = 14
    LINE_WIDTH = 18

    prev_noble = 0
    for row, noble in enumerate(NOBLES):
        if atomic <= noble:  # we are at the good row. We now need to determine the column
            nb_elem = noble - prev_noble  # number of elements on that row
            rank =  atomic - prev_noble  # rank of the input element among elements
            if INTERTWINED[row] and INTERTWINED[row] <= atomic <= INTERTWINED[row] + INTERTWINING_SIZE:  # lantanides or actinides
                row += 2
                col = rank + 1
            else:  # not a lantanide nor actinide
                # handle empty spaces between 1-2, 4-5 and 12-13.
                nb_empty = LINE_WIDTH - nb_elem  # spaces count as columns
                inside_left_element_rank = 2 if noble > 2 else 1
                col = rank + (nb_empty if rank > inside_left_element_rank else 0)
            break
        prev_noble = noble
    return row+1, col

# small test suite

TESTS = {
    1: (1, 1),
    2: (1, 18),
    29: (4,11),
    42: (5, 6),
    58: (8, 5),
    59: (8, 6),
    57: (8, 4),
    71: (8, 18),
    72: (6, 4),
    89: (9, 4),
    90: (9, 5),
    103: (9, 18),
}

for input, out in TESTS.items():
    found = perta(input)
    print('TEST:{:3d} -> '.format(input) + str(found) + (f' ; ERROR: expected {out}' if found != out else ''))


Perlin noise

The   '''computer graphics,   most notably to procedurally generate textures or heightmaps.

The Perlin noise is basically a   pseudo-random   mapping of   \R^d   into   \R   with an integer   d   which can be arbitrarily large but which is usually   2,   3,   or   4.

Either by using a dedicated library or by implementing the algorithm, show that the Perlin noise   (as defined in 2002 in the Java implementation below)   of the point in 3D-space with coordinates     3.14,   42,   7     is     0.13691995878400012.

''Note: this result assumes 64 bit IEEE-754 floating point calculations. If your language uses a different floating point representation, make a note of it and calculate the value accurate to 15 decimal places, or your languages accuracy threshold if it is less. Trailing zeros need not be displayed.''

Solution:
#include
#include
#include

int p[512];

double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); }
double lerp(double t, double a, double b) { return a + t * (b - a); }
double grad(int hash, double x, double y, double z) {
      int h = hash & 15;
      double u = h<8 ? x : y,
             v = h<4 ? y : h==12||h==14 ? x : z;
      return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
   }

double noise(double x, double y, double z) {
      int X = (int)floor(x) & 255,
          Y = (int)floor(y) & 255,
          Z = (int)floor(z) & 255;
      x -= floor(x);
      y -= floor(y);
      z -= floor(z);
      double u = fade(x),
             v = fade(y),
             w = fade(z);
      int A = p[X  ]+Y, AA = p[A]+Z, AB = p[A+1]+Z,
          B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;

      return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ),
                                     grad(p[BA  ], x-1, y  , z   )),
                             lerp(u, grad(p[AB  ], x  , y-1, z   ),
                                     grad(p[BB  ], x-1, y-1, z   ))),
                     lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),
                                     grad(p[BA+1], x-1, y  , z-1 )),
                             lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
                                     grad(p[BB+1], x-1, y-1, z-1 ))));
   }

void loadPermutation(char* fileName){
	FILE* fp = fopen(fileName,"r");
	int permutation[256],i;

	for(i=0;i<256;i++)
		fscanf(fp,"%d",&permutation[i]);

	fclose(fp);

	for (int i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i];
}

int main(int argC,char* argV[])
{
	if(argC!=5)
		printf("Usage : %s  ");
	else{
		loadPermutation(argV[1]);
		printf("Perlin Noise for (%s,%s,%s) is %.17lf",argV[2],argV[3],argV[4],noise(strtod(argV[2],NULL),strtod(argV[3],NULL),strtod(argV[4],NULL)));
	}

	return 0;
}


Perlin noise

Solution:
import math

def perlin_noise(x, y, z):
    X = math.floor(x) & 255                  # FIND UNIT CUBE THAT
    Y = math.floor(y) & 255                  # CONTAINS POINT.
    Z = math.floor(z) & 255
    x -= math.floor(x)                                # FIND RELATIVE X,Y,Z
    y -= math.floor(y)                                # OF POINT IN CUBE.
    z -= math.floor(z)
    u = fade(x)                                # COMPUTE FADE CURVES
    v = fade(y)                                # FOR EACH OF X,Y,Z.
    w = fade(z)
    A = p[X  ]+Y; AA = p[A]+Z; AB = p[A+1]+Z      # HASH COORDINATES OF
    B = p[X+1]+Y; BA = p[B]+Z; BB = p[B+1]+Z      # THE 8 CUBE CORNERS,

    return lerp(w, lerp(v, lerp(u, grad(p[AA  ], x  , y  , z   ),  # AND ADD
                                   grad(p[BA  ], x-1, y  , z   )), # BLENDED
                           lerp(u, grad(p[AB  ], x  , y-1, z   ),  # RESULTS
                                   grad(p[BB  ], x-1, y-1, z   ))),# FROM  8
                   lerp(v, lerp(u, grad(p[AA+1], x  , y  , z-1 ),  # CORNERS
                                   grad(p[BA+1], x-1, y  , z-1 )), # OF CUBE
                           lerp(u, grad(p[AB+1], x  , y-1, z-1 ),
                                   grad(p[BB+1], x-1, y-1, z-1 ))))

def fade(t):
    return t ** 3 * (t * (t * 6 - 15) + 10)

def lerp(t, a, b):
    return a + t * (b - a)

def grad(hash, x, y, z):
    h = hash & 15                      # CONVERT LO 4 BITS OF HASH CODE
    u = x if h<8 else y                # INTO 12 GRADIENT DIRECTIONS.
    v = y if h<4 else (x if h in (12, 14) else z)
    return (u if (h&1) == 0 else -u) + (v if (h&2) == 0 else -v)

p = [None] * 512
permutation = [151,160,137,91,90,15,
   131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
   190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
   88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
   77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
   102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
   135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
   5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
   223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
   138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]
for i in range(256):
    p[256+i] = p[i] = permutation[i]

if __name__ == '__main__':
    print("%1.17f" % perlin_noise(3.14, 42, 7))


Permutations/Derangements

A [http://mathworld.wolfram.com/Derangement.html derangement] is a permutation of the order of distinct items in which ''no item appears in its original place''.

For example, the only two derangements of the three items (0, 1, 2) are (1, 2, 0), and (2, 0, 1).

The number of derangements of ''n'' distinct items is known as the subfactorial of ''n'', sometimes written as !''n''.
There are various ways to calculate !''n''.

;Task:
# Create a named function/method/subroutine/... to generate derangements of the integers ''0..n-1'', (or ''1..n'' if you prefer).
# Generate ''and show'' all the derangements of 4 integers using the above routine.
# Create a function that calculates the subfactorial of ''n'', !''n''.
# Print and show a table of the ''counted'' number of derangements of ''n'' vs. the calculated !''n'' for n from 0..9 inclusive.

;Optional stretch goal:
*   Calculate    !''20''

;Related tasks:
*   [[Anagrams/Deranged anagrams]]
*   [[Best shuffle]]
*   [[Left_factorials]]

Solution:
#include
typedef unsigned long long LONG;

LONG deranged(int depth, int len, int *d, int show)
{
        int i;
        char tmp;
        LONG count = 0;

        if (depth == len) {
                if (show) {
                        for (i = 0; i < len; i++) putchar(d[i] + 'a');
                        putchar('\n');
                }
                return 1;
        }
        for (i = len - 1; i >= depth; i--) {
                if (i == d[depth]) continue;

                tmp = d[i]; d[i] = d[depth]; d[depth] = tmp;
                count += deranged(depth + 1, len, d, show);
                tmp = d[i]; d[i] = d[depth]; d[depth] = tmp;
        }
        return count;
}

LONG gen_n(int n, int show)
{
        LONG i;
        int a[1024]; /* 1024 ought to be big enough for anybody */

        for (i = 0; i < n; i++) a[i] = i;
        return deranged(0, n, a, show);
}

LONG sub_fact(int n)
{
        return n < 2 ? 1 - n : (sub_fact(n - 1) + sub_fact(n - 2)) * (n - 1);
}

int main()
{
        int i;

        printf("Deranged Four:\n");
        gen_n(4, 1);

        printf("\nCompare list vs calc:\n");
        for (i = 0; i < 10; i++)
                printf("%d:\t%llu\t%llu\n", i, gen_n(i, 0), sub_fact(i));

        printf("\nfurther calc:\n");
        for (i = 10; i <= 20; i++)
                printf("%d: %llu\n", i, sub_fact(i));

        return 0;
}


Permutations/Derangements

Solution:
from itertools import permutations
import math

def derangements(n):
    'All deranged permutations of the integers 0..n-1 inclusive'
    return ( perm for perm in permutations(range(n))
             if all(indx != p for indx, p in enumerate(perm)) )

def subfact(n):
    if n == 2 or n == 0:
        return 1
    elif n == 1:
        return 0
    elif  1 <= n <=18:
        return round(math.factorial(n) / math.e)
    elif n.imag == 0 and n.real == int(n.real) and n > 0:
        return (n-1) * ( subfact(n - 1) + subfact(n - 2) )
    else:
        raise ValueError()

def _iterlen(iter):
    'length of an iterator without taking much memory'
    l = 0
    for x in iter:
        l += 1
    return l

if __name__ == '__main__':
    n = 4
    print("Derangements of %s" % (tuple(range(n)),))
    for d in derangements(n):
        print("  %s" % (d,))

    print("\nTable of n vs counted vs calculated derangements")
    for n in range(10):
        print("%2i %-5i %-5i" %
              (n, _iterlen(derangements(n)), subfact(n)))

    n = 20
    print("\n!%i = %i" % (n, subfact(n)))


Permutations/Rank of a permutation

A particular ranking of a permutation associates an integer with a particular ordering of all the permutations of a set of distinct items.
For our purposes the ranking will assign integers 0 .. (n! - 1) to an ordering of all the permutations of the integers 0 .. (n - 1).

For example, the permutations of the digits zero to 3 arranged lexicographically have the following rank:

  PERMUTATION      RANK
  (0, 1, 2, 3) ->  0
  (0, 1, 3, 2) ->  1
  (0, 2, 1, 3) ->  2
  (0, 2, 3, 1) ->  3
  (0, 3, 1, 2) ->  4
  (0, 3, 2, 1) ->  5
  (1, 0, 2, 3) ->  6
  (1, 0, 3, 2) ->  7
  (1, 2, 0, 3) ->  8
  (1, 2, 3, 0) ->  9
  (1, 3, 0, 2) -> 10
  (1, 3, 2, 0) -> 11
  (2, 0, 1, 3) -> 12
  (2, 0, 3, 1) -> 13
  (2, 1, 0, 3) -> 14
  (2, 1, 3, 0) -> 15
  (2, 3, 0, 1) -> 16
  (2, 3, 1, 0) -> 17
  (3, 0, 1, 2) -> 18
  (3, 0, 2, 1) -> 19
  (3, 1, 0, 2) -> 20
  (3, 1, 2, 0) -> 21
  (3, 2, 0, 1) -> 22
  (3, 2, 1, 0) -> 23

Algorithms exist that can generate a rank from a permutation for some particular ordering of permutations, and that can generate the same rank from the given individual permutation (i.e. given a rank of 17 produce (2, 3, 1, 0) in the example above).

One use of such algorithms could be in generating a small, random, sample of permutations of n items without duplicates when the total number of permutations is large. Remember that the total number of permutations of n items is given by n! which grows large very quickly: A 32 bit integer can only hold 12!, a 64 bit integer only 20!. It becomes difficult to take the straight-forward approach of generating all permutations then taking a random sample of them.

A [http://stackoverflow.com/questions/12884428/generate-sample-of-1-000-000-random-permutations question on the Stack Overflow site] asked how to generate one million random and indivudual permutations of 144 items.

;Task:
# Create a function to generate a permutation from a rank.
# Create the inverse function that given the permutation generates its rank.
# Show that for n=3 the two functions are indeed inverses of each other.
# Compute and show here 4 random, individual, samples of permutations of 12 objects.

;Stretch goal:
* State how reasonable it would be to use your program to address the limits of the Stack Overflow question.

;References:
# [http://webhome.cs.uvic.ca/~ruskey/Publications/RankPerm/RankPerm.html Ranking and Unranking Permutations in Linear Time] by Myrvold & Ruskey. (Also available via Google [https://docs.google.com/viewer?a=v&q=cache:t8G2xQ3-wlkJ:citeseerx.ist.psu.edu/viewdoc/download%3Fdoi%3D10.1.1.43.4521%26rep%3Drep1%26type%3Dpdf+&hl=en≷=uk&pid=bl&srcid=ADGEESgDcCc4JVd_57ziRRFlhDFxpPxoy88eABf9UG_TLXMzfxiC8D__qx4xfY3JAhw_nuPDrZ9gSInX0MbpYjgh807ZfoNtLrl40wdNElw2JMdi94Znv1diM-XYo53D8uelCXnK053L&sig=AHIEtbQtx-sxcVzaZgy9uhniOmETuW4xKg here]).
# [http://www.davdata.nl/math/ranks.html Ranks] on the DevData site.
# [http://stackoverflow.com/a/1506337/10562 Another answer] on Stack Overflow to a different question that explains its algorithm in detail.

;Related tasks:
#[[Factorial_base_numbers_indexing_permutations_of_a_collection]]

Solution:
#include
#include

#define SWAP(a,b) do{t=(a);(a)=(b);(b)=t;}while(0)

void _mr_unrank1(int rank, int n, int *vec) {
    int t, q, r;
    if (n < 1) return;

    q = rank / n;
    r = rank % n;
    SWAP(vec[r], vec[n-1]);
    _mr_unrank1(q, n-1, vec);
}

int _mr_rank1(int n, int *vec, int *inv) {
    int s, t;
    if (n < 2) return 0;

    s = vec[n-1];
    SWAP(vec[n-1], vec[inv[n-1]]);
    SWAP(inv[s], inv[n-1]);
    return s + n * _mr_rank1(n-1, vec, inv);
}

/* Fill the integer array  (of size ) with the
 * permutation at rank .
 */
void get_permutation(int rank, int n, int *vec) {
    int i;
    for (i = 0; i < n; ++i) vec[i] = i;
    _mr_unrank1(rank, n, vec);
}

/* Return the rank of the current permutation of array
 * (of size ).
 */
int get_rank(int n, int *vec) {
    int i, r, *v, *inv;

    v = malloc(n * sizeof(int));
    inv = malloc(n * sizeof(int));

    for (i = 0; i < n; ++i) {
        v[i] = vec[i];
        inv[vec[i]] = i;
    }
    r = _mr_rank1(n, v, inv);
    free(inv);
    free(v);
    return r;
}

int main(int argc, char *argv[]) {
    int i, r, tv[4];

    for (r = 0; r < 24; ++r) {
        printf("%3d: ", r);
        get_permutation(r, 4, tv);

        for (i = 0; i < 4; ++i) {
            if (0 == i) printf("[ ");
            else printf(", ");
            printf("%d", tv[i]);
        }
        printf(" ] = %d\n", get_rank(4, tv));
    }
}


Permutations/Rank of a permutation

Solution:
from math import factorial as fact
from random import randrange
from textwrap import wrap

def identity_perm(n):
    return list(range(n))

def unranker1(n, r, pi):
    while n > 0:
        n1, (rdivn, rmodn) = n-1, divmod(r, n)
        pi[n1], pi[rmodn] = pi[rmodn], pi[n1]
        n = n1
        r = rdivn
    return pi

def init_pi1(n, pi):
    pi1 = [-1] * n
    for i in range(n):
        pi1[pi[i]] = i
    return pi1

def ranker1(n, pi, pi1):
    if n == 1:
        return 0
    n1 = n-1
    s = pi[n1]
    pi[n1], pi[pi1[n1]] = pi[pi1[n1]], pi[n1]
    pi1[s], pi1[n1] = pi1[n1], pi1[s]
    return s + n * ranker1(n1, pi, pi1)

def unranker2(n, r, pi):
    while n > 0:
        n1 = n-1
        s, rmodf = divmod(r, fact(n1))
        pi[n1], pi[s] = pi[s], pi[n1]
        n = n1
        r = rmodf
    return pi

def ranker2(n, pi, pi1):
    if n == 1:
        return 0
    n1 = n-1
    s = pi[n1]
    pi[n1], pi[pi1[n1]] = pi[pi1[n1]], pi[n1]
    pi1[s], pi1[n1] = pi1[n1], pi1[s]
    return s * fact(n1) + ranker2(n1, pi, pi1)

def get_random_ranks(permsize, samplesize):
    perms = fact(permsize)
    ranks = set()
    while len(ranks) < samplesize:
        ranks |= set( randrange(perms)
                      for r in range(samplesize - len(ranks)) )
    return ranks

def test1(comment, unranker, ranker):
    n, samplesize, n2 = 3, 4, 12
    print(comment)
    perms = []
    for r in range(fact(n)):
        pi = identity_perm(n)
        perm = unranker(n, r, pi)
        perms.append((r, perm))
    for r, pi in perms:
        pi1 = init_pi1(n, pi)
        print('  From rank %2i to %r back to %2i' % (r, pi, ranker(n, pi[:], pi1)))
    print('\n  %i random individual samples of %i items:' % (samplesize, n2))
    for r in get_random_ranks(n2, samplesize):
        pi = identity_perm(n2)
        print('    ' + ' '.join('%2i' % i for i in unranker(n2, r, pi)))
    print('')

def test2(comment, unranker):
    samplesize, n2 = 4, 144
    print(comment)
    print('  %i random individual samples of %i items:' % (samplesize, n2))
    for r in get_random_ranks(n2, samplesize):
        pi = identity_perm(n2)
        print('    ' + '\n      '.join(wrap(repr(unranker(n2, r, pi)))))
    print('')

if __name__ == '__main__':
    test1('First ordering:', unranker1, ranker1)
    test1('Second ordering:', unranker2, ranker2)
    test2('First ordering, large number of perms:', unranker1)


Permutations by swapping

;Task:
Generate permutations of n items in which successive permutations differ from each other by the swapping of any two items.

Also generate the sign of the permutation which is +1 when the permutation is generated from an even number of swaps from the initial state, and -1 for odd.

Show the permutations and signs of three items, in order of generation ''here''.

Such data are of use in generating the determinant of a square matrix and any functions created should bear this in mind.

Note: The Steinhaus–Johnson–Trotter algorithm generates successive permutations where ''adjacent'' items are swapped, but from this discussion adjacency is not a requirement.

;References:
* Steinhaus–Johnson–Trotter algorithm
* [http://www.cut-the-knot.org/Curriculum/Combinatorics/JohnsonTrotter.shtml Johnson-Trotter Algorithm Listing All Permutations]
* Heap's algorithm
* [http://www.gutenberg.org/files/18567/18567-h/18567-h.htm#ch7] Tintinnalogia

;Related tasks:
*   [[Matrix arithmetic]]
*   [[Gray code]]

Solution:
#include
#include
#include

int flag = 1;

void heapPermute(int n, int arr[],int arrLen){
	int temp;
	int i;

	if(n==1){
		printf("\n[");

		for(i=0;i",argV[0]);
	else{
		while(argV[1][i]!=00){
			if(argV[1][i++]==',')
				count++;
		}

		arr = (int*)malloc(count*sizeof(int));

		i = 0;

		token = strtok(argV[1],",");

		while(token!=NULL){
			arr[i++] = atoi(token);
			token = strtok(NULL,",");
		}

		heapPermute(i,arr,count);
	}

	return 0;
}


Permutations by swapping

Solution:
from operator import itemgetter

DEBUG = False # like the built-in __debug__

def spermutations(n):
    """permutations by swapping. Yields: perm, sign"""
    sign = 1
    p = [[i, 0 if i == 0 else -1] # [num, direction]
         for i in range(n)]

    if DEBUG: print ' #', p
    yield tuple(pp[0] for pp in p), sign

    while any(pp[1] for pp in p): # moving
        i1, (n1, d1) = max(((i, pp) for i, pp in enumerate(p) if pp[1]),
                           key=itemgetter(1))
        sign *= -1
        if d1 == -1:
            # Swap down
            i2 = i1 - 1
            p[i1], p[i2] = p[i2], p[i1]
            # If this causes the chosen element to reach the First or last
            # position within the permutation, or if the next element in the
            # same direction is larger than the chosen element:
            if i2 == 0 or p[i2 - 1][0] > n1:
                # The direction of the chosen element is set to zero
                p[i2][1] = 0
        elif d1 == 1:
            # Swap up
            i2 = i1 + 1
            p[i1], p[i2] = p[i2], p[i1]
            # If this causes the chosen element to reach the first or Last
            # position within the permutation, or if the next element in the
            # same direction is larger than the chosen element:
            if i2 == n - 1 or p[i2 + 1][0] > n1:
                # The direction of the chosen element is set to zero
                p[i2][1] = 0
        if DEBUG: print ' #', p
        yield tuple(pp[0] for pp in p), sign

        for i3, pp in enumerate(p):
            n3, d3 = pp
            if n3 > n1:
                pp[1] = 1 if i3 < i2 else -1
                if DEBUG: print ' # Set Moving'

if __name__ == '__main__':
    from itertools import permutations

    for n in (3, 4):
        print '\nPermutations and sign of %i items' % n
        sp = set()
        for i in spermutations(n):
            sp.add(i[0])
            print('Perm: %r Sign: %2i' % i)
            #if DEBUG: raw_input('?')
        # Test
        p = set(permutations(range(n)))
        assert sp == p, 'Two methods of generating permutations do not agree'


Phrase reversals

;Task:
Given a string of space separated words containing the following phrase:
  rosetta code phrase reversal

:# Reverse the characters of the string.
:# Reverse the characters of each individual word in the string, maintaining original word order within the string.
:# Reverse the order of each word of the string, maintaining the order of characters in each word.

Show your output here.

Solution:
#include
#include

/* The functions used are destructive, so after each call the string needs
 * to be copied over again. One could easily allocate new strings as
 * required, but this way allows the caller to manage memory themselves */

char* reverse_section(char *s, size_t length)
{
    if (length == 0) return s;

    size_t i; char temp;
    for (i = 0; i < length / 2 + 1; ++i)
        temp = s[i], s[i] = s[length - i], s[length - i] = temp;
    return s;
}

char* reverse_words_in_order(char *s, char delim)
{
    if (!strlen(s)) return s;

    size_t i, j;
    for (i = 0; i < strlen(s) - 1; ++i) {
        for (j = 0; s[i + j] != 0 && s[i + j] != delim; ++j)
            ;
        reverse_section(s + i, j - 1);
        s += j;
    }
    return s;
}

char* reverse_string(char *s)
{
    return strlen(s) ? reverse_section(s, strlen(s) - 1) : s;
}

char* reverse_order_of_words(char *s, char delim)
{
    reverse_string(s);
    reverse_words_in_order(s, delim);
    return s;
}

int main(void)
{
    char str[]    = "rosetta code phrase reversal";
    size_t lenstr = sizeof(str) / sizeof(str[0]);
    char scopy[lenstr];
    char delim = ' ';

    /* Original String */
    printf("Original:       \"%s\"\n", str);

    /* Reversed string */
    strncpy(scopy, str, lenstr);
    reverse_string(scopy);
    printf("Reversed:       \"%s\"\n", scopy);

    /* Reversed words in string */
    strncpy(scopy, str, lenstr);
    reverse_words_in_order(scopy, delim);
    printf("Reversed words: \"%s\"\n", scopy);

    /* Reversed order of words in string */
    strncpy(scopy, str, lenstr);
    reverse_order_of_words(scopy, delim);
    printf("Reversed order: \"%s\"\n", scopy);

    return 0;
}


Phrase reversals

Solution:
(function (p) {
  return [
    p.split('').reverse().join(''),

    p.split(' ').map(function (x) {
        return x.split('').reverse().join('');
    }).join(' '),

    p.split(' ').reverse().join(' ')

  ].join('\n');

})('rosetta code phrase reversal');


Phrase reversals

Solution:
'''String reversals at different levels.'''

# reversedCharacters :: String -> String
def reversedCharacters(s):
    '''All characters in reversed sequence.'''
    return reverse(s)

# wordsWithReversedCharacters :: String -> String
def wordsWithReversedCharacters(s):
    '''Characters within each word in reversed sequence.'''
    return unwords(map(reverse, words(s)))

# reversedWordOrder :: String -> String
def reversedWordOrder(s):
    '''Sequence of words reversed.'''
    return unwords(reverse(words(s)))

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

    s = 'rosetta code phrase reversal'
    print(
        tabulated(s + ':\n')(
            lambda f: f.__name__
        )(lambda s: "'" + s + "'")(
            lambda f: f(s)
        )([
            reversedCharacters,
            wordsWithReversedCharacters,
            reversedWordOrder
        ])
    )

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

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

# reverse :: [a] -> [a]
# reverse :: String -> String
def reverse(xs):
    '''The elements of xs in reverse order.'''
    return xs[::-1] if isinstance(xs, str) else (
        list(reversed(xs))
    )

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

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

# words :: String -> [String]
def words(s):
    '''A list of words delimited by characters
       representing white space.'''
    return s.split()

if __name__ == '__main__':
    main()


Pig the dice game

The   game of Pig   is a multiplayer game played with a single six-sided die.   The
object of the game is to reach   '''100'''   points or more.
Play is taken in turns.   On each person's turn that person has the option of either:

:# '''Rolling the dice''':   where a roll of two to six is added to their score for that turn and the player's turn continues as the player is given the same choice again;   or a roll of   '''1'''   loses the player's total points   ''for that turn''   and their turn finishes with play passing to the next player.
:# '''Holding''':   the player's score for that round is added to their total and becomes safe from the effects of throwing a   '''1'''   (one).   The player's turn finishes with play passing to the next player.

;Task:
Create a program to score for, and simulate dice throws for, a two-person game.

;Related task:
*   [[Pig the dice game/Player]]

Solution:
#include
#include
#include

const int NUM_PLAYERS = 2;
const int MAX_POINTS = 100;

//General functions
int randrange(int min, int max){
    return (rand() % (max - min + 1)) + min;
}

//Game functions
void ResetScores(int *scores){
    for(int i = 0; i < NUM_PLAYERS; i++){
        scores[i] = 0;
    }
}

void Play(int *scores){
    int scoredPoints = 0;
    int diceResult;
    int choice;

    for(int i = 0; i < NUM_PLAYERS; i++){
        while(1){
            printf("Player %d - You have %d total points and %d points this turn \nWhat do you want to do (1)roll or (2)hold: ", i + 1, scores[i], scoredPoints);
            scanf("%d", &choice);

            if(choice == 1){
                diceResult = randrange(1, 6);
                printf("\nYou rolled a %d\n", diceResult);

                if(diceResult != 1){
                    scoredPoints += diceResult;
                }
                else{
                    printf("You loose all your points from this turn\n\n");
                    scoredPoints = 0;
                    break;
                }
            }
            else if(choice == 2){
                scores[i] += scoredPoints;
                printf("\nYou holded, you have %d points\n\n", scores[i]);

                break;
            }
        }

        scoredPoints = 0;
        CheckForWin(scores[i], i + 1);

    }
}

void CheckForWin(int playerScore, int playerNum){
    if(playerScore >= MAX_POINTS){
        printf("\n\nCONGRATULATIONS PLAYER %d, YOU WIN\n\n!", playerNum);

        exit(EXIT_SUCCESS);
    }
}

int main()
{
    srand(time(0));

    int scores[NUM_PLAYERS];
    ResetScores(scores);

    while(1){
        Play(scores);
    }

    return 0;
}


Pig the dice game

Solution:
let players = [
  { name: '', score: 0 },
  { name: '', score: 0 }
];
let curPlayer = 1,
    gameOver = false;

players[0].name = prompt('Your name, player #1:').toUpperCase();
players[1].name = prompt('Your name, player #2:').toUpperCase();

function roll() { return 1 + Math.floor(Math.random()*6) }

function round(player) {
  let curSum = 0,
      quit = false,
      dice;
  alert(`It's ${player.name}'s turn (${player.score}).`);
  while (!quit) {
      dice = roll();
      if (dice == 1) {
        alert('You roll a 1. What a pity!');
        quit = true;
      } else {
        curSum += dice;
        quit = !confirm(`
          You roll a ${dice} (sum: ${curSum}).\n
          Roll again?
        `);
        if (quit) {
          player.score += curSum;
          if (player.score >= 100) gameOver = true;
        }
      }
  }
}
// main
while (!gameOver) {
  if (curPlayer == 0) curPlayer = 1; else curPlayer = 0;
  round(players[curPlayer]);
  if (gameOver) alert(`
    ${players[curPlayer].name} wins (${players[curPlayer].score}).
  `);
}


Pig the dice game

Solution:
#!/usr/bin/python3

'''
See: http://en.wikipedia.org/wiki/Pig_(dice)

This program scores and throws the dice for a two player game of Pig

'''

from random import randint

playercount = 2
maxscore = 100
safescore = [0] * playercount
player = 0
score=0

while max(safescore) < maxscore:
    rolling = input("Player %i: (%i, %i) Rolling? (Y) "
                    % (player, safescore[player], score)).strip().lower() in {'yes', 'y', ''}
    if rolling:
        rolled = randint(1, 6)
        print('  Rolled %i' % rolled)
        if rolled == 1:
            print('  Bust! you lose %i but still keep your previous %i'
                  % (score, safescore[player]))
            score, player = 0, (player + 1) % playercount
        else:
            score += rolled
    else:
        safescore[player] += score
        if safescore[player] >= maxscore:
            break
        print('  Sticking with %i' % safescore[player])
        score, player = 0, (player + 1) % playercount

print('\nPlayer %i wins with a score of %i' %(player, safescore[player]))


Pig the dice game/Player

;Task:
Create a dice simulator and scorer of [[Pig the dice game]] and add to it the ability to play the game to at least one strategy.
* State here the play strategies involved.
* Show play during a game here.

As a stretch goal:
* Simulate playing the game a number of times with two players of given strategies and report here summary statistics such as, but not restricted to, the influence of going first or which strategy seems stronger.

;Game Rules:
The game of Pig is a multiplayer game played with a single six-sided die. The
object of the game is to reach 100 points or more.
Play is taken in turns. On each person's turn that person has the option of either

# '''Rolling the dice''': where a roll of two to six is added to their score for that turn and the player's turn continues as the player is given the same choice again; or a roll of 1 loses the player's total points ''for that turn'' and their turn finishes with play passing to the next player.
# '''Holding''': The player's score for that round is added to their total and becomes safe from the effects of throwing a one. The player's turn finishes with play passing to the next player.

;References
* Pig (dice)
* [https://youtu.be/ULhRLGzoXQ0 The Math of Being a Pig] and [https://www.youtube.com/watch?v=zD9-V9Idbug Pigs (extra)] - Numberphile videos featuring Ben Sparks.

Solution:
#!/usr/bin/python3

'''
See: http://en.wikipedia.org/wiki/Pig_(dice)

This program scores, throws the dice, and plays for an N player game of Pig.

'''

from random import randint
from collections import namedtuple
import random
from pprint import pprint as pp
from collections import Counter

playercount = 2
maxscore = 100
maxgames = 100000

Game = namedtuple('Game', 'players, maxscore, rounds')
Round = namedtuple('Round', 'who, start, scores, safe')

class Player():
    def __init__(self, player_index):
        self.player_index = player_index

    def __repr__(self):
        return '%s(%i)' % (self.__class__.__name__, self.player_index)

    def __call__(self, safescore, scores, game):
        'Returns boolean True to roll again'
        pass

class RandPlay(Player):
    def __call__(self, safe, scores, game):
        'Returns random boolean choice of whether to roll again'
        return bool(random.randint(0, 1))

class RollTo20(Player):
    def __call__(self, safe, scores, game):
        'Roll again if this rounds score < 20'
        return (((sum(scores) + safe[self.player_index]) < maxscore)    # Haven't won yet
                and(sum(scores) < 20))                                  # Not at 20 this round

class Desparat(Player):
    def __call__(self, safe, scores, game):
        'Roll again if this rounds score < 20 or someone is within 20 of winning'
        return (((sum(scores) + safe[self.player_index]) < maxscore)    # Haven't won yet
                and( (sum(scores) < 20)                                 # Not at 20 this round
                     or max(safe) >= (maxscore - 20)))                  # Someone's close

def game__str__(self):
    'Pretty printer for Game class'
    return ("Game(players=%r, maxscore=%i,\n  rounds=[\n    %s\n  ])"
            % (self.players, self.maxscore,
               ',\n    '.join(repr(round) for round in self.rounds)))
Game.__str__ = game__str__

def winningorder(players, safescores):
    'Return (players in winning order, their scores)'
    return tuple(zip(*sorted(zip(players, safescores),
                            key=lambda x: x[1], reverse=True)))

def playpig(game):
    '''
    Plays the game of pig returning the players in winning order
    and their scores whilst updating argument game with the details of play.
    '''
    players, maxscore, rounds = game
    playercount = len(players)
    safescore = [0] * playercount   # Safe scores for each player
    player = 0                      # Who plays this round
    scores=[]                       # Individual scores this round

    while max(safescore) < maxscore:
        startscore = safescore[player]
        rolling = players[player](safescore, scores, game)
        if rolling:
            rolled = randint(1, 6)
            scores.append(rolled)
            if rolled == 1:
                # Bust!
                round = Round(who=players[player],
                              start=startscore,
                              scores=scores,
                              safe=safescore[player])
                rounds.append(round)
                scores, player = [], (player + 1) % playercount
        else:
            # Stick
            safescore[player] += sum(scores)
            round = Round(who=players[player],
                          start=startscore,
                          scores=scores,
                          safe=safescore[player])
            rounds.append(round)
            if safescore[player] >= maxscore:
                break
            scores, player = [], (player + 1) % playercount

    # return players in winning order and all scores
    return winningorder(players, safescore)

if __name__ == '__main__':
    game = Game(players=tuple(RandPlay(i) for i in range(playercount)),
                maxscore=20,
                rounds=[])
    print('ONE GAME')
    print('Winning order: %r; Respective scores: %r\n' % playpig(game))
    print(game)
    game = Game(players=tuple(RandPlay(i) for i in range(playercount)),
                maxscore=maxscore,
                rounds=[])
    algos = (RollTo20, RandPlay, Desparat)
    print('\n\nMULTIPLE STATISTICS using %r\n  for %i GAMES'
          % (', '.join(p.__name__ for p in algos), maxgames,))
    winners = Counter(repr(playpig(game._replace(players=tuple(random.choice(algos)(i)
                                                               for i in range(playercount)),
                                                 rounds=[]))[0])
                      for i in range(maxgames))
    print('  Players(position) winning on left; occurrences on right:\n    %s'
          % ',\n    '.join(str(w) for w in winners.most_common()))


Plasma effect

The plasma effect is a visual effect created by applying various functions, notably sine and cosine, to the color values of screen pixels. When animated (not a task requirement) the effect may give the impression of a colorful flowing liquid.

;Task
Create a plasma effect.

;See also
* [http://lodev.org/cgtutor/plasma.html Computer Graphics Tutorial (lodev.org)]
* [http://www.bidouille.org/prog/plasma Plasma (bidouille.org)]

Solution:
#include
#include
#include
#include
#include

#define pi M_PI

int main()
{
	CONSOLE_SCREEN_BUFFER_INFO info;
    int cols, rows;
	time_t t;
	int i,j;

    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
    cols = info.srWindow.Right - info.srWindow.Left + 1;
    rows = info.srWindow.Bottom - info.srWindow.Top + 1;

	HANDLE console;

	console = GetStdHandle(STD_OUTPUT_HANDLE);

	system("@clear||cls");

	srand((unsigned)time(&t));

	for(i=0;i

===Graphics version===
And here's the Graphics version, requires the [http://www.cs.colorado.edu/~main/bgi/cs1300/ WinBGIm] library. Prints out usage on incorrect invocation.

#include
#include
#include
#include

#define pi M_PI

void plasmaScreen(int width,int height){

	int x,y,sec;
	double dx,dy,dv;
	time_t t;

	initwindow(width,height,"WinBGIm Plasma");

	while(1){
		time(&t);
		sec = (localtime(&t))->tm_sec;

	for(x=0;x",argV[0]);
	else{
		plasmaScreen(atoi(argV[1]),atoi(argV[2]));
	}
	return 0;
}


Plasma effect

Solution:
import math
import colorsys
from PIL import Image

def plasma (w, h):
	out = Image.new("RGB", (w, h))
	pix = out.load()
	for x in range (w):
		for y in range(h):
			hue = 4.0 + math.sin(x / 19.0) + math.sin(y / 9.0) \
				+ math.sin((x + y) / 25.0) + math.sin(math.sqrt(x**2.0 + y**2.0) / 8.0)
			hsv = colorsys.hsv_to_rgb(hue/8.0, 1, 1)
			pix[x, y] = tuple([int(round(c * 255.0)) for c in hsv])
	return out

if __name__=="__main__":
	im = plasma(400, 400)
	im.show()


Playfair cipher

;Task:
Implement a  Playfair cipher for encryption and decryption.

The user must be able to choose   '''J'''  =  '''I'''      or   no   '''Q'''   in the alphabet.

The output of the encrypted and decrypted message must be in capitalized digraphs, separated by spaces.

;Output example:
                 HI DE TH EG OL DI NT HE TR EX ES TU MP

Solution:
from string import ascii_uppercase
from itertools import product
from re import findall

def uniq(seq):
    seen = {}
    return [seen.setdefault(x, x) for x in seq if x not in seen]

def partition(seq, n):
    return [seq[i : i + n] for i in xrange(0, len(seq), n)]

"""Instantiate a specific encoder/decoder."""
def playfair(key, from_ = 'J', to = None):
    if to is None:
        to = 'I' if from_ == 'J' else ''

    def canonicalize(s):
        return filter(str.isupper, s.upper()).replace(from_, to)

    # Build 5x5 matrix.
    m = partition(uniq(canonicalize(key + ascii_uppercase)), 5)

    # Pregenerate all forward translations.
    enc = {}

    # Map pairs in same row.
    for row in m:
        for i, j in product(xrange(5), repeat=2):
            if i != j:
                enc[row[i] + row[j]] = row[(i + 1) % 5] + row[(j + 1) % 5]

    # Map pairs in same column.
    for c in zip(*m):
        for i, j in product(xrange(5), repeat=2):
            if i != j:
                enc[c[i] + c[j]] = c[(i + 1) % 5] + c[(j + 1) % 5]

    # Map pairs with cross-connections.
    for i1, j1, i2, j2 in product(xrange(5), repeat=4):
        if i1 != i2 and j1 != j2:
            enc[m[i1][j1] + m[i2][j2]] = m[i1][j2] + m[i2][j1]

    # Generate reverse translations.
    dec = dict((v, k) for k, v in enc.iteritems())

    def sub_enc(txt):
        lst = findall(r"(.)(?:(?!\1)(.))?", canonicalize(txt))
        return " ".join(enc[a + (b if b else 'X')] for a, b in lst)

    def sub_dec(encoded):
        return " ".join(dec[p] for p in partition(canonicalize(encoded), 2))

    return sub_enc, sub_dec

(encode, decode) = playfair("Playfair example")
orig = "Hide the gold in...the TREESTUMP!!!"
print "Original:", orig
enc = encode(orig)
print "Encoded:", enc
print "Decoded:", decode(enc)


Plot coordinate pairs

;Task:
Plot a function represented as     x,  y     numerical arrays.

Post the resulting image for the following input arrays (taken from Python's Example section on ''Time a function''):
       x = {0,   1,    2,    3,    4,    5,     6,     7,     8,     9};
       y = {2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0};

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

Solution:
#include
#include
#include

#define N 40
double x[N], y[N];

void minmax(double x[], int len, double *base, double *step, int *nstep)
{
	int i;
	double diff, minv, maxv;
	*step = 1;

	minv = maxv = x[0];
	for (i = 1; i < len; i++) {
		if (minv > x[i]) minv = x[i];
		if (maxv < x[i]) maxv = x[i];
	}
	if (minv == maxv) {
		minv = floor(minv);
		maxv =  ceil(maxv);
		if (minv == maxv) {
			minv--;
			maxv++;
		}
	} else {
		diff = maxv - minv;
		while (*step < diff) *step *= 10;
		while (*step > diff)	   *step /= 10;
		if (*step > diff / 2)	   *step /= 5;
		else if (*step > diff / 5) *step /= 2;
	}

	*base = floor(minv / *step) * *step;
	*nstep =  ceil(maxv / *step) - floor(minv / *step);
}

/* writes an eps with 400 x 300 dimention, using 12 pt font */
#define CHARH 12
#define CHARW 6
#define DIMX 398
#define DIMY (300 - CHARH)
#define BOTY 20.
int plot(double x[], double y[], int len, char *spec)
{
	int nx, ny, i;
	double sx, sy, x0, y0;
	char buf[100];
	int dx, dy, lx, ly;
	double ofs_x, ofs_y, grid_x;

	minmax(x, len, &x0, &sx, &nx);
	minmax(y, len, &y0, &sy, &ny);

	dx = -log10(sx);
	dy = -log10(sy);

	ly = 0;
	for (i = 0; i <= ny; i++) {
		sprintf(buf, "%g\n", y0 + i * sy);
		if (strlen(buf) > ly) ly = strlen(buf);
	}
	ofs_x = ly * CHARW;

	printf("%%!PS-Adobe-3.0\n%%%%BoundingBox: 0 0 400 300\n"
		"/TimesRoman findfont %d scalefont setfont\n"
		"/rl{rlineto}def /l{lineto}def /s{setrgbcolor}def "
		"/rm{rmoveto}def /m{moveto}def /st{stroke}def\n",
		CHARH);
	for (i = 0; i <= ny; i++) {
		ofs_y = BOTY + (DIMY - BOTY) / ny * i;
		printf("0 %g m (%*.*f) show\n",
			ofs_y - 4, ly, dy, y0 + i * sy);
		if (i) printf("%g %g m 7 0 rl st\n",
			ofs_x, ofs_y);
	}
	printf("%g %g m %g %g l st\n", ofs_x, BOTY, ofs_x, ofs_y);

	for (i = 0; i <= nx; i++) {
		sprintf(buf, "%g", x0 + i * sx);
		lx = strlen(buf);
		grid_x = ofs_x + (DIMX - ofs_x) / nx * i;

		printf("%g %g m (%s) show\n", grid_x - CHARW * lx / 2,
			BOTY - 12, buf);
		if (i) printf("%g %g m 0 7 rl st\n", grid_x, BOTY);
	}
	printf("%g %g m %g %g l st\n", ofs_x, BOTY, grid_x, BOTY);

	if (strchr(spec, 'r'))		printf("1 0 0 s\n");
	else if (strchr(spec, 'b'))	printf("0 0 1 s\n");
	else if (strchr(spec, 'g'))	printf("0 1 0 s\n");
	else if (strchr(spec, 'm'))	printf("1 0 1 s\n");

	if (strchr(spec, 'o'))
		printf("/o { m 0 3 rm 3 -3 rl -3 -3 rl -3 3 rl closepath st} def "
			".5 setlinewidth\n");

	if (strchr(spec, '-')) {
		for (i = 0; i < len; i++) {
			printf("%g %g %s ",
				(x[i] - x0) / (sx * nx) * (DIMX - ofs_x) + ofs_x,
				(y[i] - y0) / (sy * ny) * (DIMY - BOTY) + BOTY,
				i ? "l" : "m");
		}
		printf("st\n");
	}

	if (strchr(spec, 'o'))
		for (i = 0; i < len; i++) {
			printf("%g %g o ",
				(x[i] - x0) / (sx * nx) * (DIMX - ofs_x) + ofs_x,
				(y[i] - y0) / (sy * ny) * (DIMY - BOTY) + BOTY);
		}

	printf("showpage\n%%EOF");

	return 0;
}

int main()
{
	int i;
	for (i = 0; i < N; i++) {
		x[i] = (double)i / N * 3.14159 * 6;
		y[i] = -1337 + (exp(x[i] / 10) + cos(x[i])) / 100;
	}
	/* string parts: any of "rgbm": color; "-": draw line; "o": draw symbol */
	plot(x, y, N, "r-o");
	return 0;
}


Plot coordinate pairs

Solution:
from visual import *
from visual.graph import *

plot1 = gdisplay( title='VPython Plot-Demo',
                  xtitle='x',
                  ytitle='y    (click and drag mouse to see coordinates)',
                  foreground=color.black,
                  background=color.white,
                  x=0, y=0,
                  width=400, height=400,
                  xmin=0, xmax=10,
                  ymin=0, ymax=200 )

f1 = gdots(color=color.red)                 # create plot-object

f1.plot(pos= (0,   2.7), color=color.blue ) # add a single point
f1.plot(pos=[(1,   2.8),                    # add a list of points
             (2,  31.4),
             (3,  38.1),
             (4,  58.0),
             (5,  76.2),
             (6, 100.5),
             (7, 130.0),
             (8, 149.3),
             (9, 180.0) ]
        )
label(display=plot1.display, text="Look here",
      pos=(6,100.5), xoffset=30,yoffset=-20 )


Poker hand analyser

[[Category:Cards]]
[[Category:Games]]

;Task:
Create a program to parse a single five card poker hand and rank it according to this list of poker hands.

A poker hand is specified as a space separated list of five playing cards.

Each input card has two characters indicating face and suit.

;Example:
::::'''2d'''       (two of diamonds).

Faces are:    '''a''', '''2''', '''3''', '''4''', '''5''', '''6''', '''7''', '''8''', '''9''', '''10''', '''j''', '''q''', '''k'''

Suits are:    '''h''' (hearts),   '''d''' (diamonds),   '''c''' (clubs),   and   '''s''' (spades),   or
alternatively,   the unicode card-suit characters:     ♥ ♦ ♣ ♠

Duplicate cards are illegal.

The program should analyze a single hand and produce one of the following outputs:
  straight-flush
  four-of-a-kind
  full-house
  flush
  straight
  three-of-a-kind
  two-pair
  one-pair
  high-card
  invalid

;Examples:
    2♥ 2♦ 2♣ k♣ q♦:   three-of-a-kind
    2♥ 5♥ 7♦ 8♣ 9♠:   high-card
    a♥ 2♦ 3♣ 4♣ 5♦:   straight
    2♥ 3♥ 2♦ 3♣ 3♦:   full-house
    2♥ 7♥ 2♦ 3♣ 3♦:   two-pair
    2♥ 7♥ 7♦ 7♣ 7♠:   four-of-a-kind
    10♥ j♥ q♥ k♥ a♥:  straight-flush
    4♥ 4♠ k♠ 5♦ 10♠:  one-pair
    q♣ 10♣ 7♣ 6♣ q♣:  invalid

The programs output for the above examples should be displayed here on this page.

;Extra credit:
# use the playing card characters introduced with Unicode 6.0 (U+1F0A1 - U+1F0DE).
# allow two jokers
::* use the symbol   '''joker'''
::* duplicates would be allowed (for jokers only)
::* five-of-a-kind would then be the highest hand

;More extra credit examples:
    joker  2♦  2♠  k♠  q♦:     three-of-a-kind
    joker  5♥  7♦  8♠  9♦:     straight
    joker  2♦  3♠  4♠  5♠:     straight
    joker  3♥  2♦  3♠  3♦:     four-of-a-kind
    joker  7♥  2♦  3♠  3♦:     three-of-a-kind
    joker  7♥  7♦  7♠  7♣:     five-of-a-kind
    joker  j♥  q♥  k♥  A♥:     straight-flush
    joker  4♣  k♣  5♦ 10♠:     one-pair
    joker  k♣  7♣  6♣  4♣:     flush
    joker  2♦  joker  4♠  5♠:  straight
    joker  Q♦  joker  A♠ 10♠:  straight
    joker  Q♦  joker  A♦ 10♦:  straight-flush
    joker  2♦  2♠  joker  q♦:  four-of-a-kind

;Related tasks:
* [[Playing cards]]
* [[Card shuffles]]
* [[Deal cards_for_FreeCell]]
* [[War Card_Game]]
* [[Go Fish]]

Solution:
#include
#include
#include
#include

#define TRUE 1
#define FALSE 0

#define FACES "23456789tjqka"
#define SUITS "shdc"

typedef int bool;

typedef struct {
    int face;  /* FACES map to 0..12 respectively */
    char suit;
} card;

card cards[5];

int compare_card(const void *a, const void *b) {
    card c1 = *(card *)a;
    card c2 = *(card *)b;
    return c1.face - c2.face;
}

bool equals_card(card c1, card c2) {
    if (c1.face == c2.face && c1.suit == c2.suit) return TRUE;
    return FALSE;
}

bool are_distinct() {
    int i, j;
    for (i = 0; i < 4; ++i)
        for (j = i + 1; j < 5; ++j)
            if (equals_card(cards[i], cards[j])) return FALSE;
    return TRUE;
}

bool is_straight() {
    int i;
    qsort(cards, 5, sizeof(card), compare_card);
    if (cards[0].face + 4 == cards[4].face) return TRUE;
    if (cards[4].face == 12 && cards[0].face == 0 &&
        cards[3].face == 3) return TRUE;
    return FALSE;
}

bool is_flush() {
    int i;
    char suit = cards[0].suit;
    for (i = 1; i < 5; ++i) if (cards[i].suit != suit) return FALSE;
    return TRUE;
}

const char *analyze_hand(const char *hand) {
    int i, j, gs = 0;
    char suit, *cp;
    bool found, flush, straight;
    int groups[13];
    if (strlen(hand) != 14) return "invalid";
    for (i = 0; i < 14; i += 3) {
        cp = strchr(FACES, tolower(hand[i]));
        if (cp == NULL) return "invalid";
        j = i / 3;
        cards[j].face = cp - FACES;
        suit = tolower(hand[i + 1]);
        cp = strchr(SUITS, suit);
        if (cp == NULL) return "invalid";
        cards[j].suit = suit;
    }
    if (!are_distinct()) return "invalid";
    for (i = 0; i < 13; ++i) groups[i] = 0;
    for (i = 0; i < 5; ++i) groups[cards[i].face]++;
    for (i = 0; i < 13; ++i) if (groups[i] > 0) gs++;
    switch(gs) {
        case 2:
            found = FALSE;
            for (i = 0; i < 13; ++i) if (groups[i] == 4) {
                found = TRUE;
                break;
            }
            if (found) return "four-of-a-kind";
            return "full-house";
        case 3:
            found = FALSE;
            for (i = 0; i < 13; ++i) if (groups[i] == 3) {
                found = TRUE;
                break;
            }
            if (found) return "three-of-a-kind";
            return "two-pairs";
        case 4:
            return "one-pair";
        default:
            flush = is_flush();
            straight = is_straight();
            if (flush && straight)
                return "straight-flush";
            else if (flush)
                return "flush";
            else if (straight)
                return "straight";
            else
                return "high-card";
    }
}

int main(){
    int i;
    const char *type;
    const char *hands[10] = {
        "2h 2d 2c kc qd",
        "2h 5h 7d 8c 9s",
        "ah 2d 3c 4c 5d",
        "2h 3h 2d 3c 3d",
        "2h 7h 2d 3c 3d",
        "2h 7h 7d 7c 7s",
        "th jh qh kh ah",
        "4h 4s ks 5d ts",
        "qc tc 7c 6c 4c",
        "ah ah 7c 6c 4c"
    };
    for (i = 0; i < 10; ++i) {
        type = analyze_hand(hands[i]);
        printf("%s: %s\n", hands[i], type);
    }
    return 0;
}


Poker hand analyser

Solution:
const FACES = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'j', 'q', 'k', 'a'];
const SUITS = ['♥', '♦', '♣', '♠'];

function analyzeHand(hand){
	let cards  = hand.split(' ').filter(x => x !== 'joker');
	let jokers = hand.split(' ').length - cards.length;

	let faces = cards.map( card => FACES.indexOf(card.slice(0,-1)) );
	let suits = cards.map( card => SUITS.indexOf(card.slice(-1)) );

	if( cards.some( (card, i, self) => i !== self.indexOf(card) ) || faces.some(face => face === -1) || suits.some(suit => suit === -1) )
		return 'invalid';

	let flush    = suits.every(suit => suit === suits[0]);
	let groups   = FACES.map( (face,i) => faces.filter(j => i === j).length).sort( (x, y) => y - x );
	let shifted  = faces.map(x => (x + 1) % 13);
	let distance = Math.min( Math.max(...faces) - Math.min(...faces), Math.max(...shifted) - Math.min(...shifted));
	let straight = groups[0] === 1 && distance < 5;
	groups[0] += jokers;

	if      (groups[0] === 5)                    return 'five-of-a-kind'
	else if (straight && flush)                  return 'straight-flush'
	else if (groups[0] === 4)                    return 'four-of-a-kind'
	else if (groups[0] === 3 && groups[1] === 2) return 'full-house'
	else if (flush)                              return 'flush'
	else if (straight)                           return 'straight'
	else if (groups[0] === 3)                    return 'three-of-a-kind'
	else if (groups[0] === 2 && groups[1] === 2) return 'two-pair'
	else if (groups[0] === 2)                    return 'one-pair'
	else                                         return 'high-card';
}