#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
#include <gmpxx.h>

using integer = mpz_class;

class stirling2 {
public:
    integer get(int n, int k);
private:
    std::map<std::pair<int, int>, integer> cache_;
};

integer stirling2::get(int n, int k) {
    if (k == n)
        return 1;
    if (k == 0 || k > n)
        return 0;
    auto p = std::make_pair(n, k);
    auto i = cache_.find(p);
    if (i != cache_.end())
        return i->second;
    integer s = k * get(n - 1, k) + get(n - 1, k - 1);
    cache_.emplace(p, s);
    return s;
}

void print_stirling_numbers(stirling2& s2, int n) {
    std::cout << "Stirling numbers of the second kind:\nn/k";
    for (int j = 0; j <= n; ++j) {
        std::cout << std::setw(j == 0 ? 2 : 8) << j;
    }
    std::cout << '\n';
    for (int i = 0; i <= n; ++i) {
        std::cout << std::setw(2) << i << ' ';
        for (int j = 0; j <= i; ++j)
            std::cout << std::setw(j == 0 ? 2 : 8) << s2.get(i, j);
        std::cout << '\n';
    }
}

int main() {
    stirling2 s2;
    print_stirling_numbers(s2, 12);
    std::cout << "Maximum value of S2(n,k) where n == 100:\n";
    integer max = 0;
    for (int k = 0; k <= 100; ++k)
        max = std::max(max, s2.get(100, k));
    std::cout << max << '\n';
    return 0;
}


public class Sudoku
{
    private int mBoard[][];
    private int mBoardSize;
    private int mBoxSize;
    private boolean mRowSubset[][];
    private boolean mColSubset[][];
    private boolean mBoxSubset[][];

    public Sudoku(int board[][]) {
        mBoard = board;
        mBoardSize = mBoard.length;
        mBoxSize = (int)Math.sqrt(mBoardSize);
        initSubsets();
    }

    public void initSubsets() {
        mRowSubset = new boolean[mBoardSize][mBoardSize];
        mColSubset = new boolean[mBoardSize][mBoardSize];
        mBoxSubset = new boolean[mBoardSize][mBoardSize];
        for(int i = 0; i < mBoard.length; i++) {
            for(int j = 0; j < mBoard.length; j++) {
                int value = mBoard[i][j];
                if(value != 0) {
                    setSubsetValue(i, j, value, true);
                }
            }
        }
    }

    private void setSubsetValue(int i, int j, int value, boolean present) {
        mRowSubset[i][value - 1] = present;
        mColSubset[j][value - 1] = present;
        mBoxSubset[computeBoxNo(i, j)][value - 1] = present;
    }

    public boolean solve() {
        return solve(0, 0);
    }

    public boolean solve(int i, int j) {
        if(i == mBoardSize) {
            i = 0;
            if(++j == mBoardSize) {
                return true;
            }
        }
        if(mBoard[i][j] != 0) {
            return solve(i + 1, j);
        }
        for(int value = 1; value <= mBoardSize; value++) {
            if(isValid(i, j, value)) {
                mBoard[i][j] = value;
                setSubsetValue(i, j, value, true);
                if(solve(i + 1, j)) {
                    return true;
                }
                setSubsetValue(i, j, value, false);
            }
        }

        mBoard[i][j] = 0;
        return false;
    }

    private boolean isValid(int i, int j, int val) {
        val--;
        boolean isPresent = mRowSubset[i][val] || mColSubset[j][val] || mBoxSubset[computeBoxNo(i, j)][val];
        return !isPresent;
    }

    private int computeBoxNo(int i, int j) {
        int boxRow = i / mBoxSize;
        int boxCol = j / mBoxSize;
        return boxRow * mBoxSize + boxCol;
    }

    public void print() {
        for(int i = 0; i < mBoardSize; i++) {
            if(i % mBoxSize == 0) {
                System.out.println(" -----------------------");
            }
            for(int j = 0; j < mBoardSize; j++) {
                if(j % mBoxSize == 0) {
                    System.out.print("| ");
                }
                System.out.print(mBoard[i][j] != 0 ? ((Object) (Integer.valueOf(mBoard[i][j]))) : "-");
                System.out.print(' ');
            }

            System.out.println("|");
        }

        System.out.println(" -----------------------");
    }

    public static void main(String[] args) {
        int[][] board = {
            {8, 5, 0, 0, 0, 2, 4, 0, 0},
            {7, 2, 0, 0, 0, 0, 0, 0, 9},
            {0, 0, 4, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 1, 0, 7, 0, 0, 2},
            {3, 0, 5, 0, 0, 0, 9, 0, 0},
            {0, 4, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 8, 0, 0, 7, 0},
            {0, 1, 7, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 3, 6, 0, 4, 0}
        };
        Sudoku s = new Sudoku(board);
        System.out.print("Starting grid:\n");
        s.print();
        if (s.solve()) {
            System.out.print("\nSolution:\n");
            s.print();
        } else {
            System.out.println("\nUnsolvable!");
        }
    }
}


import std.bigint;
import std.conv;
import std.functional;
import std.stdio;

alias sterling2 = memoize!sterling2Impl;
BigInt sterling2Impl(int n, int k) {
    if (n == 0 && k == 0) {
        return BigInt(1);
    }
    if ((n > 0 && k == 0) || (n == 0 && k > 0)) {
        return BigInt(0);
    }
    if (n == k) {
        return BigInt(1);
    }
    if (k > n) {
        return BigInt(0);
    }

    return BigInt(k) * sterling2(n - 1, k) + sterling2(n - 1, k - 1);
}

void main() {
    writeln("Stirling numbers of the second kind:");
    int max = 12;

    write("n/k");
    for (int n = 0; n <= max; n++) {
        writef("%10d", n);
    }
    writeln;

    for (int n = 0; n <= max; n++) {
        writef("%-3d", n);
        for (int k = 0; k <= n; k++) {
            writef("%10s", sterling2(n, k));
        }
        writeln;
    }

    writeln("The maximum value of S2(100, k) = ");
    auto previous = BigInt(0);
    for (int k = 1; k <= 100; k++) {
        auto current = sterling2(100, k);
        if (current > previous) {
            previous = current;
        } else {
            writeln(previous);
            auto ps = previous.to!string;
            writefln("(%d digits, k = %d)", ps.length, k - 1);
            break;
        }
    }
}


USING: combinators.short-circuit formatting io kernel math
math.extras prettyprint sequences ;
RENAME: stirling math.extras => (stirling)
IN: rosetta-code.stirling-second

! Tweak Factor's in-built stirling function for k=0
: stirling ( n k -- m )
    2dup { [ = not ] [ nip zero? ] } 2&&
    [ 2drop 0 ] [ (stirling) ] if ;

"Stirling numbers of the second kind: n k stirling:" print
"n\\k" write 13 dup [ "%8d" printf ] each-integer nl

<iota> [
    dup dup "%-2d " printf [0,b] [
        stirling "%8d" printf
    ] with each nl
] each nl

"Maximum value from the 100 _ stirling row:" print
100 <iota> [ 100 swap stirling ] map supremum .


dim as integer S2(0 to 12, 0 to 12)   'initially set with zeroes
dim as ubyte n, k
dim as string outstr

function padto( i as ubyte, j as integer ) as string
    return wspace(i-len(str(j)))+str(j)
end function

for k = 0 to 12   'calculate table
    S2(k,k)=1
next k
for n = 1 to 11
    for k = 1 to 12
        S2(n+1,k) = k*S2(n,k) + S2(n,k-1)
    next k
next n

print "Stirling numbers of the second kind"
print
outstr = "   k"
for k=0 to 12
    outstr += padto(12, k)
next k
print outstr
print " n"
for n = 0 to 12
    outstr = padto(2, n)+"  "
    for k = 0 to 12
        outstr += padto(12, S2(n, k))
    next k
    print outstr
next n


package main

import (
    "fmt"
    "math/big"
)

func main() {
    limit := 100
    last := 12
    s2 := make([][]*big.Int, limit+1)
    for n := 0; n <= limit; n++ {
        s2[n] = make([]*big.Int, limit+1)
        for k := 0; k <= limit; k++ {
            s2[n][k] = new(big.Int)
        }
        s2[n][n].SetInt64(int64(1))
    }
    var t big.Int
    for n := 1; n <= limit; n++ {
        for k := 1; k <= n; k++ {
            t.SetInt64(int64(k))
            t.Mul(&t, s2[n-1][k])
            s2[n][k].Add(&t, s2[n-1][k-1])
        }
    }
    fmt.Println("Stirling numbers of the second kind: S2(n, k):")
    fmt.Printf("n/k")
    for i := 0; i <= last; i++ {
        fmt.Printf("%9d ", i)
    }
    fmt.Printf("\n--")
    for i := 0; i <= last; i++ {
        fmt.Printf("----------")
    }
    fmt.Println()
    for n := 0; n <= last; n++ {
        fmt.Printf("%2d ", n)
        for k := 0; k <= n; k++ {
            fmt.Printf("%9d ", s2[n][k])
        }
        fmt.Println()
    }
    fmt.Println("\nMaximum value from the S2(100, *) row:")
    max := new(big.Int).Set(s2[limit][0])
    for k := 1; k <= limit; k++ {
        if s2[limit][k].Cmp(max) > 0 {
            max.Set(s2[limit][k])
        }
    }
    fmt.Println(max)
    fmt.Printf("which has %d digits.\n", len(max.String()))
}


[(Int, Int) = BigInt] computed

F sterling1(n, k)
   V key = (n, k)

   I key C :computed
      R :computed[key]
   I n == k == 0
      R BigInt(1)
   I n > 0 & k == 0
      R BigInt(0)
   I k > n
      R BigInt(0)
   V result = sterling1(n - 1, k - 1) + (n - 1) * sterling1(n - 1, k)
   :computed[key] = result
   R result

print(‘Unsigned Stirling numbers of the first kind:’)
V MAX = 12
print(‘n/k’.ljust(10), end' ‘’)
L(n) 0 .. MAX
   print(String(n).rjust(10), end' ‘’)
print()
L(n) 0 .. MAX
   print(String(n).ljust(10), end' ‘’)
   L(k) 0 .. n
      print(String(sterling1(n, k)).rjust(10), end' ‘’)
   print()
print(‘The maximum value of S1(100, k) = ’)
BigInt previous = 0
L(k) 1 .. 100
   V current = sterling1(100, k)
   I current > previous
      previous = current
   E
      print("#.\n(#. digits, k = #.)\n".format(previous, String(previous).len, k - 1))
      L.break


BEGIN
    # show some (unsigned) Stirling numbers of the first kind            #

    # specify the precision of LONG LONG INT, we need about 160 digits   #
    # for Stirling numbers of the first kind with n, k = 100             #
    PR precision 160 PR
    MODE SINT = LONG LONG INT;

    # returns a triangular matrix of Stirling numbers up to max n, max n #
    # the numbers are signed if signed is TRUE, unsigned otherwise       #
    PROC make s1 = ( INT max n, BOOL signed )REF[,]SINT:
    BEGIN
        REF[,]SINT s1 := HEAP[ 0 : max n, 0 : max n ]SINT;
        FOR n FROM 0 TO max n DO FOR k FROM 0 TO max n DO s1[ n, k ] := 0 OD OD;
        s1[ 0, 0 ] := 1;
        FOR n FROM 1 TO max n DO s1[ n, 0 ] := 0 OD;
        FOR n FROM 1 TO max n DO
            FOR k FROM 1 TO n DO
                SINT s1 term = ( ( n - 1 ) * s1[ n - 1, k ] );
                s1[ n, k ] := s1[ n - 1, k - 1 ] + IF signed THEN - s1 term ELSE s1 term FI
            OD
        OD;
        s1
    END # make s1 # ;
    # task requirements:                                                #
    # print Stirling numbers up to n, k = 12                            #
    BEGIN
        INT max stirling = 12;
        REF[,]SINT s1 = make s1( max stirling, FALSE );
        print( ( "Unsigned Stirling numbers of the first kind:", newline ) );
        print( ( " k" ) );
        FOR k FROM 0 TO max stirling DO print( ( whole( k, -10 ) ) ) OD;
        print( ( newline, " n", newline ) );
        FOR n FROM 0 TO max stirling DO
            print( ( whole( n, -2 ) ) );
            FOR k FROM 0 TO n DO
                print( ( whole( s1[ n, k ], -10 ) ) )
            OD;
            print( ( newline ) )
        OD
    END;
    # find the maximum Stirling number with n = 100                     #
    BEGIN
        INT max stirling = 100;
        REF[,]SINT s1 = make s1( max stirling, FALSE );
        SINT max 100 := 0;
        FOR k FROM 0 TO max stirling DO
            IF s1[ max stirling, k ] > max 100 THEN max 100 := s1[ max stirling, k ] FI
        OD;
        print( ( "Maximum Stirling number of the first kind with n = 100:", newline ) );
        print( ( whole( max 100, 0 ), newline ) )
    END
END


//-------------------------------------------[ Dancing Links and Algorithm X ]--
/**
 * The doubly-doubly circularly linked data object.
 * Data object X
 */
class DoX {
  /**
   * @param {string} V
   * @param {!DoX=} H
   */
  constructor(V, H) {
    this.V = V;
    this.L = this;
    this.R = this;
    this.U = this;
    this.D = this;
    this.S = 1;
    this.H = H || this;
    H && (H.S += 1);
  }
}

/**
 * Helper function to help build a horizontal doubly linked list.
 * @param {!DoX} e An existing node in the list.
 * @param {!DoX} n A new node to add to the right of the existing node.
 * @return {!DoX}
 */
const addRight = (e, n) => {
  n.R = e.R;
  n.L = e;
  e.R.L = n;
  return e.R = n;
};

/**
 * Helper function to help build a vertical doubly linked list.
 * @param {!DoX} e An existing node in the list.
 * @param {!DoX} n A new node to add below the existing node.
 */
const addBelow = (e, n) => {
  n.D = e.D;
  n.U = e;
  e.D.U = n;
  return e.D = n;
};

/**
 * Verbatim copy of DK's search algorithm. The meat of the DLX algorithm.
 * @param {!DoX} h The root node.
 * @param {!Array<!DoX>} s The solution array.
 */
const search = function(h, s) {
  if (h.R == h) {
    printSol(s);
  } else {
    let c = chooseColumn(h);
    cover(c);
    for (let r = c.D; r != c; r = r.D) {
      s.push(r);
      for (let j = r.R; r !=j; j = j.R) {
        cover(j.H);
      }
      search(h, s);
      r = s.pop();
      for (let j = r.R; j != r; j = j.R) {
        uncover(j.H);
      }
    }
    uncover(c);
  }
};

/**
 * Verbatim copy of DK's algorithm for choosing the next column object.
 * @param {!DoX} h
 * @return {!DoX}
 */
const chooseColumn = h => {
  let s = Number.POSITIVE_INFINITY;
  let c = h;
  for(let j = h.R; j != h; j = j.R) {
    if (j.S < s) {
      c = j;
      s = j.S;
    }
  }
  return c;
};

/**
 * Verbatim copy of DK's cover algorithm
 * @param {!DoX} c
 */
const cover = c => {
  c.L.R = c.R;
  c.R.L = c.L;
  for (let i = c.D; i != c; i = i.D) {
    for (let j = i.R; j != i; j = j.R) {
      j.U.D = j.D;
      j.D.U = j.U;
      j.H.S = j.H.S - 1;
    }
  }
};

/**
 * Verbatim copy of DK's cover algorithm
 * @param {!DoX} c
 */
const uncover = c => {
  for (let i = c.U; i != c; i = i.U) {
    for (let j = i.L; i != j; j = j.L) {
      j.H.S = j.H.S + 1;
      j.U.D = j;
      j.D.U = j;
    }
  }
  c.L.R = c;
  c.R.L = c;
};

//-----------------------------------------------------------[ Print Helpers ]--
/**
 * Given the standard string format of a grid, print a formatted view of it.
 * @param {!string|!Array} a
 */
const printGrid = function(a) {

  const getChar = c => {
    let r = Number(c);
    if (isNaN(r)) { return c }

    let o = 48;
    if (r > 9 && r < 36) { o = 55 }
    if (r >= 36) { o = 61 }
    return String.fromCharCode(r + o)
  };

  a = 'string' == typeof a ? a.split('') : a;

  let U = Math.sqrt(a.length);
  let N = Math.sqrt(U);
  let line = new Array(N).fill('+').reduce((p, c) => {
    p.push(... Array.from(new Array(1 + N*2).fill('-')));
    p.push(c);
    return p;
  }, ['\n+']).join('') + '\n';

  a = a.reduce(function(p, c, i) {
      let d = i && !(i % U), G = i && !(i % N);
      i = !(i % (U * N));
      d && !i && (p += '|\n| ');
      d && i && (p += '|');
      i && (p = '' + p + line + '| ');
      return '' + p + (G && !d ? '| ' : '') + getChar(c) + ' ';
    }, '') + '|' + line;
  console.log(a);

};

/**
 * Given a search solution, print the resultant grid.
 * @param {!Array<!DoX>} a An array of data objects
 */
const printSol = a => {
  printGrid(a.reduce((p, c) => {
    let [i, v] = c.V.split(':');
    p[i * 1] = v;
    return p;
  }, new Array(a.length).fill('.')));
};

//----------------------------------------------[ Grid to Exact cover Matrix ]--
/**
 * Helper to get some meta about the grid.
 * @param {!string} s The standard string representation of a grid.
 * @return {!Array}
 */
const gridMeta = s => {
  const g = s.split('');
  const cellCount = g.length;
  const tokenCount = Math.sqrt(cellCount);
  const N = Math.sqrt(tokenCount);
  const g2D = g.map(e => isNaN(e * 1) ?
    new Array(tokenCount).fill(1).map((_, i) => i + 1) :
    [e * 1]);
  return [cellCount, N, tokenCount, g2D];
};

/**
 * Given a cell grid index, return the row, column and box indexes.
 * @param {!number} n The n-value of the grid. 3 for a 9x9 sudoku.
 * @return {!function(!number): !Array<!number>}
 */
const indexesN = n => i => {
    let c = Math.floor(i / (n * n));
    i %= n * n;
    return [c, i, Math.floor(c / n) * n + Math.floor(i / n)];
};

/**
 * Given a puzzle string, reduce it to an exact-cover matrix and use
 * Donald Knuth's DLX algorithm to solve it.
 * @param puzString
 */
const reduceGrid = puzString => {

  printGrid(puzString);
  const [
    numCells,   // The total number of cells in a grid (81 for a 9x9 grid)
    N,          // the 'n' value of the grid. (3 for a 9x9 grid)
    U,          // The total number of unique tokens to be placed.
    g2D         // A 2D array representation of the grid, with each element
                // being an array of candidates for a cell. Known cells are
                // single element arrays.
  ] = gridMeta(puzString);

  const getIndex = indexesN(N);

  /**
   * The DLX Header row.
   * Its length is 4 times the grid's size. This is to be able to encode
   * each of the 4 Sudoku constrains, onto each of the cells of the grid.
   * The array is initialised with unlinked DoX nodes, but in the next step
   * those nodes are all linked.
   * @type {!Array.<!DoX>}
   */
  const headRow = new Array(4 * numCells)
    .fill('')
    .map((_, i) => new DoX(`H${i}`));

  /**
   * The header row root object. This is circularly linked to be to the left
   * of the first header object in the header row array.
   * It is used as the entry point into the DLX algorithm.
   * @type {!DoX}
   */
  let H = new DoX('ROOT');
  headRow.reduce((p, c) => addRight(p, c), H);

  /**
   * Transposed the sudoku puzzle into a exact cover matrix, so it can be passed
   * to the DLX algorithm to solve.
   */
  for (let i = 0; i < numCells; i++) {
    const [ri, ci, bi] = getIndex(i);
    g2D[i].forEach(num => {
      let id = `${i}:${num}`;
      let candIdx = num - 1;

      // The 4 columns that we will populate.
      const A = headRow[i];
      const B = headRow[numCells + candIdx + (ri * U)];
      const C = headRow[(numCells * 2) + candIdx + (ci * U)];
      const D = headRow[(numCells * 3) + candIdx + (bi * U)];

      // The Row-Column Constraint
      let rcc = addBelow(A.U, new DoX(id, A));

      // The Row-Number Constraint
      let rnc = addBelow(B.U, addRight(rcc, new DoX(id, B)));

      // The Column-Number Constraint
      let cnc = addBelow(C.U, addRight(rnc, new DoX(id, C)));

      // The Block-Number Constraint
      addBelow(D.U, addRight(cnc, new DoX(id, D)));
    });
  }
  search(H, []);
};


import Text.Printf (printf)
import Data.List (groupBy)
import qualified Data.MemoCombinators as Memo

stirling2 :: Integral a => (a, a) -> a
stirling2 = Memo.pair Memo.integral Memo.integral f
  where
    f (n, k)
      | n == 0 && k == 0 = 1
      | (n > 0 && k == 0) || (n == 0 && k > 0) = 0
      | n == k = 1
      | k > n = 0
      | otherwise = k * stirling2 (pred n, k) + stirling2 (pred n, pred k)

main :: IO ()
main = do
  printf "n/k"
  mapM_ (printf "%10d") ([0..12] :: [Int]) >> printf "\n"
  printf "%s\n" $ replicate (13 * 10 + 3) '-'
  mapM_ (\row -> printf "%2d|" (fst $ head row) >>
    mapM_ (printf "%10d" . stirling2) row >> printf "\n") table
  printf "\nThe maximum value of S2(100, k):\n%d\n" $
    maximum ([stirling2 (100, n) | n <- [1..100]] :: [Integer])
  where
    table :: [[(Int, Int)]]
    table = groupBy (\a b -> fst a == fst b) $ (,) <$> [0..12] <*> [0..12]


begin % show some (unsigned) Stirling numbers of the first kind              %
    integer MAX_STIRLING;
    MAX_STIRLING := 12;
    begin
        % construct a matrix of Stirling numbers up to max n, max n           %
        integer array s1 ( 0 :: MAX_STIRLING, 0 :: MAX_STIRLING );
        for n := 0 until MAX_STIRLING do begin
            for k := 0 until MAX_STIRLING do s1( n, k ) := 0
        end for_n ;
        s1( 0, 0 ) := 1;
        for n := 1 until MAX_STIRLING do s1( n, 0 ) := 0;
        for n := 1 until MAX_STIRLING do begin
            for k := 1 until n do begin
                integer s1Term;
                s1Term := ( ( n - 1 ) * s1( n - 1, k ) );
                s1( n, k ) := s1( n - 1, k - 1 ) + s1Term
            end for_k
        end for_n ;
        % print the Stirling numbers up to n, k = 12                          %
        write( "Unsigned Stirling numbers of the first kind:" );
        write( " k" );
        for k := 0 until MAX_STIRLING do writeon( i_w := 10, s_w := 0, k );
        write( " n" );
        for n := 0 until MAX_STIRLING do begin
            write( i_w := 2, s_w := 0, n );
            for k := 0 until n do begin
                writeon( i_w := 10, s_w := 0, s1( n, k ) )
            end for_k
        end for_n
    end
end.


#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct stirling_cache_tag {
    int max;
    int* values;
} stirling_cache;

int stirling_number1(stirling_cache* sc, int n, int k) {
    if (k == 0)
        return n == 0 ? 1 : 0;
    if (n > sc->max || k > n)
        return 0;
    return sc->values[n*(n-1)/2 + k - 1];
}

bool stirling_cache_create(stirling_cache* sc, int max) {
    int* values = calloc(max * (max + 1)/2, sizeof(int));
    if (values == NULL)
        return false;
    sc->max = max;
    sc->values = values;
    for (int n = 1; n <= max; ++n) {
        for (int k = 1; k <= n; ++k) {
            int s1 = stirling_number1(sc, n - 1, k - 1);
            int s2 = stirling_number1(sc, n - 1, k);
            values[n*(n-1)/2 + k - 1] = s1 + s2 * (n - 1);
        }
    }
    return true;
}

void stirling_cache_destroy(stirling_cache* sc) {
    free(sc->values);
    sc->values = NULL;
}

void print_stirling_numbers(stirling_cache* sc, int max) {
    printf("Unsigned Stirling numbers of the first kind:\nn/k");
    for (int k = 0; k <= max; ++k)
        printf(k == 0 ? "%2d" : "%10d", k);
    printf("\n");
    for (int n = 0; n <= max; ++n) {
        printf("%2d ", n);
        for (int k = 0; k <= n; ++k)
            printf(k == 0 ? "%2d" : "%10d", stirling_number1(sc, n, k));
        printf("\n");
    }
}

int main() {
    stirling_cache sc = { 0 };
    const int max = 12;
    if (!stirling_cache_create(&sc, max)) {
        fprintf(stderr, "Out of memory\n");
        return 1;
    }
    print_stirling_numbers(&sc, max);
    stirling_cache_destroy(&sc);
    return 0;
}


function check(i, j)
    id, im = div(i, 9), mod(i, 9)
    jd, jm = div(j, 9), mod(j, 9)

    jd == id && return true
    jm == im && return true

    div(id, 3) == div(jd, 3) &&
    div(jm, 3) == div(im, 3)
end

const lookup = zeros(Bool, 81, 81)

for i in 1:81
    for j in 1:81
        lookup[i,j] = check(i-1, j-1)
    end
end

function solve_sudoku(callback::Function, grid::Array{Int64})
    (function solve()
        for i in 1:81
            if grid[i] == 0
                t = Dict{Int64, Void}()

                for j in 1:81
                    if lookup[i,j]
                        t[grid[j]] = nothing
                    end
                end

                for k in 1:9
                    if !haskey(t, k)
                        grid[i] = k
                        solve()
                    end
                end

                grid[i] = 0
                return
            end
        end

        callback(grid)
    end)()
end

function display(grid)
    for i in 1:length(grid)
        print(grid[i], " ")
        i %  3 == 0 && print(" ")
        i %  9 == 0 && print("\n")
        i % 27 == 0 && print("\n")
    end
end

grid = Int64[5, 3, 0, 0, 2, 4, 7, 0, 0,
             0, 0, 2, 0, 0, 0, 8, 0, 0,
             1, 0, 0, 7, 0, 3, 9, 0, 2,
             0, 0, 8, 0, 7, 2, 0, 4, 9,
             0, 2, 0, 9, 8, 0, 0, 7, 0,
             7, 9, 0, 0, 0, 0, 0, 8, 0,
             0, 0, 0, 0, 3, 0, 5, 0, 6,
             9, 6, 0, 0, 1, 0, 3, 0, 0,
             0, 5, 0, 6, 9, 0, 0, 1, 0]

solve_sudoku(display, grid)


import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

public class SterlingNumbersSecondKind {

    public static void main(String[] args) {
        System.out.println("Stirling numbers of the second kind:");
        int max = 12;
        System.out.printf("n/k");
        for ( int n = 0 ; n <= max ; n++ ) {
            System.out.printf("%10d", n);
        }
        System.out.printf("%n");
        for ( int n = 0 ; n <= max ; n++ ) {
            System.out.printf("%-3d", n);
            for ( int k = 0 ; k <= n ; k++ ) {
                System.out.printf("%10s", sterling2(n, k));
            }
            System.out.printf("%n");
        }
        System.out.println("The maximum value of S2(100, k) = ");
        BigInteger previous = BigInteger.ZERO;
        for ( int k = 1 ; k <= 100 ; k++ ) {
            BigInteger current = sterling2(100, k);
            if ( current.compareTo(previous) > 0 ) {
                previous = current;
            }
            else {
                System.out.printf("%s%n(%d digits, k = %d)%n", previous, previous.toString().length(), k-1);
                break;
            }
        }
    }

    private static Map<String,BigInteger> COMPUTED = new HashMap<>();

    private static final BigInteger sterling2(int n, int k) {
        String key = n + "," + k;
        if ( COMPUTED.containsKey(key) ) {
            return COMPUTED.get(key);
        }
        if ( n == 0 && k == 0 ) {
            return BigInteger.valueOf(1);
        }
        if ( (n > 0 && k == 0) || (n == 0 && k > 0) ) {
            return BigInteger.ZERO;
        }
        if ( n == k ) {
            return BigInteger.valueOf(1);
        }
        if ( k > n ) {
            return BigInteger.ZERO;
        }
        BigInteger result = BigInteger.valueOf(k).multiply(sterling2(n-1, k)).add(sterling2(n-1, k-1));
        COMPUTED.put(key, result);
        return result;
    }

}


#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
#include <gmpxx.h>

using integer = mpz_class;

class unsigned_stirling1 {
public:
    integer get(int n, int k);
private:
    std::map<std::pair<int, int>, integer> cache_;
};

integer unsigned_stirling1::get(int n, int k) {
    if (k == 0)
        return n == 0 ? 1 : 0;
    if (k > n)
        return 0;
    auto p = std::make_pair(n, k);
    auto i = cache_.find(p);
    if (i != cache_.end())
        return i->second;
    integer s = get(n - 1, k - 1) + (n - 1) * get(n - 1, k);
    cache_.emplace(p, s);
    return s;
}

void print_stirling_numbers(unsigned_stirling1& s1, int n) {
    std::cout << "Unsigned Stirling numbers of the first kind:\nn/k";
    for (int j = 0; j <= n; ++j) {
        std::cout << std::setw(j == 0 ? 2 : 10) << j;
    }
    std::cout << '\n';
    for (int i = 0; i <= n; ++i) {
        std::cout << std::setw(2) << i << ' ';
        for (int j = 0; j <= i; ++j)
            std::cout << std::setw(j == 0 ? 2 : 10) << s1.get(i, j);
        std::cout << '\n';
    }
}

int main() {
    unsigned_stirling1 s1;
    print_stirling_numbers(s1, 12);
    std::cout << "Maximum value of S1(n,k) where n == 100:\n";
    integer max = 0;
    for (int k = 0; k <= 100; ++k)
        max = std::max(max, s1.get(100, k));
    std::cout << max << '\n';
    return 0;
}


// version 1.2.10

class Sudoku(rows: List<String>) {
    private val grid = IntArray(81)
    private var solved = false

    init {
        require(rows.size == 9 && rows.all { it.length == 9 }) {
            "Grid must be 9 x 9"
        }
        for (i in 0..8) {
            for (j in 0..8 ) grid[9 * i + j] = rows[i][j] - '0'
        }
    }

    fun solve() {
        println("Starting grid:\n\n$this")
        placeNumber(0)
        println(if (solved) "Solution:\n\n$this" else "Unsolvable!")
    }

    private fun placeNumber(pos: Int) {
        if (solved) return
        if (pos == 81) {
            solved = true
            return
        }
        if (grid[pos] > 0) {
            placeNumber(pos + 1)
            return
        }
        for (n in 1..9) {
            if (checkValidity(n, pos % 9, pos / 9)) {
                grid[pos] = n
                placeNumber(pos + 1)
                if (solved) return
                grid[pos] = 0
            }
        }
    }

    private fun checkValidity(v: Int, x: Int, y: Int): Boolean {
        for (i in 0..8) {
            if (grid[y * 9 + i] == v || grid[i * 9 + x] == v) return false
        }
        val startX = (x / 3) * 3
        val startY = (y / 3) * 3
        for (i in startY until startY + 3) {
            for (j in startX until startX + 3) {
                if (grid[i * 9 + j] == v) return false
            }
        }
        return true
    }

    override fun toString(): String {
        val sb = StringBuilder()
        for (i in 0..8) {
            for (j in 0..8) {
                sb.append(grid[i * 9 + j])
                sb.append(" ")
                if (j == 2 || j == 5) sb.append("| ")
            }
            sb.append("\n")
            if (i == 2 || i == 5) sb.append("------+-------+------\n")
        }
        return sb.toString()
    }
}

fun main(args: Array<String>) {
    val rows = listOf(
        "850002400",
        "720000009",
        "004000000",
        "000107002",
        "305000900",
        "040000000",
        "000080070",
        "017000000",
        "000036040"
    )
    Sudoku(rows).solve()
}


def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;

# Input:  {computed} (the cache)
# Output: {computed, result}
def stirling2($n; $k):
  "\($n),\($k)" as $key
  | if .computed[$key] then .result = .computed[$key]
    elif ($n == 0 and $k == 0) then .result = 1
    elif (($n > 0 and $k == 0) or ($n == 0 and $k > 0)) then .result = 0
    elif ($k == $n) then .result = 1
    elif ($k > $n) then .result = 0
    else stirling2($n-1; $k-1) as $s1
    | ($s1 | stirling2($n-1; $k)) as $s2
    | ($s1.result + ($k * $s2.result)) as $result
    | $s2
    | .computed[$key] = $result
    | .result = $result
    end ;

# Set .emit to a table of values and .computed to a cache of stirling2 values
# Output: {emit, computed}
def part1(max):
  {emit: "Unsigned Stirling numbers of the second kind:"}
  | .emit += "\n" + "n/k" +
      ([range(0; max+1) | lpad(10)] | join(""))
  | reduce range(0; max+1) as $n ( .computed = {};
      .emit += "\n" + ($n | lpad(3))
      | reduce range(0; $n+1) as $k (.;
          stirling2($n; $k)
          | .emit += (.result | lpad(10) ) )) ;

# "The maximum value of S2($m, k) ..."
# Input: {computed}
def part2($m):
  "The maximum value of S2(\($m), k) =",
   first(
     foreach range(1;$m+1) as $k ({computed:{}, previous: 0};
       stirling2($m; $k) as $current
       | if ($current.result > .previous)
         then .previous = $current.result
         else
           .emit = "\(.previous)\n(\(.previous|tostring|length) digits, k = \($k - 1))"
         end;
       select(.emit).emit) );

part1(12)
| .emit,
  part2(100)


using Combinatorics

const s2cache = Dict()

function stirlings2(n, k)
    if haskey(s2cache, Pair(n, k))
        return s2cache[Pair(n, k)]
    elseif n < 0
        throw(DomainError(n, "n must be nonnegative"))
    elseif n == k == 0
        return one(n)
    elseif n == 0 || k == 0
        return zero(n)
    elseif k == n - 1
        return binomial(n, 2)
    elseif k == 2
        return 2^(n-1) - 1
    end

    ret = k * stirlings2(n - 1, k) + stirlings2(n - 1, k - 1)
    s2cache[Pair(n, k)] = ret
    return ret

end

function printstirling2table(kmax)
    println("  ", mapreduce(i -> lpad(i, 10), *, 0:kmax))

    sstring(n, k) = begin i = stirlings2(n, k); lpad(k > n && i == 0 ? "" : i, 10) end

    for n in 0:kmax
        println(rpad(n, 2) * mapreduce(k -> sstring(n, k), *, 0:kmax))
    end
end

printstirling2table(12)
println("\nThe maximum for stirling2(100, _) is: ", maximum(k-> stirlings2(BigInt(100), BigInt(k)), 1:100))


import java.math.BigInteger

fun main() {
    println("Stirling numbers of the second kind:")
    val max = 12
    print("n/k")
    for (n in 0..max) {
        print("%10d".format(n))
    }
    println()
    for (n in 0..max) {
        print("%-3d".format(n))
        for (k in 0..n) {
            print("%10s".format(sterling2(n, k)))
        }
        println()
    }
    println("The maximum value of S2(100, k) = ")
    var previous = BigInteger.ZERO
    for (k in 1..100) {
        val current = sterling2(100, k)
        previous = if (current > previous) {
            current
        } else {
            println("%s%n(%d digits, k = %d)".format(previous, previous.toString().length, k - 1))
            break
        }
    }
}

private val COMPUTED: MutableMap<String, BigInteger> = HashMap()
private fun sterling2(n: Int, k: Int): BigInteger {
    val key = "$n,$k"
    if (COMPUTED.containsKey(key)) {
        return COMPUTED[key]!!
    }
    if (n == 0 && k == 0) {
        return BigInteger.valueOf(1)
    }
    if (n > 0 && k == 0 || n == 0 && k > 0) {
        return BigInteger.ZERO
    }
    if (n == k) {
        return BigInteger.valueOf(1)
    }
    if (k > n) {
        return BigInteger.ZERO
    }

    val result = BigInteger.valueOf(k.toLong()) * sterling2(n - 1, k) + sterling2(n - 1, k - 1)
    COMPUTED[key] = result
    return result
}


import std.bigint;
import std.functional;
import std.stdio;

alias sterling1 = memoize!sterling1Impl;
BigInt sterling1Impl(int n, int k) {
    if (n == 0 && k == 0) {
        return BigInt(1);
    }
    if (n > 0 && k == 0) {
        return BigInt(0);
    }
    if (k > n) {
        return BigInt(0);
    }
    return sterling1(n - 1, k - 1) + (n - 1) * sterling1(n - 1, k);
}

void main() {
    writeln("Unsigned Stirling numbers of the first kind:");
    int max = 12;
    write("n/k");
    foreach (n; 0 .. max + 1) {
        writef("%10d", n);
    }
    writeln;
    foreach (n; 0 .. max + 1) {
        writef("%-3d", n);
        foreach (k; 0 .. n + 1) {
            writef("%10s", sterling1(n, k));
        }
        writeln;
    }
    writeln("The maximum value of S1(100, k) = ");
    auto previous = BigInt(0);
    foreach (k; 1 .. 101) {
        auto current = sterling1(100, k);
        if (previous < current) {
            previous = current;
        } else {
            import std.conv;

            writeln(previous);
            writefln("(%d digits, k = %d)", previous.to!string.length, k - 1);
            break;
        }
    }
}


USING: arrays assocs formatting io kernel math math.polynomials
math.ranges prettyprint sequences ;
IN: rosetta-code.stirling-first

: stirling-row ( n -- seq )
    [ { 1 } ] [
        [ -1 ] dip neg [a,b) dup length 1 <array> zip
        { 0 1 } [ p* ] reduce [ abs ] map
    ] if-zero ;

"Unsigned Stirling numbers of the first kind:" print
"n\\k" write 13 dup [ "%10d" printf ] each-integer nl

[ dup "%-2d " printf stirling-row [ "%10d" printf ] each nl ]
each-integer nl

"Maximum value from 100th stirling row:" print
100 stirling-row supremum .


--9x9 sudoku solver in lua
--based on a branch and bound solution
--fields are not tried in plain order
--but in a way to detect dead ends earlier
concat=table.concat
insert=table.insert
constraints = { }   --contains a table with 3 constraints for every field
-- a contraint "cons" is a table containing all fields which must not have the same value
-- a field "f" is an integer from 1 to 81
columns = { }       --contains all column-constraints   variable "c"
rows = { }          --contains all row-constraints      variable "r"
blocks = { }        --contains all block-constraints    variable "b"

--initialize all constraints
for f = 1, 81 do
  constraints[f] = { }
end
all_constraints = { } --union of colums, rows and blocks
for i = 1, 9 do
  columns[i] = {
    unknown = 9, --number of fields not yet solved
    unknowns = { } --fields not yet solved
  }
  insert(all_constraints, columns[i])
  rows[i] = {
    unknown = 9, -- see l.15
    unknowns = { } -- see l.16
  }
  insert(all_constraints, rows[i])
  blocks[i] = {
    unknown = 9, --see l.15
    unknowns = { } --see l.16
  }
  insert(all_constraints, blocks[i])
end
constraints_by_unknown = { } --contraints sorted by their number of unknown fields
for i = 0, 9 do
  constraints_by_unknown[i] = {
    count = 0 --how many contraints are in here
  }
end
for r = 1, 9 do
  for c = 1, 9 do
    local f = (r - 1) * 9 + c
    insert(rows[r], f)
    insert(constraints[f], rows[r])
    insert(columns[c], f)
    insert(constraints[f], columns[c])
  end
end
for i = 1, 3 do
  for j = 1, 3 do
    local r = (i - 1) * 3 + j
    for k = 1, 3 do
      for l = 1, 3 do
        local c = (k - 1) * 3 + l
        local f = (r - 1) * 9 + c
        local b = (i - 1) * 3 + k
        insert(blocks[b], f)
        insert(constraints[f], blocks[b])
      end
    end
  end
end
working = { } --save the read values in here
function read() --read the values from stdin
  local f = 1
  local l = io.read("*a")
  for d in l:gmatch("(%d)") do
    local n = tonumber(d)
    if n > 0 then
      working[f] = n
      for _,cons in pairs(constraints[f]) do
        cons.unknown = cons.unknown - 1
      end
    else
      for _,cons in pairs(constraints[f]) do
        cons.unknowns[f] = f
      end
    end
    f = f + 1
  end
  assert((f == 82), "Wrong number of digits")
end
read()
function printer(t) --helper function for printing a 1-81 table
  local pattern = {1,2,3,false,4,5,6,false,7,8,9} --place seperators for better readability
  for _,r in pairs(pattern) do
    if r then
      local function p(c)
        return c and t[(r - 1) * 9 + c] or "|"
      end
      local line={}
      for k,v in pairs(pattern) do
        line[k]=p(v)
      end
      print(concat(line))
    else
      print("---+---+---")
    end
  end
end
order = { } --when to try a field
for _,cons in pairs(all_constraints) do --put all constraints in the corresponding constraints_by_unknown set
  local level = constraints_by_unknown[cons.unknown]
  level[cons] = cons
  level.count = level.count + 1
end
function first(t) --helper function to get a value from a set
  for k, v in pairs(t) do
    if k == v then
      return k
    end
  end
end
function establish_order() -- determine the sequence in which the fields are to be tried
  local solved = constraints_by_unknown[0].count
  while solved < 27 do --there 27 constraints
  --contraints with no unknown fields are considered "solved"
  --keep in mind the actual solving happens in function branch
    local i = 1
    while constraints_by_unknown[i].count == 0 do
      i = i + 1
      -- find a unsolved contraint with the least number of unsolved fields
    end
    local cons = first(constraints_by_unknown[i])
    local f = first(cons.unknowns)
    -- take one of its unknown fields and append it to "order"
    insert(order, f)
    for _,c in pairs(constraints[f]) do
    --each constraint "c" of "f" is moved up one "level"
    --delete "f" from the constraints unknown fields
    --decrease unknown of "c"
      c.unknowns[f] = nil
      local level = constraints_by_unknown[c.unknown]
      level[c] = nil
      level.count = level.count - 1
      c.unknown = c.unknown - 1
      level = constraints_by_unknown[c.unknown]
      level[c] = c
      level.count = level.count + 1
      constraints_by_unknown[c.unknown][c] = c
    end
    solved = constraints_by_unknown[0].count
  end
end
establish_order()
max = #order --how many fields are to be solved
function bound(f,i)
  for _,c in pairs(constraints[f]) do
    for _,x in pairs(c) do
      if i == working[x] then
        return false --i is already used in fs column/row/block
      end
    end
  end
  return true
end
function branch(n)
  local f = order[n] --recursively iterate over fields in order
  if n > max then
    return working --all fields solved without collision
  else
    for i = 1, 9 do --check all values
      if bound(f, i) then --if there is no collision
        working[f] = i
        local res = branch(n + 1) --try next field
        if res then
          return res --all fields solved without collision
        else
          working[f] = nil --this lead to a dead end
        end
      else
        working[f] = nil --reset field because of a collision
      end
    end
    return false --this is a dead end
  end
end
x = branch(1)
if x then
  return printer(x)
end


TableForm[Array[StirlingS2, {n = 12, k = 12} + 1, {0, 0}], TableHeadings -> {"n=" <> ToString[#] & /@ Range[0, n], "k=" <> ToString[#] & /@ Range[0, k]}]
Max[Abs[StirlingS2[100, #]] & /@ Range[0, 100]]


import sequtils, strutils

proc s2(n, k: Natural): Natural =
  if n == k: return 1
  if n == 0 or k == 0: return 0
  k * s2(n - 1, k) + s2(n - 1, k - 1)

echo " k      ", toSeq(0..12).mapIt(($it).align(2)).join("      ")
echo " n"
for n in 0..12:
  stdout.write ($n).align(2)
  for k in 0..n:
    stdout.write ($s2(n, k)).align(8)
  stdout.write '\n'


use strict;
use warnings;
use bigint;
use feature 'say';
use feature 'state';
no warnings 'recursion';
use List::Util qw(max);

sub Stirling2 {
    my($n, $k) = @_;
    my $n1 = $n - 1;
    return 1 if     $n1 == $k;
    return 0 unless $n1 && $k;
    state %seen;
    return ($seen{"{$n1}|{$k}"  } //= Stirling2($n1,$k  ) * $k) +
           ($seen{"{$n1}|{$k-1}"} //= Stirling2($n1,$k-1))
}

my $upto  = 12;
my $width = 1 + length max map { Stirling2($upto+1,$_) } 0..$upto+1;

say 'Unsigned Stirling2 numbers of the second kind: S2(n, k):';
print 'n\k' . sprintf "%${width}s"x(1+$upto)."\n", 0..$upto;

for my $row (1..$upto+1) {
    printf '%-3d', $row-1;
    printf "%${width}d", Stirling2($row, $_) for 0..$row-1;
    print "\n";
}

say "\nMaximum value from the S2(100, *) row:";
say max map { Stirling2(101,$_) } 0..100;


dim as integer S1(0 to 12, 0 to 12)   'initially set with zeroes
dim as ubyte n, k
dim as string outstr

function padto( i as ubyte, j as integer ) as string
    return wspace(i-len(str(j)))+str(j)
end function

S1(0, 0) = 1

for n = 0 to 12   'calculate table
    for k = 1 to n
        S1(n, k) = S1(n-1, k-1) - (n-1) * S1(n-1, k)
    next k
next n

print "Signed Stirling numbers of the first kind"
print
outstr = "   k"
for k=0 to 12
    outstr += padto(12, k)
next k
print outstr
print " n"
for n = 0 to 12
    outstr = padto(2, n)+"  "
    for k = 0 to 12
        outstr += padto(12, S1(n, k))
    next k
    print outstr
next n


package main

import (
    "fmt"
    "math/big"
)

func main() {
    limit := 100
    last := 12
    unsigned := true
    s1 := make([][]*big.Int, limit+1)
    for n := 0; n <= limit; n++ {
        s1[n] = make([]*big.Int, limit+1)
        for k := 0; k <= limit; k++ {
            s1[n][k] = new(big.Int)
        }
    }
    s1[0][0].SetInt64(int64(1))
    var t big.Int
    for n := 1; n <= limit; n++ {
        for k := 1; k <= n; k++ {
            t.SetInt64(int64(n - 1))
            t.Mul(&t, s1[n-1][k])
            if unsigned {
                s1[n][k].Add(s1[n-1][k-1], &t)
            } else {
                s1[n][k].Sub(s1[n-1][k-1], &t)
            }
        }
    }
    fmt.Println("Unsigned Stirling numbers of the first kind: S1(n, k):")
    fmt.Printf("n/k")
    for i := 0; i <= last; i++ {
        fmt.Printf("%9d ", i)
    }
    fmt.Printf("\n--")
    for i := 0; i <= last; i++ {
        fmt.Printf("----------")
    }
    fmt.Println()
    for n := 0; n <= last; n++ {
        fmt.Printf("%2d ", n)
        for k := 0; k <= n; k++ {
            fmt.Printf("%9d ", s1[n][k])
        }
        fmt.Println()
    }
    fmt.Println("\nMaximum value from the S1(100, *) row:")
    max := new(big.Int).Set(s1[limit][0])
    for k := 1; k <= limit; k++ {
        if s1[limit][k].Cmp(max) > 0 {
            max.Set(s1[limit][k])
        }
    }
    fmt.Println(max)
    fmt.Printf("which has %d digits.\n", len(max.String()))
}


solve[sudoku_] :=
 NestWhile[
  Join @@ Table[
     Table[ReplacePart[s, #1 -> n], {n, #2}] & @@
      [email protected][{#,
           Complement[[email protected], s[[[email protected]#]], s[[;; , [email protected]#]],
            [email protected]
             Extract[Partition[s, {3, 3}], Quotient[#, 3, -2]]]} & /@
         Position[s, 0, {2}],
        [email protected]@# &], {s, #}] &, {sudoku}, ! FreeQ[#, 0] &]


with javascript_semantics
include mpfr.e

constant lim = 100,
         lim1 = lim+1,
         last = 12
sequence s2 = repeat(0,lim1)
for n=1 to lim1 do
    s2[n] = mpz_inits(lim1)
    mpz_set_si(s2[n][n],1)
end for
mpz {t, m100} = mpz_inits(2)
for n=1 to lim do
    for k=1 to n do
        mpz_set_si(t,k)
        mpz_mul(t,t,s2[n][k+1])
        mpz_add(s2[n+1][k+1],t,s2[n][k])
    end for
end for
printf(1,"Stirling numbers of the second kind: S2(n, k):\n n   k:")
for i=0 to last do
    printf(1,"%5d     ", i)
end for
printf(1,"\n---    %s\n",repeat('-',last*10+5))
for n=0 to last do
    printf(1,"%2d ", n)
    for k=1 to n+1 do
        printf(1,"%9s ",{mpz_get_str(s2[n+1][k])})
    end for
    printf(1,"\n")
end for
for k=1 to lim1 do
    mpz s100k = s2[lim1][k]
    if mpz_cmp(s100k,m100) > 0 then
        mpz_set(m100,s100k)
    end if
end for
printf(1,"\nThe maximum S2(100,k): %s\n",shorten(mpz_get_str(m100)))


function solution = sudokuSolver(sudokuGrid)

    %Define what each of the sub-boxes of the sudoku grid are by defining
    %the start and end coordinates of each sub-box. The indecies represent
    %the column and row of a grid coordinate on the actual sudoku grid.
    %The contents of each cell with the same grid coordinates contain the
    %information to determine which sub-box that grid coordinate is
    %contained in on the sudoku grid. The array in position 1, i.e.
    %subBoxes{row,column}(1), represents the row indecies of the subbox.
    %The array in position 2, i.e. subBoxes{row,column}(2),represents the
    %column indecies of the subbox.

    subBoxes(1:9,1:9) = {{(1:3),(1:3)}};
    subBoxes(4:6,:)= {{(4:6),(1:3)}};
    subBoxes(7:9,:)= {{(7:9),(1:3)}};

    for column = (4:6)
        for row = (1:9)
            subBoxes{row,column}(2)= {4:6};
        end
    end
    for column = (7:9)
        for row = (1:9)
            subBoxes{row,column}(2)= {7:9};
        end
    end

    %Generate a cell of arrays which contain the possible values of the
    %sudoku grid for each cell in the grid. The possible values a specific
    %grid coordinate can take share the same indices as the sudoku grid
    %coordinate they represent.
    %For example sudokuGrid(m,n) can be possibly filled in by the
    %values stored in the array at possibleValues(m,n).
    possibleValues(1:9,1:9) = { (1:9) };

    %Filter the possibleValues so that no entry exists for coordinates that
    %have already been filled in. This will replace any array with an empty
    %array in the possibleValues cell matrix at the coordinates of a grid
    %already filled in the sudoku grid.
    possibleValues( ~isnan(sudokuGrid) )={[]};

    %Iterate through each grid coordinate and filter out the possible
    %values for that grid point that aren't alowed by the rules given the
    %current values that are filled in. Or, if there is only one possible
    %value for the current coordinate, fill it in.

    solution = sudokuGrid; %so the original sudoku input isn't modified
    memory = 0; %contains the previous iterations possibleValues
    dontStop = true; %stops the while loop when nothing else can be reasoned about the sudoku

    while( dontStop )

%% Process of elimination deduction method

        while( ~isequal(possibleValues,memory) ) %Stops using the process of elimination deduction method when this deduction rule stops working

            memory = possibleValues; %Copies the current possibleValues into memory, for the above conditional on the next iteration.

            %Iterate through everything
            for row = (1:9)
                for column = (1:9)

                    if isnan( solution(row,column) ) %If grid coordinate hasn't been filled in, try to determine it's value.

                        %Look at column to see what values have already
                        %been filled in and thus the current grid
                        %coordinate can't be
                        removableValues = solution( ~isnan(solution(:,column)),column );

                        %If there are any values that have been assigned to
                        %other cells in the same column, filter those out
                        %of the current cell's possiblValues
                        if ~isempty(removableValues)
                            for m = ( 1:numel(removableValues) )
                                possibleValues{row,column}( possibleValues{row,column}==removableValues(m) )=[];
                            end
                        end

                        %If the current grid coordinate can only atain one
                        %possible value, assign it that value
                        if numel( possibleValues{row,column} ) == 1
                            solution(row,column) = possibleValues{row,column};
                            possibleValues(row,column)={[]};
                        end
                    end  %end if

                    if isnan( solution(row,column) ) %If grid coordinate hasn't been filled in, try to determine it's value.

                        %Look at row to see what values have already
                        %been filled in and thus the current grid
                        %coordinate can't be
                        removableValues = solution( row,~isnan(solution(row,:)) );

                        %If there are any values that have been assigned to
                        %other cells in the same row, filter those out
                        %of the current cell's possiblValues
                        if ~isempty(removableValues)
                            for m = ( 1:numel(removableValues) )
                                possibleValues{row,column}( possibleValues{row,column}==removableValues(m) )=[];
                            end
                        end

                        %If the current grid coordinate can only atain one
                        %possible value, assign it that value
                        if numel( possibleValues{row,column} ) == 1
                            solution(row,column) = possibleValues{row,column};
                            possibleValues(row,column)={[]};
                        end
                    end %end if

                    if isnan( solution(row,column) ) %If grid coordinate hasn't been filled in, try to determine it's value.

                        %Look at sub-box to see if any possible values can be
                        %filtered out. First pull the boundaries of the sub-box
                        %containing the current array coordinate
                        currentBoxBoundaries=subBoxes{row,column};

                        %Then pull the sub-boxes values out of the solution
                        box = solution(currentBoxBoundaries{:});

                        %Look at sub-box to see what values have already
                        %been filled in and thus the current grid
                        %coordinate can't be
                        removableValues = box( ~isnan(box) );

                        %If there are any values that have been assigned to
                        %other cells in the same sub-box, filter those out
                        %of the current cell's possiblValues
                        if ~isempty(removableValues)
                            for m = ( 1:numel(removableValues) )
                                possibleValues{row,column}( possibleValues{row,column}==removableValues(m) )=[];
                            end
                        end

                        %If the current grid coordinate can only atain one
                        %possible value, assign it that value
                        if numel( possibleValues{row,column} ) == 1
                            solution(row,column) = possibleValues{row,column};
                            possibleValues(row,column)={[]};
                        end
                    end %end if

                end %end for column
            end %end for row
        end %stop process of elimination

%% Check that there are no contradictions in the solved grid coordinates.

        %Check that each row at most contains one of each of the integers
        %from 1 to 9
        if ~isempty( find( histc( solution,(1:9),1 )>1 ) )
            solution = false;
            return
        end

        %Check that each column at most contains one of each of the integers
        %from 1 to 9
        if ~isempty( find( histc( solution,(1:9),2 )>1 ) )
            solution = false;
            return
        end

        %Check that each sub-box at most contains one of each of the integers
        %from 1 to 9
        subBoxBins = zeros(9,9);
        counter = 0;
        for row = [2 5 8]
            for column = [2 5 8]
                counter = counter +1;

                %because the sub-boxes are extracted as square matricies,
                %we need to reshape them into row vectors so all of the
                %boxes can be input into histc simultaneously
                subBoxBins(counter,:) = reshape( solution(subBoxes{row,column}{:}),1,9 );
            end
        end
        if ~isempty( find( histc( subBoxBins,(1:9),2 )>1 ) )
            solution = false;
            return
        end

        %Check to make sure there are no grid coordinates that are not
        %filled in and have no possible values.

        [rowStack,columnStack] = find(isnan(solution)); %extracts the indicies of the unsolved grid coordinates
        if (numel(rowStack) > 0)

            for counter = (1:numel(rowStack))
                if isempty(possibleValues{rowStack(counter),columnStack(counter)})
                    solution = false;
                    return
                end
            end

        %if there are no more grid coordinates to be filed in then the
        %sudoku is solved and we can return the solution without further
        %computation
        elseif (numel(rowStack) == 0)
            return
        end

%% Use the unique relative compliment of sets deduction method

        %Because no more information can be determined by the process of
        %ellimination we have to try a new method of reasoning. Now we will
        %look at the possible values a cell can take. If there is a value that
        %that grid coordinate can take but no other coordinates in the same row,
        %column or sub-box can take that value then we assign that coordinate
        %that value.

        keepGoing = true; %signals to keep applying rules to the current grid-coordinate because it hasn't been solved using previous rules
        dontStop = false; %if this method doesn't figure anything out, this will terminate the top level while loop

        [rowStack,columnStack] = find(isnan(solution)); %This will also take care of the case where the sudoku is solved
        counter = 0; %makes sure the loop terminates when there are no more cells to consider

        while( keepGoing && (counter < numel(rowStack)) ) %stop this method of reasoning when the value of one of the cells has been determined and return to the process of elimination method

            counter = counter + 1;

            row = rowStack(counter);
            column = columnStack(counter);

            gridPossibles = [possibleValues{row,column}];

            coords = (1:9);
            coords(column) = [];
            rowPossibles = [possibleValues{row,coords}]; %extract possible values for everything in the same row except the current grid coordinate

            totalMatches = zeros( numel(gridPossibles),1 ); %preallocate for speed

            %count how many times a possible value for the current cell
            %appears as a possible value for the cells in the same row
            for n = ( 1:numel(gridPossibles) )
                totalMatches(n) = sum( (rowPossibles == gridPossibles(n)) );
            end

            %remove any possible values for the current cell that have
            %matches in other cells
            gridPossibles = gridPossibles(totalMatches==0);

            %if there is only one possible value that the current cell can
            %take that aren't shared by other cells, assign that value to
            %the current cell.
            if numel(gridPossibles) == 1

                solution(row,column) = gridPossibles;
                possibleValues(row,column)={[]};
                keepGoing = false; %stop this method of deduction and return to the process of elimination
                dontStop = true; %keep the top level loop going

            end

            if(keepGoing) %do the same as above but for the current cell's column

                gridPossibles = [possibleValues{row,column}];

                coords = (1:9);
                coords(row) = [];
                columnPossibles = [possibleValues{coords,column}];

                totalMatches = zeros( numel(gridPossibles),1 );
                for n = ( 1:numel(gridPossibles) )
                    totalMatches(n) = sum( (columnPossibles == gridPossibles(n)) );
                end

                gridPossibles = gridPossibles(totalMatches==0);

                if numel(gridPossibles) == 1

                    solution(row,column) = gridPossibles;
                    possibleValues(row,column)={[]};
                    keepGoing = false;
                    dontStop = true;

                end
            end

            if(keepGoing) %do the same as above but for the current cell's sub-box

                gridPossibles = [possibleValues{row,column}];

                currentBoxBoundaries = subBoxes{row,column};
                subBoxPossibles = [];
                for m = currentBoxBoundaries{1}
                    for n = currentBoxBoundaries{2}
                        if ~((m == row) && (n == column))
                            subBoxPossibles = [subBoxPossibles possibleValues{m,n}];
                        end
                    end
                end

                totalMatches = zeros( numel(gridPossibles),1 );
                for n = ( 1:numel(gridPossibles) )
                    totalMatches(n) = sum( (subBoxPossibles == gridPossibles(n)) );
                end

                gridPossibles = gridPossibles(totalMatches==0);

                if numel(gridPossibles) == 1

                    solution(row,column) = gridPossibles;
                    possibleValues(row,column)={[]};
                    keepGoing = false;
                    dontStop = true;

                end
            end %end

        end %end  set comliment rule while loop
    end %end top-level while loop

%% Depth-first search of the solution tree

    %There is no more reasoning that can solve the puzzle so now it is time
    %for a depth-first search of the possible answers, basically
    %guess-and-check. This is implimented recursively.

    [rowStack,columnStack] = find(isnan(solution)); %Get all of the unsolved cells

    if (numel(rowStack) > 0) %If all of the above stuff terminates then there will be at least one grid coordinate not filled in

        %Treat the rowStack and columnStack like stacks, and pop the top
        %value off the stack to act as the current node whose
        %possibleValues to search through, then assign the possible values
        %of that grid coordinate to a variable that holds that values to
        %search through
        searchTreeNodes = possibleValues{rowStack(1),columnStack(1)};

        keepSearching = true; %used to continue the search
        counter = 0; %counts the amount of possible values searched for the current node
        tempSolution = solution; %used so that the solution is not overriden until a solution hase been found

        while( keepSearching && (counter < numel(searchTreeNodes)) ) %stop recursing if we run out of possible values for the current node

            counter = counter + 1;
            tempSolution(rowStack(1),columnStack(1)) = searchTreeNodes(counter); %assign a possible value to the current node in the tree
            tempSolution = sudokuSolver(tempSolution); %recursively call the solver with the current guess value for the current grid coordinate

            if ~islogical(tempSolution) %if tempSolution is not a boolean but a valid sudoku stop recursing and set solution to tempSolution
               keepSearching = false;
               solution = tempSolution;
            elseif counter == numel(searchTreeNodes) %if we have run out of guesses for the current node, stop recursing and return a value of "false" for the solution
               solution = false;
            else %reset tempSolution to the current state of the board and try the next guess for the possible value of the current cell
               tempSolution = solution;
            end

        end %end recursion
    end  %end if

%% End of program
end %end sudokuSolver


:- dynamic stirling2_cache/3.

stirling2(N, N, 1):-!.
stirling2(_, 0, 0):-!.
stirling2(N, K, 0):-
	K > N,
	!.
stirling2(N, K, L):-
	stirling2_cache(N, K, L),
	!.
stirling2(N, K, L):-
	N1 is N - 1,
	K1 is K - 1,
	stirling2(N1, K, L1),
	stirling2(N1, K1, L2),
	!,
	L is K * L1 + L2,
	assertz(stirling2_cache(N, K, L)).

print_stirling_numbers(N):-
	between(1, N, K),
	stirling2(N, K, L),
	writef('%8r', [L]),
	fail.
print_stirling_numbers(_):-
	nl.

print_stirling_numbers_up_to(M):-
	between(1, M, N),
	print_stirling_numbers(N),
	fail.
print_stirling_numbers_up_to(_).

max_stirling2(N, Max):-
    aggregate_all(max(L), (between(1, N, K), stirling2(N, K, L)), Max).

main:-
	writeln('Stirling numbers of the second kind up to S2(12,12):'),
	print_stirling_numbers_up_to(12),
	writeln('Maximum value of S2(n,k) where n = 100:'),
	max_stirling2(100, M),
	writeln(M).


computed = {}

def sterling2(n, k):
	key = str(n) + "," + str(k)

	if key in computed.keys():
		return computed[key]
	if n == k == 0:
		return 1
	if (n > 0 and k == 0) or (n == 0 and k > 0):
		return 0
	if n == k:
		return 1
	if k > n:
		return 0
	result = k * sterling2(n - 1, k) + sterling2(n - 1, k - 1)
	computed[key] = result
	return result

print("Stirling numbers of the second kind:")
MAX = 12
print("n/k".ljust(10), end="")
for n in range(MAX + 1):
	print(str(n).rjust(10), end="")
print()
for n in range(MAX + 1):
	print(str(n).ljust(10), end="")
	for k in range(n + 1):
		print(str(sterling2(n, k)).rjust(10), end="")
	print()
print("The maximum value of S2(100, k) = ")
previous = 0
for k in range(1, 100 + 1):
	current = sterling2(100, k)
	if current > previous:
		previous = current
	else:
		print("{0}\n({1} digits, k = {2})\n".format(previous, len(str(previous)), k - 1))
		break


import Text.Printf (printf)
import Data.List (groupBy)
import qualified Data.MemoCombinators as Memo

stirling1 :: Integral a => (a, a) -> a
stirling1 = Memo.pair Memo.integral Memo.integral f
  where
    f (n, k)
      | n == 0 && k == 0 = 1
      |  n > 0 && k == 0 = 0
      | k > n            = 0
      | otherwise = stirling1 (pred n, pred k) + pred n * stirling1 (pred n, k)

main :: IO ()
main = do
  printf "n/k"
  mapM_ (printf "%10d") ([0..12] :: [Int]) >> printf "\n"
  printf "%s\n" $ replicate (13 * 10 + 3) '-'
  mapM_ (\row -> printf "%2d|" (fst $ head row) >>
    mapM_ (printf "%10d" . stirling1) row >> printf "\n") table
  printf "\nThe maximum value of S1(100, k):\n%d\n" $
    maximum ([stirling1 (100, n) | n <- [1..100]] :: [Integer])
  where
    table :: [[(Int, Int)]]
    table = groupBy (\a b -> fst a == fst b) $ (,) <$> [0..12] <*> [0..12]


{.this: self.}

type
  Sudoku = ref object
    grid : array[81, int]
    solved : bool

proc `$`(self: Sudoku): string =
  var sb: string = ""
  for i in 0..8:
    for j in 0..8:
      sb &= $grid[i * 9 + j]
      sb &= " "
      if j == 2 or j == 5:
        sb &= "| "
    sb &= "\n"
    if i == 2 or i == 5:
      sb &= "------+------+------\n"
  sb

proc init(self: Sudoku, rows: array[9, string]) =
  for i in 0..8:
    for j in 0..8:
      grid[9 * i + j] = rows[i][j].int - '0'.int

proc checkValidity(self: Sudoku, v, x, y: int): bool =
  for i in 0..8:
    if grid[y * 9 + i] == v or grid[i * 9 + x] == v:
      return false
  var startX = (x div 3) * 3
  var startY = (y div 3) * 3
  for i in startY..startY + 2:
    for j in startX..startX + 2:
      if grid[i * 9 + j] == v:
        return false
  result = true

proc placeNumber(self: Sudoku, pos: int) =
  if solved:
    return
  if pos == 81:
    solved = true
    return
  if grid[pos] > 0:
    placeNumber(pos + 1)
    return
  for n in 1..9:
    if checkValidity(n, pos mod 9, pos div 9):
      grid[pos] = n
      placeNumber(pos + 1)
      if solved:
        return
      grid[pos] = 0

proc solve(self: Sudoku) =
  echo "Starting grid:\n\n", $self
  placeNumber(0)
  if solved:
    echo "Solution:\n\n", $self
  else:
    echo "Unsolvable!"

var rows = ["850002400",
            "720000009",
            "004000000",
            "000107002",
            "305000900",
            "040000000",
            "000080070",
            "017000000",
            "000036040"]

var puzzle = Sudoku()
puzzle.init(rows)
puzzle.solve()


  [ dip number$
    over size -
    space swap of
    swap join echo$ ]      is justify ( n n -->   )

  [ table ]                is s2table (   n --> n )

  [ swap 101 * + s2table ] is s2      ( n n --> n )

  101 times
    [ i^ 101 times
      [ dup i^
          [ 2dup = iff
              [ 2drop 1 ] done
            over 0 =
            over 0 = or iff
              [ 2drop 0 ] done
            dip [ 1 - ]
            2dup tuck s2 *
            unrot 1 - s2 + ]
        ' s2table put ]
      drop ]
  cr cr
  13 times
    [ i^ dup 1+ times
      [ dup i^ s2
        10 justify ]
      drop cr ]
  cr
  0 100 times
    [ 100 i^ 1+ s2 max ]
  echo cr


sub Stirling2 (Int \n, Int \k) {
    ((1,), { (0, |@^last) »+« (|(@^last »*« @^last.keys), 0) } … *)[n;k]
}

my $upto = 12;

my $mx = (1..^$upto).map( { Stirling2($upto, $_) } ).max.chars;

put 'Stirling numbers of the second kind: S2(n, k):';
put 'n\k', (0..$upto)».fmt: "%{$mx}d";

for 0..$upto -> $row {
    $row.fmt('%-3d').print;
    put (0..$row).map( { Stirling2($row, $_) } )».fmt: "%{$mx}d";
}

say "\nMaximum value from the S2(100, *) row:";
say (^100).map( { Stirling2 100, $_ } ).max;


/*REXX program to compute and display   Stirling numbers   of the second kind.          */
parse arg lim .                                  /*obtain optional argument from the CL.*/
if lim=='' | lim==","  then lim= 12              /*Not specified?  Then use the default.*/
olim= lim                                        /*save     the original value of  LIM. */
lim= abs(lim)                                    /*only use the absolute value of  LIM. */
numeric digits max(9, 2*lim)                     /*(over) specify maximum number in grid*/
@.=
             do j=0  for lim+1
             @.j.j = 1;  if j==0  then iterate   /*define the right descending diagonal.*/
             @.0.j = 0;  @.j.0 = 0               /*   "    "  zero  values.             */
             end   /*j*/
max#.= 0                                         /* [↓]  calculate values for the grid. */
          do   n=0  for lim+1;         np= n + 1
            do k=1  for lim;           km= k - 1
            @.np.k = k * @.n.k  +  @.n.km        /*calculate a number in the grid.      */
            max#.k= max(max#.k, @.n.k)           /*find the maximum value for a column. */
            max#.b= max(max#.b, @.n.k)           /*find the maximum value for all rows. */
            end   /*k*/
          end     /*n*/
                                                 /* [↓]  only show the maximum value ?  */
        do k=0  for lim+1                        /*find max column width for each column*/
        max#.a= max#.a + length(max#.k)
        end   /*k*/

w= length(max#.b)                                /*calculate max width of all numbers.  */
if olim<0  then do;  say 'The maximum value  (which has '       w      " decimal digits):"
                     say max#.b                  /*display maximum number in the grid.  */
                     exit                        /*stick a fork in it,  we're all done. */
                end
wgi= max(5, length(lim+1) )                      /*the maximum width of the grid's index*/
say '═row═'  center("columns", max(9, max#.a + lim), '═')  /*display header of the grid.*/

    do   r=0  for lim+1;        $=               /* [↓]  display the grid to the term.  */
      do c=0  for lim+1  until c>=r              /*build a row of grid, 1 col at a time.*/
      $= $  right(@.r.c, length(max#.c) )        /*append a column to a row of the grid.*/
      end   /*c*/
    say center(r, wgi)  strip( substr($,2), 'T') /*display a single row of the grid.    */
    end     /*r*/                                /*stick a fork in it,  we're all done. */


import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

public class SterlingNumbersFirstKind {

    public static void main(String[] args) {
        System.out.println("Unsigned Stirling numbers of the first kind:");
        int max = 12;
        System.out.printf("n/k");
        for ( int n = 0 ; n <= max ; n++ ) {
            System.out.printf("%10d", n);
        }
        System.out.printf("%n");
        for ( int n = 0 ; n <= max ; n++ ) {
            System.out.printf("%-3d", n);
            for ( int k = 0 ; k <= n ; k++ ) {
                System.out.printf("%10s", sterling1(n, k));
            }
            System.out.printf("%n");
        }
        System.out.println("The maximum value of S1(100, k) = ");
        BigInteger previous = BigInteger.ZERO;
        for ( int k = 1 ; k <= 100 ; k++ ) {
            BigInteger current = sterling1(100, k);
            if ( current.compareTo(previous) > 0 ) {
                previous = current;
            }
            else {
                System.out.printf("%s%n(%d digits, k = %d)%n", previous, previous.toString().length(), k-1);
                break;
            }
        }
    }

    private static Map<String,BigInteger> COMPUTED = new HashMap<>();

    private static final BigInteger sterling1(int n, int k) {
        String key = n + "," + k;
        if ( COMPUTED.containsKey(key) ) {
            return COMPUTED.get(key);
        }
        if ( n == 0 && k == 0 ) {
            return BigInteger.valueOf(1);
        }
        if ( n > 0 && k == 0 ) {
            return BigInteger.ZERO;
        }
        if ( k > n ) {
            return BigInteger.ZERO;
        }
        BigInteger result = sterling1(n-1, k-1).add(BigInteger.valueOf(n-1).multiply(sterling1(n-1, k)));
        COMPUTED.put(key, result);
        return result;
    }

}


(* Ocamlgraph demo program: solving the Sudoku puzzle using graph coloring
   Copyright 2004-2007 Sylvain Conchon, Jean-Christophe Filliatre, Julien Signoles

   This software is free software; you can redistribute it and/or modify
   it under the terms of the GNU Library General Public License version 2,
   with the special exception on linking described in file LICENSE.

   This software is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *)

open Format
open Graph

(* We use undirected graphs with nodes containing a pair of integers
   (the cell coordinates in 0..8 x 0..8).
   The integer marks of the nodes will store the colors. *)
module G = Imperative.Graph.Abstract(struct type t = int * int end)

(* The Sudoku grid = a graph with 9x9 nodes *)
let g = G.create ()

(* We create the 9x9 nodes, add them to the graph and keep them in a matrix
   for later access *)
let nodes =
  let new_node i j = let v = G.V.create (i, j) in G.add_vertex g v; v in
  Array.init 9 (fun i -> Array.init 9 (new_node i))

let node i j = nodes.(i).(j) (* shortcut for easier access *)

(* We add the edges:
   two nodes are connected whenever they can't have the same value,
   i.e. they belong to the same line, the same column or the same 3x3 group *)
let () =
  for i = 0 to 8 do for j = 0 to 8 do
    for k = 0 to 8 do
      if k <> i then G.add_edge g (node i j) (node k j);
      if k <> j then G.add_edge g (node i j) (node i k);
    done;
    let gi = 3 * (i / 3) and gj = 3 * (j / 3) in
    for di = 0 to 2 do for dj = 0 to 2 do
      let i' = gi + di and j' = gj + dj in
      if i' <> i || j' <> j then G.add_edge g (node i j) (node i' j')
    done done
  done done

(* Displaying the current state of the graph *)
let display () =
  for i = 0 to 8 do
    for j = 0 to 8 do printf "%d" (G.Mark.get (node i j)) done;
    printf "\n";
  done;
  printf "@?"

(* We read the initial constraints from standard input and we display g *)
let () =
  for i = 0 to 8 do
    let s = read_line () in
    for j = 0 to 8 do match s.[j] with
      | '1'..'9' as ch -> G.Mark.set (node i j) (Char.code ch - Char.code '0')
      | _ -> ()
    done
  done;
  display ();
  printf "[email protected]"

(* We solve the Sudoku by 9-coloring the graph g and we display the solution *)
module C = Coloring.Mark(G)

let () = C.coloring g 9; display ()


@memo = {}

def sterling2(n, k)
  key = [n,k]
  return @memo[key] if @memo.key?(key)
  return 1 if n.zero? and k.zero?
  return 0 if n.zero? or  k.zero?
  return 1 if n == k
  return 0 if k > n
  res = k * sterling2(n-1, k) + sterling2(n - 1, k-1)
  @memo[key] = res
end

r = (0..12)
puts "Sterling2 numbers:"
puts "n/k #{r.map{|n| "%11d" % n}.join}"

r.each do |row|
  print "%-4s" % row
  puts "#{(0..row).map{|col| "%11d" % sterling2(row, col)}.join}"
end

puts "\nMaximum value from the sterling2(100, k)";
puts (1..100).map{|a| sterling2(100,a)}.max


func S2(n, k) {     # Stirling numbers of the second kind
    stirling2(n, k)
}

const r = (0..12)

var triangle = r.map {|n| 0..n -> map {|k| S2(n, k) } }
var widths   = r.map {|n| r.map {|k| (triangle[k][n] \\ 0).len }.max }

say ('n\k ', r.map {|n| "%*s" % (widths[n], n) }.join(' '))

r.each {|n|
    var str = ('%-3s ' % n)
    str += triangle[n].map_kv {|k,v| "%*s" % (widths[k], v) }.join(' ')
    say str
}

with (100) {|n|
    say "\nMaximum value from the S2(#{n}, *) row:"
    say { S2(n, _) }.map(^n).max
}


# For efficiency, define the helper function for `stirling1/2` as a
# top-level function so we can use it directly for constructing the table:
   # input: [m,j,cache]
   # output: [s, cache]
   def stirling1:
    . as [$m, $j, $cache]
    | "\($m),\($j)" as $key
    | $cache
    | if has($key) then [.[$key], .]
      elif $m == 0 and $j == 0 then [1, .]
      elif $m > 0 and $j == 0 then [0, .]
      elif $j > $m then [0, .]
      else ([$m-1, $j-1, .] | stirling1) as [$s1, $c1]
      | ([$m-1, $j, $c1] | stirling1)    as [$s2, $c2]
      | (($s1 +  ($m-1) * $s2)) as $result
      | ($c2 | (.[$key] = $result)) as $c3
      | [$result, $c3]
      end;

def stirling1($n; $k):
  [$n, $k, {}] | stirling1 | .[0];

# produce the table for 0 ... $n inclusive
def stirlings($n):
  # state: [cache, array_of_results]
  reduce range(0; $n+1) as $i ([{}, []];
    reduce range(0; $i+1) as $j (.;
      . as [$cache, $a]
      | ([$i, $j, $cache] | stirling1) as [$s, $c]
      | [$c, ($a|setpath([$i,$j]; $s))] ));

def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;

def task($n):
  "Unsigned Stirling numbers of the first kind:",
  "n/k  \( [range(0;$n+1)|lpad(10)] | join(" "))",
   ((stirlings($n) | .[1]) as $a
    | range(0; $n+1) as $i
    | "\($i|lpad(3)): \( [$a[$i][]| lpad(10)] | join(" ") )" ),
  "\nThe maximum value of S1(100, k) is",
  ([stirling1(100; range(0;101)) ] | max) ;

task(12)


using Combinatorics

const s1cache = Dict()

function stirlings1(n, k, signed::Bool=false)
    if signed == true && isodd(n - k)
        return -stirlings1(n, k)
    elseif haskey(s1cache, Pair(n, k))
        return s1cache[Pair(n, k)]
    elseif n < 0
        throw(DomainError(n, "n must be nonnegative"))
    elseif n == k == 0
        return one(n)
    elseif n == 0 || k == 0
        return zero(n)
    elseif n == k
        return one(n)
    elseif k == 1
        return factorial(n-1)
    elseif k == n - 1
        return binomial(n, 2)
    elseif k == n - 2
        return div((3 * n - 1) * binomial(n, 3), 4)
    elseif k == n - 3
        return binomial(n, 2) * binomial(n, 4)
    end

    ret = (n - 1) * stirlings1(n - 1, k) + stirlings1(n - 1, k - 1)
    s1cache[Pair(n, k)] = ret
    return ret
end

function printstirling1table(kmax)
    println("  ", mapreduce(i -> lpad(i, 10), *, 0:kmax))

    sstring(n, k) = begin i = stirlings1(n, k); lpad(k > n && i == 0 ? "" : i, 10) end

    for n in 0:kmax
        println(rpad(n, 2) * mapreduce(k -> sstring(n, k), *, 0:kmax))
    end
end

printstirling1table(12)
println("\nThe maximum for stirling1(100, _) is:\n", maximum(k-> stirlings1(BigInt(100), BigInt(k)), 1:100))


import java.math.BigInteger

fun main() {
    println("Unsigned Stirling numbers of the first kind:")
    val max = 12
    print("n/k")
    for (n in 0..max) {
        print("%10d".format(n))
    }
    println()
    for (n in 0..max) {
        print("%-3d".format(n))
        for (k in 0..n) {
            print("%10s".format(sterling1(n, k)))
        }
        println()
    }
    println("The maximum value of S1(100, k) = ")
    var previous = BigInteger.ZERO
    for (k in 1..100) {
        val current = sterling1(100, k)
        previous = if (current!! > previous) {
            current
        } else {
            println("$previous\n(${previous.toString().length} digits, k = ${k - 1})")
            break
        }
    }
}

private val COMPUTED: MutableMap<String, BigInteger?> = HashMap()
private fun sterling1(n: Int, k: Int): BigInteger? {
    val key = "$n,$k"
    if (COMPUTED.containsKey(key)) {
        return COMPUTED[key]
    }

    if (n == 0 && k == 0) {
        return BigInteger.valueOf(1)
    }
    if (n > 0 && k == 0) {
        return BigInteger.ZERO
    }
    if (k > n) {
        return BigInteger.ZERO
    }

    val result = sterling1(n - 1, k - 1)!!.add(BigInteger.valueOf(n - 1.toLong()).multiply(sterling1(n - 1, k)))
    COMPUTED[key] = result
    return result
}


declare
  %% a puzzle is a function that returns an initial board configuration
  fun {Puzzle1}
     %% a board is a list of 9 rows
     [[4 _ _  _ _ _  _ 6 _]
      [5 _ _  _ 8 _  9 _ _]
      [3 _ _  _ _ 1  _ _ _]

      [_ 2 _  7 _ _  _ _ 1]
      [_ 9 _  _ _ _  _ 4 _]
      [8 _ _  _ _ 3  _ 5 _]

      [_ _ _  2 _ _  _ _ 7]
      [_ _ 6  _ 5 _  _ _ 8]
      [_ 1 _  _ _ _  _ _ 6]]
  end

  %% Returns a list of solutions for the given puzzle.
  fun {Solve Puzzle}
     {SearchAll {GetScript Puzzle}}
  end

  %% Creates a solver script for a puzzle.
  fun {GetScript Puzzle}
     proc {$ Board}
        %% Every row is a list of nine finite domain vars
        %% with the domain 1..9.
        Board = {MapRange fun {$ _} {FD.list 9 1#9} end}
        %% Post initial configuration.
        Board = {Puzzle}

        %% The core constraints:
        {ForAll {Rows Board} FD.distinct}
        {ForAll {Columns Board} FD.distinct}
        {ForAll {Boxes Board} FD.distinct}

        %% Search if necessary.
        {FD.distribute ff {Flatten Board}}
     end
  end

  %% Returns the board as a list of rows.
  fun {Rows Board}
     Board %% This is already the representation we have chosen.
  end

  %% Returns the board as a list of columns.
  fun {Columns Board}
     {MapRange fun {$ I} {Column Board I} end}
  end

  %% Returns the board as a list of boxes (sub-grids).
  fun {Boxes Board}
     {MapRange fun {$ I} {Box Board I} end}
  end

  %% Helper function: map the range 1..9 to something.
  fun {MapRange F}
     {Map [1 2 3 4 5 6 7 8 9] F}
  end

  %% Returns a column of the board as a list of fields.
  fun {Column Board Index}
     {Map Board
      fun {$ Row}
         {Nth Row Index}
      end
     }
  end

  %% Returns a box of the board as a list of fields.
  fun {Box Board Index}
     Index0 = Index-1
     Fields = {Flatten Board}
     Start = (Index0 div 3) * 27 + (Index0 mod 3)*3
  in
     {Flatten
      for I in 0..2 collect:C do
         {C {List.take {List.drop Fields Start+I*9} 3}}
      end
     }
  end
in
  {Inspect {Solve Puzzle1}.1}


proc S2 {n k} {
    set nk [list $n $k]
    if {[info exists ::S2cache($nk)]} {
        return      $::S2cache($nk)
    }
    if {($n > 0 && $k == 0) || ($n == 0 && $k > 0)} {
        return 0
    }
    if {$n == $k} {
        return 1
    }
    if {$n < $k} {
        return 0
    }
    set n1 [expr {$n - 1}]
    set k1 [expr {$k - 1}]
    set r  [expr {($k * [S2 $n1 $k]) + [S2 $n1 $k1]}]
    set ::S2cache($nk) $r
}

proc main {} {
    puts "Stirling numbers of the second kind:"
    set max 12                  ;# last table line to print
    set L   8                   ;# space to use for 1 number
    puts -nonewline "n\\k"
    for {set n 0} {$n <= $max} {incr n} {
        puts -nonewline [format %${L}d $n]
    }
    puts ""
    for {set n 0} {$n <= $max} {incr n} {
        puts -nonewline [format %-3d $n]
        for {set k 0} {$k <= $n} {incr k} {
            puts -nonewline [format %${L}s [S2 $n $k]]
        }
        puts ""
    }
    puts "The maximum value of S2(100, k) = "
    set previous 0
    for {set k 1} {$k <= 100} {incr k} {
        set current [S2 100 $k]
        if {$current > $previous} {
            set previous $current
        } else {
            puts $previous
            puts "([string length $previous] digits, k = [expr {$k-1}])"
            break
        }
    }
}
main


TableForm[Array[StirlingS1, {n = 12, k = 12} + 1, {0, 0}], TableHeadings -> {"n=" <> ToString[#] & /@ Range[0, n], "k=" <> ToString[#] & /@ Range[0, k]}]
Max[Abs[StirlingS1[100, #]] & /@ Range[0, 100]]


import sequtils, strutils

proc s1(n, k: Natural): Natural =
  if k == 0: return ord(n == 0)
  if k > n: return 0
  s1(n - 1, k - 1) + (n - 1) * s1(n - 1, k)

echo " k        ", toSeq(0..12).mapIt(($it).align(2)).join("        ")
echo " n"
for n in 0..12:
  stdout.write ($n).align(2)
  for k in 0..n:
    stdout.write ($s1(n, k)).align(10)
  stdout.write '\n'


use strict;
use warnings;
use bigint;
use feature 'say';
use feature 'state';
no warnings 'recursion';
use List::Util qw(max);

sub Stirling1 {
    my($n, $k) = @_;
    return 1 unless $n || $k;
    return 0 unless $n && $k;
    state %seen;
    return ($seen{"{$n-1}|{$k-1}"} //= Stirling1($n-1, $k-1)) +
           ($seen{"{$n-1}|{$k}"  } //= Stirling1($n-1, $k  )) * ($n-1)
}

my $upto  = 12;
my $width = 1 + length max map { Stirling1($upto,$_) } 0..$upto;

say 'Unsigned Stirling1 numbers of the first kind: S1(n, k):';
print 'n\k' . sprintf "%${width}s"x(1+$upto)."\n", 0..$upto;

for my $row (0..$upto) {
    printf '%-3d', $row;
    printf "%${width}d", Stirling1($row, $_) for 0..$row;
    print "\n";
}

say "\nMaximum value from the S1(100, *) row:";
say max map { Stirling1(100,$_) } 0..100;


#include <pari/pari.h>

typedef int SUDOKU [9][9];

static inline int check_num(SUDOKU s, int row, int col, int num)
{
  int i, r = (row/3)*3, c = (col/3)*3;

  for (i = 0; i < 9; i++)
    if (s[row][i] == num || s[i][col] == num || s[i%3 + r][i/3 + c] == num)
      return 0;

  return 1;
}

static int sudoku_solve(SUDOKU s, int row, int col)
{
  int num;

  if (row < 9 && col < 9) {
    if (s[row][col]) {
      if (col < 8)
	return sudoku_solve(s, row, col+1);
      if (row < 8)
	return sudoku_solve(s, row+1, 0);
      return 1;
    }
    else
      for (num = 1; num < 10; num++)
	if (check_num(s, row, col, num)) {
	  s[row][col] = num;
	  if (sudoku_solve(s, row, col))
	    return 1;
	  else
	    s[row][col] = 0;
	}
    return 0;
  }
  return 1;
}

GEN plug_sudoku(GEN M)
{
  SUDOKU s;
  GEN S;
  int i, k;

  if (typ(M) != t_MAT)
    pari_err(e_MISC, "parameter not matrix");

  S = matsize(M);

  if (itos(gel(S, 1)) < 9 || itos(gel(S, 2)) < 9)
    pari_err(e_MISC, "parameter not 9x9 matrix");

  for (i = 0; i < 9; i++)
    for (k = 0; k < 9; k++)
      s[i][k] = itos(gcoeff(M, i+1, k+1));	/* get sudoku */

  if (sudoku_solve(s, 0, 0)) {			/* solve sudoku */
    S = cgetg(10, t_MAT);
    for (k = 0; k < 9; k++) {			/* create 9x9 matrix */
      gel(S, k+1) = cgetg(10, t_COL);
      for (i = 0; i < 9; i++)
	gcoeff(S, i+1, k+1) = stoi(s[i][k]);	/* fill in elements */
    }
    return S;
  }
  return gen_0;		/* no solution */
}


Imports System.Numerics

Module Module1

    Class Sterling
        Private Shared ReadOnly COMPUTED As New Dictionary(Of String, BigInteger)

        Private Shared Function CacheKey(n As Integer, k As Integer) As String
            Return String.Format("{0}:{1}", n, k)
        End Function

        Private Shared Function Impl(n As Integer, k As Integer) As BigInteger
            If n = 0 AndAlso k = 0 Then
                Return 1
            End If
            If (n > 0 AndAlso k = 0) OrElse (n = 0 AndAlso k > 0) Then
                Return 0
            End If
            If n = k Then
                Return 1
            End If
            If k > n Then
                Return 0
            End If

            Return k * Sterling2(n - 1, k) + Sterling2(n - 1, k - 1)
        End Function

        Public Shared Function Sterling2(n As Integer, k As Integer) As BigInteger
            Dim key = CacheKey(n, k)
            If COMPUTED.ContainsKey(key) Then
                Return COMPUTED(key)
            End If

            Dim result = Impl(n, k)
            COMPUTED.Add(key, result)
            Return result
        End Function
    End Class

    Sub Main()
        Console.WriteLine("Stirling numbers of the second kind:")
        Dim max = 12
        Console.Write("n/k")
        For n = 0 To max
            Console.Write("{0,10}", n)
        Next
        Console.WriteLine()
        For n = 0 To max
            Console.Write("{0,3}", n)
            For k = 0 To n
                Console.Write("{0,10}", Sterling.Sterling2(n, k))
            Next
            Console.WriteLine()
        Next
        Console.WriteLine("The maximum value of S2(100, k) = ")
        Dim previous = BigInteger.Zero
        For k = 1 To 100
            Dim current = Sterling.Sterling2(100, k)
            If current > previous Then
                previous = current
            Else
                Console.WriteLine(previous)
                Console.WriteLine("({0} digits, k = {1})", previous.ToString().Length, k - 1)
                Exit For
            End If
        Next
    End Sub

End Module


with javascript_semantics
include mpfr.e

constant lim = 100,
         lim1 = lim+1,
         last = 12
bool unsigned = true
sequence s1 = repeat(0,lim1)
for n=1 to lim1 do
    s1[n] = mpz_inits(lim1)
end for
mpz_set_si(s1[1][1],1)
mpz {t, m100} = mpz_inits(2)
for n=1 to lim do
    for k=1 to n do
        mpz_set_si(t,n-1)
        mpz_mul(t,t,s1[n][k+1])
        if unsigned then
            mpz_add(s1[n+1][k+1],s1[n][k],t)
        else
            mpz_sub(s1[n+1][k+1],s1[n][k],t)
        end if
    end for
end for
string s = iff(unsigned?"Uns":"S")
printf(1,"%signed Stirling numbers of the first kind: S1(n, k):\n n   k:",s)
for i=0 to last do
    printf(1,"%5d     ", i)
end for
printf(1,"\n---    %s\n",repeat('-',last*10+5))
for n=0 to last do
    printf(1,"%2d ", n)
    for k=1 to n+1 do
        printf(1,"%9s ",{mpz_get_str(s1[n+1][k])})
    end for
    printf(1,"\n")
end for
for k=1 to lim1 do
    mpz s100k = s1[lim1][k]
    if mpz_cmp(s100k,m100) > 0 then
        mpz_set(m100,s100k)
    end if
end for
printf(1,"\nThe maximum S1(100,k): %s\n",shorten(mpz_get_str(m100)))


Program soduko;
{$IFDEF FPC}
  {$CODEALIGN proc=16,loop=8}
{$ENDIF}
uses
  sysutils,crt;
const
  carreeSize = 3;
  maxCoor = carreeSize*carreeSize;
  maxValue = maxCoor;
  maxMask = 1 shl (maxCoor+1)-1;
type
  tLimit = 0..maxCoor-1;
  tValue = 0..maxCoor;
  tSteps = 0..maxCoor*maxCoor;
  tValField = array[tLimit,tLimit] of NativeInt;//tValue;
  tBitrepr = 0..maxMask;
  tcol = array[tLimit] of NativeInt;// tBitrepr;
  trow = array[tLimit] of NativeInt;// tBitrepr;
  tcar = array[tLimit] of NativeInt;// tBitrepr;
  tpValue = ^NativeInt;//^tValue;
  tpLimit = ^tLimit;
  tpBitrepr=  ^NativeInt;//^tBitrepr;
  tchgVal = record
              cvCol,
              cvRow,
              cvCar : tpBitrepr;
              cvVal : tpValue;
            end;
  tpChgVal = ^tchgVal;
  tchgList = array[tSteps] of tchgVal;

  tField = record
             fdChgList: tchgList;
             fdCol : tcol;
             fdRow : trow;
             fdcar : tcar;
             fdVal : tValField;
             fdChgIdx : tSteps;

           end;
const
  Expl0:tValField = ((9,0,7,0,0,0,3,0,0),
                     (0,0,0,1,0,0,2,0,0),
                     (6,0,0,0,0,8,0,0,0),
                     (0,0,5,0,3,0,0,0,0),
                     (0,0,0,0,0,0,0,8,4),
                     (0,0,0,0,0,0,0,6,0),
                     (0,0,0,2,7,0,0,0,0),
                     (8,4,0,0,0,0,0,0,0),
                     (0,6,0,0,0,0,0,0,0));
  Expl1:tValField=((0,0,0,1,0,0,0,3,8),
                   (2,0,0,0,0,5,0,0,0),
                   (0,0,0,0,0,0,0,0,0),
                   (0,5,0,0,0,0,4,0,0),
                   (4,0,0,0,3,0,0,0,0),
                   (0,0,0,7,0,0,0,0,6),
                   (0,0,1,0,0,0,0,5,0),
                   (0,0,0,0,6,0,2,0,0),
                   (0,6,0,0,0,4,0,0,0));

var
  F,
  solF : TField;
  solCnt,
  callCnt: NativeUint;
  solFound : Boolean;

procedure OutField(const F:tField);
var
  rw,cl : tLimit;
  rowS: AnsiString;
Begin
  GotoXy(1,1);
  For rw := low(tLimit) to High(tLimit) do
  Begin
    rowS := '  ';
    For cl := low(tLimit) to High(tLimit) do
      RowS :=RowS+IntToStr(F.fdVal[rw,cl]);
    writeln(RowS);
  end;
end;

function CarIdx(rw,cl: NativeInt):NativeInt;
begin
  CarIdx:= (rw DIV carreeSize)*carreeSize +cl DIV carreeSize;
end;
function InsertTest(const F:tField;rw,cl:tLimit;value:tValue):boolean;
var
  msk: tBitrepr;
Begin
  result := (Value = 0);
  IF result then
    EXIT;
  msk := 1 shl (value-1);
  with F do
  Begin
    result := fdRow[rw] AND msk = 0;
    result := result AND (fdCol[cl] AND msk = 0);
    rw :=CarIdx(rw,cl);
    result := result AND (fdCar[rw] AND msk = 0);
  end;
end;

function InitField(var F:tField;const InFd:tValField;DoReverse:boolean):boolean;
var
  TmpchgVal:tchgVal;
  rw,cl,
  value,
  msk    : NativeInt;
  leftSteps:tSteps;
Begin
  Fillchar(F,SizeOf(F),#0);
  leftSteps := High(tSteps)-1;
  //unknown fields inserted from end
  For rw := low(tLimit) to High(tLimit) do
    For cl := low(tLimit) to High(tLimit) do
    Begin
      value := InFd[rw,cl];
      IF InsertTest(F,rw,cl,value) then
      Begin
        with F do
        Begin
          if value > 0 then
          Begin
            msk := 1 shl (value-1);
            //given state
            //use pointer to the relevant places and mark as occupied
            with fdChgList[fdChgIdx] do
            begin
               cvCol := @fdCol[cl];
               cvCol^ +=Msk;
               cvRow := @fdRow[rw];
               cvRow^ +=Msk;
               cvCar := @fdCar[CarIdx(rw,cl)];
               cvCar^ +=Msk;
               cvVal := @fdVal[rw,cl];
               cvVal^ := value;
            end;
            inc(fdChgIdx);
          end
          else
          Begin
            //use pointer to the relevant places
            with fdChgList[leftSteps] do
            begin
               cvCol := @fdCol[cl];
               cvRow := @fdRow[rw];
               cvCar := @fdCar[CarIdx(rw,cl)];
               cvVal := @fdVal[rw,cl];
            end;
            dec(leftSteps);
          end;
        end
      end
      else
      Begin
        writeln(rw:10,cl:10,value:10);
        Writeln(' not solvable SuDoKu ');
        delay(2000);
        result := false;
        EXIT;
      end;
    end;
  //reverse direction of left over
  IF DoReverse then
  Begin
    leftSteps := High(tSteps)-1;
    rw := F.fdChgIdx;
    repeat
      TmpchgVal:= F.fdChgList[leftSteps];
      F.fdChgList[leftSteps]:= F.fdChgList[rw];
      F.fdChgList[rw] :=TmpchgVal;
      dec(leftSteps);
      inc(rw);
    until rw>=leftSteps;
  end;
  //OutField(F);
  solFound := false;
  result := true;
end;
procedure SolIsFound;
begin
  solF := F;
  inc(solCnt);
  solFound := True;
end;

procedure TryCell(var ChgVal:tpchgVal);
var
  value :NativeInt;
  poss,msk: NativeInt;
Begin
  IF solFound then EXIT;
  with ChgVal^ do
    poss:= (cvRow^ OR cvCol^ OR cvCar^) XOR maxMask;
  IF Poss = 0 then
    EXIT;

  value := 1;
  msk   := 1;

  repeat
    IF Poss AND MSK <>0 then
    Begin
      inc(callCnt);
      //insert test value
      with ChgVal^ do
      Begin
        cvCol^ := cvCol^ OR msk;
        cvRow^ := cvRow^ OR msk;
        cvCar^ := cvCar^ OR msk;
        cvVAl^ := value;
      end;
      //try next in list, if beyond last
      inc(ChgVal);

      IF ChgVal^.cvCol <> NIL then
        TryCell(ChgVal)
      else
        SolIsFound;
      //remove test value
      dec(ChgVal);
      with ChgVal^  do
      Begin
        cvCol^ := cvCol^ XOR msk;
        cvRow^ := cvRow^ XOR msk;
        cvCar^ := cvCar^ XOR msk;
        cvVAl^ := 0;
      end;
    end;
    inc(msk,msk);
    inc(value);
  until value> maxValue;
end;

var
  ChangeBegin : tpChgVal;
  k : NativeInt;
  T1,T0: TDateTime;
begin
  randomize;
  ClrScr;
  solCnt := 0;
  callCnt:= 0;
  T0 := time;
  k := 0;
  repeat
    InitField(F,Expl1,FALSE);
    ChangeBegin := @F.fdChgList[F.fdChgIdx];
    TryCell(ChangeBegin);
    inc(k);
  until k >= 5;
  T1 := time;
  Outfield(solF);
  writeln(86400*1000*(T1-T0)/k:10:3,' ms Test calls :',callCnt/k:8:0);
end.


import "/big" for BigInt
import "/fmt" for Fmt

var computed = {}

var stirling2 // recursive
stirling2 = Fn.new { |n, k|
    var key = "%(n),%(k)"
    if (computed.containsKey(key)) return computed[key]
    if (n == 0 && k == 0) return BigInt.one
    if ((n > 0 && k == 0) || (n == 0 && k > 0)) return BigInt.zero
    if (k == n) return BigInt.one
    if (k > n) return BigInt.zero
    var result = stirling2.call(n-1, k-1) + stirling2.call(n-1, k)*k
    computed[key] = result
    return result
}

System.print("Unsigned Stirling numbers of the second kind:")
var max = 12
System.write("n/k")
for (n in 0..max) Fmt.write("$10d", n)
System.print()
for (n in 0..max) {
    Fmt.write("$-3d", n)
    for (k in 0..n) Fmt.write("$10i", stirling2.call(n, k))
    System.print()
}
System.print("The maximum value of S2(100, k) =")
var previous = BigInt.zero
for (k in 1..100) {
    var current = stirling2.call(100, k)
    if (current > previous) {
        previous = current
    } else {
        Fmt.print("$i\n($d digits, k = $d)", previous, previous.toString.count, k - 1)
        break
    }
}


:- dynamic stirling1_cache/3.

stirling1(N, N, 1):-!.
stirling1(_, 0, 0):-!.
stirling1(N, K, 0):-
	K > N,
	!.
stirling1(N, K, L):-
	stirling1_cache(N, K, L),
	!.
stirling1(N, K, L):-
	N1 is N - 1,
	K1 is K - 1,
	stirling1(N1, K, L1),
	stirling1(N1, K1, L2),
	!,
	L is L2 + (N - 1) * L1,
	assertz(stirling1_cache(N, K, L)).

print_stirling_numbers(N):-
	between(1, N, K),
	stirling1(N, K, L),
	writef('%10r', [L]),
	fail.
print_stirling_numbers(_):-
	nl.

print_stirling_numbers_up_to(M):-
	between(1, M, N),
	print_stirling_numbers(N),
	fail.
print_stirling_numbers_up_to(_).

max_stirling1(N, Max):-
    aggregate_all(max(L), (between(1, N, K), stirling1(N, K, L)), Max).

main:-
	writeln('Unsigned Stirling numbers of the first kind up to S1(12,12):'),
	print_stirling_numbers_up_to(12),
	writeln('Maximum value of S1(n,k) where n = 100:'),
	max_stirling1(100, M),
	writeln(M).


EnableExplicit
#MAX=12
#LZ=10
#SP$="  "
Dim s1.i(#MAX,#MAX)
Define n.i,k.i,x.i,s$,esc$

s1(0,0)=1
esc$=#ESC$+"[8;24;170t" ; Enlarges the console window

For n=0 To #MAX
  For k=1 To n
    s1(n,k)=s1(n-1,k-1)-(n-1)*s1(n-1,k)
  Next
Next

If OpenConsole()
  Print(esc$)
  PrintN(~"Signed Stirling numbers of the first kind\n")
  Print(#SP$+"k")
  For x=0 To #MAX : Print(#SP$+RSet(Str(x),#LZ)) : Next
  PrintN(~"\n  n"+LSet("-",13*12,"-"))
  For n=0 To #MAX
    Print(RSet(Str(n),3))
    For k=0 To #MAX : Print(#SP$+RSet(Str(s1(n,k)),#LZ)) : Next
    PrintN("")
  Next
  Input()
EndIf


fcn stirling2(n,k){
   var seen=Dictionary();	// cache for recursion
   if(n==k)       return(1);	// (0.0)==1
   if(n<1 or k<1) return(0);
   z1,z2 := "%d,%d".fmt(n-1,k), "%d,%d".fmt(n-1,k-1);
   if(Void==(s1 := seen.find(z1))){ s1 = seen[z1] = stirling2(n-1,k)   }
   if(Void==(s2 := seen.find(z2))){ s2 = seen[z2] = stirling2(n-1,k-1) }
   k*s1 + s2;   // k is first to cast to BigInt (if using BigInts)
}


computed = {}

def sterling1(n, k):
	key = str(n) + "," + str(k)

	if key in computed.keys():
		return computed[key]
	if n == k == 0:
		return 1
	if n > 0 and k == 0:
		return 0
	if k > n:
		return 0
	result = sterling1(n - 1, k - 1) + (n - 1) * sterling1(n - 1, k)
	computed[key] = result
	return result

print("Unsigned Stirling numbers of the first kind:")
MAX = 12
print("n/k".ljust(10), end="")
for n in range(MAX + 1):
	print(str(n).rjust(10), end="")
print()
for n in range(MAX + 1):
	print(str(n).ljust(10), end="")
	for k in range(n + 1):
		print(str(sterling1(n, k)).rjust(10), end="")
	print()
print("The maximum value of S1(100, k) = ")
previous = 0
for k in range(1, 100 + 1):
	current = sterling1(100, k)
	if current > previous:
		previous = current
	else:
		print("{0}\n({1} digits, k = {2})\n".format(previous, len(str(previous)), k - 1))
		break


  [ dip number$
    over size -
    space swap of
    swap join echo$ ]      is justify  ( n n -->   )

  [ table ]                is s1table  (   n --> n )

  [ swap 101 * + s1table ] is s1       ( n n --> n )

  101 times
    [ i^ 101 times
      [ dup i^
          [ over 0 =
            over 0 = and iff
              [ 2drop 1 ] done
            over 0 >
            over 0 = and iff
              [ 2drop 0 ] done
            2dup < iff
              [ 2drop 0 ] done
            2dup 1 - swap
            1 - swap s1 unrot
            dip [ 1 - dup ]
            s1 * + ]
        ' s1table put ]
      drop ]

  say "Unsigned Stirling numbers of the first kind."
  cr cr
  13 times
    [ i^ dup 1+ times
      [ dup i^ s1
        10 justify ]
      drop cr ]
  cr
  0 100 times
    [ 100 i^ 1+ s1 max ]
  echo cr


sub Stirling1 (Int \n, Int \k) {
    return 1 unless n || k;
    return 0 unless n && k;
    state %seen;
    (%seen{"{n - 1}|{k - 1}"} //= Stirling1(n - 1, k - 1)) +
    (n - 1) * (%seen{"{n - 1}|{k}"} //= Stirling1(n - 1, k))
}

my $upto = 12;

my $mx = (1..^$upto).map( { Stirling1($upto, $_) } ).max.chars;

put 'Unsigned Stirling numbers of the first kind: S1(n, k):';
put 'n\k', (0..$upto)».fmt: "%{$mx}d";

for 0..$upto -> $row {
    $row.fmt('%-3d').print;
    put (0..$row).map( { Stirling1($row, $_) } )».fmt: "%{$mx}d";
}

say "\nMaximum value from the S1(100, *) row:";
say (^100).map( { Stirling1 100, $_ } ).max;