import Text.Printf         (printf)
import Data.Numbers.Primes (isPrime, primes)

type Pair = (Int, Int)
type Triplet = (Int, Int, Int)
type Quad = (Int, Int, Int, Int)
type Quin = (Int, Int, Int, Int, Int)

type Result = ([Pair], [Triplet], [Quad], [Quin], [Int])

groups :: Int -> Result -> Result
groups n r@(p, t, q, qn, u)
  | isPrime n4 && isPrime n3 && isPrime n2 && isPrime n1 = (addPair, addTriplet, addQuad, addQuin, u)
  | isPrime n3 && isPrime n2 && isPrime n1               = (addPair, addTriplet, addQuad, qn, u)
  | isPrime n2 && isPrime n1                             = (addPair, addTriplet, q, qn, u)
  | isPrime n1                                           = (addPair, t, q, qn, u)
  | not (isPrime (n+6)) && not (isPrime n1)              = (p, t, q, qn, n : u)
  | otherwise                                            = r
  where addPair    = (n1, n) : p
        addTriplet = (n2, n1, n) : t
        addQuad    = (n3, n2, n1, n) : q
        addQuin    = (n4, n3, n2, n1, n) : qn
        n1         = n - 6
        n2         = n - 12
        n3         = n - 18
        n4         = n - 24

main :: IO ()
main = do
  printf ("Number of sexy prime pairs: %d\n" <> lastFiveText) (length pairs) (lastFive pairs)
  printf ("Number of sexy prime triplets: %d\n" <> lastFiveText) (length triplets) (lastFive triplets)
  printf ("Number of sexy prime quadruplets: %d\n" <> lastFiveText) (length quads) (lastFive quads)
  printf "Number of sexy prime quintuplets: %d\n  Last 1 : %s\n\n" (length quins) (show $ last quins)
  printf "Number of unsexy primes: %d\n  Last 10: %s\n\n" (length unsexy) (show $ drop (length unsexy - 10) unsexy)
  where (pairs, triplets, quads, quins, unsexy) = foldr groups ([], [], [], [], []) $ takeWhile (< 1000035) primes
        lastFive xs = show $ drop (length xs - 5) xs
        lastFiveText = "  Last 5 : %s\n\n"


NB. Primes Not Greater Than (the input)
NB. The 1 _1 p: ... logic here allows the input value to
NB. be included in the list in the case it itself is prime
pngt =: p:@:[email protected]:([: +/ 1 _1 p:"0 ])

NB.  Add 6 and see which sums appear in input list
sexy =:  ] #~ + e. ]

NB.  Iterate "sexy" logic up to orgy size
orgy =:  sexy&.>^:( ({[email protected]:[) ` (<@:{:@:[) ` (<@:]) )

sp =: dyad define
  'pd os' =. x  NB. x is  prime distance (6), orgy size (5)
  p =.  pngt y
  o =.  x orgy p
  g =.  o +/&.> <\ +/\ _1 |.!.0 os # pd NB. Groups

  's g' =.  split g  NB. Split singles from groups
  l =. (({.~ -) 5 <. #)&.> g NB. Last (max) 5 groups

  NB. I'm sure there's something clever with p-.s or similar,
  NB. but (a) I don't want to think through it, and (b)
  NB. it causes the kind of edge-case issues the spec warns
  NB. about with 1000033
  us =. p (] #~ 1 +:/@:p: +/)~ (+,-) pd NB. Unsexy numbers
  ( (# ; _10&{.) us ) , (#&.> g) ,. l
)


import java.util.ArrayList;
import java.util.List;

public class SexyPrimes {

    public static void main(String[] args) {
        sieve();
        int pairs = 0;
        List<String> pairList = new ArrayList<>();
        int triples = 0;
        List<String> tripleList = new ArrayList<>();
        int quadruplets = 0;
        List<String> quadrupletList = new ArrayList<>();
        int unsexyCount = 1;  //  2 (the even prime) not found in tests below.
        List<String> unsexyList = new ArrayList<>();
        for ( int i = 3 ; i < MAX ; i++ ) {
            if ( i-6 >= 3 && primes[i-6] && primes[i] ) {
                pairs++;
                pairList.add((i-6) + " " + i);
                if ( pairList.size() > 5 ) {
                    pairList.remove(0);
                }
            }
            else if ( i < MAX-2 && primes[i] && ! (i+6<MAX && primes[i] && primes[i+6])) {
                unsexyCount++;
                unsexyList.add("" + i);
                if ( unsexyList.size() > 10 ) {
                    unsexyList.remove(0);
                }
            }
            if ( i-12 >= 3 && primes[i-12] && primes[i-6] && primes[i] ) {
                triples++;
                tripleList.add((i-12) + " " + (i-6) + " " + i);
                if ( tripleList.size() > 5 ) {
                    tripleList.remove(0);
                }
            }
            if ( i-16 >= 3 && primes[i-18] && primes[i-12] && primes[i-6] && primes[i] ) {
                quadruplets++;
                quadrupletList.add((i-18) + " " + (i-12) + " " + (i-6) + " " + i);
                if ( quadrupletList.size() > 5 ) {
                    quadrupletList.remove(0);
                }
            }
        }
        System.out.printf("Count of sexy triples less than %,d = %,d%n", MAX, pairs);
        System.out.printf("The last 5 sexy pairs:%n  %s%n%n", pairList.toString().replaceAll(", ", "], ["));
        System.out.printf("Count of sexy triples less than %,d = %,d%n", MAX, triples);
        System.out.printf("The last 5 sexy triples:%n  %s%n%n", tripleList.toString().replaceAll(", ", "], ["));
        System.out.printf("Count of sexy quadruplets less than %,d = %,d%n", MAX, quadruplets);
        System.out.printf("The last 5 sexy quadruplets:%n  %s%n%n", quadrupletList.toString().replaceAll(", ", "], ["));
        System.out.printf("Count of unsexy primes less than %,d = %,d%n", MAX, unsexyCount);
        System.out.printf("The last 10 unsexy primes:%n  %s%n%n", unsexyList.toString().replaceAll(", ", "], ["));
    }

    private static int MAX = 1_000_035;
    private static boolean[] primes = new boolean[MAX];

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

}


using Primes

function nextby6(n, a)
    top = length(a)
    i = n + 1
    j = n + 2
    k = n + 3
    if n >= top
        return n
    end
    possiblenext = a[n] + 6
    if i <= top && possiblenext == a[i]
        return i
    elseif j <= top && possiblenext == a[j]
        return j
    elseif k <= top && possiblenext == a[k]
        return k
    end
    return n
end

function lastones(dict, n)
    arr = sort(collect(keys(dict)))
    beginidx = max(1, length(arr) - n + 1)
    arr[beginidx: end]
end

function lastoneslessthan(dict, n, ceiling)
    arr = filter(y -> y < ceiling, lastones(dict, n+3))
    beginidx = max(1, length(arr) - n + 1)
    arr[beginidx: end]
end

function primesbysexiness(x)
    twins = Dict{Int64, Array{Int64,1}}()
    triplets = Dict{Int64, Array{Int64,1}}()
    quadruplets = Dict{Int64, Array{Int64,1}}()
    quintuplets = Dict{Int64, Array{Int64,1}}()
    possibles = primes(x + 30)
    singles = filter(y -> y <= x - 6, possibles)
    unsexy = Dict(p => true for p in singles)
    for (i, p) in enumerate(singles)
        twinidx = nextby6(i, possibles)
        if twinidx > i
            delete!(unsexy, p)
            delete!(unsexy, p + 6)
            twins[p] = [i, twinidx]
            tripidx = nextby6(twinidx, possibles)
            if tripidx > twinidx
                triplets[p] = [i, twinidx, tripidx]
                quadidx = nextby6(tripidx, possibles)
                if quadidx > tripidx
                    quadruplets[p] = [i, twinidx, tripidx, quadidx]
                    quintidx = nextby6(quadidx, possibles)
                    if quintidx > quadidx
                        quintuplets[p] = [i, twinidx, tripidx, quadidx, quintidx]
                    end
                end
            end
        end
    end
    # Find and display the count of each group
    println("There are:\n$(length(twins)) twins,\n",
            "$(length(triplets)) triplets,\n",
            "$(length(quadruplets)) quadruplets, and\n",
            "$(length(quintuplets)) quintuplets less than $x.")
    println("The last 5 twin primes start with ", lastoneslessthan(twins, 5, x - 6))
    println("The last 5 triplet primes start with ", lastones(triplets, 5))
    println("The last 5 quadruplet primes start with ", lastones(quadruplets, 5))
    println("The quintuplet primes start with ", lastones(quintuplets, 5))
    println("There are $(length(unsexy)) unsexy primes less than $x.")
    lastunsexy = sort(collect(keys(unsexy)))[length(unsexy) - 9: end]
    println("The last 10 unsexy primes are: $lastunsexy")
end

primesbysexiness(1000035)


// Version 1.2.71

fun sieve(lim: Int): BooleanArray {
    var limit = lim + 1
    // True denotes composite, false denotes prime.
    val c = BooleanArray(limit)  // all false by default
    c[0] = true
    c[1] = true
    // No need to bother with even numbers over 2 for this task.
    var p = 3  // Start from 3.
    while (true) {
        val p2 = p * p
        if (p2 >= limit) break
        for (i in p2 until limit step 2 * p) c[i] = true
        while (true) {
            p += 2
            if (!c[p]) break
        }
    }
    return c
}

fun printHelper(cat: String, len: Int, lim: Int, max: Int): Pair<Int, String> {
    val cat2 = if (cat != "unsexy primes") "sexy prime " + cat  else cat
    System.out.printf("Number of %s less than %d = %,d\n", cat2, lim, len)
    val last = if (len < max) len else max
    val verb = if (last == 1) "is" else "are"
    return last to verb
}

fun main(args: Array<String>) {
    val lim = 1_000_035
    val sv = sieve(lim - 1)
    val pairs = mutableListOf<List<Int>>()
    val trips = mutableListOf<List<Int>>()
    val quads = mutableListOf<List<Int>>()
    val quins = mutableListOf<List<Int>>()
    val unsexy = mutableListOf(2, 3)
    for (i in 3 until lim step 2) {
        if (i > 5 && i < lim - 6 && !sv[i] && sv[i - 6] && sv[i + 6]) {
            unsexy.add(i)
            continue
        }

        if (i < lim - 6 && !sv[i] && !sv[i + 6]) {
            val pair = listOf(i, i + 6)
            pairs.add(pair)
        } else continue

        if (i < lim - 12 && !sv[i + 12]) {
            val trip = listOf(i, i + 6, i + 12)
            trips.add(trip)
        } else continue

        if (i < lim - 18 && !sv[i + 18]) {
            val quad = listOf(i, i + 6, i + 12, i + 18)
            quads.add(quad)
        } else continue

        if (i < lim - 24 && !sv[i + 24]) {
            val quin = listOf(i, i + 6, i + 12, i + 18, i + 24)
            quins.add(quin)
        }
    }

    var (n2, verb2) = printHelper("pairs", pairs.size, lim, 5)
    System.out.printf("The last %d %s:\n  %s\n\n", n2, verb2, pairs.takeLast(n2))

    var (n3, verb3) = printHelper("triplets", trips.size, lim, 5)
    System.out.printf("The last %d %s:\n  %s\n\n", n3, verb3, trips.takeLast(n3))

    var (n4, verb4) = printHelper("quadruplets", quads.size, lim, 5)
    System.out.printf("The last %d %s:\n  %s\n\n", n4, verb4, quads.takeLast(n4))

    var (n5, verb5) = printHelper("quintuplets", quins.size, lim, 5)
    System.out.printf("The last %d %s:\n  %s\n\n", n5, verb5, quins.takeLast(n5))

    var (nu, verbu) = printHelper("unsexy primes", unsexy.size, lim, 10)
    System.out.printf("The last %d %s:\n  %s\n\n", nu, verbu, unsexy.takeLast(nu))
}


local N = 1000035

-- 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.map = function(t,f,...) local s=T{} for _,v in ipairs(t) do s[#s+1]=f(v,...) end return s end
table.lastn = function(t,n) local s=T{} n=n>#t and #t or n for i = 1,n do s[i]=t[#t-n+i] end return s end
table.each = function(t,f,...) for _,v in ipairs(t) do f(v,...) end end

-- PRIMES:
local sieve, primes = {false}, T{}
for i = 2,N+6 do sieve[i]=true end
for i = 2,N+6 do if sieve[i] then for j=i*i,N+6,i do sieve[j]=nil end end end
for i = 2,N+6 do if sieve[i] then primes[#primes+1]=i end end

-- TASKS:
local sexy, name = { primes }, { "primes", "pairs", "triplets", "quadruplets", "quintuplets" }
local function sexy2str(v,n) local s=T{} for i=1,n do s[i]=v+(i-1)*6 end return "("..s:concat(" ")..")" end
for i = 2, 5 do
  sexy[i] = sexy[i-1]:filter(function(v) return v+(i-1)*6<N and sieve[v+(i-1)*6] end)
  print(#sexy[i] .. " " .. name[i] .. ", ending with: " .. sexy[i]:lastn(5):map(sexy2str,i):concat(" "))
end
local unsexy = primes:filter(function(v) return not (v>=N or sieve[v-6] or sieve[v+6]) end)
print(#unsexy .. " unsexy, ending with: " ..unsexy:lastn(10):concat(" "))


ClearAll[AllSublengths]
AllSublengths[l_List] := If[Length[l] > 2,
  Catenate[Partition[l, #, 1] & /@ Range[2, Length[l]]]
  ,
  {l}
  ]
primes = Prime[Range[PrimePi[1000035]]];
ps = Union[Intersection[primes + 6, primes] - 6, Intersection[primes - 6, primes] + 6];
a = Intersection[ps + 6, ps] - 6;
b = Intersection[ps - 6, ps] + 6;
g = Graph[DeleteDuplicates[Thread[a \[UndirectedEdge] (a + 6)]~Join~Thread[(b - 6) \[UndirectedEdge] b]]];
sp = Sort /@ ConnectedComponents[g];
sp //= SortBy[First];
sp //= Map[AllSublengths];
sp //= Catenate;
sp //= SortBy[First];
sp //= DeleteDuplicates;
sel = Select[sp, Length /* EqualTo[2]];
Length[sel]
sel[[-5 ;;]] // Column
sel = Select[sp, Length /* EqualTo[3]];
Length[sel]
sel[[-5 ;;]] // Column
sel = Select[sp, Length /* EqualTo[4]];
Length[sel]
sel[[-5 ;;]] // Column
sel = Select[sp, Length /* EqualTo[5]];
Length[sel]
sel // Column

Select[Complement[primes, DeleteDuplicates[[email protected]]][[-20 ;;]], ! (PrimeQ[# + 6] \[Or] PrimeQ[# - 6]) &][[-10 ;;]] // Column


import math, strformat, strutils

const Lim = 1_000_035

type Group {.pure.} = enum        # "ord" gives the number of terms.
  Unsexy = (1, "unsexy primes")
  Pairs = (2, "sexy prime pairs")
  Triplets = (3, "sexy prime triplets")
  Quadruplets = (4, "sexy prime quadruplets")
  Quintuplets = (5, "sexy prime quintuplets")

# Sieve of Erathosthenes.
var composite: array[1..Lim, bool]                # Default is false.
composite[1] = true
for p in countup(3, sqrt(Lim.toFloat).int, 2):    # Ignore even numbers.
  if not composite[p]:
    for k in countup(p * p, Lim, 2 * p):
      composite[k] = true

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

proc expandGroup(n: int; group: Group): string =
  ## Given the first term of a group, return the full group
  ## representation as a string.
  var n = n
  for _ in 1..ord(group):
    result.addSep(", ")
    result.add $n
    inc n, 6
  if group != Unsexy: result = '(' & result & ')'

proc printResult(group: Group; values: seq[int]; count: int) =
  ## Print a result.

  echo &"\nNumber of {group} less than {Lim}: {values.len}"
  let last = min(values.len, count)
  let verb = if last == 1: "is" else: "are"
  echo &"The last {last} {verb}:"

  var line = ""
  for i in countdown(last, 1):
    line.addSep(", ")
    line.add expandGroup(values[^i], group)
  echo "    ", line

var
  pairs, trips, quads, quints: seq[int]  # Keep only the first prime of the group.
  unsexy = @[2, 3]

for n in countup(3, Lim, 2):
  if composite[n]: continue

  if n in 7..(Lim - 8) and composite[n - 6] and composite[n + 6]:
    unsexy.add n
    continue

  if n < Lim - 6 and isPrime(n + 6):
    pairs.add n
  else: continue

  if n < Lim - 12 and isPrime(n + 12):
    trips.add n
  else: continue

  if n < Lim - 18 and isPrime(n + 18):
    quads.add n
  else: continue

  if n < Lim - 24 and isPrime(n + 24):
    quints.add n

printResult(Pairs, pairs, 5)
printResult(Triplets, trips, 5)
printResult(Quadruplets, quads, 5)
printResult(Quintuplets, quints, 5)
printResult(Unsexy, unsexy, 10)


program SexyPrimes;

uses
  SysUtils
{$IFNDEF FPC}
 ,windows // GettickCount64
{$ENDIF}

const
  ctext: array[0..5] of string = ('Primes',
    'sexy prime pairs',
    'sexy prime triplets',
    'sexy prime quadruplets',
    'sexy prime quintuplet',
    'sexy prime sextuplet');

  primeLmt = 1000 * 1000 + 35;
type
  sxPrtpl = record
    spCnt,
    splast5Idx: nativeInt;
    splast5: array[0..6] of NativeInt;
  end;

var
  sieve: array[0..primeLmt] of byte;
  sexyPrimesTpl: array[0..5] of sxPrtpl;
  unsexyprimes: NativeUint;

  procedure dosieve;
  var
    p, delPos, fact: NativeInt;
  begin
    p := 2;
    repeat
      if sieve[p] = 0 then
      begin
        delPos := primeLmt div p;
        if delPos < p then
          BREAK;
        fact := delPos * p;
        while delPos >= p do
        begin
          if sieve[delPos] = 0 then
            sieve[fact] := 1;
          Dec(delPos);
          Dec(fact, p);
        end;
      end;
      Inc(p);
    until False;
  end;
  procedure CheckforSexy;
  var
    i, idx, sieveMask, tstMask: NativeInt;
  begin
    sieveMask := -1;
    for i := 2 to primelmt do
    begin
      tstMask := 1;
      sieveMask := sieveMask + sieveMask + sieve[i];
      idx := 0;
      repeat
        if (tstMask and sieveMask) = 0 then
          with sexyPrimesTpl[idx] do
          begin
            Inc(spCnt);
            //memorize the last entry
            Inc(splast5idx);
            if splast5idx > 5 then
              splast5idx := 1;
            splast5[splast5idx] := i;
            tstMask := tstMask shl 6 + 1;
          end
        else
        begin
          BREAK;
        end;
        Inc(idx);
      until idx > 5;
    end;
  end;

  procedure CheckforUnsexy;
  var
    i: NativeInt;
  begin
    for i := 2 to 6 do
    begin
      if (Sieve[i] = 0) and (Sieve[i + 6] = 1) then
        Inc(unsexyprimes);
    end;
    for i := 2 + 6 to primelmt - 6 do
    begin
      if (Sieve[i] = 0) and (Sieve[i - 6] = 1) and (Sieve[i + 6] = 1) then
        Inc(unsexyprimes);
    end;
  end;

  procedure OutLast5(idx: NativeInt);
  var
    i, j, k: nativeInt;
  begin
    with sexyPrimesTpl[idx] do
    begin
      writeln(cText[idx], '  ', spCnt);
      i := splast5idx + 1;
      for j := 1 to 5 do
      begin
        if i > 5 then
          i := 1;
        if splast5[i] <> 0 then
        begin
          Write('[');
          for k := idx downto 1 do
            Write(splast5[i] - k * 6, ' ');
          Write(splast5[i], ']');
        end;
        Inc(i);
      end;
    end;
    writeln;
  end;

  procedure OutLastUnsexy(cnt:NativeInt);
  var
    i: NativeInt;
    erg: array of NativeUint;
  begin
    if cnt < 1 then
      EXIT;
    setlength(erg,cnt);
    dec(cnt);
    if cnt < 0 then
      EXIT;
    for i := primelmt downto 2 + 6 do
    begin
      if (Sieve[i] = 0) and (Sieve[i - 6] = 1) and (Sieve[i + 6] = 1) then
      Begin
        erg[cnt] := i;
        dec(cnt);
        If cnt < 0 then
          BREAK;
       end;
    end;
    write('the last ',High(Erg)+1,' unsexy primes ');
    For i := 0 to High(erg)-1 do
      write(erg[i],',');
    write(erg[High(erg)]);
  end;
var
  T1, T0: int64;
  i: nativeInt;

begin

  T0 := GettickCount64;
  dosieve;
  T1 := GettickCount64;
  writeln('Sieving is done in ', T1 - T0, ' ms');
  T0 := GettickCount64;
  CheckforSexy;
  T1 := GettickCount64;
  writeln('Checking is done in ', T1 - T0, ' ms');

  unsexyprimes := 0;
  T0 := GettickCount64;
  CheckforUnsexy;
  T1 := GettickCount64;
  writeln('Checking unsexy is done in ', T1 - T0, ' ms');

  writeln('Limit : ', primelmt);
  for i := 0 to 4 do
  begin
    OutLast5(i);
  end;
  writeln;
  writeln(unsexyprimes,' unsexy primes');
  OutLastUnsexy(10);
end.


use ntheory qw/prime_iterator is_prime/;

sub tuple_tail {
    my($n,$cnt,@array) = @_;
    $n = @array if $n > @array;
    my @tail;
    for (1..$n) {
        my $p = $array[-$n+$_-1];
        push @tail, "(" . join(" ", map { $p+6*$_ } 0..$cnt-1) . ")";
    }
    return @tail;
}

sub comma {
    (my $s = reverse shift) =~ s/(.{3})/$1,/g;
    ($s = reverse $s) =~ s/^,//;
    return $s;
}

sub sexy_string { my $p = shift; is_prime($p+6) || is_prime($p-6) ? 'sexy' : 'unsexy' }

my $max = 1_000_035;
my $cmax = comma $max;

my $iter = prime_iterator;
my $p = $iter->();
my %primes;
push @{$primes{sexy_string($p)}}, $p;
while ( ($p = $iter->()) < $max) {
    push @{$primes{sexy_string($p)}}, $p;
    $p+ 6 < $max && is_prime($p+ 6) ? push @{$primes{'pair'}},       $p : next;
    $p+12 < $max && is_prime($p+12) ? push @{$primes{'triplet'}},    $p : next;
    $p+18 < $max && is_prime($p+18) ? push @{$primes{'quadruplet'}}, $p : next;
    $p+24 < $max && is_prime($p+24) ? push @{$primes{'quintuplet'}}, $p : next;
}

print "Total primes less than $cmax: " . comma(@{$primes{'sexy'}} + @{$primes{'unsexy'}}) . "\n\n";

for (['pair', 2], ['triplet', 3], ['quadruplet', 4], ['quintuplet', 5]) {
    my($sexy,$cnt) = @$_;
    print "Number of sexy prime ${sexy}s less than $cmax: " . comma(scalar @{$primes{$sexy}}) . "\n";
    print "   Last 5 sexy prime ${sexy}s less than $cmax: " . join(' ', tuple_tail(5,$cnt,@{$primes{$sexy}})) . "\n";
    print "\n";
}

print "Number of unsexy primes less than $cmax: ". comma(scalar @{$primes{unsexy}}) . "\n";
print "  Last 10 unsexy primes less than $cmax: ". join(' ', @{$primes{unsexy}}[-10..-1]) . "\n";


function create_sieve(integer limit)
    sequence sieve = repeat(true,limit)
    sieve[1] = false
    for i=4 to limit by 2 do
        sieve[i] = false
    end for
    for p=3 to floor(sqrt(limit)) by 2 do
        integer p2 = p*p
        if sieve[p2] then
            for k=p2 to limit by p*2 do
                sieve[k] = false
            end for
        end if
    end for
    return sieve
end function

constant lim = 1000035,
--constant lim = 100, -- (this works too)
         limit = lim-(and_bits(lim,1)=0),   -- (limit must be odd)
         sieve = create_sieve(limit+6)  -- (+6 to check for sexiness)

sequence sets = repeat({},5),   -- (unsexy,pairs,trips,quads,quins)
         limits = {10,5,4,3,1},
         counts = 1&repeat(0,4) -- (2 is an unsexy prime)
integer  total = 1              -- ""

for i=limit to 3 by -2 do       -- (this loop skips 2)
    if sieve[i] then
        total += 1
        if sieve[i+6]=false and (i-6<0 or sieve[i-6]=false) then
            counts[1] += 1 -- unsexy
            if length(sets[1])<limits[1] then
                sets[1] = prepend(sets[1],i)
            end if
        else
            sequence set = {i}
            for j=i-6 to 3 by -6 do
                if j<=0 or sieve[j]=false then exit end if
                set = prepend(set,j)
                integer l = length(set)
                if length(sets[l])<limits[l] then
                    sets[l] = prepend(sets[l],set)
                end if
                counts[l] += 1
            end for
        end if
    end if
end for
if length(sets[1])<limits[1] then
    sets[1] = prepend(sets[1],2) -- (as 2 skipped above)
end if

constant fmt = """
Of %,d primes less than %,d there are:
%,d unsexy primes, the last %d being %s
%,d pairs, the last %d being %s
%,d triplets, the last %d being %s
%,d quadruplets, the last %d being %s
%,d quintuplet, the last %d being %s
"""
sequence results = {total,lim,
                    0,0,"",
                    0,0,"",
                    0,0,"",
                    0,0,"",
                    0,0,""}
for i=1 to 5 do
    results[i*3..i*3+2] = {counts[i],length(sets[i]),sprint(sets[i])}
end for
printf(1,fmt,results)


sexy_prime_group(1, N, _, [N]):-
    is_prime(N),
    !.
sexy_prime_group(Size, N, Limit, [N|Group]):-
    is_prime(N),
    N1 is N + 6,
    N1 =< Limit,
    S1 is Size - 1,
    sexy_prime_group(S1, N1, Limit, Group).

print_sexy_prime_groups(Size, Limit):-
    findall(G, (is_prime(P), P =< Limit, sexy_prime_group(Size, P, Limit, G)), Groups),
    length(Groups, Len),
    writef('Number of groups of size %t is %t\n', [Size, Len]),
    last_n(Groups, 5, Len, Last, Last_len),
    writef('Last %t groups of size %t: %t\n\n', [Last_len, Size, Last]).

last_n([], _, L, [], L):-!.
last_n([_|List], Max, Length, Last, Last_len):-
    Max < Length,
    !,
    Len1 is Length - 1,
    last_n(List, Max, Len1, Last, Last_len).
last_n([E|List], Max, Length, [E|Last], Last_len):-
    last_n(List, Max, Length, Last, Last_len).

unsexy(P):-
    P1 is P + 6,
    \+is_prime(P1),
    P2 is P - 6,
    \+is_prime(P2).

main(Limit):-
    Max is Limit + 6,
    find_prime_numbers(Max),
    print_sexy_prime_groups(2, Limit),
    print_sexy_prime_groups(3, Limit),
    print_sexy_prime_groups(4, Limit),
    print_sexy_prime_groups(5, Limit),
    findall(P, (is_prime(P), P =< Limit, unsexy(P)), Unsexy),
    length(Unsexy, Count),
    writef('Number of unsexy primes is %t\n', [Count]),
    last_n(Unsexy, 10, Count, Last10, _),
    writef('Last 10 unsexy primes: %t', [Last10]).

main:-
    main(1000035).


DisableDebugger
EnableExplicit

#LIM=1000035

Macro six(mul)
  6*mul
EndMacro

Macro form(n)
  RSet(Str(n),8)
EndMacro

Macro put(m,g,n)
  PrintN(Str(m)+" "+g)
  PrintN(n)
EndMacro

Define c1.i=2,c2.i,c3.i,c4.i,c5.i,t1$,t2$,t3$,t4$,t5$,i.i,j.i

Global Dim soe.b(#LIM)
FillMemory(@soe(0),#LIM,#True,#PB_Byte)
If Not OpenConsole("")
  End 1
EndIf

For i=2 To Sqr(#LIM)
  If soe(i)=#True
    j=i*i
    While j<=#LIM
      soe(j)=#False
      j+i
    Wend
  EndIf
Next

Procedure.s formtab(t$,l.i)
  If CountString(t$,~"\n")>l
    t$=Mid(t$,FindString(t$,~"\n")+1)
  EndIf
  ProcedureReturn t$
EndProcedure

For i=3 To #LIM Step 2
  If i>5 And i<#LIM-6 And soe(i)&~(soe(i-six(1))|soe(i+six(1)))
    c1+1
    t1$+form(i)+~"\n"
    t1$=formtab(t1$,10)
    Continue
  EndIf
  If i<#LIM-six(1) And soe(i)&soe(i+six(1))
    c2+1
    t2$+form(i)+form(i+six(1))+~"\n"
    t2$=formtab(t2$,5)
  EndIf
  If i<#LIM-six(2) And soe(i)&soe(i+six(1))&soe(i+six(2))
    c3+1
    t3$+form(i)+form(i+six(1))+form(i+six(2))+~"\n"
    t3$=formtab(t3$,5)
  EndIf
  If i<#LIM-six(3) And soe(i)&soe(i+six(1))&soe(i+six(2))&soe(i+six(3))
    c4+1
    t4$+form(i)+form(i+six(1))+form(i+six(2))+form(i+six(3))+~"\n"
    t4$=formtab(t4$,5)
  EndIf
  If i<#LIM-six(4) And soe(i)&soe(i+six(1))&soe(i+six(2))&soe(i+six(3))&soe(i+six(4))
    c5+1
    t5$+form(i)+form(i+six(1))+form(i+six(2))+form(i+six(3))+form(i+six(4))+~"\n"
    t5$=formtab(t5$,5)
  EndIf
Next

put(c2,"pairs ending with ...",t2$)
put(c3,"triplets ending with ...",t3$)
put(c4,"quadruplets ending with ...",t4$)
put(c5,"quintuplets ending with ...",t5$)
put(c1,"unsexy primes ending with ...",t1$)

Input()


LIMIT = 1_000_035
def primes2(limit=LIMIT):
    if limit < 2: return []
    if limit < 3: return [2]
    lmtbf = (limit - 3) // 2
    buf = [True] * (lmtbf + 1)
    for i in range((int(limit ** 0.5) - 3) // 2 + 1):
        if buf[i]:
            p = i + i + 3
            s = p * (i + 1) + i
            buf[s::p] = [False] * ((lmtbf - s) // p + 1)
    return [2] + [i + i + 3 for i, v in enumerate(buf) if v]

primes = primes2(LIMIT +6)
primeset = set(primes)
primearray = [n in primeset for n in range(LIMIT)]

#%%
s = [[] for x in range(4)]
unsexy = []

for p in primes:
    if p > LIMIT:
        break
    if p + 6 in primeset and p + 6 < LIMIT:
        s[0].append((p, p+6))
    elif p + 6 in primeset:
        break
    else:
        if p - 6 not in primeset:
            unsexy.append(p)
        continue
    if p + 12 in primeset and p + 12 < LIMIT:
        s[1].append((p, p+6, p+12))
    else:
        continue
    if p + 18 in primeset and p + 18 < LIMIT:
        s[2].append((p, p+6, p+12, p+18))
    else:
        continue
    if p + 24 in primeset and p + 24 < LIMIT:
        s[3].append((p, p+6, p+12, p+18, p+24))

#%%
print('"SEXY" PRIME GROUPINGS:')
for sexy, name in zip(s, 'pairs triplets quadruplets quintuplets'.split()):
    print(f'  {len(sexy)} {na (not isPrime(n-6))))) |> Array.ofSeq
printfn "There are %d unsexy primes less than 1,000,035. The last 10 are:" n.Length
Array.skip (n.Length-10) n |> Array.iter(fun n->printf "%d " n); printfn ""
let ni=pCache |> Seq.takeWhile(fun n->nme} ending with ...')
    for sx in sexy[-5:]:
        print('   ',sx)

print(f'\nThere are {len(unsexy)} unsexy primes ending with ...')
for usx in unsexy[-10:]:
    print(' ',usx)


use Math::Primesieve;
my $sieve = Math::Primesieve.new;

my $max = 1_000_035;
my @primes = $sieve.primes($max);

my $filter = @primes.Set;
my $primes = @primes.categorize: &sexy;

say "Total primes less than {comma $max}: ", comma +@primes;

for <pair 2 triplet 3 quadruplet 4 quintuplet 5> -> $sexy, $cnt {
    say "Number of sexy prime {$sexy}s less than {comma $max}: ", comma +$primes{$sexy};
    say "   Last 5 sexy prime {$sexy}s less than {comma $max}: ",
      join ' ', $primes{$sexy}.tail(5).grep(*.defined).map:
      { "({ $_ «+« (0,6 … 24)[^$cnt] })" }
    say '';
}

say "Number of unsexy primes less than {comma $max}: ", comma +$primes<unsexy>;
say "  Last 10 unsexy primes less than {comma $max}: ", $primes<unsexy>.tail(10);

sub sexy ($i) {
    gather {
        take 'quintuplet' if all($filter{$i «+« (6,12,18,24)});
        take 'quadruplet' if all($filter{$i «+« (6,12,18)});
        take 'triplet'    if all($filter{$i «+« (6,12)});
        take 'pair'       if $filter{$i + 6};
        take (($i >= $max - 6) && ($i + 6).is-prime) ||
          (so any($filter{$i «+« (6, -6)})) ?? 'sexy' !! 'unsexy';
    }
}

sub comma { $^i.flip.comb(3).join(',').flip }


/*REXX program finds and displays various kinds of  sexy and unsexy  primes less than N.*/
parse arg N endU end2 end3 end4 end5 .           /*obtain optional argument from the CL.*/
if    N==''  |    N==","  then    N= 1000035 - 1 /*Not specified?  Then use the default.*/
if endU==''  | endU==","  then endU=      10     /* "      "         "   "   "     "    */
if end2==''  | end2==","  then end2=       5     /* "      "         "   "   "     "    */
if end3==''  | end3==","  then end3=       5     /* "      "         "   "   "     "    */
if end4==''  | end4==","  then end4=       5     /* "      "         "   "   "     "    */
if end5==''  | end5==","  then end4=       5     /* "      "         "   "   "     "    */
call genSq                                       /*gen some squares for the DO k=7 UNTIL*/
call genPx                                       /* " prime (@.) & sexy prime (X.) array*/
call genXU                                       /*gen lists, types of sexy Ps, unsexy P*/
call getXs                                       /*gen lists, last # of types of sexy Ps*/
 @sexy= ' sexy prime'                            /*a handy literal for some of the SAYs.*/
 w2= words( translate(x2,, '~') ); y2= words(x2) /*count #primes in the sexy pairs.     */
 w3= words( translate(x3,, '~') ); y3= words(x3) /*  "   "   "    "  "    "  triplets.  */
 w4= words( translate(x4,, '~') ); y4= words(x4) /*  "   "   "    "  "    "  quadruplets*/
 w5= words( translate(x5,, '~') ); y5= words(x5) /*  "   "   "    "  "    "  quintuplets*/
say 'There are ' commas(w2%2) @sexy "pairs less than "             Nc
say 'The last '  commas(end2) @sexy "pairs are:";        say subword(x2, max(1,y2-end2+1))
say
say 'There are ' commas(w3%3) @sexy "triplets less than "          Nc
say 'The last '  commas(end3) @sexy "triplets are:";     say subword(x3, max(1,y3-end3+1))
say
say 'There are ' commas(w4%4) @sexy "quadruplets less than "       Nc
say 'The last '  commas(end4) @sexy "quadruplets are:";  say subword(x4, max(1,y4-end4+1))
say
say 'There is  ' commas(w5%5) @sexy "quintuplet less than "        Nc
say 'The last '  commas(end4) @sexy "quintuplet are:";   say subword(x5, max(1,y5-end4+1))
say
say 'There are ' commas(s1)         "   sexy primes less than "    Nc
say 'There are ' commas(u1)         " unsexy primes less than "    Nc
say 'The last '  commas(endU)       " unsexy primes are: "   subword(u,  max(1,u1-endU+1))
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: procedure;  parse arg _;    n= _'.9';     #= 123456789;       b= verify(n, #, "M")
        e= verify(n, #'0', , verify(n, #"0.", 'M') ) - 4
           do j=e  to b  by -3;    _= insert(',', _, j);     end  /*j*/;          return _
/*──────────────────────────────────────────────────────────────────────────────────────*/
genSQ: do i=17  by 2  until i**2 > N+7; s.i= i**2; end; return /*S used for square roots*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
genPx: @.=;              #= 0;          !.= 0.          /*P array; P count; sexy P array*/
       if N>1  then do;  #= 1;   @.1= 2;  !.2= 1;   end /*count of primes found (so far)*/
       x.=!.;                        LPs=3 5 7 11 13 17 /*sexy prime array;  low P list.*/
         do j=3  by 2  to  N+6                          /*start in the cellar & work up.*/
         if j<19  then if wordpos(j, LPs)==0  then iterate
                                              else do; #= #+1;  @.#= j;  !.j= 1;  b= j - 6
                                                       if !.b  then x.b= 1;        iterate
                                                   end
         if j// 3 ==0  then iterate                /* ··· and eliminate multiples of  3.*/
         parse var  j  ''  -1  _                   /* get the rightmost digit of  J.    */
         if     _ ==5  then iterate                /* ··· and eliminate multiples of  5.*/
         if j// 7 ==0  then iterate                /* ···  "      "         "      "  7.*/
         if j//11 ==0  then iterate                /* ···  "      "         "      " 11.*/
         if j//13 ==0  then iterate                /* ···  "      "         "      " 13.*/
                    do k=7  until s._ > j;  _= @.k /*÷ by primes starting at 7th prime. */
                    if j // _ == 0  then iterate j /*get the remainder of  j÷@.k    ___ */
                    end   /*k*/                    /*divide up through & including √ J  */
         if j<=N  then do;  #= #+1;  @.#= j;  end  /*bump P counter;  assign prime to @.*/
         !.j= 1                                    /*define  Jth  number as being prime.*/
              b= j - 6                             /*B: lower part of a sexy prime pair?*/
         if !.b then do; x.b=1; if j<=N then x.j=1; end /*assign (both parts ?) sexy Ps.*/
         end   /*j*/;       return
/*──────────────────────────────────────────────────────────────────────────────────────*/
genXU: u= 2;         Nc=commas(N+1);  s=           /*1st unsexy prime; add commas to N+1*/
       say 'There are ' commas(#)    " primes less than "          Nc;           say
          do k=2  for #-1; p= @.k; if x.p  then s=s p   /*if  sexy prime, add it to list*/
                                           else u= u p  /* " unsexy  "     "   "  "   " */
          end   /*k*/                                   /* [↑]  traispe through odd Ps. */
       s1= words(s);  u1= words(u);   return       /*# of sexy primes;  # unsexy primes.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
getXs: x2=;  do k=2  for #-1;  [email protected].k;   if \x.p  then iterate  /*build sexy prime list. */
                               b=p- 6;  if \x.b  then iterate; x2=x2 b'~'p
             end   /*k*/
       x3=;  do k=2  for #-1;  [email protected].k;   if \x.p  then iterate  /*build sexy P triplets. */
                               b=p- 6;  if \x.b  then iterate
                               t=p-12;  if \x.t  then iterate; x3=x3 t'~' || b"~"p
             end   /*k*/
       x4=;  do k=2  for #-1;  [email protected].k;   if \x.p  then iterate  /*build sexy P quads.    */
                               b=p- 6;  if \x.b  then iterate
                               t=p-12;  if \x.t  then iterate
                               q=p-18;  if \x.q  then iterate; x4=x4 q'~'t"~" || b'~'p
             end   /*k*/
       x5=;  do k=2  for #-1;  [email protected].k;   if \x.p  then iterate  /*build sexy P quints.   */
                               b=p- 6;  if \x.b  then iterate
                               t=p-12;  if \x.t  then iterate
                               q=p-18;  if \x.q  then iterate
                               v=p-24;  if \x.v  then iterate; x5=x5 v'~'q"~"t'~' || b"~"p
             end   /*k*/;    return


load "stdlib.ring"

primes = []
for n = 1 to 100
    if isprime(n)
       add(primes,n)
    ok
next

see "Sexy prime pairs under 100:" + nl + nl
for n = 1 to len(primes)-1
    for m = n + 1 to len(primes)
        if primes[m] - primes[n] = 6
           see "(" + primes[n] +  " " + primes[m] + ")" + nl
        ok
    next
next
see nl

see "Sexy prime triplets under 100:" + nl +nl
for n = 1 to len(primes)-2
    for m = n + 1 to len(primes)-1
        for x = m + 1 to len(primes)
            bool1 = (primes[m] - primes[n] = 6)
            bool2 = (primes[x] - primes[m] = 6)
            bool = bool1 and bool2
            if bool
               see "(" + primes[n] +  " " + primes[m] + " " + primes[x] + ")" + nl
            ok
        next
    next
next
see nl

see "Sexy prime quadruplets under 100:" + nl + nl
for n = 1 to len(primes)-3
    for m = n + 1 to len(primes)-2
        for x = m + 1 to len(primes)-1
            for y = m + 1 to len(primes)
                bool1 = (primes[m] - primes[n] = 6)
                bool2 = (primes[x] - primes[m] = 6)
                bool3 = (primes[y] - primes[x] = 6)
                bool = bool1 and bool2 and bool3
                if bool
                   see "(" + primes[n] +  " " + primes[m] + " " + primes[x] + " " + primes[y] + ")" + nl
                ok
             next
        next
    next
next
see nl

see "Sexy prime quintuplets under 100:" + nl + nl
for n = 1 to len(primes)-4
    for m = n + 1 to len(primes)-3
        for x = m + 1 to len(primes)-2
            for y = m + 1 to len(primes)-1
                for z = y + 1 to len(primes)
                    bool1 = (primes[m] - primes[n] = 6)
                    bool2 = (primes[x] - primes[m] = 6)
                    bool3 = (primes[y] - primes[x] = 6)
                    bool4 = (primes[z] - primes[y] = 6)
                    bool = bool1 and bool2 and bool3 and bool4
                    if bool
                       see "(" + primes[n] + " " + primes[m] + " " + primes[x] + " " +
                                 primes[y] + " " + primes[z] + ")" + nl
                    ok
                 next
             next
        next
    next
next


require 'prime'

prime_array, sppair2, sppair3, sppair4, sppair5 = Array.new(5) {Array.new()} # arrays for prime numbers and index number to array for each pair.
unsexy, i, start = [2], 0, Time.now
Prime.each(1_000_100) {|prime| prime_array.push prime}

while prime_array[i] < 1_000_035
  i+=1
  unsexy.push(i) if prime_array[(i+1)..(i+2)].include?(prime_array[i]+6) == false && prime_array[(i-2)..(i-1)].include?(prime_array[i]-6) == false && prime_array[i]+6 < 1_000_035
  prime_array[(i+1)..(i+4)].include?(prime_array[i]+6) && prime_array[i]+6 < 1_000_035 ? sppair2.push(i) : next
  prime_array[(i+2)..(i+5)].include?(prime_array[i]+12) && prime_array[i]+12 < 1_000_035 ? sppair3.push(i) : next
  prime_array[(i+3)..(i+6)].include?(prime_array[i]+18) && prime_array[i]+18 < 1_000_035 ? sppair4.push(i) : next
  prime_array[(i+4)..(i+7)].include?(prime_array[i]+24) && prime_array[i]+24 < 1_000_035 ? sppair5.push(i) : next
end

puts "\nSexy prime pairs: #{sppair2.size} found:"
sppair2.last(5).each {|prime| print [prime_array[prime], prime_array[prime]+6].join(" - "), "\n"}
puts "\nSexy prime triplets: #{sppair3.size} found:"
sppair3.last(5).each {|prime| print [prime_array[prime], prime_array[prime]+6, prime_array[prime]+12].join(" - "), "\n"}
puts "\nSexy prime quadruplets: #{sppair4.size} found:"
sppair4.last(5).each {|prime| print [prime_array[prime], prime_array[prime]+6, prime_array[prime]+12, prime_array[prime]+18].join(" - "), "\n"}
puts "\nSexy prime quintuplets: #{sppair5.size} found:"
sppair5.last(5).each {|prime| print [prime_array[prime], prime_array[prime]+6, prime_array[prime]+12, prime_array[prime]+18, prime_array[prime]+24].join(" - "), "\n"}

puts "\nUnSexy prime: #{unsexy.size} found. Last 10 are:"
unsexy.last(10).each {|item| print prime_array[item], " "}
print "\n\n", Time.now - start, " seconds"


// [dependencies]
// primal = "0.2"
// circular-queue = "0.2.5"

use circular_queue::CircularQueue;

fn main() {
    let max = 1000035;
    let max_group_size = 5;
    let diff = 6;
    let max_groups = 5;
    let max_unsexy = 10;

    let sieve = primal::Sieve::new(max + diff);
    let mut group_count = vec![0; max_group_size];
    let mut unsexy_count = 0;
    let mut groups = Vec::new();
    let mut unsexy_primes = CircularQueue::with_capacity(max_unsexy);

    for _ in 0..max_group_size {
        groups.push(CircularQueue::with_capacity(max_groups));
    }

    for p in sieve.primes_from(2).take_while(|x| *x < max) {
        if !sieve.is_prime(p + diff) && (p < diff + 2 || !sieve.is_prime(p - diff)) {
            unsexy_count += 1;
            unsexy_primes.push(p);
        } else {
            let mut group = Vec::new();
            group.push(p);
            for group_size in 1..max_group_size {
                let next = p + group_size * diff;
                if next >= max || !sieve.is_prime(next) {
                    break;
                }
                group.push(next);
                group_count[group_size] += 1;
                groups[group_size].push(group.clone());
            }
        }
    }

    for size in 1..max_group_size {
        println!(
            "Number of groups of size {} is {}",
            size + 1,
            group_count[size]
        );
        println!("Last {} groups of size {}:", groups[size].len(), size + 1);
        println!(
            "{}\n",
            groups[size]
                .asc_iter()
                .map(|g| format!("({})", to_string(&mut g.iter())))
                .collect::<Vec<String>>()
                .join(", ")
        );
    }
    println!("Number of unsexy primes is {}", unsexy_count);
    println!("Last {} unsexy primes:", unsexy_primes.len());
    println!("{}", to_string(&mut unsexy_primes.asc_iter()));
}

fn to_string<T: ToString>(iter: &mut dyn std::iter::Iterator<Item = T>) -> String {
    iter.map(|n| n.to_string())
        .collect::<Vec<String>>()
        .join(", ")
}


/* We could reduce the number of functions through a polymorphism since we're trying to retrieve sexy N-tuples (pairs, triplets etc...)
  but one practical solution would be to use the Shapeless library for this purpose; here we only use built-in Scala packages. */

object SexyPrimes {

  /** Check if an input number is prime or not*/
  def isPrime(n: Int): Boolean = ! ((2 until n-1) exists (n % _ == 0)) && n > 1

  /** Retrieve pairs of sexy primes given a list of Integers*/
  def getSexyPrimesPairs (primes : List[Int]) = {
    primes
      .map(n => if(primes.contains(n+6)) (n, n+6))
      .filter(p => p != ())
      .map{ case (a,b) => (a.toString.toInt, b.toString.toInt)}
  }

  /** Retrieve triplets of sexy primes given a list of Integers*/
  def getSexyPrimesTriplets (primes : List[Int]) = {
    primes
      .map(n => if(
        primes.contains(n+6) && primes.contains(n+12))
        (n, n+6, n+12)
      )
      .filter(p => p != ())
      .map{ case (a,b,c) => (a.toString.toInt, b.toString.toInt, c.toString.toInt)}
  }

  /** Retrieve quadruplets of sexy primes given a list of Integers*/
  def getSexyPrimesQuadruplets (primes : List[Int]) = {
    primes
      .map(n => if(
        primes.contains(n+6) && primes.contains(n+12) && primes.contains(n+18))
        (n, n+6, n+12, n+18)
      )
      .filter(p => p != ())
      .map{ case (a,b,c,d) => (a.toString.toInt, b.toString.toInt, c.toString.toInt, d.toString.toInt)}
  }

  /** Retrieve quintuplets of sexy primes given a list of Integers*/
  def getSexyPrimesQuintuplets (primes : List[Int]) = {
    primes
      .map(n => if (
        primes.contains(n+6) && primes.contains(n+12) && primes.contains(n+18) && primes.contains(n + 24))
        (n, n + 6, n + 12, n + 18, n + 24)
      )
      .filter(p => p != ())
      .map { case (a, b, c, d, e) => (a.toString.toInt, b.toString.toInt, c.toString.toInt, d.toString.toInt, e.toString.toInt) }

  }

  /** Retrieve all unsexy primes between 1 and a given limit from an input list of Integers*/
  def removeOutsideSexyPrimes( l : List[Int], limit : Int) : List[Int] = {
    l.filter(n => !isPrime(n+6) && n+6 < limit)
  }

  def main(args: Array[String]): Unit = {
    val limit = 1000035
    val l = List.range(1,limit)
    val primes = l.filter( n => isPrime(n))

    val sexyPairs = getSexyPrimesPairs(primes)
    println("Number of sexy pairs : " + sexyPairs.size)
    println("5 last sexy pairs : " + sexyPairs.takeRight(5))

    val primes2 = sexyPairs.flatMap(t => List(t._1, t._2)).distinct.sorted
    val sexyTriplets = getSexyPrimesTriplets(primes2)
    println("Number of sexy triplets : " + sexyTriplets.size)
    println("5 last sexy triplets : " + sexyTriplets.takeRight(5))

    val primes3 = sexyTriplets.flatMap(t => List(t._1, t._2, t._3)).distinct.sorted
    val sexyQuadruplets = getSexyPrimesQuadruplets(primes3)
    println("Number of sexy quadruplets : " + sexyQuadruplets.size)
    println("5 last sexy quadruplets : " + sexyQuadruplets.takeRight(5))

    val primes4 = sexyQuadruplets.flatMap(t => List(t._1, t._2, t._3, t._4)).distinct.sorted
    val sexyQuintuplets = getSexyPrimesQuintuplets(primes4)
    println("Number of sexy quintuplets : " + sexyQuintuplets.size)
    println("The last sexy quintuplet : " + sexyQuintuplets.takeRight(10))

    val sexyPrimes = primes2.toSet
    val unsexyPrimes = removeOutsideSexyPrimes( primes.toSet.diff((sexyPrimes)).toList.sorted, limit)
    println("Number of unsexy primes : " + unsexyPrimes.size)
    println("10 last unsexy primes : " + unsexyPrimes.takeRight(10))

  }

}


var limit  = 1e6+35
var primes = limit.primes

say "Total number of primes <= #{limit.commify} is #{primes.len.commify}."
say "Sexy k-tuple primes <= #{limit.commify}:\n"

(2..5).each {|k|
    var groups = []
    primes.each {|p|
        var group = (1..^k -> map {|j| 6*j + p })
        if (group.all{.is_prime} && (group[-1] <= limit)) {
            groups << [p, group...]
        }
    }

    say "...total number of sexy #{k}-tuple primes = #{groups.len.commify}"
    say "...where last 5 tuples are: #{groups.last(5).map{'('+.join(' ')+')'}.join(' ')}\n"
}

var unsexy_primes = primes.grep {|p| is_prime(p+6) || is_prime(p-6) -> not }
say "...total number of unsexy primes = #{unsexy_primes.len.commify}"
say "...where last 10 unsexy primes are: #{unsexy_primes.last(10)}"


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

var printHelper = Fn.new { |cat, le, lim, max|
    var cle = Fmt.commatize(le)
    var clim = Fmt.commatize(lim)
    if (cat != "unsexy primes") cat = "sexy prime " + cat
    System.print("Number of %(cat) less than %(clim) = %(cle)")
    var last = (le < max) ? le : max
    var verb = (last == 1) ? "is" : "are"
    return [le, last, verb]
}

var lim = 1000035
var sv = Int.primeSieve(lim-1, false)
var pairs = []
var trips = []
var quads = []
var quins = []
var unsexy = [2, 3]
var i = 3
while (i < lim) {
    if (i > 5 && i < lim-6 && !sv[i] && sv[i-6] && sv[i+6]) {
        unsexy.add(i)
    } else {
        if (i < lim-6 && !sv[i] && !sv[i+6]) {
            pairs.add([i, i+6])
            if (i < lim-12 && !sv[i+12]) {
                trips.add([i, i+6, i+12])
                if (i < lim-18 && !sv[i+18]) {
                    quads.add([i, i+6, i+12, i+18])
                    if (i < lim-24 && !sv[i+24]) {
                        quins.add([i, i+6, i+12, i+18, i+24])
                    }
                }
            }
        }
    }
    i = i + 2
}
var le
var n
var verb
var unwrap = Fn.new { |t|
    le = t[0]
    n = t[1]
    verb = t[2]
}

unwrap.call(printHelper.call("pairs", pairs.count, lim, 5))
System.print("The last %(n) %(verb):\n  %(pairs[le-n..-1])\n")

unwrap.call(printHelper.call("triplets", trips.count, lim, 5))
System.print("The last %(n) %(verb):\n  %(trips[le-n..-1])\n")

unwrap.call(printHelper.call("quadruplets", quads.count, lim, 5))
System.print("The last %(n) %(verb):\n  %(quads[le-n..-1])\n")

unwrap.call(printHelper.call("quintuplets", quins.count, lim, 5))
System.print("The last %(n) %(verb):\n  %(quins[le-n..-1])\n")

unwrap.call(printHelper.call("unsexy primes", unsexy.count, lim, 10))
System.print("The last %(n) %(verb):\n  %(unsexy[le-n..-1])\n")


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;
];

int CU, C2, C3, C4, C5, N, I;
int Unsexy(10), Pairs(5), Trips(5), Quads(5), Quins(5);
[CU:= 0;  C2:= 0;  C3:= 0;  C4:= 0;  C5:= 0;
for N:= 1000035 downto 2 do
    [if IsPrime(N) then
        [if IsPrime(N-6) then
                [if C2 < 5 then Pairs(C2):= N;
                C2:= C2+1;
                if IsPrime(N-12) then
                    [if C3 < 5 then Trips(C3):= N;
                    C3:= C3+1;
                    if IsPrime(N-18) then
                        [if C4 < 5 then Quads(C4):= N;
                        C4:= C4+1;
                        if IsPrime(N-24) then
                            [if C5 < 5 then Quins(C5):= N;
                            C5:= C5+1;
                            ];
                        ];
                    ];
                ]
        else    if not IsPrime(N+6) then
                    [if CU < 10 then Unsexy(CU):= N;
                    CU:= CU+1;
                    ];
        ];
    ];
IntOut(0, C2);  Text(0, " pairs ending with:^m^j");
for I:= 4 downto 0 do
        [Text(0, "  [");
        IntOut(0, Pairs(I)-6);  Text(0, ", ");
        IntOut(0, Pairs(I));    Text(0, "]^m^j");
        ];
IntOut(0, C3);  Text(0, " triplets ending with:^m^j");
for I:= 4 downto 0 do
        [Text(0, "  [");
        IntOut(0, Trips(I)-12);  Text(0, ", ");
        IntOut(0, Trips(I)-6);   Text(0, ", ");
        IntOut(0, Trips(I));     Text(0, "]^m^j");
        ];
IntOut(0, C4);  Text(0, " quadruplets ending with:^m^j");
for I:= 4 downto 0 do
        [Text(0, "  [");
        IntOut(0, Quads(I)-18);  Text(0, ", ");
        IntOut(0, Quads(I)-12);  Text(0, ", ");
        IntOut(0, Quads(I)-6);   Text(0, ", ");
        IntOut(0, Quads(I));     Text(0, "]^m^j");
        ];
IntOut(0, C5);  Text(0, " quintuplet(s) ending with:^m^j");
I:= if C5 > 5 then 5 else C5;
for I:= I-1 downto 0 do
        [Text(0, "  [");
        IntOut(0, Quins(I)-24);  Text(0, ", ");
        IntOut(0, Quins(I)-18);  Text(0, ", ");
        IntOut(0, Quins(I)-12);  Text(0, ", ");
        IntOut(0, Quins(I)-6);   Text(0, ", ");
        IntOut(0, Quins(I));     Text(0, "]^m^j");
        ];
IntOut(0, CU);  Text(0, " unsexy primes ending with:^m^j");
for I:= 9 downto 0 do
        [IntOut(0, Unsexy(I));  if I then Text(0, ", ")];
CrLf(0);
]


var [const] BI=Import("zklBigNum");  // libGMP
const N=1_000_035, M=N+24; // M allows prime group to span N, eg N=100, (97,103)
const OVR=6;	// 6 if prime group can NOT span N, else 0
ps,p := Data(M+50).fill(0), BI(1); // slop at the end (for reverse wrap around)
while(p.nextPrime()<=M){ ps[p]=1 } // bitmap of primes

ns:=(N-OVR).filter('wrap(n){ 2==(ps[n] + ps[n+6]) }); # know 2 isn't, check anyway
msg(N,"sexy prime pairs",ns,5,1);

ns:=[3..N-(6+OVR),2].filter('wrap(n){ 3==(ps[n] + ps[n+6] + ps[n+12]) }); # can't be even
msg(N,"sexy triplet primes",ns,5,2);

ns:=[3..N-(12+OVR),2].filter('wrap(n){ 4==(ps[n] + ps[n+6] + ps[n+12] + ps[n+18]) }); # no evens
msg(N,"sexy quadruplet primes",ns,5,3);

ns:=[3..N-(18+OVR),2].filter('wrap(n){ 5==(ps[n] + ps[n+6] + ps[n+12] + ps[n+18] + ps[n+24]) });
msg(N,"sexy quintuplet primes",ns,1,4);

ns:=(N-OVR).filter('wrap(n){ ps[n] and 0==(ps[n-6] + ps[n+6]) });  // include 2
msg(N,"unsexy primes",ns,10,0);

fcn msg(N,s,ps,n,g){
   n=n.min(ps.len());	// if the number of primes is less than n
   gs:=ps[-n,*].apply('wrap(n){ [0..g*6,6].apply('+(n)) })
       .pump(String,T("concat", ","),"(%s) ".fmt);
   println("Number of %s less than %,d is %,d".fmt(s,N,ps.len()));
   println("The last %d %s:\n  %s\n".fmt(n, (n>1 and "are" or "is"), gs));
}


/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program sha1_64.s   */

/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"

.equ SHA_DIGEST_LENGTH, 20

//.include "../../ficmacros64.s"

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessRosetta:         .asciz "Rosetta Code"
szMessTest1:           .asciz "abc"
szMessSup64:           .ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                       .ascii "abcdefghijklmnopqrstuvwxyz"
                       .asciz "1234567890AZERTYUIOP"
szMessTest2:           .asciz "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
szMessFinPgm:          .asciz "Program End ok.\n"
szMessResult:          .asciz "Rosetta Code => "
szCarriageReturn:      .asciz "\n"

/* array constantes Hi */
tbConstHi:           .int 0x67452301       // H0
                     .int 0xEFCDAB89       // H1
                     .int 0x98BADCFE       // H2
                     .int 0x10325476       // H3
                     .int 0xC3D2E1F0       // H4
/* array constantes Kt */
tbConstKt:           .int 0x5A827999
                     .int 0x6ED9EBA1
                     .int 0x8F1BBCDC
                     .int 0xCA62C1D6

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
iNbBlocs:                    .skip 8
sZoneConv:                   .skip 24
sZoneResult:                 .skip 24
sZoneTrav:                   .skip 1000
tbH:                         .skip 4 * 5         // 5 variables H
tbW:                         .skip 4 * 80        // 80 words W
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                      // entry of program

    ldr x0,qAdrszMessRosetta
    //ldr x0,qAdrszMessTest1
    //ldr x0,qAdrszMessTest2
    //ldr x0,qAdrszMessSup64
    bl computeSHA1                         // call routine SHA1

    ldr x0,qAdrszMessResult
    bl affichageMess                       // display message

    ldr x0, qAdrsZoneResult
    bl displaySHA1

    ldr x0,qAdrszMessFinPgm
    bl affichageMess                       // display message

100:                                       // standard end of the program
    mov x0,0                               // return code
    mov x8,EXIT                            // request to exit program
    svc 0                                  // perform the system call

qAdrszCarriageReturn:     .quad szCarriageReturn
qAdrszMessResult:         .quad szMessResult
qAdrszMessRosetta:        .quad szMessRosetta
qAdrszMessTest1:          .quad szMessTest1
qAdrszMessTest2:          .quad szMessTest2
qAdrsZoneTrav:            .quad sZoneTrav
qAdrsZoneConv:            .quad sZoneConv
qAdrszMessFinPgm:         .quad szMessFinPgm
qAdrszMessSup64:          .quad szMessSup64
/******************************************************************/
/*     compute SHA1                         */
/******************************************************************/
/* x0 contains the address of the message */
computeSHA1:
    stp x1,lr,[sp,-16]!       // save  registers
    ldr x1,qAdrsZoneTrav
    mov x2,#0                // counter length
debCopy:                     // copy string in work area
    ldrb w3,[x0,x2]
    strb w3,[x1,x2]
    cmp x3,#0
    add x4,x2,1
    csel x2,x4,x2,ne
    bne debCopy
    lsl x6,x2,#3             // initial message length in bits
    mov x3,#0b10000000       // add bit 1 at end of string
    strb w3,[x1,x2]
    add x2,x2,#1             // length in bytes
    lsl x4,x2,#3             // length in bits
    mov x3,#0
addZeroes:
    lsr x5,x2,#6
    lsl x5,x5,#6
    sub x5,x2,x5
    cmp x5,#56
    beq storeLength          // yes -> end add
    strb w3,[x1,x2]          // add zero at message end
    add x2,x2,#1                // increment lenght bytes
    add x4,x4,#8                // increment length in bits
    b addZeroes
storeLength:
    add x2,x2,#4                // add four bytes
    rev w6,w6                // inversion bits initials message length
    str w6,[x1,x2]           // and store at end

    ldr x7,qAdrtbConstHi     // constantes H address
    ldr x4,qAdrtbH           // start area H
    mov x5,#0
loopConst:                   // init array H with start constantes
    ldr w6,[x7,x5,lsl #2]    // load constante
    str w6,[x4,x5,lsl #2]    // and store
    add x5,x5,#1
    cmp x5,#5
    blt loopConst
                             // split into block of 64 bytes
    add x2,x2,#4                //  TODO : à revoir
    lsr x4,x2,#6             // blocks number
    ldr x0,qAdriNbBlocs
    str x4,[x0]              // save block maxi
    mov x7,#0                // n° de block et x1 contient l'adresse zone de travail
loopBlock:                   // begin loop of each block of 64 bytes
    mov x0,x7
    bl inversion             // inversion each word because little indian
    ldr x3,qAdrtbW           // working area W address
    mov x6,#0                // indice t
                             /* x2  address begin each block */
    ldr x1,qAdrsZoneTrav
    add x2,x1,x7,lsl #6      //  compute block begin  indice * 4 * 16

loopPrep:                    // loop for expand 80 words
    cmp x6,#15               //
    bgt expand1
    ldr w0,[x2,x6,lsl #2]    // load four byte message
    str w0,[x3,x6,lsl #2]    // store in first 16 block
    b expandEnd
expand1:
    sub x8,x6,#3
    ldr w9,[x3,x8,lsl #2]
    sub x8,x6,#8
    ldr w10,[x3,x8,lsl #2]
    eor x9,x9,x10
    sub x8,x6,#14
    ldr w10,[x3,x8,lsl #2]
    eor x9,x9,x10
    sub x8,x6,#16
    ldr w10,[x3,x8,lsl #2]
    eor x9,x9,x10
    ror w9,w9,#31

    str w9,[x3,x6,lsl #2]
expandEnd:
    add x6,x6,#1
    cmp x6,#80                 // 80 words ?
    blt loopPrep               // and loop
    /* COMPUTING THE MESSAGE DIGEST */
    /* x1  area H constantes address */
    /* x3  working area W address  */
    /* x5  address constantes K   */
    /* x6  counter t */
    /* x7  block counter */
    /* x8  a, x9 b, x10 c, x11 d, x12 e */

                               // init variable a b c d e
    ldr x0,qAdrtbH
    ldr w8,[x0]
    ldr w9,[x0,#4]
    ldr w10,[x0,#8]
    ldr w11,[x0,#12]
    ldr w12,[x0,#16]

    ldr x1,qAdrtbConstHi
    ldr x5,qAdrtbConstKt
    mov x6,#0
loop80T:                       // begin loop 80 t
    cmp x6,#19
    bgt T2
    ldr w0,[x5]                // load constantes k0
    and x2,x9,x10              // b and c
    mvn w4,w9                  // not b
    and x4,x4,x11              // and d
    orr x2,x2,x4
    b T_fin
T2:
    cmp x6,#39
    bgt T3
    ldr w0,[x5,#4]             // load constantes k1
    eor x2,x9,x10
    eor x2,x2,x11
    b T_fin
T3:
    cmp x6,#59
    bgt T4
    ldr w0,[x5,#8]             // load constantes k2
    and x2,x9,x10
    and x4,x9,x11
    orr x2,x2,x4
    and x4,x10,x11
    orr x2,x2,x4
    b T_fin
T4:
    ldr w0,[x5,#12]            // load constantes k3
    eor x2,x9,x10
    eor x2,x2,x11
    b T_fin
T_fin:
    ror w4,w8,#27            // left rotate a to 5
    add w2,w2,w4
    //affregtit Tfin 0
    //affregtit Tfin 8
    add w2,w2,w12
    ldr w4,[x3,x6,lsl #2]    // Wt
    add w2,w2,w4
    add w2,w2,w0                // Kt
    mov x12,x11              // e = d
    mov x11,x10              // d = c
    ror w10,w9,#2            // c
    mov x9,x8                // b = a
    mov x8,x2                // nouveau a

    add x6,x6,#1             // increment t
    cmp x6,#80
    blt loop80T
                             // other bloc
    add x7,x7,1                // increment block
    ldr x0,qAdriNbBlocs
    ldr w4,[x0]              // restaur maxi block
    cmp x7,x4                // maxi ?
    bge End
                             // End block
    ldr x0,qAdrtbH           // start area H
    ldr w3,[x0]
    add w3,w3,w8
    str w3,[x0]              // store a in H0
    ldr w3,[x0,#4]
    add w3,w3,w9
    str w3,[x0,#4]           // store b in H1
    ldr w3,[x0,#8]
    add w3,w3,w10
    str w3,[x0,#8]           // store c in H2
    ldr w3,[x0,#12]
    add w3,w3,w11
    str w3,[x0,#12]          // store d in H3
    ldr w3,[x0,#16]
    add w3,w3,w12
    str w3,[x0,#16]          // store e in H4
    b loopBlock              //  loop

End:
                             // compute final result
    ldr x0,qAdrtbH           // start area H
    ldr x2,qAdrsZoneResult
    ldr w1,[x0]
    add x1,x1,x8
    rev w1,w1
    str w1,[x2]
    ldr w1,[x0,#4]
    add x1,x1,x9
    rev w1,w1
    str w1,[x2,#4]
    ldr w1,[x0,#8]
    add x1,x1,x10
    rev w1,w1
    str w1,[x2,#8]
    ldr w1,[x0,#12]
    add x1,x1,x11
    rev w1,w1
    str w1,[x2,#12]
    ldr w1,[x0,#16]
    add x1,x1,x12
    rev w1,w1
    str w1,[x2,#16]
    mov x0,#0                    // routine OK
100:

    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
qAdrtbConstHi:            .quad tbConstHi
qAdrtbConstKt:            .quad tbConstKt
qAdrtbH:                  .quad tbH
qAdrtbW:                  .quad tbW
qAdrsZoneResult:          .quad sZoneResult
qAdriNbBlocs:             .quad iNbBlocs
/******************************************************************/
/*     inversion des mots de 32 bits d'un bloc                    */
/******************************************************************/
/* x0 contains N° block   */
inversion:
    stp x1,lr,[sp,-16]!          // save  registers
    stp x2,x3,[sp,-16]!          // save  registers
    ldr x1,qAdrsZoneTrav
    add x1,x1,x0,lsl 6           // debut du bloc
    mov x2,#0
1:                               // start loop
    ldr w3,[x1,x2,lsl #2]
    rev w3,w3
    str w3,[x1,x2,lsl #2]
    add x2,x2,#1
    cmp x2,#16
    blt 1b
100:
    ldp x2,x3,[sp],16            // restaur  2 registers
    ldp x1,lr,[sp],16            // restaur  2 registers
    ret                          // return to address lr x30
/******************************************************************/
/*     display hash  SHA1                         */
/******************************************************************/
/* x0 contains the address of hash  */
displaySHA1:
    stp x1,lr,[sp,-16]!       // save  registers
    stp x2,x3,[sp,-16]!       // save  registers
    mov x3,x0
    mov x2,#0
1:
    ldr w0,[x3,x2,lsl #2]          // load 4 bytes
    rev w0,w0                      // reverse bytes
    ldr x1,qAdrsZoneConv
    bl conversion16_4W                // conversion hexa
    ldr x0,qAdrsZoneConv
    bl affichageMess
    add x2,x2,#1
    cmp x2,#SHA_DIGEST_LENGTH / 4
    blt 1b                         // and loop
    ldr x0,qAdrszCarriageReturn
    bl affichageMess               // display message
100:
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/******************************************************************/
/*     conversion  hexadecimal register 32 bits                   */
/******************************************************************/
/* x0 contains value and x1 address zone receptrice   */
conversion16_4W:
    stp x0,lr,[sp,-48]!        // save  registres
    stp x1,x2,[sp,32]          // save  registres
    stp x3,x4,[sp,16]          // save  registres
    mov x2,#28                 // start bit position
    mov x4,#0xF0000000         // mask
    mov x3,x0                  // save entry value
1:                             // start loop
    and x0,x3,x4               // value register and mask
    lsr x0,x0,x2               // right shift
    cmp x0,#10                 // >= 10 ?
    bge 2f                     // yes
    add x0,x0,#48              // no is digit
    b 3f
2:
    add x0,x0,#55              // else is a letter A-F
3:
    strb w0,[x1],#1            // load result  and + 1 in address
    lsr x4,x4,#4               // shift mask 4 bits left
    subs x2,x2,#4              // decrement counter 4 bits <= zero  ?
    bge 1b                     // no -> loop

100:                           // fin standard de la fonction
    ldp x3,x4,[sp,16]          // restaur des  2 registres
    ldp x1,x2,[sp,32]          // restaur des  2 registres
    ldp x0,lr,[sp],48          // restaur des  2 registres
    ret
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"


with Ada.Text_IO;
with GNAT.SHA1;

procedure Main is
begin
   Ada.Text_IO.Put_Line ("SHA1 (""Rosetta Code"") = " &
                         GNAT.SHA1.Digest ("Rosetta Code"));
end Main;


/* ARM assembly Raspberry PI  */
/*  program sha1-1.s   */
/* use with library openssl */
/* link with gcc option  -lcrypto -lssl  */

/* REMARK 1 : this program use routines in a include file
   see task Include a file language arm assembly
   for the routine affichageMess conversion10
   see at end of this program the instruction include */

/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"

.equ SHA_DIGEST_LENGTH, 20

/*******************************************/
/* Fichier des macros                       */
/********************************************/
.include "../../ficmacros.s"

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessRosetta:        .asciz "Rosetta Code"
                      .equ LGMESSROSETTA, . - szMessRosetta - 1
szCarriageReturn:     .asciz "\n"
szMessSup64:          .ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                      .ascii "abcdefghijklmnopqrstuvwxyz"
                      .asciz "1234567890AZERTYUIOP"
                      .equ LGMESSSUP64, . - szMessSup64 - 1
szMessTest2:          .asciz "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
                      .equ LGMESSTEST2,  . - szMessTest2 - 1

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
szMessResult:              .skip 24
sZoneConv:                 .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                      @ entry of program

    ldr r0,iAdrszMessRosetta
    mov r1,#LGMESSROSETTA
    ldr r2,iAdrszMessResult
    bl SHA1                                @ appel fonction openssl
    ldr r0,iAdrszMessResult
    bl displaySHA1

100:                                       @ standard end of the program
    mov r0, #0                             @ return code
    mov r7, #EXIT                          @ request to exit program
    svc #0                                 @ perform the system call

iAdrszMessRosetta:        .int szMessRosetta
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrszMessResult:         .int szMessResult
iAdrsZoneConv:            .int sZoneConv
iAdrszMessSup64:          .int szMessSup64
iAdrszMessTest2:          .int szMessTest2
/******************************************************************/
/*     display hash  SHA1                         */
/******************************************************************/
/* r0 contains the address of hash  */
displaySHA1:
    push {r1-r3,lr}                  @ save  registres
    mov r3,r0
    mov r2,#0
1:
    ldr r0,[r3,r2,lsl #2]            @ load 4 bytes
    rev r0,r0                        @ reverse bytes
    ldr r1,iAdrsZoneConv
    bl conversion16                  @ conversion hexa
    ldr r0,iAdrsZoneConv
    bl affichageMess
    add r2,r2,#1
    cmp r2,#SHA_DIGEST_LENGTH / 4
    blt 1b                           @ and loop
    ldr r0,iAdrszCarriageReturn
    bl affichageMess                 @ display message
100:
    pop {r1-r3,lr}                   @ restaur registers
    bx lr                            @ return
/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "../affichage.inc"


print digest.sha "The quick brown fox jumped over the lazy dog's back"


import crypto { sha1 }
let hash = sha1.hexdigest('Ars longa, vita brevis')
print hash


str := "Rosetta Code"
MsgBox, % "String:`n" (str) "`n`nSHA:`n" SHA(str)

; SHA ===============================================================================
SHA(string, encoding = "utf-8")
{
    return CalcStringHash(string, 0x8004, encoding)
}

; CalcAddrHash ======================================================================
CalcAddrHash(addr, length, algid, byref hash = 0, byref hashlength = 0)
{
    static h := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F"]
    static b := h.minIndex()
    o := ""
    if (DllCall("advapi32\CryptAcquireContext", "Ptr*", hProv, "Ptr", 0, "Ptr", 0, "UInt", 24, "UInt", 0xF0000000))
    {
        if (DllCall("advapi32\CryptCreateHash", "Ptr", hProv, "UInt", algid, "UInt", 0, "UInt", 0, "Ptr*", hHash))
        {
            if (DllCall("advapi32\CryptHashData", "Ptr", hHash, "Ptr", addr, "UInt", length, "UInt", 0))
            {
                if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", 0, "UInt*", hashlength, "UInt", 0))
                {
                    VarSetCapacity(hash, hashlength, 0)
                    if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", &hash, "UInt*", hashlength, "UInt", 0))
                    {
                        loop, % hashlength
                        {
                            v := NumGet(hash, A_Index - 1, "UChar")
                            o .= h[(v >> 4) + b] h[(v & 0xf) + b]
                        }
                    }
                }
            }
            DllCall("advapi32\CryptDestroyHash", "Ptr", hHash)
        }
        DllCall("advapi32\CryPtreleaseContext", "Ptr", hProv, "UInt", 0)
    }
    return o
}

; CalcStringHash ====================================================================
CalcStringHash(string, algid, encoding = "utf-8", byref hash = 0, byref hashlength = 0)
{
    chrlength := (encoding = "cp1200" || encoding = "utf-16") ? 2 : 1
    length := (StrPut(string, encoding) - 1) * chrlength
    VarSetCapacity(data, length, 0)
    StrPut(string, &data, floor(length / chrlength), encoding)
    return CalcAddrHash(&data, length, algid, hash, hashlength)
}


      PRINT FNsha1("Rosetta Code")
      END

      DEF FNsha1(message$)
      LOCAL buflen%, buffer%, hprov%, hhash%, hash$, i%
      CALG_SHA1 = &8004
      CRYPT_VERIFYCONTEXT = &F0000000
      HP_HASHVAL = 2
      PROV_RSA_FULL = 1
      buflen% = 64
      DIM buffer% LOCAL buflen%-1
      SYS "CryptAcquireContext", ^hprov%, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT
      SYS "CryptCreateHash", hprov%, CALG_SHA1, 0, 0, ^hhash%
      SYS "CryptHashData", hhash%, message$, LEN(message$), 0
      SYS "CryptGetHashParam", hhash%, HP_HASHVAL, buffer%, ^buflen%, 0
      SYS "CryptDestroyHash", hhash%
      SYS "CryptReleaseContext", hprov%
      FOR i% = 0 TO buflen%-1
        hash$ += RIGHT$("0" + STR$~buffer%?i%, 2)
      NEXT
      = hash$


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>

int main()
{
  int i;
  unsigned char result[SHA_DIGEST_LENGTH];
  const char *string = "Rosetta Code";

  SHA1(string, strlen(string), result);

  for(i = 0; i < SHA_DIGEST_LENGTH; i++)
    printf("%02x%c", result[i], i < (SHA_DIGEST_LENGTH-1) ? ' ' : '\n');

  return EXIT_SUCCESS;
}


using System;
using System.Security.Cryptography;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace RosettaCode.SHA1
{
    [TestClass]
    public class SHA1CryptoServiceProviderTest
    {
        [TestMethod]
        public void TestComputeHash()
        {
            var input = new UTF8Encoding().GetBytes("Rosetta Code");
            var output = new SHA1CryptoServiceProvider().ComputeHash(input);
            Assert.AreEqual(
                "48-C9-8F-7E-5A-6E-73-6D-79-0A-B7-40-DF-C3-F5-1A-61-AB-E2-B5",
                BitConverter.ToString(output));
        }
    }
}


#include <string>
#include <iostream>
#include "Poco/SHA1Engine.h"
#include "Poco/DigestStream.h"

using Poco::DigestEngine ;
using Poco::SHA1Engine ;
using Poco::DigestOutputStream ;

int main( ) {
   std::string myphrase ( "Rosetta Code" ) ;
   SHA1Engine sha1 ;
   DigestOutputStream outstr( sha1 ) ;
   outstr << myphrase ;
   outstr.flush( ) ; //to pass everything to the digest engine
   const DigestEngine::Digest& digest = sha1.digest( ) ;
   std::cout << myphrase << " as a sha1 digest :" << DigestEngine::digestToHex( digest )
      << " !" << std::endl ;
   return 0 ;
}


USER>set hash=$System.Encryption.SHA1Hash("Rosetta Code")
USER>zzdump hash
0000: 48 C9 8F 7E 5A 6E 73 6D 79 0A B7 40 DF C3 F5 1A
0010: 61 AB E2 B5


;;; in addition to sha1, ironclad provides sha224, sha256, sha384, and sha512.
(defun sha1-hash (data)
  (let ((sha1 (ironclad:make-digest 'ironclad:sha1))
        (bin-data (ironclad:ascii-string-to-byte-array data)))
    (ironclad:update-digest sha1 bin-data)
    (ironclad:byte-array-to-hex-string (ironclad:produce-digest sha1))))


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

struct RealSet {
    bool(*contains)(struct RealSet*, struct RealSet*, double);
    struct RealSet *left;
    struct RealSet *right;
    double low, high;
};

typedef enum {
    CLOSED,
    LEFT_OPEN,
    RIGHT_OPEN,
    BOTH_OPEN,
} RangeType;

double length(struct RealSet *self) {
    const double interval = 0.00001;
    double p = self->low;
    int count = 0;

    if (isinf(self->low) || isinf(self->high)) return -1.0;
    if (self->high <= self->low) return 0.0;

    do {
        if (self->contains(self, NULL, p)) count++;
        p += interval;
    } while (p < self->high);
    return count * interval;
}

bool empty(struct RealSet *self) {
    if (self->low == self->high) {
        return !self->contains(self, NULL, self->low);
    }
    return length(self) == 0.0;
}

static bool contains_closed(struct RealSet *self, struct RealSet *_, double d) {
    return self->low <= d && d <= self->high;
}

static bool contains_left_open(struct RealSet *self, struct RealSet *_, double d) {
    return self->low < d && d <= self->high;
}

static bool contains_right_open(struct RealSet *self, struct RealSet *_, double d) {
    return self->low <= d && d < self->high;
}

static bool contains_both_open(struct RealSet *self, struct RealSet *_, double d) {
    return self->low < d && d < self->high;
}

static bool contains_intersect(struct RealSet *self, struct RealSet *_, double d) {
    return self->left->contains(self->left, NULL, d) && self->right->contains(self->right, NULL, d);
}

static bool contains_union(struct RealSet *self, struct RealSet *_, double d) {
    return self->left->contains(self->left, NULL, d) || self->right->contains(self->right, NULL, d);
}

static bool contains_subtract(struct RealSet *self, struct RealSet *_, double d) {
    return self->left->contains(self->left, NULL, d) && !self->right->contains(self->right, NULL, d);
}

struct RealSet* makeSet(double low, double high, RangeType type) {
    bool(*contains)(struct RealSet*, struct RealSet*, double);
    struct RealSet *rs;

    switch (type) {
    case CLOSED:
        contains = contains_closed;
        break;
    case LEFT_OPEN:
        contains = contains_left_open;
        break;
    case RIGHT_OPEN:
        contains = contains_right_open;
        break;
    case BOTH_OPEN:
        contains = contains_both_open;
        break;
    default:
        return NULL;
    }

    rs = malloc(sizeof(struct RealSet));
    rs->contains = contains;
    rs->left = NULL;
    rs->right = NULL;
    rs->low = low;
    rs->high = high;
    return rs;
}

struct RealSet* makeIntersect(struct RealSet *left, struct RealSet *right) {
    struct RealSet *rs = malloc(sizeof(struct RealSet));
    rs->contains = contains_intersect;
    rs->left = left;
    rs->right = right;
    rs->low = fmin(left->low, right->low);
    rs->high = fmin(left->high, right->high);
    return rs;
}

struct RealSet* makeUnion(struct RealSet *left, struct RealSet *right) {
    struct RealSet *rs = malloc(sizeof(struct RealSet));
    rs->contains = contains_union;
    rs->left = left;
    rs->right = right;
    rs->low = fmin(left->low, right->low);
    rs->high = fmin(left->high, right->high);
    return rs;
}

struct RealSet* makeSubtract(struct RealSet *left, struct RealSet *right) {
    struct RealSet *rs = malloc(sizeof(struct RealSet));
    rs->contains = contains_subtract;
    rs->left = left;
    rs->right = right;
    rs->low = left->low;
    rs->high = left->high;
    return rs;
}

int main() {
    struct RealSet *a = makeSet(0.0, 1.0, LEFT_OPEN);
    struct RealSet *b = makeSet(0.0, 2.0, RIGHT_OPEN);
    struct RealSet *c = makeSet(1.0, 2.0, LEFT_OPEN);
    struct RealSet *d = makeSet(0.0, 3.0, RIGHT_OPEN);
    struct RealSet *e = makeSet(0.0, 1.0, BOTH_OPEN);
    struct RealSet *f = makeSet(0.0, 1.0, CLOSED);
    struct RealSet *g = makeSet(0.0, 0.0, CLOSED);
    int i;

    for (i = 0; i < 3; ++i) {
        struct RealSet *t;

        t = makeUnion(a, b);
        printf("(0, 1]   union   [0, 2) contains %d is %d\n", i, t->contains(t, NULL, i));
        free(t);

        t = makeIntersect(b, c);
        printf("[0, 2) intersect (1, 2] contains %d is %d\n", i, t->contains(t, NULL, i));
        free(t);

        t = makeSubtract(d, e);
        printf("[0, 3)     -     (0, 1) contains %d is %d\n", i, t->contains(t, NULL, i));
        free(t);

        t = makeSubtract(d, f);
        printf("[0, 3)     -     [0, 1] contains %d is %d\n", i, t->contains(t, NULL, i));
        free(t);

        printf("\n");
    }

    printf("[0, 0] is empty %d\n", empty(g));

    free(a);
    free(b);
    free(c);
    free(d);
    free(e);
    free(f);
    free(g);

    return 0;
}


require "openssl"
puts OpenSSL::Digest.new("sha1").update("Rosetta Code")


void main() {
    import std.stdio, std.digest.sha;

    writefln("%-(%02x%)", "Ars longa, vita brevis".sha1Of);
}


using System;

namespace RosettaCode.SetOfRealNumbers
{
    public class Set<TValue>
    {
        public Set(Predicate<TValue> contains)
        {
            Contains = contains;
        }

        public Predicate<TValue> Contains
        {
            get;
            private set;
        }

        public Set<TValue> Union(Set<TValue> set)
        {
            return new Set<TValue>(value => Contains(value) || set.Contains(value));
        }

        public Set<TValue> Intersection(Set<TValue> set)
        {
            return new Set<TValue>(value => Contains(value) && set.Contains(value));
        }

        public Set<TValue> Difference(Set<TValue> set)
        {
            return new Set<TValue>(value => Contains(value) && !set.Contains(value));
        }
    }
}


#include <cassert>
#include <functional>
#include <iostream>

#define _USE_MATH_DEFINES
#include <math.h>

enum RangeType {
    CLOSED,
    BOTH_OPEN,
    LEFT_OPEN,
    RIGHT_OPEN
};

class RealSet {
private:
    double low, high;
    double interval = 0.00001;
    std::function<bool(double)> predicate;

public:
    RealSet(double low, double high, const std::function<bool(double)>& predicate) {
        this->low = low;
        this->high = high;
        this->predicate = predicate;
    }

    RealSet(double start, double end, RangeType rangeType) {
        low = start;
        high = end;

        switch (rangeType) {
        case CLOSED:
            predicate = [start, end](double d) { return start <= d && d <= end; };
            break;
        case BOTH_OPEN:
            predicate = [start, end](double d) { return start < d && d < end; };
            break;
        case LEFT_OPEN:
            predicate = [start, end](double d) { return start < d && d <= end; };
            break;
        case RIGHT_OPEN:
            predicate = [start, end](double d) { return start <= d && d < end; };
            break;
        default:
            assert(!"Unexpected range type encountered.");
        }
    }

    bool contains(double d) const {
        return predicate(d);
    }

    RealSet unionSet(const RealSet& rhs) const {
        double low2 = fmin(low, rhs.low);
        double high2 = fmax(high, rhs.high);
        return RealSet(
            low2, high2,
            [this, &rhs](double d) { return predicate(d) || rhs.predicate(d); }
        );
    }

    RealSet intersect(const RealSet& rhs) const {
        double low2 = fmin(low, rhs.low);
        double high2 = fmax(high, rhs.high);
        return RealSet(
            low2, high2,
            [this, &rhs](double d) { return predicate(d) && rhs.predicate(d); }
        );
    }

    RealSet subtract(const RealSet& rhs) const {
        return RealSet(
            low, high,
            [this, &rhs](double d) { return predicate(d) && !rhs.predicate(d); }
        );
    }

    double length() const {
        if (isinf(low) || isinf(high)) return -1.0; // error value
        if (high <= low) return 0.0;

        double p = low;
        int count = 0;
        do {
            if (predicate(p)) count++;
            p += interval;
        } while (p < high);
        return count * interval;
    }

    bool empty() const {
        if (high == low) {
            return !predicate(low);
        }
        return length() == 0.0;
    }
};

int main() {
    using namespace std;

    RealSet a(0.0, 1.0, LEFT_OPEN);
    RealSet b(0.0, 2.0, RIGHT_OPEN);
    RealSet c(1.0, 2.0, LEFT_OPEN);
    RealSet d(0.0, 3.0, RIGHT_OPEN);
    RealSet e(0.0, 1.0, BOTH_OPEN);
    RealSet f(0.0, 1.0, CLOSED);
    RealSet g(0.0, 0.0, CLOSED);

    for (int i = 0; i <= 2; ++i) {
        cout << "(0, 1] ∪ [0, 2) contains " << i << " is " << boolalpha << a.unionSet(b).contains(i) << "\n";
        cout << "[0, 2) ∩ (1, 2] contains " << i << " is " << boolalpha << b.intersect(c).contains(i) << "\n";
        cout << "[0, 3) - (0, 1) contains " << i << " is " << boolalpha << d.subtract(e).contains(i) << "\n";
        cout << "[0, 3) - [0, 1] contains " << i << " is " << boolalpha << d.subtract(f).contains(i) << "\n";
        cout << endl;
    }

    cout << "[0, 0] is empty is " << boolalpha << g.empty() << "\n";
    cout << endl;

    RealSet aa(
        0.0, 10.0,
        [](double x) { return (0.0 < x && x < 10.0) && abs(sin(M_PI * x * x)) > 0.5; }
    );
    RealSet bb(
        0.0, 10.0,
        [](double x) { return (0.0 < x && x < 10.0) && abs(sin(M_PI * x)) > 0.5; }
    );
    auto cc = aa.subtract(bb);
    cout << "Approximate length of A - B is " << cc.length() << endl;

    return 0;
}


program Sha_1;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  DCPsha1;

function SHA1(const Str: string): string;
var
  HashDigest: array of byte;
  d: Byte;
begin
  Result := '';
  with TDCP_sha1.Create(nil) do
  begin
    Init;
    UpdateStr(Str);
    SetLength(HashDigest, GetHashSize div 8);
    final(HashDigest[0]);
    for d in HashDigest do
      Result := Result + d.ToHexString(2);
    Free;
  end;
end;

begin
  Writeln(SHA1('Rosetta Code'));
  readln;
end.


PrintLn( HashSHA1.HashData('Rosetta code') );


(sha1 "Rosetta Code") ;=> "48c98f7e5a6e736d790ab740dfc3f51a61abe2b5"
(secure-hash 'sha1 "Rosetta Code") ;=> "48c98f7e5a6e736d790ab740dfc3f51a61abe2b5"


let n = System.Security.Cryptography.SHA1.Create()
Array.iter (printf "%x ") (n.ComputeHash "Rosetta Code"B)


(deftype set== (a b) `(real ,a ,b))
(deftype set<> (a b) `(real (,a) (,b)))
(deftype set=> (a b) `(real ,a (,b)))
(deftype set<= (a b) `(real (,a) ,b))

(deftype set-union (s1 s2) `(or ,s1 ,s2))
(deftype set-intersection (s1 s2) `(and ,s1 ,s2))
(deftype set-diff (s1 s2) `(and ,s1 (not ,s2)))

(defun in-set-p (x set)
  (typep x set))

(defun test ()
  (let ((set '(set-union (set<= 0 1) (set=> 0 2))))
    (assert (in-set-p 0 set))
    (assert (in-set-p 1 set))
    (assert (not (in-set-p 2 set))))
  (let ((set '(set-intersection (set=> 0 2) (set<= 1 2))))
    (assert (not (in-set-p 0 set)))
    (assert (not (in-set-p 1 set)))
    (assert (not (in-set-p 2 set))))
  (let ((set '(set-diff (set=> 0 3) (set<> 0 1))))
    (assert (in-set-p 0 set))
    (assert (in-set-p 1 set))
    (assert (in-set-p 2 set)))
  (let ((set '(set-diff (set<= 0 3) (set== 0 1))))
    (assert (not (in-set-p 0 set)))
    (assert (not (in-set-p 1 set)))
    (assert (in-set-p 2 set))))


IN: scratchpad USING: checksums checksums.sha ;
IN: scratchpad "Rosetta Code" sha1 checksum-bytes hex-string .
"48c98f7e5a6e736d790ab740dfc3f51a61abe2b5"


module sha1_mod
    use kernel32
    use advapi32
    implicit none
    integer, parameter :: SHA1LEN = 20
contains
    subroutine sha1hash(name, hash, dwStatus, filesize)
        implicit none
        character(*) :: name
        integer, parameter :: BUFLEN = 32768
        integer(HANDLE) :: hFile, hProv, hHash
        integer(DWORD) :: dwStatus, nRead
        integer(BOOL) :: status
        integer(BYTE) :: buffer(BUFLEN)
        integer(BYTE) :: hash(SHA1LEN)
        integer(UINT64) :: filesize

        dwStatus = 0
        filesize = 0
        hFile = CreateFile(trim(name) // char(0), GENERIC_READ, FILE_SHARE_READ, NULL, &
                           OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)

        if (hFile == INVALID_HANDLE_VALUE) then
            dwStatus = GetLastError()
            print *, "CreateFile failed."
            return
        end if

        if (CryptAcquireContext(hProv, NULL, NULL, PROV_RSA_FULL, &
                                CRYPT_VERIFYCONTEXT) == FALSE) then

            dwStatus = GetLastError()
            print *, "CryptAcquireContext failed."
            goto 3
        end if

        if (CryptCreateHash(hProv, CALG_SHA1, 0_ULONG_PTR, 0_DWORD, hHash) == FALSE) then

            dwStatus = GetLastError()
            print *, "CryptCreateHash failed."
            go to 2
        end if

        do
            status = ReadFile(hFile, loc(buffer), BUFLEN, nRead, NULL)
            if (status == FALSE .or. nRead == 0) exit
            filesize = filesize + nRead
            if (CryptHashData(hHash, buffer, nRead, 0) == FALSE) then
                dwStatus = GetLastError()
                print *, "CryptHashData failed."
                go to 1
            end if
        end do

        if (status == FALSE) then
            dwStatus = GetLastError()
            print *, "ReadFile failed."
            go to 1
        end if

        nRead = SHA1LEN
        if (CryptGetHashParam(hHash, HP_HASHVAL, hash, nRead, 0) == FALSE) then
            dwStatus = GetLastError()
            print *, "CryptGetHashParam failed.", status, nRead, dwStatus
        end if

      1 status = CryptDestroyHash(hHash)
      2 status = CryptReleaseContext(hProv, 0)
      3 status = CloseHandle(hFile)
    end subroutine
end module

program sha1
    use sha1_mod
    implicit none
    integer :: n, m, i, j
    character(:), allocatable :: name
    integer(DWORD) :: dwStatus
    integer(BYTE) :: hash(SHA1LEN)
    integer(UINT64) :: filesize

    n = command_argument_count()
    do i = 1, n
        call get_command_argument(i, length=m)
        allocate(character(m) :: name)
        call get_command_argument(i, name)
        call sha1hash(name, hash, dwStatus, filesize)
        if (dwStatus == 0) then
            do j = 1, SHA1LEN
                write(*, "(Z2.2)", advance="NO") hash(j)
            end do
            write(*, "(' ',A,' (',G0,' bytes)')") name, filesize
        end if
        deallocate(name)
    end do
end program


struct Set(T) {
    const pure nothrow bool delegate(in T) contains;

    bool opIn_r(in T x) const pure nothrow {
        return contains(x);
    }

    Set opBinary(string op)(in Set set)
    const pure nothrow if (op == "+" || op == "-") {
        static if (op == "+")
            return Set(x => contains(x) || set.contains(x));
        else
            return Set(x => contains(x) && !set.contains(x));
    }

    Set intersection(in Set set) const pure nothrow {
        return Set(x => contains(x) && set.contains(x));
    }
}

unittest { // Test union.
    alias DSet = Set!double;
    const s = DSet(x => 0.0 < x && x <= 1.0) +
              DSet(x => 0.0 <= x && x < 2.0);
    assert(0.0 in s);
    assert(1.0 in s);
    assert(2.0 !in s);
}

unittest { // Test difference.
    alias DSet = Set!double;
    const s1 = DSet(x => 0.0 <= x && x < 3.0) -
               DSet(x => 0.0 < x && x < 1.0);
    assert(0.0 in s1);
    assert(0.5 !in s1);
    assert(1.0 in s1);
    assert(2.0 in s1);

    const s2 = DSet(x => 0.0 <= x && x < 3.0) -
               DSet(x => 0.0 <= x && x <= 1.0);
    assert(0.0 !in s2);
    assert(1.0 !in s2);
    assert(2.0 in s2);

    const s3 = DSet(x => 0 <= x && x <= double.infinity) -
               DSet(x => 1.0 <= x && x <= 2.0);
    assert(0.0 in s3);
    assert(1.5 !in s3);
    assert(3.0 in s3);
}

unittest { // Test intersection.
    alias DSet = Set!double;
    const s = DSet(x => 0.0 <= x && x < 2.0).intersection(
              DSet(x => 1.0 < x && x <= 2.0));
    assert(0.0 !in s);
    assert(1.0 !in s);
    assert(2.0 !in s);
}

void main() {}


' version 18-10-2016
' started with SHA-1/FIPS-180-1
' but used the BBC BASIC native version to finish.
' compile with: fbc -s console

Function SHA_1(test_str As String) As String

  Dim As String message = test_str   ' strings are passed as ByRef's

  Dim As Long i, j
  Dim As UByte Ptr ww1
  Dim As UInteger<32> Ptr ww4

  Dim As ULongInt l = Len(message)
  ' set the first bit after the message to 1
  message = message + Chr(1 Shl 7)
  ' add one char to the length
  Dim As ULong padding = 64 - ((l +1) Mod (512 \ 8)) ' 512 \ 8 = 64 char.

  ' check if we have enough room for inserting the length
  If padding < 8 Then padding = padding + 64

  message = message + String(padding, Chr(0))   ' adjust length
  Dim As ULong l1 = Len(message)                ' new length

  l = l * 8    ' orignal length in bits
  ' create ubyte ptr to point to l ( = length in bits)
  Dim As UByte Ptr ub_ptr = Cast(UByte Ptr, @l)

  For i = 0 To 7  'copy length of message to the last 8 bytes
    message[l1 -1 - i] = ub_ptr[i]
  Next

  Dim As UInteger<32> A, B, C, D, E, k, temp, W(0 To 79)
  Dim As UInteger<32> H0 = &H67452301
  Dim As UInteger<32> H1 = &HEFCDAB89
  Dim As UInteger<32> H2 = &H98BADCFE
  Dim As UInteger<32> H3 = &H10325476
  Dim As UInteger<32> H4 = &HC3D2E1F0

  For j = 0 To (l1 -1) \ 64 ' split into block of 64 bytes
    ww1 = Cast(Ubyte Ptr, @message[j * 64])
    ww4 = Cast(UInteger<32> Ptr, @message[j * 64])

    For i = 0 To 60 Step 4  'little endian -> big endian
      Swap ww1[i   ], ww1[i +3]
      Swap ww1[i +1], ww1[i +2]
    Next

    For i = 0 To 15    ' copy the 16 32bit block into the array
      W(i) = ww4[i]
    Next

    For i = 16 To 79   ' fill the rest of the array
      temp = W(i -3) Xor W(i -8) Xor W(i -14) Xor W(i -16)
      temp = temp Shl 1 + temp Shr 31
      W(i) = temp
    Next

    A = h0 : B = h1 : C = h2 : D = h3 : E = h4

    For i = 0 To 79
      Select Case As Const i
        Case 0 To 19
          temp = (B And C) or ((Not B) And D)
          k = &H5A827999
        Case 20 To 39
          temp = B Xor C Xor D
          k = &H6ED9EBA1
        Case 40 To 59
          temp = (B And C) Or (B And D) Or (C And D)
          k = &H8F1BBCDC
        Case 60 To 79
          temp = B Xor C Xor D
          k = &hCA62C1D6
      End Select

      temp = A Shl 5 + A Shr 27 + temp + E + k + W(i)
      E = D
      D = C
      C = (B Shl 30) or (B Shr 2)
      B = A
      A = temp

    Next

    h0 += A : h1 += B : h2 += C : h3 += D : h4 += E

  Next

  Return Hex(h0, 8) + Hex(h1, 8) + Hex(h2, 8) + Hex(h3, 8) + Hex(h4, 8)

End Function

' ------=< MAIN >=------

Dim As String test = "Rosetta Code"
Print test; " => "; SHA_1(test)

' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End


program Set_of_real_numbers;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

type
  TSet = TFunc<Double, boolean>;

function Union(a, b: TSet): TSet;
begin
  Result :=
    function(x: double): boolean
    begin
      Result := a(x) or b(x);
    end;
end;

function Inter(a, b: TSet): TSet;
begin
  Result :=
    function(x: double): boolean
    begin
      Result := a(x) and b(x);
    end;
end;

function Diff(a, b: TSet): TSet;
begin
  Result :=
    function(x: double): boolean
    begin
      Result := a(x) and not b(x);
    end;
end;

function Open(a, b: double): TSet;
begin
  Result :=
    function(x: double): boolean
    begin
      Result := (a < x) and (x < b);
    end;
end;

function closed(a, b: double): TSet;
begin
  Result :=
    function(x: double): boolean
    begin
      Result := (a <= x) and (x <= b);
    end;
end;

function opCl(a, b: double): TSet;
begin
  Result :=
    function(x: double): boolean
    begin
      Result := (a < x) and (x <= b);
    end;
end;

function clOp(a, b: double): TSet;
begin
  Result :=
    function(x: double): boolean
    begin
      Result := (a <= x) and (x < b);
    end;
end;

const
  BOOLSTR: array[Boolean] of string = ('False', 'True');

begin
  var s: TArray<TSet>;
  SetLength(s, 4);

  s[0] := Union(opCl(0, 1), clOp(0, 2));  // (0,1] ? [0,2)
  s[1] := Inter(clOp(0, 2), opCl(1, 2));  // [0,2) n (1,2]
  s[2] := Diff(clOp(0, 3), open(0, 1));   // [0,3) - (0,1)
  s[3] := Diff(clOp(0, 3), closed(0, 1)); // [0,3) - [0,1]

  for var i := 0 to High(s) do
  begin
    for var x := 0 to 2 do
      writeln(format('%d e s%d: %s', [x, i, BOOLSTR[s[i](x)]]));
    writeln;
  end;
  readln;
end.


print Checksum.compute_for_string(ChecksumType.SHA1, "Rosetta code", -1)


package main

import (
    "crypto/sha1"
    "fmt"
)

func main() {
    h := sha1.New()
    h.Write([]byte("Rosetta Code"))
    fmt.Printf("%x\n", h.Sum(nil))
}


(lib 'match) ;; reader-infix macros

(reader-infix '∈ )
(reader-infix '∩ )
(reader-infix '∪ )
(reader-infix '⊖ ) ;; set difference

(define-syntax-rule (∈ x a) (a x))
(define-syntax-rule (∩ a b) (lambda(x) (and ( a x) (b x))))
(define-syntax-rule (∪ a b) (lambda(x) (or ( a x) (b x))))
(define-syntax-rule (⊖ a b) (lambda(x) (and ( a x) (not (b x)))))

;; predicates to define common sets
(define (∅ x) #f) ;; the empty set predicate
(define (Z x) (integer? x))
(define (N x) (and (Z x) (>= x 0)))
(define (Q x) (rational? x))
(define (ℜ x) #t)

;; predicates to define convex sets
(define (⟦...⟧ a b)(lambda(x) (and (>= x a) (<= x b))))
(define (⟦...⟦ a b)(lambda(x) (and (>= x a) (< x b))))
(define (⟧...⟧ a b)(lambda(x) (and (> x a) (<= x b))))
(define (⟧...⟦ a b)(lambda(x) (and (> x a) (< x b))))


use crypto::sha1;
use encoding::hex;
use fmt;
use hash;
use os;
use strings;

export fn main() void = {
	const sha = sha1::sha1();
	hash::write(&sha, strings::toutf8("Rosetta Code"));

	let sum: [sha1::SIZE]u8 = [0...];
	hash::sum(&sha, sum);
	hex::encode(os::stdout, sum)!;
	fmt::println()!;
};


module Digestor
   where
import Data.Digest.Pure.SHA
import qualified Data.ByteString.Lazy as B

convertString :: String -> B.ByteString
convertString phrase = B.pack $ map ( fromIntegral . fromEnum ) phrase

convertToSHA1 :: String -> String
convertToSHA1 word = showDigest $ sha1 $ convertString word

main = do
   putStr "Rosetta Code SHA1-codiert: "
   putStrLn $ convertToSHA1 "Rosetta Code"


import haxe.crypto.Sha1;

class Main {
  static function main() {
    var sha1 = Sha1.encode("Rosetta Code");
    Sys.println(sha1);
  }
}


import extensions;

extension setOp
{
    union(func)
        = (val => self(val) || func(val) );

    intersection(func)
        = (val => self(val) && func(val) );

    difference(func)
        = (val => self(val) && (func(val)).Inverted );
}

public program()
{
    // union
    var set := (x => x >= 0.0r && x <= 1.0r ).union:(x => x >= 0.0r && x < 2.0r );

    set(0.0r).assertTrue();
    set(1.0r).assertTrue();
    set(2.0r).assertFalse();

    // intersection
    var set2 := (x => x >= 0.0r && x < 2.0r ).intersection:(x => x >= 1.0r && x <= 2.0r );

    set2(0.0r).assertFalse();
    set2(1.0r).assertTrue();
    set2(2.0r).assertFalse();

    // difference
    var set3 := (x => x >= 0.0r && x < 3.0r ).difference:(x => x >= 0.0r && x <= 1.0r );

    set3(0.0r).assertFalse();
    set3(1.0r).assertFalse();
    set3(2.0r).assertTrue();
}


open System

let union s1 s2 =
    fun x -> (s1 x) || (s2 x);

let difference s1 s2 =
    fun x -> (s1 x) && not (s2 x)

let intersection s1 s2 =
    fun x -> (s1 x) && (s2 x)

[<EntryPoint>]
let main _ =
    //test set union
    let u1 = union (fun x -> 0.0 < x && x <= 1.0) (fun x -> 0.0 <= x && x < 2.0)
    assert (u1 0.0)
    assert (u1 1.0)
    assert (not (u1 2.0))

    //test set difference
    let d1 = difference (fun x -> 0.0 <= x && x < 3.0) (fun x -> 0.0 < x && x < 1.0)
    assert (d1 0.0)
    assert (not (d1 0.5))
    assert (d1 1.0)
    assert (d1 2.0)

    let d2 = difference (fun x -> 0.0 <= x && x < 3.0) (fun x -> 0.0 <= x && x <= 1.0)
    assert (not (d2 0.0))
    assert (not (d2 1.0))
    assert (d2 2.0)

    let d3 = difference (fun x -> 0.0 <= x && x <= Double.PositiveInfinity) (fun x -> 1.0 <= x && x <= 2.0)
    assert (d3 0.0)
    assert (not (d3 1.5))
    assert (d3 3.0)

    //test set intersection
    let i1 = intersection (fun x -> 0.0 <= x && x < 2.0) (fun x -> 1.0 < x && x <= 2.0)
    assert (not (i1 0.0))
    assert (not (i1 1.0))
    assert (not (i1 2.0))

    0 // return an integer exit code


   require '~addons/ide/qt/qt.ijs'
   getsha1=: 'sha1'&gethash_jqtide_
   getsha1 'Rosetta Code'
48c98f7e5a6e736d790ab740dfc3f51a61abe2b5


/* SHA-1 hash in Jsish */
var str = 'Rosetta code';
puts(Util.hash(str, {type:'sha1'}));

/*
=!EXPECTSTART!=
b18c883f4da750164b5af362ea9b9f27f90904b4
=!EXPECTEND!=
*/


using Nettle

testdict = Dict("abc" => "a9993e364706816aba3e25717850c26c9cd0d89d",
                "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" =>
                    "84983e441c3bd26ebaae4aa1f95129e5e54670f1",
                "a" ^ 1_000_000 => "34aa973cd4c4daa4f61eeb2bdbad27316534016f",)

for (text, expect) in testdict
    digest = hexdigest("sha1", text)
    if length(text) > 50 text = text[1:50] * "..." end
    println("# $text\n -> digest: $digest\n -> expect: $expect")
end


package main

import "fmt"

type Set func(float64) bool

func Union(a, b Set) Set      { return func(x float64) bool { return a(x) || b(x) } }
func Inter(a, b Set) Set      { return func(x float64) bool { return a(x) && b(x) } }
func Diff(a, b Set) Set       { return func(x float64) bool { return a(x) && !b(x) } }
func open(a, b float64) Set   { return func(x float64) bool { return a < x && x < b } }
func closed(a, b float64) Set { return func(x float64) bool { return a <= x && x <= b } }
func opCl(a, b float64) Set   { return func(x float64) bool { return a < x && x <= b } }
func clOp(a, b float64) Set   { return func(x float64) bool { return a <= x && x < b } }

func main() {
	s := make([]Set, 4)
	s[0] = Union(opCl(0, 1), clOp(0, 2))  // (0,1] ∪ [0,2)
	s[1] = Inter(clOp(0, 2), opCl(1, 2))  // [0,2) ∩ (1,2]
	s[2] = Diff(clOp(0, 3), open(0, 1))   // [0,3) − (0,1)
	s[3] = Diff(clOp(0, 3), closed(0, 1)) // [0,3) − [0,1]

	for i := range s {
		for x := float64(0); x < 3; x++ {
			fmt.Printf("%v ∈ s%d: %t\n", x, i, s[i](x))
		}
		fmt.Println()
	}
}