#include <assert.h>
#include <locale.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct bit_array_tag {
    uint32_t size;
    uint32_t* array;
} bit_array;

bool bit_array_create(bit_array* b, uint32_t size) {
    uint32_t* array = calloc((size + 31)/32, sizeof(uint32_t));
    if (array == NULL)
        return false;
    b->size = size;
    b->array = array;
    return true;
}

void bit_array_destroy(bit_array* b) {
    free(b->array);
    b->array = NULL;
}

void bit_array_set(bit_array* b, uint32_t index, bool value) {
    assert(index < b->size);
    uint32_t* p = &b->array[index >> 5];
    uint32_t bit = 1 << (index & 31);
    if (value)
        *p |= bit;
    else
        *p &= ~bit;
}

bool bit_array_get(const bit_array* b, uint32_t index) {
    assert(index < b->size);
    uint32_t* p = &b->array[index >> 5];
    uint32_t bit = 1 << (index & 31);
    return (*p & bit) != 0;
}

typedef struct sieve_tag {
    uint32_t limit;
    bit_array not_prime;
} sieve;

bool sieve_create(sieve* s, uint32_t limit) {
    if (!bit_array_create(&s->not_prime, limit/2))
        return false;
    for (uint32_t p = 3; p * p <= limit; p += 2) {
        if (bit_array_get(&s->not_prime, p/2 - 1) == false) {
            uint32_t inc = 2 * p;
            for (uint32_t q = p * p; q <= limit; q += inc)
                bit_array_set(&s->not_prime, q/2 - 1, true);
        }
    }
    s->limit = limit;
    return true;
}

void sieve_destroy(sieve* s) {
    bit_array_destroy(&s->not_prime);
}

bool is_prime(const sieve* s, uint32_t n) {
    assert(n <= s->limit);
    if (n == 2)
        return true;
    if (n < 2 || n % 2 == 0)
        return false;
    return bit_array_get(&s->not_prime, n/2 - 1) == false;
}

// return number of decimal digits
uint32_t count_digits(uint32_t n) {
    uint32_t digits = 0;
    for (; n > 0; ++digits)
        n /= 10;
    return digits;
}

// return the number with one digit replaced
uint32_t change_digit(uint32_t n, uint32_t index, uint32_t new_digit) {
    uint32_t p = 1;
    uint32_t changed = 0;
    for (; index > 0; p *= 10, n /= 10, --index)
        changed += p * (n % 10);
    changed += (10 * (n/10) + new_digit) * p;
    return changed;
}

// returns true if n unprimeable
bool unprimeable(const sieve* s, uint32_t n) {
    if (is_prime(s, n))
        return false;
    uint32_t d = count_digits(n);
    for (uint32_t i = 0; i < d; ++i) {
        for (uint32_t j = 0; j <= 9; ++j) {
            uint32_t m = change_digit(n, i, j);
            if (m != n && is_prime(s, m))
                return false;
        }
    }
    return true;
}

int main() {
    const uint32_t limit = 10000000;
    setlocale(LC_ALL, "");
    sieve s = { 0 };
    if (!sieve_create(&s, limit)) {
        fprintf(stderr, "Out of memory\n");
        return 1;
    }
    printf("First 35 unprimeable numbers:\n");
    uint32_t n = 100;
    uint32_t lowest[10] = { 0 };
    for (uint32_t count = 0, found = 0; n < limit && (found < 10 || count < 600); ++n) {
        if (unprimeable(&s, n)) {
            if (count < 35) {
                if (count != 0)
                    printf(", ");
                printf("%'u", n);
            }
            ++count;
            if (count == 600)
                printf("\n600th unprimeable number: %'u\n", n);
            uint32_t last_digit = n % 10;
            if (lowest[last_digit] == 0) {
                lowest[last_digit] = n;
                ++found;
            }
        }
    }
    sieve_destroy(&s);
    for (uint32_t i = 0; i < 10; ++i)
        printf("Least unprimeable number ending in %u: %'u\n" , i, lowest[i]);
    return 0;
}


#include <iostream>
#include <cstdint>
#include "prime_sieve.hpp"

typedef uint32_t integer;

// return number of decimal digits
int count_digits(integer n) {
    int digits = 0;
    for (; n > 0; ++digits)
        n /= 10;
    return digits;
}

// return the number with one digit replaced
integer change_digit(integer n, int index, int new_digit) {
    integer p = 1;
    integer changed = 0;
    for (; index > 0; p *= 10, n /= 10, --index)
        changed += p * (n % 10);
    changed += (10 * (n/10) + new_digit) * p;
    return changed;
}

// returns true if n unprimeable
bool unprimeable(const prime_sieve& sieve, integer n) {
    if (sieve.is_prime(n))
        return false;
    int d = count_digits(n);
    for (int i = 0; i < d; ++i) {
        for (int j = 0; j <= 9; ++j) {
            integer m = change_digit(n, i, j);
            if (m != n && sieve.is_prime(m))
                return false;
        }
    }
    return true;
}

int main() {
    const integer limit = 10000000;
    prime_sieve sieve(limit);

    // print numbers with commas
    std::cout.imbue(std::locale(""));

    std::cout << "First 35 unprimeable numbers:\n";
    integer n = 100;
    integer lowest[10] = { 0 };
    for (int count = 0, found = 0; n < limit && (found < 10 || count < 600); ++n) {
        if (unprimeable(sieve, n)) {
            if (count < 35) {
                if (count != 0)
                    std::cout << ", ";
                std::cout << n;
            }
            ++count;
            if (count == 600)
                std::cout << "\n600th unprimeable number: " << n << '\n';
            int last_digit = n % 10;
            if (lowest[last_digit] == 0) {
                lowest[last_digit] = n;
                ++found;
            }
        }
    }
    for (int i = 0; i < 10; ++i)
        std::cout << "Least unprimeable number ending in " << i << ": " << lowest[i] << '\n';
    return 0;
}


import std.algorithm;
import std.array;
import std.conv;
import std.range;
import std.stdio;

immutable MAX = 10_000_000;
bool[] primes;

bool[] sieve(int limit) {
    bool[] p = uninitializedArray!(bool[])(limit);
    p[0..2] = false;
    p[2..$] = true;
    foreach (i; 2..limit) {
        if (p[i]) {
            for (int j = 2 * i; j < limit; j += i) {
                p[j] = false;
            }
        }
    }
    return p;
}

string replace(CHAR)(CHAR[] str, int position, CHAR value) {
    str[position] = value;
    return str.idup;
}

bool unPrimeable(int n) {
    if (primes[n]) {
        return false;
    }
    auto test = n.to!string;
    foreach (i; 0 .. test.length) {
        for (char j = '0'; j <= '9'; j++) {
            auto r = replace(test.dup, i, j);
            if (primes[r.to!int]) {
                return false;
            }
        }
    }
    return true;
}

void displayUnprimeableNumbers(int maxCount) {
    int test = 1;
    for (int count = 0; count < maxCount;) {
        test++;
        if (unPrimeable(test)) {
            count++;
            write(test, ' ');
        }
    }
    writeln;
}

int nthUnprimeableNumber(int maxCount) {
    int test = 1;
    for (int count = 0; count < maxCount;) {
        test++;
        if (unPrimeable(test)) {
            count++;
        }
    }
    return test;
}

int[] genLowest() {
    int[] lowest = uninitializedArray!(int[])(10);
    lowest[] = 0;

    int count = 0;
    int test = 1;
    while (count < 10) {
        test++;
        if (unPrimeable(test) && lowest[test % 10] == 0) {
            lowest[test % 10] = test;
            count++;
        }
    }

    return lowest;
}

void main() {
    primes = sieve(MAX);

    writeln("First 35 unprimeable numbers:");
    displayUnprimeableNumbers(35);
    writeln;

    int n = 600;
    writefln("The %dth unprimeable number = %,d", n, nthUnprimeableNumber(n));
    writeln;

    writeln("Least unprimeable number that ends in:");
    foreach (i,v; genLowest()) {
        writefln(" %d is %,d", i, v);
    }
}


// Unprimeable numbers. Nigel Galloway: May 4th., 2021
let rec fN i g e l=seq{yield! [0..9]|>Seq.map(fun n->n*g+e+l); if g>1 then let g=g/10 in yield! fN(i+g*(e/g)) g (e%g) i}
let     fG(n,g)=fN(n*(g/n)) n (g%n) 0|>Seq.exists(isPrime)
let uP()=let rec fN n g=seq{yield! {n..g-1}|>Seq.map(fun g->(n,g)); yield! fN(g)(g*10)} in fN 1 10|>Seq.filter(fG>>not)|>Seq.map snd


USING: assocs formatting io kernel lists lists.lazy
lists.lazy.examples math math.functions math.primes math.ranges
math.text.utils prettyprint sequences tools.memory.private ;

: one-offs ( n -- seq )
    dup 1 digit-groups [
        swapd 10^ [ * ] keep [ - ] dip
        2dup [ 9 * ] [ + ] [ <range> ] tri*
    ] with map-index concat ;

: (unprimeable?) ( n -- ? )
    [ f ] [ one-offs [ prime? ] none? ] if-zero ;

: unprimeable? ( n -- ? )
    dup prime? [ drop f ] [ (unprimeable?) ] if ;

: unprimeables ( -- list ) naturals [ unprimeable? ] lfilter ;

: ?set-at ( value key assoc -- )
    2dup key? [ 3drop ] [ set-at ] if ;

: first-digits ( -- assoc )
    unprimeables H{ } clone [ dup assoc-size 10 = ]
    [ [ unswons dup 10 mod ] dip [ ?set-at ] keep ] until nip ;

"The first 35 unprimeable numbers:" print bl bl
35 unprimeables ltake [ pprint bl ] leach nl nl

"The 600th unprimeable number:" print bl bl
599 unprimeables lnth commas print nl

"The first unprimeable number ending with" print
first-digits [ commas "  %d: %9s\n" printf ] assoc-each


Function isprime(n As Ulongint) As boolean
    If (n=2) Or (n=3) Then Return 1
    If n Mod 2 = 0 Then Return 0
    If n Mod 3 = 0 Then Return 0
    Dim As Ulongint limit=Sqr(N)+1
    For I As Ulongint = 6 To limit Step 6
        If N Mod (i-1) = 0 Then Return 0
        If N Mod (i+1) = 0 Then Return 0
    Next I
    Return 1
End Function

Sub getnonprimeables(a() As Long)
    Dim As String s,g
    Dim As Long count,lim=1300000
    Redim a(1 To lim)
    For num As Long=1 To lim
        g=Str(num)
        s=g
        For n As Long=0 To Len(s)-1
            For m As Long=48 To 57
                s[n]=m
                If isprime(Vallng(s)) Then Goto lbl
            Next m
            s=g
        Next n
        count+=1
        a(count)=num
        lbl:
    Next num
    Redim Preserve a(1 To count)
End Sub

Function endings(n As String,a() As Long) As Long
    For m As Long=1 To Ubound(a)
        If Right(Str(a(m)),1)=n Then Return a(m)
    Next m
End Function

Redim As Long n()
getnonprimeables(n())
print " First 35"
For m As Long=1 To 35
    Print n(m);
Next
Print
Print "600th number ";n(600)
For z As Long=0 To 9
    Print "first umprimable number ending in ";z; " is ";endings(Str(z),n())
Next z
sleep


package main

import (
    "fmt"
    "strconv"
)

func isPrime(n int) bool {
    switch {
    case n < 2:
        return false
    case n%2 == 0:
        return n == 2
    case n%3 == 0:
        return n == 3
    default:
        d := 5
        for d*d <= n {
            if n%d == 0 {
                return false
            }
            d += 2
            if n%d == 0 {
                return false
            }
            d += 4
        }
        return true
    }
}

func commatize(n int) string {
    s := fmt.Sprintf("%d", n)
    le := len(s)
    for i := le - 3; i >= 1; i -= 3 {
        s = s[0:i] + "," + s[i:]
    }
    return s
}

func main() {
    fmt.Println("The first 35 unprimeable numbers are:")
    count := 0           // counts all unprimeable numbers
    var firstNum [10]int // stores the first unprimeable number ending with each digit
outer:
    for i, countFirst := 100, 0; countFirst < 10; i++ {
        if isPrime(i) {
            continue // unprimeable number must be composite
        }
        s := strconv.Itoa(i)
        le := len(s)
        b := []byte(s)
        for j := 0; j < le; j++ {
            for k := byte('0'); k <= '9'; k++ {
                if s[j] == k {
                    continue
                }
                b[j] = k
                n, _ := strconv.Atoi(string(b))
                if isPrime(n) {
                    continue outer
                }
            }
            b[j] = s[j] // restore j'th digit to what it was originally
        }
        lastDigit := s[le-1] - '0'
        if firstNum[lastDigit] == 0 {
            firstNum[lastDigit] = i
            countFirst++
        }
        count++
        if count <= 35 {
            fmt.Printf("%d ", i)
        }
        if count == 35 {
            fmt.Print("\n\nThe 600th unprimeable number is: ")
        }
        if count == 600 {
            fmt.Printf("%s\n\n", commatize(i))
        }
    }

    fmt.Println("The first unprimeable number that ends in:")
    for i := 0; i < 10; i++ {
        fmt.Printf("  %d is: %9s\n", i, commatize(firstNum[i]))
    }
}


import Control.Lens ((.~), ix, (&))
import Data.Numbers.Primes (isPrime)
import Data.List (find, intercalate)
import Data.Char (intToDigit)
import Data.Maybe (mapMaybe)
import Data.List.Split (chunksOf)
import Text.Printf (printf)

isUnprimable :: Int -> Bool
isUnprimable = all (not . isPrime) . swapdigits

swapdigits :: Int -> [Int]
swapdigits n = map read $ go $ pred $ length digits
 where
  digits = show n
  go (-1) = []
  go n''  = map (\x -> digits & (ix n'') .~ intToDigit x) [0..9] <> go (pred n'')

unPrimeable :: [Int]
unPrimeable = filter isUnprimable [1..]

main :: IO ()
main = do
  printf "First 35 unprimeable numbers:\n%s\n\n" $ show $ take 35 unPrimeable
  printf "600th unprimeable number: %d\n\n" $ unPrimeable !! 599
  mapM_ (uncurry (printf "Lowest unprimeable number ending with %d: %10s\n")) $ mapMaybe lowest [0..9]
 where
  thousands = reverse . intercalate "," . chunksOf 3 . reverse
  lowest n = do
    x <- find (\x -> x `mod` 10 == n) unPrimeable
    pure (n, thousands $ show x)


NB. replace concatenates at various ranks and in boxes to avoid fill
NB. the curtailed prefixes (}:\) with all of 0..9 (i.10) with the beheaded suffixes (}.\.)
NB. under the antibase 10 representation (10&#.inv)
replace=: ([: ; <@}:\ ,"1 L:_1 ([: < (i.10) ,"0 1 }.)\.)&.(10&#.inv)

NB. primable tests if one of the replacements is prime
primable=: (1 e. 1 p: replace)&>

unprimable=: [email protected]:primable

assert 0 1 -: unprimable 193 200


public class UnprimeableNumbers {

    private static int MAX = 10_000_000;
    private static boolean[] primes = new boolean[MAX];

    public static void main(String[] args) {
        sieve();
        System.out.println("First 35 unprimeable numbers:");
        displayUnprimeableNumbers(35);
        int n = 600;
        System.out.printf("%nThe %dth unprimeable number = %,d%n%n", n, nthUnprimeableNumber(n));
        int[] lowest = genLowest();
        System.out.println("Least unprimeable number that ends in:");
        for ( int i = 0 ; i <= 9 ; i++ ) {
            System.out.printf(" %d is %,d%n", i, lowest[i]);
        }
    }

    private static int[] genLowest() {
        int[] lowest = new int[10];
        int count = 0;
        int test = 1;
        while ( count < 10 ) {
            test++;
            if ( unPrimable(test) && lowest[test % 10] == 0 ) {
                lowest[test % 10] = test;
                count++;
            }
        }
        return lowest;
    }

    private static int nthUnprimeableNumber(int maxCount) {
        int test = 1;
        int count = 0;
        int result = 0;
        while ( count < maxCount ) {
            test++;
            if ( unPrimable(test) ) {
                count++;
                result = test;
            }
        }
        return result;
    }

    private static void displayUnprimeableNumbers(int maxCount) {
        int test = 1;
        int count = 0;
        while ( count < maxCount ) {
            test++;
            if ( unPrimable(test) ) {
                count++;
                System.out.printf("%d ", test);
            }
        }
        System.out.println();
    }

    private static boolean unPrimable(int test) {
        if ( primes[test] ) {
            return false;
        }
        String s = test + "";
        for ( int i = 0 ; i < s.length() ; i++ ) {
            for ( int j = 0 ; j <= 9 ; j++ ) {
                if ( primes[Integer.parseInt(replace(s, i, j))] ) {
                    return false;
                }
            }
        }
        return true;
    }

    private static String replace(String str, int position, int value) {
        char[] sChar = str.toCharArray();
        sChar[position] = (char) value;
        return str.substring(0, position) + value + str.substring(position + 1);
    }

    private static final void sieve() {
        //  primes
        for ( int i = 2 ; i < MAX ; i++ ) {
            primes[i] = true;
        }
        for ( int i = 2 ; i < MAX ; i++ ) {
            if ( primes[i] ) {
                for ( int j = 2*i ; j < MAX ; j += i ) {
                    primes[j] = false;
                }
            }
        }
    }

}


Number.prototype.isPrime = function() {
  let i = 2, num = this;
  if (num == 0 || num == 1) return false;
  if (num == 2) return true;
  while (i <= Math.ceil(Math.sqrt(num))) {
    if (num % i == 0) return false;
    i++;
  }
  return true;
}


def digits: tostring | explode | map([.] | implode | tonumber);

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


using Primes, Lazy, Formatting

function isunprimeable(n)
    dvec = digits(n)
    for pos in 1:length(dvec), newdigit in 0:9
        olddigit, dvec[pos] = dvec[pos], newdigit
        isprime(foldr((i, j) -> i + 10j, dvec)) && return false
        dvec[pos] = olddigit
    end
    return true
end

println("First 35 unprimeables: ", take(35, filter(isunprimeable, Lazy.range())))

println("\nThe 600th unprimeable is ",
    collect(take(600, filter(isunprimeable, Lazy.range())))[end])

println("\nDigit  First unprimeable ending with that digit")
println("-----------------------------------------")

for dig in 0:9
    n = first(filter(x -> (x % 10 == dig) && isunprimeable(x), Lazy.range()))
    println("  $dig  ", lpad(format(n, commas=true), 9))
end


private const val MAX = 10000000
private val primes = BooleanArray(MAX)

fun main() {
    sieve()
    println("First 35 unprimeable numbers:")
    displayUnprimeableNumbers(35)
    val n = 600
    println()
    println("The ${n}th unprimeable number = ${nthUnprimeableNumber(n)}")
    println()
    val lowest = genLowest()
    println("Least unprimeable number that ends in:")
    for (i in 0..9) {
        println(" $i is ${lowest[i]}")
    }
}

private fun genLowest(): IntArray {
    val lowest = IntArray(10)
    var count = 0
    var test = 1
    while (count < 10) {
        test++
        if (unPrimable(test) && lowest[test % 10] == 0) {
            lowest[test % 10] = test
            count++
        }
    }
    return lowest
}

private fun nthUnprimeableNumber(maxCount: Int): Int {
    var test = 1
    var count = 0
    var result = 0
    while (count < maxCount) {
        test++
        if (unPrimable(test)) {
            count++
            result = test
        }
    }
    return result
}

private fun displayUnprimeableNumbers(maxCount: Int) {
    var test = 1
    var count = 0
    while (count < maxCount) {
        test++
        if (unPrimable(test)) {
            count++
            print("$test ")
        }
    }
    println()
}

private fun unPrimable(test: Int): Boolean {
    if (primes[test]) {
        return false
    }
    val s = test.toString() + ""
    for (i in s.indices) {
        for (j in 0..9) {
            if (primes[replace(s, i, j).toInt()]) {
                return false
            }
        }
    }
    return true
}

private fun replace(str: String, position: Int, value: Int): String {
    val sChar = str.toCharArray()
    sChar[position] = value.toChar()
    return str.substring(0, position) + value + str.substring(position + 1)
}

private fun sieve() {
    //  primes
    for (i in 2 until MAX) {
        primes[i] = true
    }
    for (i in 2 until MAX) {
        if (primes[i]) {
            var j = 2 * i
            while (j < MAX) {
                primes[j] = false
                j += i
            }
        }
    }
}


-- FUNCS:
local function T(t) return setmetatable(t, {__index=table}) end
table.filter = function(t,f) local s=T{} for _,v in ipairs(t) do if f(v) then s[#s+1]=v end end return s end
table.firstn = function(t,n) local s=T{} n=n>#t and #t or n for i = 1,n do s[i]=t[i] end return s end

-- SIEVE:
local sieve, S = {}, 10000000
for i = 2,S do sieve[i]=true end
for i = 2,S do if sieve[i] then for j=i*i,S,i do sieve[j]=nil end end end

-- UNPRIMABLE:
local unprimables, lowests = T{}, T{}
local floor, log10 = math.floor, math.log10

local function unprimable(n)
  if sieve[n] then return false end
  local nd = floor(log10(n))+1
  for i = 1, nd do
    local pow10 = 10^(nd-i)
    for j = 0, 9 do
      local p = (floor(n/10/pow10) * 10 + j) * pow10 + (n % pow10)
      if sieve[p] then return false end
    end
  end
  return true
end

local n, done = 1, 0
while done < 10 do
  if unprimable(n) then
    unprimables:insert(n)
    if not lowests[n%10] then
      lowests[n%10] = n
      done = done + 1
    end
  end
  n = n + 1
end

-- OUTPUT:
local function commafy(i) return tostring(i):reverse():gsub("(%d%d%d)","%1,"):reverse():gsub("^,","") end
print("The first 35 unprimable numbers are:")
print(unprimables:firstn(35):concat(" "))
print()
print("The 600th unprimable number is:  " .. commafy(unprimables[600]))
print()
print("The lowest unprimable number that ends in..")
for i = 0, 9 do
  print("  " .. i .. " is:  " .. commafy(lowests[i]))
end


ClearAll[Unprimeable]
Unprimeable[in_Integer] := Module[{id, new, pos},
  id = IntegerDigits[in];
  pos = [email protected][
     Table[
      new = id;
      new[[d]] = n;
      new
      ,
      {n, 0, 9}
      ]
     ,
     {d, Length[id]}
     ];
  pos //= Map[FromDigits];
  NoneTrue[pos, PrimeQ]
  ]
res = {};
PrintTemporary[Dynamic[{Length[res], i}]];
i = 0;
While[Length[res] < 600,
  If[Unprimeable[i],
   AppendTo[res, i]
   ];
  i++
  ];

PrintTemporary[Dynamic[{lastdig, i}]];
out = Table[
   i = lastdig;
   While[! Unprimeable[i],
    i += 10
    ];
   i
   ,
   {lastdig, 0, 9}
   ];

res[[;; 35]]
res[[600]]

lastdigit = IntegerDigits /* Last;
Print["Least unprimeable number ending in ", lastdigit[#], ": ", #] & /@ SortBy[out, lastdigit];


import strutils

const N = 10_000_000

# Erastosthenes sieve.
var composite: array[0..N, bool]  # Defualt is false i.e. composite.
composite[0] = true
composite[1] = true
for n in 2..N:
  if not composite[n]:
    for k in countup(n * n, N, n):
      composite[k] = true

template isPrime(n: int): bool = not composite[n]

proc isUmprimeable(n: Positive): bool =
  if n.isPrime: return false
  var nd = $n
  for i, prevDigit in nd:
    for newDigit in '0'..'9':
      if newDigit != prevDigit:
        nd[i] = newDigit
        if nd.parseInt.isPrime: return false
    nd[i] = prevDigit   # Restore initial digit.
  result = true

echo "First 35 unprimeable numbers:"
var n = 100
var list: seq[int]
while list.len < 35:
  if n.isUmprimeable:
    list.add n
  inc n
echo list.join(" "), '\n'

var count = 0
n = 199
while count != 600:
  inc n
  if n.isUmprimeable: inc count
echo "600th unprimeable number: ", ($n).insertSep(','), '\n'

for d in 0..9:
  var n = 200 + d
  while not n.isUmprimeable:
    inc n, 10
  echo "Lowest unprimeable number ending in ", d, " is ", ($n).insertSep(',')


program unprimable;
{$IFDEF FPC}{$Mode Delphi}{$ELSE}{$APPTYPE CONSOLE}{$ENDIF}

const
  base = 10;

type
  TNumVal = array[0..base-1] of NativeUint;
  TConvNum = record
               NumRest : TNumVal;
               LowDgt,
               MaxIdx : NativeUint;
             end;

var //global
  PotBase,
  EndDgtFound : TNumVal;
  TotalCnt,
  EndDgtCnt :NativeUint;

procedure Init;
var
  i,val : NativeUint;
Begin
  val := 1;
  For i := low(TNumVal) to High(TNumVal) do
  Begin
    EndDgtFound[i] :=0;
    PotBase[i] := val;
    val := val * Base;
  end;
  TotalCnt := 0;
  EndDgtCnt := 0;
end;

Procedure ConvertNum(n: NativeUint;var NConv:TConvNum);
//extract digit position replace by "0" to get NumRest
// 173 -> 170 -> 103 -> 073
var
  i, dgt,n_red,n_mod: NativeUint;
begin
  i := 0;
  n_red := n;
  with NConv do
  Begin
    repeat
      n_mod := n_red DIV Base;
      dgt := n_red-Base*n_mod;
      n_red := n_mod;
      IF i = 0 then
        LowDgt := dgt;
      NumRest[i]:= n-dgt*PotBase[i];
      inc(i);
    until (i > High(TNumVal)) OR (n<PotBase[i]);
    MaxIdx := i-1;
  end;
end;

procedure CheckOutPut(n: NativeUint);
Begin
  IF TotalCnt > 600 then
    EXIT;
  IF TotalCnt <= 35 then
    write(n,' ');
  IF TotalCnt = 600 then
  Begin
    writeln;
    writeln;
    writeln('the 600.th unprimable number: ',n);
  end;
end;

function isPrime(n : NativeUint):boolean;inline;
var
  p : NativeUint;
Begin
  result := (N=2) OR (N=3);
  IF result then
    EXIT;
  //now result = false
  IF (n<2) OR (NOT(ODD(n))) or (n mod 3= 0) then
    EXIT;
  p := 5;
  while p*p <= n do
  Begin
    if n mod p = 0 then
      Exit;
    inc(p,2);
    if n mod p = 0 then
      Exit;
    inc(p,4);
  end;
  result := true;
end;

procedure InsertFound(LowDgt,n:NativeUInt);
Begin
  inc(TotalCnt);
  IF EndDgtFound[LowDgt] = 0 then
  Begin
    EndDgtFound[LowDgt] := n;
    inc(EndDgtCnt);
  end;
end;

function CheckUnprimable(n:NativeInt):boolean;
var
  ConvNum : TConvNum;
  val,dgt,i,dtfac: NativeUint;
Begin
  ConvertNum(n,ConvNum);
  result := false;
  //lowest digit
  with ConvNum do
  Begin
    val := NumRest[0];
    For dgt := 0 to Base-1 do
      IF isPrime(val+dgt) then
        EXIT;
    dgt := LowDgt;

    result := true;
    i := MaxIdx;
    IF NumRest[i] >= Base then
    Begin
//****Only for base=10 if even or divisible by 5***
      IF Not(ODD(dgt)) OR (dgt=5) then
      Begin
        InsertFound(dgt,n);
        EXIT;
      end;
    end;

    result := false;
    For i := MaxIdx downto 1 do
    Begin
      dtfac := PotBase[i];
      val := NumRest[i];
      For dgt := 0 to Base-1 do
      Begin
        IF isPrime(val) then
          EXIT;
        inc(val,dtfac);
      end;
    end;
    InsertFound(LowDgt,n);
    result := true;
  end;
end;

function CheckUnprimableReduced(n:NativeInt):boolean;
//lowest digit already tested before
var
  ConvNum : TConvNum;
  val,dgt,i,dtfac: NativeUint;
Begin
  ConvertNum(n,ConvNum);
  result := true;
  with ConvNum do
  Begin
    i := MaxIdx;
    IF NumRest[i] >= Base then
    Begin
      dgt := LowDgt;
      IF Not(ODD(dgt)) OR (dgt=5) then
      Begin
        InsertFound(dgt,n);
        EXIT;
      end;
    end;

    result := false;
    For i := i downto 1 do
    Begin
      dtfac := PotBase[i];
      val := NumRest[i];
      For dgt := 0 to Base-1 do
      Begin
        IF isPrime(val) then
          EXIT;
        inc(val,dtfac);
      end;
    end;
    InsertFound(LowDgt,n);
    result := true;
  end;
end;

var
  n,i : NativeUint;
Begin
  init;
  n := Base;
  repeat
    If CheckUnprimable(n) then
    Begin
      CheckOutPut(n);
      For i := 1 to Base-1 do
      Begin
        IF CheckUnprimableReduced(n+i) then
          CheckOutPut(n+i);
      end;
    end;
    inc(n,Base);
  until EndDgtCnt = Base;
  writeln;
  For i := 0 to Base-1 do
    Writeln ('lowest digit ',i:2,' found first ',EndDgtFound[i]:7);
  writeln;
  writeln('There are ',TotalCnt,' unprimable numbers upto ',n);
  {$IFNDEF UNIX}readln;{$ENDIF}
end.


use strict;
use warnings;
use feature 'say';
use ntheory 'is_prime';
use enum qw(False True);

sub comma { reverse ((reverse shift) =~ s/(.{3})/$1,/gr) =~ s/^,//r }

sub is_unprimeable {
    my($n) = @_;
    return False if is_prime($n);
    my $chrs = length $n;
    for my $place (0..$chrs-1) {
        my $pow = 10**($chrs - $place - 1);
        my $this = substr($n, $place, 1) * $pow;
        map { return False if $this != $_ and is_prime($n - $this + $_ * $pow) } 0..9;
     }
     True
}

my($n, @ups);
do { push @ups, $n if is_unprimeable(++$n); } until @ups == 600;
say "First 35 unprimeables:\n" . join ' ', @ups[0..34];
printf "\n600th unprimeable: %s\n", comma $ups[599];

map {
    my $x = $_;
    while ($x += 10) { last if is_unprimeable($x) }
    say "First unprimeable that ends with $_: " . sprintf "%9s", comma $x;
} 0..9;


with javascript_semantics
printf(1,"The first 35 unprimeable numbers are:\n")
integer count := 0,          -- counts all unprimeable numbers
        countFirst = 0,
        i = 100
sequence firstNum = repeat(0,10) -- stores the first unprimeable number ending with each digit
atom t0 = time(), t1=t0+1
while countFirst<10 do
    if not is_prime(i) then -- unprimeable number must be composite
        string s = sprintf("%d",i), b = s
        integer le := length(s)
        bool primeable = false
        for j=1 to le do
            for k='0' to '9' do
                if s[j]!=k then
                    b[j] = k
                    integer n = to_integer(b)
                    if is_prime(n) then
                        primeable = true
                        exit
                    end if
                end if
            end for
            if primeable then exit end if
            b[j] = s[j] -- restore j'th digit to what it was originally
        end for
        if not primeable then
            integer lastDigit = s[le]-'0'+1
            if firstNum[lastDigit] == 0 then
                firstNum[lastDigit] = i
                countFirst += 1
            end if
            count += 1
            if count <= 35 then
                printf(1,"%d ", i)
            elsif count == 600 then
                printf(1,"\n\nThe 600th unprimeable number is: %,d\n\n",i)
            end if
        end if
    end if
    if platform()!=JS and time()>t1 then
        printf(1,"checking %d, %d `endswiths` found\r",{i,countFirst})
        t1 = time()+1
    end if
    i += 1
end while

printf(1,"The first unprimeable number that ends in:\n")
for i=1 to 10 do
    printf(1,"  %d is: %,9d\n", {i-1, firstNum[i]})
end for
?elapsed(time()-t0)


bool is_unprimeable(int i)
{
    string s = i->digits();
    for(int offset; offset < sizeof(s); offset++) {
	foreach("0123456789"/1, string repl) {
	    array chars = s/1;
	    chars[offset] = repl;
	    int testme = (int)(chars*"");
	    if( testme->probably_prime_p() )
		return false;
	}
    }
    return true;
}

void main()
{
    int i, count;
    array unprimes = ({});
    mapping first_enders = ([]); // first unprimeable ending with each digit
    while(sizeof(first_enders) != 10) {
	i++;
	if( is_unprimeable(i) ) {
	    count++;
	    unprimes += ({ i });
	    string last_digit = i->digits()[<0..];
	    if( !first_enders[last_digit] )
		first_enders[last_digit] = i;
	}
	werror("%d\r", i); // Progress output
    }

    write("First 35 unprimeables: %s\n\n", (array(string))unprimes[0..34]*" ");
    write("The 600th unprimeable is %d\n\n", unprimes[599]);
    write("The first unprimeable number that ends in\n");
    foreach(sort(indices(first_enders)), string e) {
	write("  %s is: %9d\n", e, first_enders[e]);
    }
}


from itertools import count, islice

def primes(_cache=[2, 3]):
    yield from _cache
    for n in count(_cache[-1]+2, 2):
        if isprime(n):
            _cache.append(n)
            yield n

def isprime(n, _seen={0: False, 1: False}):
    def _isprime(n):
        for p in primes():
            if p*p > n:
                return True
            if n%p == 0:
                return False

    if n not in _seen:
        _seen[n] = _isprime(n)
    return _seen[n]

def unprime():
    for a in count(1):
        d = 1
        while d <= a:
            base = (a//(d*10))*(d*10) + (a%d) # remove current digit
            if any(isprime(y) for y in range(base, base + d*10, d)):
                break
            d *= 10
        else:
            yield a

print('First 35:')
print(' '.join(str(i) for i in islice(unprime(), 35)))

print('\nThe 600-th:')
print(list(islice(unprime(), 599, 600))[0])
print()

first, need = [False]*10, 10
for p in unprime():
    i = p%10
    if first[i]: continue

    first[i] = p
    need -= 1
    if not need:
        break

for i,v in enumerate(first):
    print(f'{i} ending: {v}')


#lang racket

(require math/number-theory)

(define cached-prime?
  (let ((hsh# (make-hash))) (λ (p) (hash-ref! hsh# p (λ () (prime? p))))))

(define (zero-digit n d)
  (define p (expt 10 d))
  (+ (remainder n p) (* 10 p (quotient n (* p 10)))))

(define (primeable? n)
  (or (cached-prime? n)
      (for*/first ((d (in-range (add1 (order-of-magnitude n))))
                   (n0 (in-value (zero-digit n d)))
                   (p (in-value (expt 10 d)))
                   (r (in-range 10))
                   (n+ (in-value (+ n0 (* r p))))
                   #:when (cached-prime? n+))
                  n+)))

(define unprimeable? (negate primeable?))

(module+
  main
  (printf "First 35 unprimeable numbers: ~a~%"
          (let recur ((i 0) (n 1) (acc null))
            (cond [(= i 35) (reverse acc)]
                  [(unprimeable? n) (recur (add1 i) (add1 n) (cons n acc))]
                  [else (recur i (add1 n) acc)])))

  (printf "600th unprimeable number: ~a~%"
             (let recur ((i 0) (n 1) (u #f))
               (cond [(= i 600) u]
                     [(unprimeable? n) (recur (add1 i) (add1 n) n)]
                     [else (recur i (add1 n) u)])))

  (for ((d 10))
       (printf "Least unprimeable number ending in ~a = ~a~%" d
               (for/first ((i (in-range (+ 100 d) +Inf.0 10)) #:when (unprimeable? i)) i))))

(module+ test
  (require rackunit)
  (check-equal? (zero-digit 1234 2) 1034)
  (check-equal? (primeable? 10) 11)
  (check-true (unprimeable? 200))
  (check-false (unprimeable? 201)))


use ntheory:from<Perl5> <is_prime>;
use Lingua::EN::Numbers;

sub is-unprimeable (\n) {
     return False if n.&is_prime;
     my \chrs = n.chars;
     for ^chrs -> \place {
         my \pow = 10**(chrs - place - 1);
         my \this = n.substr(place, 1) × pow;
         ^10 .map: -> \dgt {
             next if this == dgt;
             return False if is_prime(n - this + dgt × pow)
         }
     }
     True
}

my @ups = lazy ^∞ .grep: { .&is-unprimeable };

say "First 35 unprimeables:\n" ~ @ups[^35];

say "\n{ordinal-digit(600, :u)} unprimeable: " ~ comma( @ups[599] ) ~ "\n";

^10 .map: -> \n {
    print "First unprimeable that ends with {n}: " ~
    sprintf "%9s\n", comma (n, *+10 … *).race.first: { .&is-unprimeable }
}


/*REXX program  finds and displays   unprimeable   numbers  (non─negative integers).    */
parse arg n x hp .                               /*obtain optional arguments from the CL*/
if  n=='' |  n==","  then  n=       35           /*Not specified?  Then use the default.*/
if  x=='' |  x==","  then  x=      600           /* "      "         "   "   "     "    */
if hp=='' | hp==","  then hp= 10000000           /* "      "         "   "   "     "    */
u= 0                                             /*number of unprimeable numbers so far.*/
eds=4;     ed.1= 1;  ed.2= 3;  ed.3= 7;  ed.4= 9 /*"end" digits which are prime; prime>9*/
call genP hp                                     /*generate primes up to & including HP.*/
$$=;                       $.=.                  /*a list  "      "         "     "  "  */
      do j=100;            if !.j  then iterate  /*Prime?  Unprimeable must be composite*/
      Lm= length(j)                              /*obtain the length-1 of the number J. */
      meat= left(j, Lm)                          /*obtain the first  Lm   digits of  J. */
                                                 /* [↑]  examine the "end" digit of  J. */
        do e_=1  for eds;  new= meat || ed.e_    /*obtain a different number  (than  J).*/
        if new==j  then iterate                  /*Is it the original number? Then skip.*/
        if !.new   then iterate j                /*This new number a prime?     "    "  */
        end  /*e_*/
                                                 /* [↑]  examine a new 1st digit of  J. */
        do f_=0  for 10;   new= (f_||meat) + 0   /*obtain a different number  (than  J).*/
        if new==j  then iterate                  /*Is it the original number? Then skip.*/
        if !.new   then iterate j                /*This new number a prime?     "    "  */
        end  /*f_*/                              /* [↑]  examine the front digit of  J. */
                    do a_= 2  for Lm-1           /*traipse through the middle digits.   */
                    meat=   left(j, a_ - 1)      /*use a number of left─most dec. digits*/
                    rest= substr(j, a_ + 1)      /* "  "    "    " right─most "     "   */
                       do n_=0  for 10           /*traipse through all 1─digit numbers. */
                       new= meat || n_ || rest   /*construct new number, like a phoenix.*/
                       if new==j  then iterate   /*Is it the original number? Then skip.*/
                       if !.new   then iterate j /*This new number a prime?     "    "  */
                       end   /*n_*/
                    end      /*a_*/
      u= u + 1                                   /*bump the count of unprimeable numbers*/
      if u<=n    then $$= $$ commas(j)           /*maybe add unprimeable # to  $$  list.*/
      if u==x    then $.ox=  commas(j)           /*assign the   Xth  unprimeable number.*/
      parse var   j     ''  -1  _                /*obtain the right─most dec digit of J.*/
      if $._==.  then $._= j                     /*the 1st unprimeable # that ends in _.*/
      if $.3==.  then iterate;  if $.7==.  then iterate    /*test if specific #'s found.*/
      if $.1==.  then iterate;  if $.9==.  then iterate    /*  "   "     "     "    "   */
      leave                                                /*if here,  then we're done. */
      end   /*j*/

if n>0  then do;  say center(' first '       n       "unprimeable numbers ", 139, '═')
                  say strip($$);    say
             end
if x>0  then say '     the '     th(x)       " unprimeable number is: "       $.ox
say
     do o=0  for 10;      if length($.o)==0  then iterate
     say '     the first unprimeable number that ends in '  o  " is:"right(commas($.o),11)
     end   /*o*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas:  parse arg ?;  do c=length(?)-3  to 1  by -3; ?=insert(',', ?, c); end;   return ?
th:procedure;parse arg x;return x||word('th st nd rd',1+(x//10)*(x//100%10\==1)*(x//10<4))
/*──────────────────────────────────────────────────────────────────────────────────────*/
genP: @.1=2; @.2=3; @.3=5; @.4=7; @.5=11; @.6=13; @.7=17; @.8=19; @.9=23; @.10=29; @.11=31
      !.=0; !.2=1; !.3=1; !.5=1; !.7=1; !.11=1; !.13=1; !.17=1; !.19=1; !.23=1; !.29=1
                           #= 11;  sq.#= @.# **2
                   do lim=100  until lim*lim>=hp /*only keep primes up to the sqrt(hp). */
                   end   /*lim*/                 /* [↑]  find limit for storing primes. */
       do [email protected].#+2  by 2  to hp;  parse var j '' -1 _;  if _==5  then iterate   /*÷ by 5?*/
       if j// 3==0  then iterate;   if j// 7==0  then iterate;   if j//11==0  then iterate
       if j//13==0  then iterate;   if j//17==0  then iterate;   if j//19==0  then iterate
       if j//23==0  then iterate;   if j//29==0  then iterate
          do k=11  while sq.k<=j                 /*divide by some generated odd primes. */
          if j//@.k==0  then iterate j           /*Is J divisible by  P?  Then not prime*/
          end   /*k*/                            /* [↓]  a prime  (J)  has been found.  */
       #= #+1;   if #<=lim  then @.#=j;   !.j=1  /*bump prime count; assign prime to @. */
                 sq.#= j*j                       /*calculate square of J for fast WHILE.*/


// main.rs
mod bit_array;
mod prime_sieve;

use prime_sieve::PrimeSieve;

// return number of decimal digits
fn count_digits(mut n: u32) -> u32 {
    let mut digits = 0;
    while n > 0 {
        n /= 10;
        digits += 1;
    }
    digits
}

// return the number with one digit replaced
fn change_digit(mut n: u32, mut index: u32, new_digit: u32) -> u32 {
    let mut p = 1;
    let mut changed = 0;
    while index > 0 {
        changed += p * (n % 10);
        p *= 10;
        n /= 10;
        index -= 1;
    }
    changed += (10 * (n / 10) + new_digit) * p;
    changed
}

fn unprimeable(sieve: &PrimeSieve, n: u32) -> bool {
    if sieve.is_prime(n as usize) {
        return false;
    }
    let d = count_digits(n);
    for i in 0..d {
        for j in 0..10 {
            let m = change_digit(n, i, j);
            if m != n && sieve.is_prime(m as usize) {
                return false;
            }
        }
    }
    true
}

fn main() {
    let mut count = 0;
    let mut n = 100;
    let mut lowest = vec![0; 10];
    let mut found = 0;
    let sieve = PrimeSieve::new(10000000);
    println!("First 35 unprimeable numbers:");
    while count < 600 || found < 10 {
        if unprimeable(&sieve, n) {
            if count < 35 {
                if count > 0 {
                    print!(", ");
                }
                print!("{}", n);
            }
            count += 1;
            if count == 600 {
                println!("\n600th unprimeable number: {}", n);
            }
            let last_digit = n as usize % 10;
            if lowest[last_digit] == 0 {
                lowest[last_digit] = n;
                found += 1;
            }
        }
        n += 1;
    }
    for i in 0..10 {
        println!("Least unprimeable number ending in {}: {}", i, lowest[i]);
    }
}


func is_unprimeable(n) {
    var t = 10*floor(n/10)
    for k in (t+1 .. t+9 `by` 2) {
        return false if k.is_prime
    }

    if (n.is_div(2) || n.is_div(5)) {
        return true if !is_prime(n%10)
        return true if (n % 10**n.ilog(10) > 9)
    }

    for k in (1 .. n.ilog(10)) {
        var u = 10**k
        var v = (n - (u * (floor(n/u) % 10)))
        0..9 -> any {|d| is_prime(v + d*u) } && return false
    }

    return true
}

with (35) {|n|
    say ("First #{n} unprimeables:\n", is_unprimeable.first(n).join(' '))
}

with (600) {|n|
    say ("\n#{n}th unprimeable: ", is_unprimeable.nth(n), "\n")
}

for d in (0..9) {
    say ("First unprimeable that ends with #{d}: ",
        1..Inf -> lazy.map {|k| k*10 + d }.grep(is_unprimeable).first)
}


import Foundation

class BitArray {
    var array: [UInt32]

    init(size: Int) {
        array = Array(repeating: 0, count: (size + 31)/32)
    }

    func get(index: Int) -> Bool {
        let bit = UInt32(1) << (index & 31)
        return (array[index >> 5] & bit) != 0
    }

    func set(index: Int, value: Bool) {
        let bit = UInt32(1) << (index & 31)
        if value {
            array[index >> 5] |= bit
        } else {
            array[index >> 5] &= ~bit
        }
    }
}

class PrimeSieve {
    let composite: BitArray

    init(size: Int) {
        composite = BitArray(size: size/2)
        var p = 3
        while p * p <= size {
            if !composite.get(index: p/2 - 1) {
                let inc = p * 2
                var q = p * p
                while q <= size {
                    composite.set(index: q/2 - 1, value: true)
                    q += inc
                }
            }
            p += 2
        }
    }

    func isPrime(number: Int) -> Bool {
        if number < 2 {
            return false
        }
        if (number & 1) == 0 {
            return number == 2
        }
        return !composite.get(index: number/2 - 1)
    }
}

// return number of decimal digits
func countDigits(number: Int) -> Int {
    var digits = 0
    var n = number
    while n > 0 {
        n /= 10
        digits += 1
    }
    return digits
}

// return the number with one digit replaced
func changeDigit(number: Int, index: Int, digit: Int) -> Int {
    var p = 1
    var changed = 0
    var n = number
    var i = index
    while i > 0 {
        changed += p * (n % 10)
        p *= 10
        n /= 10
        i -= 1
    }
    changed += (10 * (n / 10) + digit) * p
    return changed
}

func unprimeable(sieve: PrimeSieve, number: Int) -> Bool {
    if sieve.isPrime(number: number) {
        return false
    }
    for i in 0..<countDigits(number: number) {
        for j in 0..<10 {
            let n = changeDigit(number: number, index: i, digit: j)
            if n != number && sieve.isPrime(number: n) {
                return false
            }
        }
    }
    return true
}

var count = 0
var n = 100
var lowest = Array(repeating: 0, count: 10)
var found = 0
let sieve = PrimeSieve(size: 10000000)
print("First 35 unprimeable numbers:")
while count < 600 || found < 10 {
    if unprimeable(sieve: sieve, number: n) {
        if count < 35 {
            if count > 0 {
                print(", ", terminator: "")
            }
            print(n, terminator: "")
        }
        count += 1
        if count == 600 {
            print("\n600th unprimeable number: \(n)")
        }
        let lastDigit = n % 10
        if lowest[lastDigit] == 0 {
            lowest[lastDigit] = n
            found += 1
        }
    }
    n += 1
}
for i in 0..<10 {
    let number = NSNumber(value: lowest[i])
    let str = NumberFormatter.localizedString(from: number, number: .decimal)
    print("Least unprimeable number ending in \(i): \(str)")
}


import "/fmt" for Fmt
import "/math" for Int

System.print("The first 35 unprimeable numbers are:")
var count = 0                     // counts all unprimeable numbers
var firstNum = List.filled(10, 0) // stores the first unprimeable number ending with each digit
var i = 100
var countFirst = 0
while (countFirst < 10) {
    if (!Int.isPrime(i)) { // unprimeable number must be composite
        var s = "%(i)"
        var le = s.count
        var b = s.bytes.toList
        var outer = false
        for (j in 0...le) {
            for (k in 48..57) {
                if (s[j].bytes[0] != k) {
                    b[j] = k
                    var bb = b.reduce("") { |acc, byte| acc + String.fromByte(byte) }
                    var n = Num.fromString(bb)
                    if (Int.isPrime(n)) {
                        outer = true
                        break
                    }
                }
            }
            if (outer) break
            b[j] = s[j].bytes[0] // restore j'th digit to what it was originally
        }
        if (!outer) {
            var lastDigit = s[-1].bytes[0] - 48
            if (firstNum[lastDigit] == 0) {
                firstNum[lastDigit] = i
                countFirst = countFirst + 1
            }
            count = count + 1
            if (count <= 35) System.write("%(i) ")
            if (count == 35) System.write("\n\nThe 600th unprimeable number is: ")
            if (count == 600) System.print("%(Fmt.dc(0, i))\n")
        }
    }
    i = i + 1
}

System.print("The first unprimeable number that ends in:")
for (i in 0...10) System.print("  %(i) is:  %(Fmt.dc(9, firstNum[i]))")


func IsPrime(N);        \Return 'true' if N is prime
int  N, I;
[if N <= 2 then return N = 2;
if (N&1) = 0 then \even >2\ return false;
for I:= 3 to sqrt(N) do
    [if rem(N/I) = 0 then return false;
    I:= I+1;
    ];
return true;
];

func Unprimeable(N);    \Return 'true' if N is unprimeable
int  N, I, J, Len, D, SD;
char Num(10);
[I:= 0;                         \take N apart
repeat  N:= N/10;
        Num(I):= rem(0);
        I:= I+1;
until   N = 0;
Len:= I;                        \number of digits in N (length)
for J:= 0 to Len-1 do
    [SD:= Num(J);               \save digit
    for D:= 0 to 9 do           \replace with all digits
        [Num(J):= D;
        N:= 0;                  \rebuild N
        for I:= Len-1 downto 0 do
            N:= N*10 + Num(I);
        if IsPrime(N) then return false;
        ];
    Num(J):= SD;                \restore saved digit
    ];
return true;
];

int C, N, D;
[Text(0, "First 35 unprimeables:^m^j");
C:= 0;
N:= 100;
loop    [if Unprimeable(N) then
            [C:= C+1;
            if C <= 35 then
                [IntOut(0, N);  ChOut(0, ^ )];
            if C = 600 then quit;
            ];
        N:= N+1;
        ];
Text(0, "^m^j600th unprimeable: ");
IntOut(0, N);  CrLf(0);
for D:= 0 to 9 do
        [IntOut(0, D);  Text(0, ": ");
        N:= 100 + D;
        loop    [if Unprimeable(N) then
                    [IntOut(0, N);  CrLf(0);
                    quit;
                    ];
                N:= N+10;
                ];
        ];
]


var [const] BI=Import("zklBigNum");  // libGMP

fcn isUnprimeable(n){  //--> n (!0) or Void, a filter
   bn,t := BI(0),n/10*10;
   foreach k in ([t+1..t+9,2]){ if(bn.set(k).probablyPrime()) return(Void.Skip) }
   if(n==n/2*2 or n==n/5*5){
      if(not bn.set(n%10).probablyPrime())          return(n);
      if( (n % (10).pow(n.toFloat().log10()) ) > 9) return(n);
   }
   foreach k in ([1 .. n.toFloat().log10()]){
      u,v := (10).pow(k), (n - (u * ((n/u) % 10)));
      foreach d in (10){ if(bn.set(v + d*u).probablyPrime()) return(Void.Skip); }
   }
   n
}
fcn isUnprimeableW{ [100..].tweak(isUnprimeable) }	// --> iterator


package main

import (
    "fmt"
    "math/big"
    "time"
)

var maxChar = 128

type Node struct {
    children    []*Node
    suffixLink  *Node
    start       int
    end         *int
    suffixIndex int
}

var (
    text                 string
    root                 *Node
    lastNewNode          *Node
    activeNode           *Node
    activeEdge           = -1
    activeLength         = 0
    remainingSuffixCount = 0
    leafEnd              = -1
    rootEnd              *int
    splitEnd             *int
    size                 = -1
)

func newNode(start int, end *int) *Node {
    node := new(Node)
    node.children = make([]*Node, maxChar)
    node.suffixLink = root
    node.start = start
    node.end = end
    node.suffixIndex = -1
    return node
}

func edgeLength(n *Node) int {
    if n == root {
        return 0
    }
    return *(n.end) - n.start + 1
}

func walkDown(currNode *Node) bool {
    if activeLength >= edgeLength(currNode) {
        activeEdge += edgeLength(currNode)
        activeLength -= edgeLength(currNode)
        activeNode = currNode
        return true
    }
    return false
}

func extendSuffixTree(pos int) {
    leafEnd = pos
    remainingSuffixCount++
    lastNewNode = nil
    for remainingSuffixCount > 0 {
        if activeLength == 0 {
            activeEdge = pos
        }
        if activeNode.children[text[activeEdge]] == nil {
            activeNode.children[text[activeEdge]] = newNode(pos, &leafEnd)
            if lastNewNode != nil {
                lastNewNode.suffixLink = activeNode
                lastNewNode = nil
            }
        } else {
            next := activeNode.children[text[activeEdge]]
            if walkDown(next) {
                continue
            }
            if text[next.start+activeLength] == text[pos] {
                if lastNewNode != nil && activeNode != root {
                    lastNewNode.suffixLink = activeNode
                    lastNewNode = nil
                }
                activeLength++
                break
            }
            temp := next.start + activeLength - 1
            splitEnd = &temp
            split := newNode(next.start, splitEnd)
            activeNode.children[text[activeEdge]] = split
            split.children[text[pos]] = newNode(pos, &leafEnd)
            next.start += activeLength
            split.children[text[next.start]] = next
            if lastNewNode != nil {
                lastNewNode.suffixLink = split
            }
            lastNewNode = split
        }
        remainingSuffixCount--
        if activeNode == root && activeLength > 0 {
            activeLength--
            activeEdge = pos - remainingSuffixCount + 1
        } else if activeNode != root {
            activeNode = activeNode.suffixLink
        }
    }
}

func setSuffixIndexByDFS(n *Node, labelHeight int) {
    if n == nil {
        return
    }
    if n.start != -1 {
        // Uncomment line below to print suffix tree
        // fmt.Print(text[n.start: *(n.end) +1])
    }
    leaf := 1
    for i := 0; i < maxChar; i++ {
        if n.children[i] != nil {
            // Uncomment the 3 lines below to print suffix index
            //if leaf == 1 && n.start != -1 {
            //    fmt.Printf(" [%d]\n", n.suffixIndex)
            //}
            leaf = 0
            setSuffixIndexByDFS(n.children[i], labelHeight+edgeLength(n.children[i]))
        }
    }
    if leaf == 1 {
        n.suffixIndex = size - labelHeight
        // Uncomment line below to print suffix index
        //fmt.Printf(" [%d]\n", n.suffixIndex)
    }
}

func buildSuffixTree() {
    size = len(text)
    temp := -1
    rootEnd = &temp
    root = newNode(-1, rootEnd)
    activeNode = root
    for i := 0; i < size; i++ {
        extendSuffixTree(i)
    }
    labelHeight := 0
    setSuffixIndexByDFS(root, labelHeight)
}

func doTraversal(n *Node, labelHeight int, maxHeight, substringStartIndex *int) {
    if n == nil {
        return
    }
    if n.suffixIndex == -1 {
        for i := 0; i < maxChar; i++ {
            if n.children[i] != nil {
                doTraversal(n.children[i], labelHeight+edgeLength(n.children[i]),
                    maxHeight, substringStartIndex)
            }
        }
    } else if n.suffixIndex > -1 && (*maxHeight < labelHeight-edgeLength(n)) {
        *maxHeight = labelHeight - edgeLength(n)
        *substringStartIndex = n.suffixIndex
    }
}

func getLongestRepeatedSubstring(s string) {
    maxHeight := 0
    substringStartIndex := 0
    doTraversal(root, 0, &maxHeight, &substringStartIndex)
    // Uncomment line below to print maxHeight and substringStartIndex
    // fmt.Printf("maxHeight %d, substringStartIndex %d\n", maxHeight, substringStartIndex)
    if s == "" {
        fmt.Printf("  %s is: ", text)
    } else {
        fmt.Printf("  %s is: ", s)
    }
    k := 0
    for ; k < maxHeight; k++ {
        fmt.Printf("%c", text[k+substringStartIndex])
    }
    if k == 0 {
        fmt.Print("No repeated substring")
    }
    fmt.Println()
}

func calculatePi() *big.Float {
    one := big.NewFloat(1)
    two := big.NewFloat(2)
    four := big.NewFloat(4)
    prec := uint(325 * 1024) // enough to calculate Pi to 100,182 decimal digits

    a := big.NewFloat(1).SetPrec(prec)
    g := new(big.Float).SetPrec(prec)

    // temporary variables
    t := new(big.Float).SetPrec(prec)
    u := new(big.Float).SetPrec(prec)

    g.Quo(a, t.Sqrt(two))
    sum := new(big.Float)
    pow := big.NewFloat(2)

    for a.Cmp(g) != 0 {
        t.Add(a, g)
        t.Quo(t, two)
        g.Sqrt(u.Mul(a, g))
        a.Set(t)
        pow.Mul(pow, two)
        t.Sub(t.Mul(a, a), u.Mul(g, g))
        sum.Add(sum, t.Mul(t, pow))
    }

    t.Mul(a, a)
    t.Mul(t, four)
    pi := t.Quo(t, u.Sub(one, sum))
    return pi
}

func main() {
    tests := []string{
        "GEEKSFORGEEKS$",
        "AAAAAAAAAA$",
        "ABCDEFG$",
        "ABABABA$",
        "ATCGATCGA$",
        "banana$",
        "abcpqrabpqpq$",
        "pqrpqpqabab$",
    }
    fmt.Println("Longest Repeated Substring in:\n")
    for _, test := range tests {
        text = test
        buildSuffixTree()
        getLongestRepeatedSubstring("")
    }
    fmt.Println()

    pi := calculatePi()
    piStr := fmt.Sprintf("%v", pi)
    piStr = piStr[2:] // remove initial 3.
    numbers := []int{1e3, 1e4, 1e5}
    maxChar = 58
    for _, number := range numbers {
        start := time.Now()
        text = piStr[0:number] + "$"
        buildSuffixTree()
        getLongestRepeatedSubstring(fmt.Sprintf("first %d d.p. of Pi", number))
        elapsed := time.Now().Sub(start)
        fmt.Printf("  (this took %s)\n\n", elapsed)
    }
}


const oo = typemax(Int)

"""The suffix-tree's node."""
mutable struct Node
    children::Dict{Char, Int}
    start::Int
    ending::Int
    suffixlink::Int
    suffixindex::Int
end

Node() = Node(Dict(), 0, oo, 0, -1)
Node(start, ending) = Node(Dict(), start, ending, 0, -1)

""" Ukkonen Suffix-Tree """
mutable struct SuffixTree
    nodes::Vector{Node}
    text::Vector{Char}
    root::Int
    position::Int
    currentnode::Int
    needsuffixlink::Int
    remainder::Int
    activenode::Int
    activelength::Int
    activeedge::Int
end

edgelength(st, n::Node) = min(n.ending, st.position + 1) - n.start

function newnode(st, start, ending)
    st.currentnode += 1
    st.nodes[st.currentnode] = Node(start, ending)
    return st.currentnode
end

function SuffixTree(str::String)
    nodes = [Node() for _ in 1:length(str) * 2]
    st = SuffixTree(nodes, [c for c in str], 1, 0, 0, 0, 0, 1, 1, 1)
    st.root = newnode(st, 0, 0)
    st.activenode = st.root
    for i in 1:length(st.text)
        extendsuffixtree(st, i)
    end
    setsuffixindexbyDFS(st, st.nodes[st.root], 0)
    return st
end

function addsuffixlink(st, nodenum::Int)
    if st.needsuffixlink > 0
        st.nodes[st.needsuffixlink].suffixlink = nodenum
    end
    st.needsuffixlink = nodenum
end

activeedge(st) = st.text[st.activeedge]

function walkdown!(st, currnode::Int)
    len = edgelength(st, st.nodes[currnode])
    st.activelength < len && return false
    st.activeedge += len
    st.activelength -= len
    st.activenode = currnode
    return true
end

function extendsuffixtree(st, pos)
    st.position = pos
    st.needsuffixlink = 0
    st.remainder += 1
    while st.remainder > 0
        st.activelength == 0 && (st.activeedge = st.position)
        if !haskey(st.nodes[st.activenode].children, activeedge(st))
            nodenum = newnode(st, st.position, oo)
            st.nodes[st.activenode].children[activeedge(st)] = nodenum
            addsuffixlink(st, st.activenode)
        else
            next = st.nodes[st.activenode].children[activeedge(st)]
            walkdown!(st, next) && continue
            if st.text[st.nodes[next].start + st.activelength] == st.text[pos]
                addsuffixlink(st, st.activenode)
                st.activelength += 1
                break
            end
            splt = newnode(st, st.nodes[next].start, st.nodes[next].start + st.activelength)
            st.nodes[st.activenode].children[activeedge(st)] = splt
            nodenum = newnode(st, st.position, oo)
            st.nodes[splt].children[st.text[pos]] = nodenum
            st.nodes[next].start += st.activelength
            st.nodes[splt].children[st.text[st.nodes[next].start]] = next
            addsuffixlink(st, splt)
        end
        st.remainder -= 1
        if st.activenode == st.root && st.activelength > 0
            st.activelength -= 1
            st.activeedge = st.position - st.remainder + 1
        elseif st.activenode != st.root
            st.activenode = st.nodes[st.activenode].suffixlink
        end
    end
end

function setsuffixindexbyDFS(st, node, labelheight, verbose=false)
    verbose && node.start > 0 && print(st.text[node.start:min(node.ending, length(st.text))])
    isleaf = true
    for child in map(v -> st.nodes[v], collect(values(node.children)))
        verbose && isleaf && node.start > 0 && println(" [", node.suffixindex, "]")
        isleaf = false
        setsuffixindexbyDFS(st, child, labelheight + edgelength(st, child))
    end
    if isleaf
        idx = length(st.text) - labelheight
        node.suffixindex = idx
        verbose && println(" [$idx]")
    end
end

function dotraversal(st)
    maxheight, substringstartindices = 0, [0]
    function traversal(node::Node, labelheight)
        if node.suffixindex == -1
            for child in map(v -> st.nodes[v], collect(values(node.children)))
                traversal(child, labelheight + edgelength(st, child))
            end
        elseif maxheight < labelheight - edgelength(st, node)
            maxheight = labelheight - edgelength(st, node)
            substringstartindices = [node.suffixindex + 1]
        elseif maxheight == labelheight - edgelength(st, node)
            push!(substringstartindices, node.suffixindex + 1)
        end
    end
    traversal(st.nodes[st.root], 0)
    return maxheight, substringstartindices
end

function getlongestrepeatedsubstring(st::SuffixTree, label="", printresult=true)
    len, starts = dotraversal(st)
    substring = len == 0 ? "" :
        join(unique(map(x -> String(st.text[x:x+len-1]), starts)), " (or) ")
    if printresult
        print("  ", label == "" ? String(st.text) : label, ": ")
        println(len == 0 ? "No repeated substring." : substring)
    end
    return substring
end

function testsuffixtree()
    tests = [
        "CAAAABAAAABD\$",
        "GEEKSFORGEEKS\$",
        "AAAAAAAAAA\$",
        "ABCDEFG\$",
        "ABABABA\$",
        "ATCGATCGA\$",
        "banana\$",
        "abcpqrabpqpq\$",
        "pqrpqpqabab\$",
    ]
    println("Longest Repeated Substring in:\n")
    for test in tests
        st = SuffixTree(test)
        getlongestrepeatedsubstring(st)
    end
    println()
    sπ = ""
    setprecision(4000000) do
        sπ = string(BigFloat(π))[3:end]
    end
    for number in [1000, 10000, 100000, 1000000]
        text = sπ[1:number] * "\$"
        @time begin
            st = SuffixTree(text)
            getlongestrepeatedsubstring(st, "first $number d.p. of π")
        end
    end
end

testsuffixtree()


-- demo/rosetta/Ukkonens_Suffix_Tree.exw
with javascript_semantics
integer maxChar = 'z'

sequence children = {},
         suffixLinks = {},
         starts = {},
         endIndices = {},
         suffixIndices = {},
         leaves = {}

function new_leaf(integer v=0)
    leaves = append(leaves,v)
    return length(leaves)
end function

string text
integer splitEndIdx,
        rootEndIdx,
        leafEndIdx = new_leaf(),
        root = NULL,
        lastNewNode,
        activeNode,
        activeEdge = -1,
        activeLength = 0,
        remainingSuffixCount = 0,
        size = -1

function newNode(integer start, finishIdx, bool bKids=false)
    children = append(children,iff(bKids?repeat(NULL,maxChar):0))
    suffixLinks = append(suffixLinks,root)
    starts = append(starts,start)
    endIndices = append(endIndices,finishIdx)
    suffixIndices = append(suffixIndices,-1)
    return length(children)
end function

function edgeLength(integer n)
    return iff(n==root?0:leaves[endIndices[n]] - starts[n] + 1)
end function

function walkDown(integer currNode)
    integer l = edgeLength(currNode)
    if activeLength >= l then
        activeEdge += l
        activeLength -= l
        activeNode = currNode
        return true
    end if
    return false
end function

procedure extendSuffixTree(integer pos)
    leaves[leafEndIdx] = pos
    remainingSuffixCount += 1
    lastNewNode = NULL
    while remainingSuffixCount > 0 do
        if activeLength == 0 then
            activeEdge = pos
        end if
        integer ta = text[activeEdge]
        bool ca0 = children[activeNode]=0
        integer next = iff(ca0?NULL:children[activeNode][ta])
        if next==null then
            if ca0 then
                children[activeNode] = repeat(NULL,maxChar)
            end if
            children[activeNode][ta] = newNode(pos, leafEndIdx)
            if lastNewNode!=NULL then
                suffixLinks[lastNewNode] = activeNode
                lastNewNode = NULL
            end if
        else
            if walkDown(next) then
                continue
            end if
            integer tp = text[pos]
            if text[starts[next]+activeLength] == tp then
                if lastNewNode!=NULL and activeNode!=root then
                    suffixLinks[lastNewNode] = activeNode
                    lastNewNode = NULL
                end if
                activeLength += 1
                exit
            end if
            integer temp = starts[next] + activeLength - 1
            splitEndIdx = new_leaf(temp)
            integer splitnode = newNode(starts[next], splitEndIdx, true)
            ta = text[activeEdge]
            children[activeNode][ta] = splitnode
            children[splitnode][tp] = newNode(pos, leafEndIdx)
            starts[next] += activeLength
            children[splitnode][text[starts[next]]] = next
            if lastNewNode!=NULL then
                suffixLinks[lastNewNode] = splitnode
            end if
            lastNewNode = splitnode
        end if
        remainingSuffixCount -= 1
        if activeNode==root and activeLength>0 then
            activeLength -= 1
            activeEdge = pos - remainingSuffixCount + 1
        elsif activeNode!=root then
            activeNode = suffixLinks[activeNode]
        end if
    end while
end procedure

procedure setSuffixIndexByDFS(integer n, labelHeight)
    if n!=NULL then
        if children[n]=0 then
            suffixIndices[n] = size - labelHeight
        else
            bool leaf = true
            for i=1 to maxChar do
                integer nci = children[n][i]
                if nci!=NULL then
                    leaf = false
                    setSuffixIndexByDFS(nci, labelHeight+edgeLength(nci))
                end if
            end for
            if leaf then ?9/0 end if -- (sanity check)
        end if
    end if
end procedure

procedure buildSuffixTree()
    size = length(text)
    rootEndIdx = new_leaf(-1)
    root = newNode(-1, rootEndIdx)
    activeNode = root
    for i=1 to size do
        extendSuffixTree(i)
    end for
    integer labelHeight = 0
    setSuffixIndexByDFS(root, labelHeight)
end procedure

procedure doTraversal(integer n, labelHeight, maxHeightIdx, substringStartIndex)
    if n!=NULL then
        integer nsi = suffixIndices[n], newHeight
        if nsi == -1 then
            for i=1 to maxChar do
                integer nci = children[n][i]
                if nci!=NULL then
                    newHeight = labelHeight+edgeLength(nci)
                    doTraversal(nci, newHeight, maxHeightIdx, substringStartIndex)
                end if
            end for
        elsif nsi > -1 then
            newHeight = labelHeight-edgeLength(n)
            if leaves[maxHeightIdx]<newHeight then
                leaves[maxHeightIdx] = newHeight
                leaves[substringStartIndex] = nsi
            end if
        end if
    end if
end procedure

function getLongestRepeatedSubstring()
    integer maxHeightIdx = new_leaf(),
            substringStartIndex = new_leaf()
    doTraversal(root, 0, maxHeightIdx, substringStartIndex)
    integer maxHeight = leaves[maxHeightIdx],
            start = leaves[substringStartIndex]
    string t = iff(maxHeight=0?"No repeated substring"
                              :text[start+1..start+maxHeight])
    return t
end function

constant tests = {"CAAAABAAAABD$",
                  "GEEKSFORGEEKS$",
                  "AAAAAAAAAA$",
                  "ABCDEFG$",
                  "ABABABA$",
                  "ATCGATCGA$",
                  "banana$",
                  "abcpqrabpqpq$",
                  "pqrpqpqabab$"}
printf(1,"Longest Repeated Substring in:\n")
for i=1 to length(tests) do
    text = tests[i]
    buildSuffixTree()
    printf(1,"  %s is: %s\n", {text,getLongestRepeatedSubstring()})
end for
printf(1,"\n")

include mpfr.e
string piStr
if platform()=JS then
    mpfr pi = mpfr_init(0,-1001) -- (set precision to 1,000 dp, plus the "3.")
    mpfr_const_pi(pi)
    piStr = mpfr_get_fixed(pi,1000) -- (all we can really manage under pwa/p2js)
else
    -- gmp crashes when I try 100,000 dp, so just get from file
    piStr = get_text(`E:\downloads\misc\arm\pi-10million.txt`)
end if
piStr = piStr[3..$] -- discard leading "3."
maxChar = '9'
for i=3 to iff(platform()=JS?3:6) do
    atom t0 = time()
    integer n = power(10,i)
    text = piStr[1..n] & "$"
    buildSuffixTree()
    string r = getLongestRepeatedSubstring(),
           e = elapsed(time()-t0)
    printf(1,"  first %,d d.p. of Pi is: %s (%s)\n", {n,r,e})
end for


import "/big" for BigRat
import "/dynamic" for Struct
import "/trait" for ByRef
import "io" for File

var maxChar = 128

var Node = Struct.create("Node", ["children", "suffixLink", "start", "pEnd", "suffixIndex"])

var text                 = ""
var root                 = null
var lastNewNode          = null
var activeNode           = null
var activeEdge           = -1
var activeLength         = 0
var remainingSuffixCount = 0
var pLeafEnd             = ByRef.new(-1)
var pRootEnd             = null
var pSplitEnd            = null
var size                 = -1

var newNode = Fn.new { |start, pEnd|
    var children = List.filled(maxChar, null)
    var suffixLink = root
    var suffixIndex = -1
    return Node.new(children, suffixLink, start, pEnd, suffixIndex)
}

var edgeLength = Fn.new { |n|
    if (n == root) return 0
    return n.pEnd.value - n.start + 1
}

var walkDown = Fn.new { |currNode|
    var el = edgeLength.call(currNode)
    if (activeLength >= el) {
        activeEdge = activeEdge + el
        activeLength = activeLength - el
        activeNode = currNode
        return true
    }
    return false
}

var extendSuffixTree = Fn.new { |pos|
    pLeafEnd.value = pos
    remainingSuffixCount = remainingSuffixCount + 1
    lastNewNode = null
    while (remainingSuffixCount > 0) {
        if (activeLength == 0) activeEdge = pos
        if (!activeNode.children[text[activeEdge].bytes[0]]) {
            activeNode.children[text[activeEdge].bytes[0]] = newNode.call(pos, pLeafEnd)
            if (lastNewNode) {
                lastNewNode.suffixLink = activeNode
                lastNewNode = null
            }
        } else {
            var next = activeNode.children[text[activeEdge].bytes[0]]
            if (walkDown.call(next)) continue
            if (text[next.start + activeLength] == text[pos]) {
                if (lastNewNode && activeNode != root) {
                    lastNewNode.suffixLink = activeNode
                    lastNewNode = null
                }
                activeLength = activeLength + 1
                break
            }
            var temp = next.start + activeLength - 1
            pSplitEnd = ByRef.new(temp)
            var split = newNode.call(next.start, pSplitEnd)
            activeNode.children[text[activeEdge].bytes[0]] = split
            split.children[text[pos].bytes[0]] = newNode.call(pos, pLeafEnd)
            next.start = next.start + activeLength
            split.children[text[next.start].bytes[0]] = next
            if (lastNewNode) lastNewNode.suffixLink = split
            lastNewNode = split
        }
        remainingSuffixCount = remainingSuffixCount - 1
        if (activeNode == root && activeLength > 0) {
            activeLength = activeLength - 1
            activeEdge = pos - remainingSuffixCount + 1
        } else if (activeNode != root) {
            activeNode = activeNode.suffixLink
        }
    }
}

var setSuffixIndexByDFS  // recursive
setSuffixIndexByDFS = Fn.new { |n, labelHeight|
    if (!n) return
    if (n.start != -1) {
        // Uncomment line below to print suffix tree
        // System.write(text[n.start..n.pEnd.value])
    }
    var leaf = 1
    for (i in 0...maxChar) {
        if (n.children[i]) {
            // Uncomment the 3 lines below to print suffix index
            // if (leaf == 1 && n.start != -1) {
            //    System.print(" [%(n.suffixIndex)]")
            // }
            leaf = 0
            setSuffixIndexByDFS.call(n.children[i], labelHeight + edgeLength.call(n.children[i]))
        }
    }
    if (leaf == 1) {
        n.suffixIndex = size - labelHeight
        // Uncomment line below to print suffix index
        // System.print(" [%(n.suffixIndex)]")
    }
}

var buildSuffixTree = Fn.new {
    size = text.count
    var temp = -1
    pRootEnd = ByRef.new(temp)
    root = newNode.call(-1, pRootEnd)
    activeNode = root
    for (i in 0...size) extendSuffixTree.call(i)
    var labelHeight = 0
    setSuffixIndexByDFS.call(root, labelHeight)
}

var doTraversal  // recursive
doTraversal = Fn.new { |n, labelHeight, pMaxHeight, pSubstringStartIndex|
    if (!n) return
    if (n.suffixIndex == -1) {
        for (i in 0...maxChar) {
            if (n.children[i]) {
                doTraversal.call(n.children[i], labelHeight + edgeLength.call(n.children[i]),
                    pMaxHeight, pSubstringStartIndex)
             }
        }
    } else if (n.suffixIndex > -1 && (pMaxHeight.value < labelHeight - edgeLength.call(n))) {
        pMaxHeight.value = labelHeight - edgeLength.call(n)
        pSubstringStartIndex.value = n.suffixIndex
    }
}

var getLongestRepeatedSubstring = Fn.new { |s|
    var maxHeight = 0
    var substringStartIndex = 0
    var pMaxHeight = ByRef.new(maxHeight)
    var pSubstringStartIndex = ByRef.new(substringStartIndex)
    doTraversal.call(root, 0, pMaxHeight, pSubstringStartIndex)
    maxHeight = pMaxHeight.value
    substringStartIndex = pSubstringStartIndex.value
    // Uncomment line below to print maxHeight and substringStartIndex
    // System.print("maxHeight %(maxHeight), substringStartIndex %(substringStartIndex)")
    if (s == "") {
        System.write("  %(text) is: ")
    } else {
        System.write("  %(s) is: ")
    }
    var k = 0
    while (k < maxHeight) {
        System.write(text[k + substringStartIndex])
        k = k + 1
    }
    if (k == 0) {
        System.write("No repeated substring")
    }
    System.print()
}

var tests = [
    "GEEKSFORGEEKS$",
    "AAAAAAAAAA$",
    "ABCDEFG$",
    "ABABABA$",
    "ATCGATCGA$",
    "banana$",
    "abcpqrabpqpq$",
    "pqrpqpqabab$",
]
System.print("Longest Repeated Substring in:\n")
for (test in tests) {
    text = test
    buildSuffixTree.call()
    getLongestRepeatedSubstring.call("")
}
System.print()

// load pi to 100,182 digits
var piStr = File.read("pi_100000.txt")
piStr = piStr[2..-1] // remove initial 3.
var numbers = [1e3, 1e4, 1e5]
maxChar = 58
for (number in numbers) {
    var start = System.clock
    text = piStr[0...number] + "$"
    buildSuffixTree.call()
    getLongestRepeatedSubstring.call("first %(number) d.p. of Pi")
    var elapsed = (System.clock - start) * 1000
    System.print("  (this took %(elapsed) ms)\n")
}


UInt32 seed = 0
F nonrandom(n)
   :seed = 1664525 * :seed + 1013904223
   R Int(:seed >> 16) % n

V cylinder = [0B] * 6

F rshift()
   V t = :cylinder[5]
   L(i) (4..0).step(-1)
      :cylinder[i + 1] = :cylinder[i]
   :cylinder[0] = t

F unload()
   L(i) 6
      :cylinder[i] = 0B

F load()
   L :cylinder[0]
      rshift()
   :cylinder[0] = 1B
   rshift()

F spin()
   L 1..nonrandom(6)
      rshift()

F fire()
   V shot = :cylinder[0]
   rshift()
   R shot

F method(s)
   unload()
   L(c) s
      S c
         ‘L’
            load()
         ‘S’
            spin()
         ‘F’
            I fire()
               R 1
   R 0

F mstring(s)
   [String] l
   L(c) s
      S c
         ‘L’
            l [+]= ‘load’
         ‘S’
            l [+]= ‘spin’
         ‘F’
            l [+]= ‘fire’
   R l.join(‘, ’)

V tests = 100000
L(m) [‘LSLSFSF’, ‘LSLSFF’, ‘LLSFSF’, ‘LLSFF’]
   V sum = 0
   L 0 .< tests
      sum += method(m)
   V pc = Float(sum) * 100 / tests
   print(‘#<40 produces #2.3% deaths.’.format(mstring(m), pc))


var foo; // untyped
var bar:*; // explicitly untyped

trace(foo + ", " + bar); // outputs "undefined, undefined"

if (foo == undefined)
    trace("foo is undefined"); // outputs "foo is undefined"


methods =
(
load, spin, load, spin, fire, spin, fire
load, spin, load, spin, fire, fire
load, load, spin, fire, spin, fire
load, load, spin, fire, fire
)

for i, method in StrSplit(methods, "`n", "`r"){
	death := 0
	main:
	loop 100000	{
		sixGun := []
		for i, v in StrSplit(StrReplace(method," "), ",")
			if %v%()
				continue, main
	}
	output .= Format("{1:0.3f}", death/1000) "% Deaths for : """ method """`n"
}
MsgBox % output
return

load(){
	global
	if !sixGun.Count()
		sixGun := [0,1,0,0,0,0]
	else
		if sixGun[2]
			sixGun[1] := 1
	sixGun[2] := 1
}
fire(){
	global
	if bullet := sixGun[1]
		death++
	temp := sixGun[6]
	loop, 5
		sixGun[7-A_Index] := sixGun[6-A_Index]
	sixGun[1] := temp
	return bullet
}
spin(){
	global
	Random, rnd, 1, 12
	loop, % rnd	{
		temp := sixGun[6]
		loop, 5
			sixGun[7-A_Index] := sixGun[6-A_Index]
		sixGun[1] := temp
	}
}


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

static int nextInt(int size) {
    return rand() % size;
}

static bool cylinder[6];

static void rshift() {
    bool t = cylinder[5];
    int i;
    for (i = 4; i >= 0; i--) {
        cylinder[i + 1] = cylinder[i];
    }
    cylinder[0] = t;
}

static void unload() {
    int i;
    for (i = 0; i < 6; i++) {
        cylinder[i] = false;
    }
}

static void load() {
    while (cylinder[0]) {
        rshift();
    }
    cylinder[0] = true;
    rshift();
}

static void spin() {
    int lim = nextInt(6) + 1;
    int i;
    for (i = 1; i < lim; i++) {
        rshift();
    }
}

static bool fire() {
    bool shot = cylinder[0];
    rshift();
    return shot;
}

static int method(const char *s) {
    unload();
    for (; *s != '\0'; s++) {
        switch (*s) {
        case 'L':
            load();
            break;
        case 'S':
            spin();
            break;
        case 'F':
            if (fire()) {
                return 1;
            }
            break;
        }
    }
    return 0;
}

static void append(char *out, const char *txt) {
    if (*out != '\0') {
        strcat(out, ", ");
    }
    strcat(out, txt);
}

static void mstring(const char *s, char *out) {
    for (; *s != '\0'; s++) {
        switch (*s) {
        case 'L':
            append(out, "load");
            break;
        case 'S':
            append(out, "spin");
            break;
        case 'F':
            append(out, "fire");
            break;
        }
    }
}

static void test(char *src) {
    char buffer[41] = "";
    const int tests = 100000;
    int sum = 0;
    int t;
    double pc;

    for (t = 0; t < tests; t++) {
        sum += method(src);
    }

    mstring(src, buffer);
    pc = 100.0 * sum / tests;

    printf("%-40s produces %6.3f%% deaths.\n", buffer, pc);
}

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

    test("LSLSFSF");
    test("LSLSFF");
    test("LLSFSF");
    test("LLSFF");

    return 0;
}


pragma Initialize_Scalars;
with Ada.Text_IO;  use Ada.Text_IO;

procedure Invalid_Value is
   type Color is (Red, Green, Blue);
   X : Float;
   Y : Color;
begin
   if not X'Valid then
      Put_Line ("X is not valid");
   end if;
   X := 1.0;
   if X'Valid then
      Put_Line ("X is" & Float'Image (X));
   end if;
   if not Y'Valid then
      Put_Line ("Y is not valid");
   end if;
   Y := Green;
   if Y'Valid then
      Put_Line ("Y is " & Color'Image (Y));
   end if;
end Invalid_Value;


MODE R = REF BOOL;
R r := NIL;

MODE U = UNION(BOOL, VOID);
U u := EMPTY;

IF r IS R(NIL) THEN
  print(("r IS NIL", new line))
ELSE
  print(("r ISNT NIL", new line))
FI;

CASE u IN
  (VOID):print(("u is EMPTY", new line))
  OUT    print(("u isnt EMPTY", new line))
ESAC


#include <array>
#include <iomanip>
#include <iostream>
#include <random>
#include <sstream>

class Roulette {
private:
    std::array<bool, 6> cylinder;

    std::mt19937 gen;
    std::uniform_int_distribution<> distrib;

    int next_int() {
        return distrib(gen);
    }

    void rshift() {
        std::rotate(cylinder.begin(), cylinder.begin() + 1, cylinder.end());
    }

    void unload() {
        std::fill(cylinder.begin(), cylinder.end(), false);
    }

    void load() {
        while (cylinder[0]) {
            rshift();
        }
        cylinder[0] = true;
        rshift();
    }

    void spin() {
        int lim = next_int();
        for (int i = 1; i < lim; i++) {
            rshift();
        }
    }

    bool fire() {
        auto shot = cylinder[0];
        rshift();
        return shot;
    }

public:
    Roulette() {
        std::random_device rd;
        gen = std::mt19937(rd());
        distrib = std::uniform_int_distribution<>(1, 6);

        unload();
    }

    int method(const std::string &s) {
        unload();
        for (auto c : s) {
            switch (c) {
            case 'L':
                load();
                break;
            case 'S':
                spin();
                break;
            case 'F':
                if (fire()) {
                    return 1;
                }
                break;
            }
        }
        return 0;
    }
};

std::string mstring(const std::string &s) {
    std::stringstream ss;
    bool first = true;

    auto append = [&ss, &first](const std::string s) {
        if (first) {
            first = false;
        } else {
            ss << ", ";
        }
        ss << s;
    };

    for (auto c : s) {
        switch (c) {
        case 'L':
            append("load");
            break;
        case 'S':
            append("spin");
            break;
        case 'F':
            append("fire");
            break;
        }
    }

    return ss.str();
}

void test(const std::string &src) {
    const int tests = 100000;
    int sum = 0;

    Roulette r;
    for (int t = 0; t < tests; t++) {
        sum += r.method(src);
    }

    double pc = 100.0 * sum / tests;

    std::cout << std::left << std::setw(40) << mstring(src) << " produces " << pc << "% deaths.\n";
}

int main() {
    test("LSLSFSF");
    test("LSLSFF");
    test("LLSFSF");
    test("LLSFF");

    return 0;
}


      ok% = TRUE
      ON ERROR LOCAL IF ERR<>26 REPORT : END ELSE ok% = FALSE
      IF ok% THEN
        PRINT variable$
      ELSE
        PRINT "Not defined"
      ENDIF
      RESTORE ERROR


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

int main()
{
  int junk, *junkp;

  /* Print an unitialized variable! */
  printf("junk: %d\n", junk);

  /* Follow a pointer to unitialized memory! */
  junkp = malloc(sizeof *junkp);
  if (junkp)
    printf("*junkp: %d\n", *junkp);
  return 0;
}


#include <iostream>

int main()
{
    int undefined;
    if (undefined == 42)
    {
        std::cout << "42";
    }

    if (undefined != 42)
    {
        std::cout << "not 42";
    }
}


len cyl[] 6
func rshift . .
  h = cyl[5]
  for i = 5 downto 1
    cyl[i] = cyl[i - 1]
  .
  cyl[0] = h
.
func unload . .
  for i range 6
    cyl[i] = 0
  .
.
func load . .
  while cyl[0] = 1
    call rshift
  .
  cyl[0] = 1
  call rshift
.
func spin . .
  lim = random 6 + 1
  for i = 1 to lim - 1
    call rshift
  .
.
func fire . shot .
  shot = cyl[0]
  call rshift
.
func method m[] . shot .
  call unload
  shot = 0
  for m in m[]
    if m = 0
      call load
    elif m = 1
      call spin
    elif m = 2
      call fire shot
      if shot = 1
        break 1
      .
    .
  .
.
method$[] = [ "load" "spin" "fire" ]
func test m[] . .
  n = 100000
  for i range n
    call method m[] shot
    sum += shot
  .
  for m in m[]
    write method$[m] & " "
  .
  print "-> " & 100 * sum / n & "% deaths"
.
call test [ 0 1 0 1 2 1 2 ]
call test [ 0 1 0 1 2 2 ]
call test [ 0 0 1 2 1 2 ]
call test [ 0 0 1 2 2 ]


USING: accessors assocs circular formatting fry kernel literals
math random sequences ;
IN: rosetta-code.roulette

CONSTANT: cyl $[ { f f f f f f } <circular> ]

: cylinder ( -- seq ) cyl [ drop f ] map! ;

: load ( seq -- seq' )
    0 over nth [ dup rotate-circular ] when
    t 0 rot [ set-nth ] [ rotate-circular ] [ ] tri ;

: spin ( seq -- seq' ) [ 6 random 1 + + ] change-start ;

: fire ( seq -- ? seq' )
    [ 0 swap nth ] [ rotate-circular ] [ ] tri ;

: LSLSFSF ( -- ? ) cylinder load spin load spin fire spin fire drop or ;
: LSLSFF  ( -- ? ) cylinder load spin load spin fire fire drop or ;
: LLSFSF  ( -- ? ) cylinder load load spin fire spin fire drop or ;
: LLSFF   ( -- ? ) cylinder load load spin fire fire drop or ;

: percent ( ... n quot: ( ... -- ... ? ) -- ... x )
    0 -rot '[ _ call( -- ? ) 1 0 ? + ] [ times ] keepd /f 100 * ; inline

: run-test ( description quot -- )
    100,000 swap percent
    "Method <%s> produces %.3f%% deaths.\n" printf ;

: main ( -- )
    {
        { "load, spin, load, spin, fire, spin, fire" [ LSLSFSF ] }
        { "load, spin, load, spin, fire, fire" [ LSLSFF ] }
        { "load, load, spin, fire, spin, fire" [ LLSFSF ] }
        { "load, load, spin, fire, fire" [ LLSFF ] }
    } [ run-test ] assoc-each ;

MAIN: main


package main

import (
    "fmt"
    "math/rand"
    "strings"
    "time"
)

var cylinder = [6]bool{}

func rshift() {
    t := cylinder[5]
    for i := 4; i >= 0; i-- {
        cylinder[i+1] = cylinder[i]
    }
    cylinder[0] = t
}

func unload() {
    for i := 0; i < 6; i++ {
        cylinder[i] = false
    }
}

func load() {
    for cylinder[0] {
        rshift()
    }
    cylinder[0] = true
    rshift()
}

func spin() {
    var lim = 1 + rand.Intn(6)
    for i := 1; i < lim; i++ {
        rshift()
    }
}

func fire() bool {
    shot := cylinder[0]
    rshift()
    return shot
}

func method(s string) int {
    unload()
    for _, c := range s {
        switch c {
        case 'L':
            load()
        case 'S':
            spin()
        case 'F':
            if fire() {
                return 1
            }
        }
    }
    return 0
}

func mstring(s string) string {
    var l []string
    for _, c := range s {
        switch c {
        case 'L':
            l = append(l, "load")
        case 'S':
            l = append(l, "spin")
        case 'F':
            l = append(l, "fire")
        }
    }
    return strings.Join(l, ", ")
}

func main() {
    rand.Seed(time.Now().UnixNano())
    tests := 100000
    for _, m := range []string{"LSLSFSF", "LSLSFF", "LLSFSF", "LLSFF"} {
        sum := 0
        for t := 1; t <= tests; t++ {
            sum += method(m)
        }
        pc := float64(sum) * 100 / float64(tests)
        fmt.Printf("%-40s produces %6.3f%% deaths.\n", mstring(m), pc)
    }
}


  ;; assumption: none of these variables initially exist

  (defvar *x*)    ;; variable exists now, but has no value
  (defvar *y* 42) ;; variable exists now, and has a value

  (special-variable-p '*x*) -> T  ;; Symbol *x* names a special variable
  (boundp '*x*) -> NIL            ;; *x* has no binding
  (boundp '*y*) -> T

  (special-variable-p '*z*) -> NIL ;; *z* does not name a special variable


void main() {
    // Initialized:
    int a = 5;
    double b = 5.0;
    char c = 'f';
    int[] d = [1, 2, 3];

    // Default initialized:
    int aa; // set to 0
    double bb; // set to double.init, that is a NaN
    char cc; // set to 0xFF
    int[] dd; // set to null
    int[3] ee; // set to [0, 0, 0]

    // Undefined (contain garbage):
    int aaa = void;
    double[] bbb = void;
    int[3] eee = void;
}


var
    P: PInteger;
begin
    New(P);  //Allocate some memory
    try
        If Assigned(P) Then //...
        begin
            P^ := 42;
        end;
    finally
        Dispose(P); //Release memory allocated by New
    end;
end;


try:
  bogus
catch name-error:
  !print "There is *no* :bogus in the current context"
  return
!print "You won't see this."


let Pistol = function(method) {
  this.fired = false;
  this.cylinder = new Array(6).fill(false);
  this.trigger = 0;
  this.rshift = function() {
    this.trigger = this.trigger == 0 ? 5 : this.trigger-1;
  }
  this.load = function() {
    while (this.cylinder[this.trigger]) this.rshift();
    this.cylinder[this.trigger] = true;
    this.rshift();
  }
  // actually we don't need this here: just for completeness
  this.unload = function() { this.cylinder.fill(false); }

  this.spin = function() { this.trigger = Math.floor(Math.random() * 6); }
  this.fire = function() {
    if (this.cylinder[this.trigger]) this.fired = true;
    this.rshift();
  }
  this.exec = function() {
    if (!method) console.error('No method provided');
    else {
      method = method.toUpperCase();
      for (let x = 0; x < method.length; x++)
        switch (method[x]) {
          case 'F' : this.fire(); break;
          case 'L' : this.load(); break;
          case 'S' : this.spin(); break;
          case 'U' : this.unload(); break;
          default: console.error(`Unknown character in method: ${method[x]}`);
        }
      return this.fired;
    }
  }
}

// simulating
const ITERATIONS = 25e4;
let methods = 'lslsfsf lslsff llsfsf llsff'.split(' '),
    bodyCount;
console.log(`@ ${ITERATIONS.toLocaleString('en')} iterations:`);
console.log();
for (let x = 0; x < methods.length; x++) {
  bodyCount = 0;
  for (let y = 1; y <= ITERATIONS; y++)
    if (new Pistol(methods[x]).exec()) bodyCount++;
  console.log(`${methods[x]}:`);
  console.log(`deaths: ${bodyCount.toLocaleString('en')} (${(bodyCount / ITERATIONS * 100).toPrecision(3)} %) `);
  console.log();
}


if (foo == bar || (def baz := lookup(foo)) != null) {
     ...
}


-module( undefined_values ).

-export( [task/0] ).

-record( a_record, {member_1, member_2} ).

task() ->
    Record = #a_record{member_1=a_value},
    io:fwrite( "Record member_1 ~p, member_2 ~p~n", [Record#a_record.member_1, Record#a_record.member_2] ),
    io:fwrite( "Member_2 is undefined ~p~n", [Record#a_record.member_2 =:= undefined] ).


const cyl = zeros(Bool, 6)

function load()
    while cyl[1]
        cyl .= circshift(cyl, 1)
    end
    cyl[1] = true
    cyl .= circshift(cyl, 1)
end

spin() = (cyl .= circshift(cyl, rand(1:6)))

fire() = (shot = cyl[1]; cyl .= circshift(cyl, 1); shot)

function LSLSFSF()
    cyl .= 0
    load(); spin(); load(); spin()
    fire() && return true
    spin(); return fire()
end

function LSLSFF()
    cyl .= 0
    load(); spin(); load(); spin()
    fire() && return true
    return fire()
end

function LLSFSF()
    cyl .= 0
    load(); load(); spin()
    fire() && return true
    spin(); return fire()
end

function LLSFF()
    cyl .= 0
    load(); load(); spin()
    fire() && return true
    return fire()
end

function testmethods(N = 10000000)
    for (name, method) in [("load, spin, load, spin, fire, spin, fire", LSLSFSF),
                           ("load, spin, load, spin, fire, fire", LSLSFF),
                           ("load, load, spin, fire, spin, fire", LLSFSF),
                           ("load, load, spin, fire, fire", LLSFF)]
        percentage = 100 * sum([method() for _ in 1:N]) / N
        println("Method $name produces $percentage per cent deaths.")
    end
end

testmethods()


import kotlin.random.Random

val cylinder = Array(6) { false }

fun rShift() {
    val t = cylinder[cylinder.size - 1]
    for (i in (0 until cylinder.size - 1).reversed()) {
        cylinder[i + 1] = cylinder[i]
    }
    cylinder[0] = t
}

fun unload() {
    for (i in cylinder.indices) {
        cylinder[i] = false
    }
}

fun load() {
    while (cylinder[0]) {
        rShift()
    }
    cylinder[0] = true
    rShift()
}

fun spin() {
    val lim = Random.nextInt(0, 6) + 1
    for (i in 1..lim) {
        rShift()
    }
}

fun fire(): Boolean {
    val shot = cylinder[0]
    rShift()
    return shot
}

fun method(s: String): Int {
    unload()
    for (c in s) {
        when (c) {
            'L' -> {
                load()
            }
            'S' -> {
                spin()
            }
            'F' -> {
                if (fire()) {
                    return 1
                }
            }
        }
    }
    return 0
}

fun mString(s: String): String {
    val buf = StringBuilder()
    fun append(txt: String) {
        if (buf.isNotEmpty()) {
            buf.append(", ")
        }
        buf.append(txt)
    }
    for (c in s) {
        when (c) {
            'L' -> {
                append("load")
            }
            'S' -> {
                append("spin")
            }
            'F' -> {
                append("fire")
            }
        }
    }
    return buf.toString()
}

fun test(src: String) {
    val tests = 100000
    var sum = 0

    for (t in 0..tests) {
        sum += method(src)
    }

    val str = mString(src)
    val pc = 100.0 * sum / tests
    println("%-40s produces %6.3f%% deaths.".format(str, pc))
}

fun main() {
    test("LSLSFSF");
    test("LSLSFF");
    test("LLSFSF");
    test("LLSFF");
}


' FB 1.05.0 Win64

Dim i As Integer        '' initialized to 0 by default
Dim j As Integer = 3    '' initialized to 3
Dim k As Integer = Any  '' left uninitialized (compiler warning but can be ignored)

Print i, j, k
Sleep


IsBound(a);
# true

Unbind(a);

IsBound(a);
# false


package main

import "fmt"

var (
    s []int
    p *int
    f func()
    i interface{}
    m map[int]int
    c chan int
)

func main() {
    fmt.Println("Exercise nil objects:")
    status()

    // initialize objects
    s = make([]int, 1)
    p = &s[0] // yes, reference element of slice just created
    f = func() { fmt.Println("function call") }
    i = user(0) // see user defined type just below
    m = make(map[int]int)
    c = make(chan int, 1)

    fmt.Println("\nExercise objects after initialization:")
    status()
}

type user int

func (user) m() {
    fmt.Println("method call")
}

func status() {
    trySlice()
    tryPointer()
    tryFunction()
    tryInterface()
    tryMap()
    tryChannel()
}

func reportPanic() {
    if x := recover(); x != nil {
        fmt.Println("panic:", x)
    }
}

func trySlice() {
    defer reportPanic()
    fmt.Println("s[0] =", s[0])
}

func tryPointer() {
    defer reportPanic()
    fmt.Println("*p =", *p)
}

func tryFunction() {
    defer reportPanic()
    f()
}

func tryInterface() {
    defer reportPanic()

    // normally the nil identifier accesses a nil value for one of
    // six predefined types.  In a type switch however, nil can be used
    // as a type.  In this case, it matches the nil interface.
    switch i.(type) {
    case nil:
        fmt.Println("i is nil interface")
    case interface {
        m()
    }:
        fmt.Println("i has method m")
    }

    // assert type with method and then call method
    i.(interface {
        m()
    }).m()
}

func tryMap() {
    defer reportPanic()
    m[0] = 0
    fmt.Println("m[0] =", m[0])
}

func tryChannel() {
    defer reportPanic()
    close(c)
    fmt.Println("channel closed")
}


ClearAll[Unload, Load, Spin, Fire]
Unload[] := ConstantArray[False, 6]
Load[state_List] := Module[{s = state},
  While[s[[2]],
   s = RotateRight[s, 1]
   ];
  s[[2]] = True;
  s
  ]
Spin[state_List] := RotateRight[state, RandomInteger[{1, 6}]]
Fire[state_List] := Module[{shot},
  shot = First[state];
  {RotateRight[state, 1], shot}
  ]
ClearAll[LSLSFSF]
LSLSFSF[] := Module[{state, shot},
  state = Unload[];
  state = Load[state];
  state = Spin[state];
  state = Load[state];
  state = Spin[state];
  {state, shot} = Fire[state];
  If[shot,
   Return[True]
   ];
  state = Spin[state];
  {state, shot} = Fire[state];
  If[shot,
   Return[True]
   ];
  Return[False]
  ]
ClearAll[LSLSFF]
LSLSFF[] := Module[{state, shot},
  state = Unload[];
  state = Load[state];
  state = Spin[state];
  state = Load[state];
  state = Spin[state];
  {state, shot} = Fire[state];
  If[shot,
   Return[True]
   ];
  {state, shot} = Fire[state];
  If[shot,
   Return[True]
   ];
  Return[False]
  ]
ClearAll[LLSFSF]
LLSFSF[] := Module[{state, shot},
  state = Unload[];
  state = Load[state];
  state = Load[state];
  state = Spin[state];
  {state, shot} = Fire[state];
  If[shot,
   Return[True]
   ];
  state = Spin[state];
  {state, shot} = Fire[state];
  If[shot,
   Return[True]
   ];
  Return[False]
  ]
ClearAll[LLSFF]
LLSFF[] := Module[{state, shot},
  state = Unload[];
  state = Load[state];
  state = Load[state];
  state = Spin[state];
  {state, shot} = Fire[state];
  If[shot,
   Return[True]
   ];
  {state, shot} = Fire[state];
  If[shot,
   Return[True]
   ];
  Return[False]
  ]
n = 10^5;
Count[Table[LSLSFSF[], n], True]/N[n]
Count[Table[LSLSFF[], n], True]/N[n]
Count[Table[LLSFSF[], n], True]/N[n]
Count[Table[LLSFF[], n], True]/N[n]


import algorithm, random, sequtils, strformat, strutils, tables

type
  Revolver = array[6, bool]
  Action {.pure.} = enum Load, Spin, Fire, Error

const Actions = {'L': Load, 'S': Spin, 'F': Fire}.toTable

func spin(revolver: var Revolver; count: Positive) =
  revolver.rotateLeft(-count)

func load(revolver: var Revolver) =
  while revolver[1]:
    revolver.spin(1)
  revolver[1] = true
  revolver.spin(1)

func fire(revolver: var Revolver): bool =
  result = revolver[0]
  revolver.spin(1)

proc test(scenario: string) =
  let actions = scenario.mapIt(Actions.getOrDefault(it, Error))
  var deaths = 0
  var count = 100_000
  for _ in 1..count:
    var revolver: Revolver
    for action in actions:
      case action
      of Load:
        revolver.load()
      of Spin:
        revolver.spin(rand(1..6))
      of Fire:
        if revolver.fire():
          inc deaths
          break
      of Error:
        raise newException(ValueError, "encountered an unknown action.")
  echo &"""{100 * deaths / count:5.2f}% deaths for scenario {actions.join(", ")}."""

randomize()
for scenario in ["LSLSFSF", "LSLSFF", "LLSFSF", "LLSFF"]:
  test(scenario)


use strict;
use warnings;
use feature 'say';

my @cyl;
my $shots = 6;

sub load  {
    push @cyl, shift @cyl while $cyl[1];
    $cyl[1] = 1;
    push @cyl, shift @cyl
}

sub spin  { push @cyl, shift @cyl for 0 .. int rand @cyl }
sub fire  { push @cyl, shift @cyl; $cyl[0] }

sub LSLSFSF {
    @cyl = (0) x $shots;
    load, spin, load, spin;
    return 1 if fire;
    spin;
    fire
}

sub LSLSFF {
    @cyl = (0) x $shots;
    load, spin, load, spin;
    fire or fire
}

sub LLSFSF {
    @cyl = (0) x $shots;
    load, load, spin;
    return 1 if fire;
    spin;
    fire
}

sub LLSFF {
    @cyl = (0) x $shots;
    load, load, spin;
    fire or fire
}

my $trials = 10000;

for my $ref (<LSLSFSF LSLSFF LLSFSF LLSFF>) {
    no strict 'refs';
    my $total = 0;
    $total += &$ref for 1..$trials;
    printf "%7s %.2f%%\n", $ref, $total / $trials * 100;
}


main = print $ "Incoming error--" ++ undefined
-- When run in GHC:
-- "Incoming error--*** Exception: Prelude.undefined


global G1

procedure main(arglist)
local ML1
static MS1
undeftest()
end

procedure undeftest(P1)
static S1
local L1,L2
every                                                                   #write all local, parameter, static, and global variable names
   write((localnames|paramnames|staticnames|globalnames)(&current,0))   # ... visible in the current co-expression at this calling level (0)
return
end


String string = null;        // the variable string is undefined
System.out.println(string);           //prints "null" to std out
System.out.println(string.length());  // dereferencing null throws java.lang.NullPointerException


var a;

typeof(a) === "undefined";
typeof(b) === "undefined";

var obj = {}; // Empty object.
typeof(obj.c) === "undefined";

obj.c = 42;

obj.c === 42;
delete obj.c;
typeof(obj.c) === "undefined";


with javascript_semantics
function spin(sequence revolver, integer count)
    while count do
        revolver = revolver[$]&revolver[1..$-1]
        count -= 1
    end while
    return revolver
end function

function load(sequence revolver)
    while revolver[1] do
        revolver = spin(revolver,1)
    end while
    revolver[1] = true
    revolver = spin(revolver,1)
    return revolver
end function

function fire(sequence revolver, bool dead)
    if revolver[1] then dead = true end if
    revolver = spin(revolver,1)
    return {revolver,dead}
end function

procedure test(sequence me)
    {string method, atom expected} = me
    integer deaths = 0,
            limit = 100_000
    for n=1 to limit do
        sequence revolver = repeat(false,6)
        bool dead = false
        for i=1 to length(method) do
            integer ch = method[i]
            switch ch
              case 'L': revolver = load(revolver)
              case 'S': revolver = spin(revolver,rand(6))
              case 'F': {revolver,dead} = fire(revolver,dead)
            end switch
        end for
        deaths += dead
    end for
    printf(1,"%s: %5.2f (expected %.2f%%)\n",{method,100*deaths/limit,expected*100})
end procedure

printf(1,"Load/Spin/Fire method percentage fatalities:\n")
papply({{"LSLSFSF",5/9},{"LSLSFF",7/12},{"LLSFSF",5/9},{"LLSFF",1/2}},test)