local(str = 'The quick grey rhino jumped over the lazy green fox.')

//starting from n characters in and of m length;
#str->substring(16,5) //rhino

//starting from n characters in, up to the end of the string
#str->substring(16) //rhino jumped over the lazy green fox.

//whole string minus last character
#str->substring(1,#str->size - 1) //The quick grey rhino jumped over the lazy green fox

//starting from a known character within the string and of m length;
#str->substring(#str->find('g'),10) //grey rhino

//starting from a known substring within the string and of m length
#str->substring(#str->find('rhino'),12) //rhino jumped


> (set n 3)
3
> (set m 5)
5
> (string:sub_string "abcdefghijklm" n)
"cdefghijklm"
> (string:sub_string "abcdefghijklm" n (+ n m -1))
"cdefg"
> (string:sub_string "abcdefghijklm" 1 (- (length "abcdefghijklm") 1))
"abcdefghijkl"
> (set char-index (string:chr "abcdefghijklm" #\e))
5
> (string:sub_string "abcdefghijklm" char-index (+ char-index m -1))
"efghi"
> (set start-str (string:str "abcdefghijklm" "efg"))
5
> (string:sub_string "abcdefghijklm" start-str (+ start-str m -1))
"efghi"


'These tasks can be completed with various combinations of Liberty Basic's
'built in Mid$()/ Instr()/ Left$()/ Right$()/ and Len() functions, but these
'examples only use the Mid$()/ Instr()/ and Len() functions.

baseString$ = "Thequickbrownfoxjumpsoverthelazydog."
n = 12
m = 5

'starting from n characters in and of m length
Print Mid$(baseString$, n, m)

'starting from n characters in, up to the end of the string
Print Mid$(baseString$, n)

'whole string minus last character
Print Mid$(baseString$, 1, (Len(baseString$) - 1))

'starting from a known character within the string and of m length
Print Mid$(baseString$, Instr(baseString$, "f", 1), m)

'starting from a known substring within the string and of m length
Print Mid$(baseString$, Instr(baseString$, "jump", 1), m)


str = "The quick brown fox jumps over the lazy dog"

-- starting from n characters in and of m length
n = 5
m = 11
put str.char[n..n+m-1]
-- "quick brown"

-- starting from n characters in, up to the end of the string
n = 11
put str.char[n..str.length]
-- "brown fox jumps over the lazy dog"

-- whole string minus last character
put str.char[1..str.length-1]
-- "The quick brown fox jumps over the lazy do"

-- starting from a known character within the string and of m length
c = "x"
m = 7
pos = offset(c, str)
put str.char[pos..pos+m-1]
-- "x jumps"

-- starting from a known substring within the string and of m length
sub = "fox"
m = 9
pos = offset(sub, str)
put str.char[pos..pos+m-1]
-- "fox jumps"


put "pple" into x
answer char 2 to char 5 of x  // n = 2, m=5
answer char 2 to len(x) of x  // n = 2, m = len(x), can also use -1
answer char 1 to -2 of x  // n = 1, m = 1 less than length of string
answer char offset("p",x) to -1 of x // known char "p" to end of string
answer char offset("pl",x) to -1 of x // known "pl" to end of string


to items :n :thing
  if :n >= count :thing [output :thing]
  output items :n butlast :thing
end

to butitems :n :thing
  if or :n <= 0 empty? :thing [output :thing]
  output butitems :n-1 butfirst :thing
end

to middle :n :m :thing
  output items :m-(:n-1) butitems :n-1 :thing
end

to lastitems :n :thing
  if :n >= count :thing [output :thing]
 output lastitems :n butfirst :thing
end

to starts.with :sub :thing
  if empty? :sub [output "true]
  if empty? :thing [output "false]
  if not equal? first :sub first :thing [output "false]
  output starts.with butfirst :sub butfirst :thing
end

to members :sub :thing
  output cascade [starts.with :sub ?] [bf ?] :thing
end

; note: Logo indices start at one
make "s "abcdefgh
print items 3 butitems 2 :s ; cde
print middle 3 5  :s   ; cde
print butitems 2  :s   ; cdefgh
print butlast     :s   ; abcdefg
print items 3 member  "d  :s ; def
print items 3 members "de :s ; def


:- object(substring).

    :- public(test/5).

    test(String, N, M, Character, Substring) :-
        sub_atom(String, N, M, _, Substring1),
        write(Substring1), nl,
        sub_atom(String, N, _, 0, Substring2),
        write(Substring2), nl,
        sub_atom(String, 0, _, 1, Substring3),
        write(Substring3), nl,
        % there can be multiple occurences of the character
        once(sub_atom(String, Before4, 1, _, Character)),
        sub_atom(String, Before4, M, _, Substring4),
        write(Substring4), nl,
        % there can be multiple occurences of the substring
        once(sub_atom(String, Before5, _, _, Substring)),
        sub_atom(String, Before5, M, _, Substring5),
        write(Substring5), nl.

:- end_object.


str = "abcdefghijklmnopqrstuvwxyz"
n, m = 5, 15

print( string.sub( str, n, m ) )    -- efghijklmno
print( string.sub( str, n, -1 ) )   -- efghijklmnopqrstuvwxyz
print( string.sub( str, 1, -2 ) )   -- abcdefghijklmnopqrstuvwxy

pos = string.find( str, "i" )
if pos ~= nil then print( string.sub( str, pos, pos+m ) ) end -- ijklmnopqrstuvwx

pos = string.find( str, "ijk" )
if pos ~= nil then print( string.sub( str, pos, pos+m ) ) end-- ijklmnopqrstuvwx

-- Alternative (more modern) notation

print ( str:sub(n,m) )         -- efghijklmno
print ( str:sub(n) )           -- efghijklmnopqrstuvwxyz
print ( str:sub(1,-2) )        -- abcdefghijklmnopqrstuvwxy

pos = str:find "i"
if pos then print (str:sub(pos,pos+m)) end -- ijklmnopqrstuvwx

pos = str:find "ijk"
if pos then print (str:sub(pos,pos+m)) end d-- ijklmnopqrstuvwx


Module CheckAnsi {
      \\ ANSI STRING
      Locale 1033
      \\ convert UTF16-LE to ANSI 8bit
      s$ =Str$("ABCDEFG")
      Print Len(s$)=3.5  ' 3.5 words, means 7 bytes (3.5*2)
      AnsiLen=Len(s$)*2
      ' From 4th byte get 3 bytes
      n=4
      m=3
      substring$=Mid$(s$, n, m as byte)
      substring2End$=Mid$(s$, n , AnsiLen as byte)
      substringMinusOne$=Left$(s$, AnsiLen-1 as byte)
      substringFromKnownCharacter$=Mid$(s$, Instr(s$, str$("B") as byte) , m as byte)
      substringFromKnownSubstring$=Mid$(s$, Instr(s$, str$("BC") as byte) , m as byte)
      Print Len(substring$)*2=m

      \\ convert to UTF-16LE
      Print Chr$(substring$)="DEF"
      Print Chr$(substring2End$)="DEFG"
      Print Chr$(substringMinusOne$)="ABCDEF"
      Print Chr$(substringFromKnownCharacter$)="BCD"
      Print Chr$(substringFromKnownSubstring$)="BCD"
}
CheckAnsi
Module CheckUTF16LE {
      s$ ="ABCDEFG"
      Print Len(s$)=7
      Utf16Len=Len(s$)
      ' From 4th byte get 3 bytes
      n=4
      m=3
      substring$=Mid$(s$, n, m)
      substring2End$=Mid$(s$, n , Utf16Len)
      substringMinusOne$=Left$(s$, Utf16Len-1)
      substringFromKnownCharacter$=Mid$(s$, Instr(s$, "B") , m)
      substringFromKnownSubstring$=Mid$(s$, Instr(s$, "BC") , m)
      Print Len(substring$)=m

      \\ convert to UTF-16LE
      Print substring$="DEF"
      Print substring2End$="DEFG"
      Print substringMinusOne$="ABCDEF"
      Print substringFromKnownCharacter$="BCD"
      Print substringFromKnownSubstring$="BCD"
}
CheckUTF16LE


> n, m := 3, 5:
> s := "The Higher, The Fewer!":
> s[ n .. n + m - 1 ];
                     "e Hig"


n = 2
m = 3
StringTake["Mathematica", {n+1, n+m-1}]
StringDrop["Mathematica", n]
(* StringPosition returns a list of starting and ending character positions for a substring *)
pos = StringPosition["Mathematica", "e"][[1]][[1]]
StringTake["Mathematica", {pos, pos+m-1}]
(* Similar to above *)
pos = StringPosition["Mathematica", "the"][[1]]
StringTake["Mathematica", {pos, pos+m-1}]


    % starting from n characters in and of m length;
        s(n+(1:m))
        s(n+1:n+m)
    % starting from n characters in, up to the end of the string;
        s(n+1:end)
    % whole string minus last character;
        s(1:end-1)
    % starting from a known character within the string and of m length;
        s(find(s==c,1)+[0:m-1])
    % starting from a known substring within the string and of m length.
        s(strfind(s,pattern)+[0:m-1])


s: "the quick brown fox jumps over the lazy dog";
substring(s, 17);
/* "fox jumps over the lazy dog" */
substring(s, 17, 20);
/* "fox" */


SUBSTR(S,N,M,C,K)
 ;show substring operations
 ;S is the string
 ;N is a position within the string (that is, n<length(string))
 ;M is an integer of positions to show
 ;C is a character within the string S
 ;K is a substring within the string S
 ;$Find returns the position after the substring
 NEW X
 WRITE !,"The base string is:",!,?5,"'",S,"'"
 WRITE !,"From position ",N," for ",M," characters:"
 WRITE !,?5,$EXTRACT(S,N,N+M-1)
 WRITE !,"From position ",N," to the end of the string:"
 WRITE !,?5,$EXTRACT(S,N,$LENGTH(S))
 WRITE !,"Whole string minus last character:"
 WRITE !,?5,$EXTRACT(S,1,$LENGTH(S)-1)
 WRITE !,"Starting from character '",C,"' for ",M," characters:"
 SET X=$FIND(S,C)-$LENGTH(C)
 WRITE !,?5,$EXTRACT(S,X,X+M-1)
 WRITE !,"Starting from string '",K,"' for ",M," characters:"
 SET X=$FIND(S,K)-$LENGTH(K)
 W !,?5,$EXTRACT(S,X,X+M-1)
 QUIT


str = "test string"

println substr(str, m, m + n)
println substr(str, n, len(str))
println substr(str, 0, len(str) - 1)
println substr(str, str.indexOf("s"), str.indexOf("s") + m)
println substr(str, str.indexOf("str"), str.indexOf("str") + m)


using System;
using System.Console;

module Substrings
{
    Main() : void
    {
        string s = "0123456789";
        def n = 3;
        def m = 2;
        def c = '3';
        def z = "345";

        WriteLine(s.Substring(n, m));
        WriteLine(s.Substring(n, s.Length - n));
        WriteLine(s.Substring(0, s.Length - 1));
        WriteLine(s.Substring(s.IndexOf(c,0,s.Length), m));
        WriteLine(s.Substring(s.IndexOf(z, 0, s.Length), m));
    }
}


/* NetRexx */

options replace format comments java crossref savelog symbols

s = 'abcdefghijk'
n = 4
m = 3

say s
say s.substr(n, m)
say s.substr(n)
say s.substr(1, s.length - 1)
say s.substr(s.pos('def'), m)
say s.substr(s.pos('g'), m)

return


> (set 'str "alphabet" 'n 2 'm 4)
4
> ; starting from n characters in and of m length
> (slice str n m)
"phab"
> ; starting from n characters in, up to the end of the string
> (slice str n)
"phabet"
> ; whole string minus last character
> (chop str)
"alphabe"
> ; starting from a known character within the string and of m length
> (slice str (find "l" str) m)
"lpha"
> ; starting from a known substring within the string and of m length
> (slice str (find "ph" str) m)
"phab"


import strformat, strutils, unicode

let
  s1 = "abcdefgh"   # ASCII string.
  s2 = "àbĉdéfgĥ"   # UTF-8 string.
  n = 2
  m = 3
  c = 'd'
  cs1 = "de"
  cs2 = "dé"

var pos: int

# ASCII strings.
# We can take a substring using "s.substr(first, last)" or "s[first..last]".
# The latter form can also be used as lvalue to assign a substring.

echo "ASCII string: ", s1

echo &"Starting from n = {n} characters in and of m = {m} length: ", s1[(n - 1)..(n + m - 2)]
echo &"Starting from n = {n} characters in, up to the end of the string: ", s1[(n - 1)..^1]
echo "Whole string minus the last character: ", s1[0..^2]

pos = s1.find(c)
if pos > 0:
  echo &"Starting from character '{c}' within the string and of m = {m} length: ", s1[pos..<(pos + m)]
else:
  echo &"Character '{c}' not found."

pos = s1.find(cs1)
if pos > 0:
  echo &"Starting from substring “{cs1}” within the string and of m = {m} length: ", s1[pos..<(pos + m)]
else:
  echo &"String “{cs1}” not found."

# UTF-8 strings.

proc findUtf8(s: string; c: char): int =
  ## Return the codepoint index of the first occurrence of a given character in a string.
  ## Return - 1 if not found.
  s.toRunes.find(Rune(c))

proc findUtf8(s1, s2: string): int =
  ## Return the codepoint index of the first occurrence of a given string in a string.
  ## Return - 1 if not found.
  let s1 = s1.toRunes
  let s2 = s2.toRunes
  for i in 0..(s1.len - s2.len):
    if s1[i..(i + s2.len - 1)] == s2: return i
  result = -1

echo()
echo "UTF-8 string: ", s2

echo &"Starting from n = {n} characters in and of m = {m} length: ", s2.runeSubStr(n - 1, m)
echo &"Starting from n = {n} characters in, up to the end of the string: ", s2.runeSubstr(n - 1)
echo "Whole string minus the last character: ", s2.runeSubStr(0, s2.runeLen - 1)

pos = s2.findUtf8(c)
if pos > 0:
  echo &"Starting from character '{c}' within the string and of m = {m} length: ", s2.runeSubStr(pos, m)
else:
  echo &"String “{cs1}” not found."

pos = s2.findUtf8(cs2)
if pos > 0:
  echo &"Starting from substring “{cs2}” within the string and of m = {m} length: ", s2.runeSubStr(pos, m)
else:
  echo &"String “{cs2}” not found."


( based on the JavaScript code )
'abcdefgh 's ;
s str-len 'len ;
2 'n ;
3 'm ;

( starting from n characters in and of m length )
s n n m + substring . ( => cde ) newline

( starting from n characters in, up to the end of the string )
s n len substring . ( => cdefgh ) newline

( whole string minus last character )
s 0 len 1 - substring . ( => abcdefg ) newline

( starting from a known character within the string and of m length )
s s 'b str-find dup m + substring . ( => bcd ) newline

( starting from a known substring within the string and of m length )
s s 'bc str-find dup m + substring . ( => bcd ) newline


bundle Default {
  class SubString {
    function : Main(args : String[]) ~ Nil {
      s := "0123456789";

      n := 3;
      m := 4;
      c := '2';
      sub := "456";

      s->SubString(n, m)->PrintLine();
      s->SubString(n)->PrintLine();
      s->SubString(0, s->Size())->PrintLine();
      s->SubString(s->Find(c), m)->PrintLine();
      s->SubString(s->Find(sub), m)->PrintLine();
    }
  }
}


$ ocaml
# let s = "ABCDEFGH" ;;
val s : string = "ABCDEFGH"

# let n, m = 2, 3 ;;
val n : int = 2
val m : int = 3

# String.sub s n m ;;
- : string = "CDE"

# String.sub s n (String.length s - n) ;;
- : string = "CDEFGH"

# String.sub s 0 (String.length s - 1) ;;
- : string = "ABCDEFG"

# String.sub s (String.index s 'D') m ;;
- : string = "DEF"

# #load "str.cma";;
# let n = Str.search_forward (Str.regexp_string "DE") s 0 in
  String.sub s n m ;;
- : string = "DEF"


: substrings(s, n, m)
   s sub(n, m) println
   s right(s size n - 1 +) println
   s left(s size 1 - ) println
   s sub(s indexOf('d'), m) println
   s sub(s indexOfAll("de"), m) println ;


declare
  fun {DropUntil Xs Prefix}
     case Xs of nil then nil
     [] _|Xr then
        if {List.isPrefix Prefix Xs} then Xs
        else {DropUntil Xr Prefix}
        end
     end
  end

  Digits = "1234567890"
in
  {ForAll
   [{List.take {List.drop Digits 2} 3}     = "345"
    {List.drop Digits 2}                   = "34567890"
    {List.take Digits {Length Digits}-1}   = "123456789"
    {List.take {DropUntil Digits "4"} 3}   = "456"
    {List.take {DropUntil Digits "56"} 3}  = "567"
    {List.take {DropUntil Digits "31"} 3}  = ""
   ]
   System.showInfo}


\\ Returns the substring of string str specified by the start position s and length n.
\\ If n=0 then to the end of str.
\\ ssubstr() 3/5/16 aev
ssubstr(str,s=1,n=0)={
my(vt=Vecsmall(str),ve,vr,vtn=#str,n1);
if(vtn==0,return(""));
if(s<1||s>vtn,return(str));
n1=vtn-s+1; if(n==0,n=n1); if(n>n1,n=n1);
ve=vector(n,z,z-1+s); vr=vecextract(vt,ve); return(Strchr(vr));
}

{\\ TEST
my(s="ABCDEFG",ns=#s);
print(" *** Testing ssubstr():");
print("1.",ssubstr(s,2,3));
print("2.",ssubstr(s));
print("3.",ssubstr(s,,ns-1));
print("4.",ssubstr(s,2));
print("5.",ssubstr(s,,4));
print("6.",ssubstr(s,0,4));
print("7.",ssubstr(s,3,7));
print("8.|",ssubstr("",1,4),"|");
}


my $str = 'abcdefgh';
print substr($str, 2, 3), "\n"; # Returns 'cde'
print substr($str, 2), "\n"; # Returns 'cdefgh'
print substr($str, 0, -1), "\n"; #Returns 'abcdefg'
print substr($str, index($str, 'd'), 3), "\n"; # Returns 'def'
print substr($str, index($str, 'de'), 3), "\n"; # Returns 'def'


--(1) starting from n characters in and of m length;
--(2) starting from n characters in, up to the end of the string;
--(3) whole string minus last character;
--(4) starting from a known character within the string and of m length;
--(5) starting from a known substring within the string and of m length.

constant sentence = "the last thing the man said was the",
         n = 10, m = 5
integer k, l
l = n+m-1
if l<=length(sentence) then
    ?sentence[n..l]           -- (1)
end if
if n<=length(sentence) then
    ?sentence[n..-1]          -- (2) or [n..$]
end if
if length(sentence)>0 then
    ?sentence[1..-2]          -- (3) or [1..$-1]
end if
k = find('m',sentence)
l = k+m-1
if l<=length(sentence) then
    ?sentence[k..l]           -- (4)
end if
k = match("aid",sentence)
l = k+m-1
if l<=length(sentence) then
    ?sentence[k..l]           -- (5)
end if


include ..\Utilitys.pmt

/#
--(1) starting from n characters in and of m length;
--(2) starting from n characters in, up to the end of the string;
--(3) whole string minus last character;
--(4) starting from a known character within the string and of m length;
--(5) starting from a known substring within the string and of m length.
#/

def myslice
    rot len var _|long
    rot rot
    over _|long swap - 1 +
    min
    slice
enddef

"the last thing the man said was the"
10 var n 5 var m

n m myslice ?   /# (1) #/
len n swap myslice ?    /# (2) #/
dup -1 del ? /# (3) #/
'm' find m myslice ? /# (4) #/
"aid" find m myslice ? /# (5) #/


<?php
$str = 'abcdefgh';
$n = 2;
$m = 3;
echo substr($str, $n, $m), "\n"; //cde
echo substr($str, $n), "\n"; //cdefgh
echo substr($str, 0, -1), "\n"; //abcdefg
echo substr($str, strpos($str, 'd'), $m), "\n"; //def
echo substr($str, strpos($str, 'de'), $m), "\n"; //def
?>


go =>
  S = "Picat is fun",
  N = 3,
  M = 4,
  C = 'i', % must be a char
  SS = "is",
  test(S,N,M,C,SS).

test(S,N,M,C,SS) =>
  println($test(S,N,M,C,SS)),

  % - starting from n characters in and of m length;
  println(1=slice(S,N,N+M)),
  println(1=S[N..N+M]),

  % - starting from n characters in, up to the end of the string;
  println(2=S.slice(N)),

  % - whole string minus last character;
  println(3=but_last(S)),
  println(3=S[1..S.len-1]),

  % - starting from a known character within the string and of m length;
  println(4=substring4(S,C)),

  % - starting from a known substring within the string and of m length.
  println(5=substring5(S,SS,M)),
  nl.

but_last(S) = slice(S,1,S.length-1).

substring4(S,C) = slice(S,S.find_first_of(C)).

% find is non-deterministic, hence the once/1
substring5(S,SS,M) = slice(S,Start,Start+M) =>
  once(find(S,SS,Start,_End)).


(let Str (chop "This is a string")
   (prinl (head 4 (nth Str 6)))        # From 6 of 4 length
   (prinl (nth Str 6))                 # From 6 up to the end
   (prinl (head -1 Str))               # Minus last character
   (prinl (head 8 (member "s" Str)))   # From character "s" of length 8
   (prinl                              # From "isa" of length 8
      (head 8
         (seek '((S) (pre? "is a" S)) Str) ) ) )


s='abcdefghijk';
n=4; m=3;
u=substr(s,n,m);
u=substr(s,n);
u=substr(s,1,length(s)-1);
u=left(s,length(s)-1);
u=substr(s,1,length(s)-1);
u=substr(s,index(s,'g'),m);


# test string
$s = "abcdefgh"
# test parameters
$n, $m, $c, $s2 = 2, 3, [char]'d', $s2 = 'cd'

# starting from n characters in and of m length
# n = 2, m = 3
$s.Substring($n-1, $m)              # returns 'bcd'

# starting from n characters in, up to the end of the string
# n = 2
$s.Substring($n-1)                  # returns 'bcdefgh'

# whole string minus last character
$s.Substring(0, $s.Length - 1)      # returns 'abcdefg'

# starting from a known character within the string and of m length
# c = 'd', m =3
$s.Substring($s.IndexOf($c), $m)    # returns 'def'

# starting from a known substring within the string and of m length
# s2 = 'cd', m = 3
$s.Substring($s.IndexOf($s2), $m)   # returns 'cde'


substring_task(Str, N, M, Char, SubStr) :-
    sub_string(Str, N, M, _, Span),
    sub_string(Str, N, _, 0, ToEnd),
    sub_string(Str, 0, _, 1, MinusLast),
    string_from_substring_to_m(Str, Char, M, FromCharToMth),
    string_from_substring_to_m(Str, SubStr, M, FromSubToM),
    maplist( writeln,
            [ 'from n to m ':Span,
              'from n to end ': ToEnd,
              'string minus last char ': MinusLast,
              'form known char to m ': FromCharToMth,
              'from known substring to m ': FromSubToM ]).

string_from_substring_to_m(String, Sub, M, FromSubToM) :-
    sub_string(String, Before, _, _, Sub),
    sub_string(String, Before, M, _, FromSubToM).


If OpenConsole()

  Define baseString.s, m, n

  baseString = "Thequickbrownfoxjumpsoverthelazydog."
  n = 12
  m = 5

  ;Display the substring starting from n characters in and of m length.
  PrintN(Mid(baseString, n, m))

  ;Display the substring starting from n characters in, up to the end of the string.
  PrintN(Mid(baseString, n)) ;or PrintN(Right(baseString, Len(baseString) - n))

  ;Display the substring whole string minus last character
  PrintN(Left(baseString, Len(baseString) - 1))

  ;Display the substring starting from a known character within the string and of m length.
  PrintN(Mid(baseString, FindString(baseString, "b", 1), m))

  ;Display the substring starting from a known substring within the string and of m length.
  PrintN(Mid(baseString, FindString(baseString, "ju", 1), m))

  Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
  Input()
  CloseConsole()
EndIf


>>> s = 'abcdefgh'
>>> n, m, char, chars = 2, 3, 'd', 'cd'
>>> # starting from n=2 characters in and m=3 in length;
>>> s[n-1:n+m-1]
'bcd'
>>> # starting from n characters in, up to the end of the string;
>>> s[n-1:]
'bcdefgh'
>>> # whole string minus last character;
>>> s[:-1]
'abcdefg'
>>> # starting from a known character char="d" within the string and of m length;
>>> indx = s.index(char)
>>> s[indx:indx+m]
'def'
>>> # starting from a known substring chars="cd" within the string and of m length.
>>> indx = s.index(chars)
>>> s[indx:indx+m]
'cde'
>>>


DefStr S
DefInt I
string1 = "abcdefghijklmnopqrstuvwxyz"
substring = "klm"
Dim Achar As String * 1
Istart = 6
Ilength = 10
Achar = "c"

'  starting from   n   characters in and of   m   length;
Print Mid$(string1, Istart, Ilength)
'  starting from   n   characters in,   up to the end of the string;
Print Mid$(string1, Istart)
Print Right$(string1, Len(string1) - Istart + 1)
'  whole string minus the last character;
Print Left$(string1, Len(string1) - 1)
Print Mid$(string1, 1, Len(string1) - 1)
'  starting from a known   character   within the string and of   m   length;
Print Mid$(string1, InStr(string1, Achar), Ilength)
'  starting from a known   substring   within the string and of   m   length.
Print Mid$(string1, InStr(string1, substring), Ilength)
End


  [ $ "abcdefgh" ] is s  ( --> $ )
  [ 2 ]            is n  ( --> n )
  [ 3 ]            is m  ( --> n )
  [ char d ]       is ch ( --> c )
  [ $ "cd" ]       is ss ( --> $ )

  s n split nip m split drop echo$ cr
  s n split nip echo$ cr
  s -1 split drop echo$ cr
  ch s tuck find split nip m split drop echo$ cr
  ss s tuck find$ split nip m split drop echo$ cr


s <- "abcdefgh"
n <- 2; m <- 2; char <- 'd'; chars <- 'cd'
substring(s, n, n + m)
substring(s, n)
substring(s, 1, nchar(s)-1)
indx <- which(strsplit(s, '')[[1]] %in% strsplit(char, '')[[1]])
substring(s, indx, indx + m)
indx <- which(strsplit(s, '')[[1]] %in% strsplit(chars, '')[[1]])[1]
substring(s, indx, indx + m)


#lang racket

(define str "abcdefghijklmnopqrstuvwxyz")

(define n 10)
(define m 2)
(define start-char #\x)
(define start-str "xy")

;; starting from n characters in and of m length;
(substring str n (+ n m)) ; -> "kl"

;; starting from n characters in, up to the end of the string;
(substring str m) ; -> "klmnopqrstuvwxyz"

;; whole string minus last character;
(substring str 0 (sub1 (string-length str))) ; -> "abcdefghijklmnopqrstuvwxy"

;; starting from a known character within the string and of m length;
(substring str (caar (regexp-match-positions (regexp-quote (string start-char))
                                             str))) ; -> "xyz"

;; starting from a known substring within the string and of m length.
(substring str (caar (regexp-match-positions (regexp-quote start-str)
                                             str))) ; -> "xyz"


my $str = 'abcdefgh';
my $n = 2;
my $m = 3;
say $str.substr($n, $m);
say $str.substr($n);
say $str.substr(0, *-1);
say $str.substr($str.index('d'), $m);
say $str.substr($str.index('de'), $m);


define println use $s
   $s print "\n" print

"0123456789" as $str

$str 3 2 extract println      # at 4th pos get 2 chars
$str 8 4 extract println      # at 9th pos get 4 chars (when only 1 char available)

$str 3  $str length  extract println      # at 4th pos get all chars to end of str
$str 3  0x7FFFFFFF  extract println      # at 4th pos get all chars to end of str

$str 3 -1 extract println      # at 4th pos get rest of chars but last one
$str 0 -1 extract println      # all chars but last one

"3" as $matchChr               # starting chr for extraction
4 as $subLen                   # Nr chars after found starting char
$str $matchChr split as $l
"" $l 0 set     $l $matchChr join
0 $subLen extract println

"345" as $matchChrs            # starting chrs for extraction
6 as $subLen                   # Nr chars after found starting chars
$str $matchChrs split as $l
"" $l 0 set     $l $matchChrs join
0 $subLen extract println


rebol [
	Title: "Retrieve Substring"
	URL: http://rosettacode.org/wiki/Substring#REBOL
]

s: "abcdefgh"  n: 2  m: 3  char: #"d"  chars: "cd"

; Note that REBOL uses base-1 indexing. Strings are series values,
; just like blocks or lists so I can use the same words to manipulate
; them. All these examples use the 'copy' function against the 's'
; string with a particular offset as needed.

; For the fragment "copy/part  skip s n - 1  m", read from right to
; left.  First you have 'm', which we ignore for now. Then evaluate
; 'n - 1' (makes 1), to adjust the offset. Then 'skip' jumps from the
; start of the string by that offset. 'copy' starts copying from the
; new start position and the '/part' refinement limits the copy by 'm'
; characters.

print ["Starting from n, length m:"
	copy/part  skip s n - 1  m]

; It may be helpful to see the expression with optional parenthesis:

print ["Starting from n, length m (parens):"
	(copy/part  (skip s (n - 1))  m)]

; This example is much simpler, so hopefully it's easier to see how
; the string start is position for the copy:

print ["Starting from n to end of string:"
	copy skip s n - 1]

print ["Whole string minus last character:"
	copy/part s (length? s) - 1]

print ["Starting from known character, length m:"
	copy/part  find s char  m]

print ["Starting from substring, length m:"
	copy/part  find s chars  m]


let s = "ABCDEFGH"
let from = 2
let length = 3

Js.log2("Original string: ", s)

Js.log(Js.String.substrAtMost(~from, ~length, s))
Js.log(Js.String.substr(~from, s))
Js.log(Js.String.substrAtMost(~from=0, ~length=(Js.String2.length(s) - 1), s))

Js.log(Js.String.substrAtMost(~from=(Js.String.indexOf("B", s)), ~length, s))
Js.log(Js.String.substrAtMost(~from=(Js.String.indexOf("BC", s)), ~length, s))


/*REXX program demonstrates various ways to extract substrings from a  string  of characters.*/
$='abcdefghijk';  n=4;  m=3        /*define some constants: string, index, length of string. */
say 'original string='$            /* [↑]   M   can be zero  (which indicates a null string).*/
L=length($)                        /*the length of the  $  string   (in bytes or characters).*/
              say center(1,30,'═') /*show a centered title for the  1st  task requirement.   */
u=substr($, n, m)                  /*start from  N  characters in  and of  M  length.        */
say u
parse var $ =(n) a +(m)            /*an alternate method by using the  PARSE  instruction.   */
say a
              say center(2,30,'═') /*show a centered title for the  2nd  task requirement.   */
u=substr($,n)                      /*start from  N  characters in,  up to the end-of-string. */
say u
parse var $ =(n) a                 /*an alternate method by using the  PARSE  instruction.   */
say a
              say center(3,30,'═') /*show a centered title for the  3rd  task requirement.   */
u=substr($, 1, L-1)                /*OK:     the entire string  except  the last character.  */
say u
v=substr($, 1, max(0, L-1) )       /*better: this version handles the case of a null string. */
say v
lm=L-1
parse var $ a +(lm)                /*an alternate method by using the  PARSE  instruction.   */
say a
              say center(4,30,'═') /*show a centered title for the  4th  task requirement.   */
u=substr($,pos('g',$), m)          /*start from a known char within the string of length  M. */
say u
parse var $ 'g' a +(m)             /*an alternate method by using the  PARSE  instruction.   */
say a
              say center(5,30,'═') /*show a centered title for the  5th  task requirement.   */
u=substr($,pos('def',$),m)         /*start from a known substr within the string of length M.*/
say u
parse var $ 'def' a +(m)           /*an alternate method by using the  PARSE  instruction.   */
say a                              /*stick a fork in it, we're all done and Bob's your uncle.*/


cStr = "a":"h"  # 'abcdefgh'
n = 3  m = 3
# starting from n characters in and of m length
See substr(cStr,n, m) + nl          #=> cde
# starting from n characters in, up to the end of the string
See substr(cStr,n) + nl             #=> cdefgh
# whole string minus last character
See substr(cstr,1,len(cStr)-1) + nl #=> abcdefg
# starting from a known character within the string and of m length
See substr(cStr,substr(cStr,"e"),m) +nl #=> efg
# starting from a known substring within the string and of m length
See substr(cStr,substr(cStr,"de"),m) +nl #=> def


      *                                         1...5....1....5....2....5..
     D myString        S             30    inz('Liebe bewegt das Universum!')
     D output          S             30    inz('')
     D n               S              2  0 inz(1)
     D m               S              2  0 inz(5)
     D length          S              2  0 inz(0)
     D find            S              2  0 inz(0)

      /free
       *inlr = *on;
        dsply    %subst(myString:n:m);
        dsply    %subst(myString:7:20);

        length = %len(%trim(myString));
        dsply    %subst(myString:1:length-1);

        find   = %scan('U':myString);
        dsply    %subst(myString:find:9);

        find   = %scan('bewegt':myString);
        dsply    %subst(myString:find:%len('bewegt'));

        output = ' *** end *** ';
        dsply ' ' ' ' output;
      /end-free


str = 'abcdefgh'
n = 2
m = 3
puts str[n, m]                  #=> cde
puts str[n..m]                  #=> cd
puts str[n..-1]                 #=> cdefgh
puts str[0..-2]                 #=> abcdefg
puts str[str.index('d'), m]     #=> def
puts str[str.index('de'), m]    #=> def
puts str[/a.*d/]                #=> abcd


n  = 2
m  = 3
s$ = "abcd"
a$ = mid$(a$,n,m)                  ' starting from n characters in and of m length
a$ = mid$(a$,n)                    ' starting from n characters in, up to the end of the string
a$ = Print mid$(a$,1,(len(a$)-1))  ' whole string minus last character
a$ = mid$(a$,instr(a$,s$,1),m)     ' starting from a known character within the string and of m length
a$ = mid$(a$,instr(a$,s$,1), m)    ' starting from a known substring within the string and of m length.


let s = "abc文字化けdef";
let n = 2;
let m = 3;

    // Print 3 characters starting at index 2 (c文字)
println!("{}", s.chars().skip(n).take(m).collect::<String>());

    // Print all characters starting at index 2 (c文字化けdef)
println!("{}", s.chars().skip(n).collect::<String>());

    // Print all characters except the last (abc文字化けde)
println!("{}", s.chars().rev().skip(1).collect::<String>());

    // Print 3 characters starting with 'b' (bc文)
let cpos = s.find('b').unwrap();
println!("{}", s[cpos..].chars().take(m).collect::<String>());

    // Print 3 characters starting with "けd" (けde)
let spos = s.find("けd").unwrap();
println!("{}", s[spos..].chars().take(m).collect::<String>());


data _null_;
   a="abracadabra";
   b=substr(a,2,3); /* first number is position, starting at 1,
                       second number is length */
   put _all_;
run;


class MAIN is
  main is
    s ::= "hello world shortest program";
    #OUT + s.substring(12, 5) + "\n";
    #OUT + s.substring(6) + "\n";
    #OUT + s.head( s.size - 1) + "\n";
    #OUT + s.substring(s.search('w'), 5) + "\n";
    #OUT + s.substring(s.search("ro"), 3) + "\n";
  end;
end;


object Substring {
  // Ruler             1         2         3         4         5         6
  //         012345678901234567890123456789012345678901234567890123456789012
  val str = "The good life is one inspired by love and guided by knowledge."
  val (n, m) = (21, 16) // An one-liner to set n = 21, m = 16

  // Starting from n characters in and of m length
  assert("inspired by love" == str.slice(n, n + m))

  // Starting from n characters in, up to the end of the string
  assert("inspired by love and guided by knowledge." == str.drop(n))

  // Whole string minus last character
  assert("The good life is one inspired by love and guided by knowledge" == str.init)

  // Starting from a known character within the string and of m length
  assert("life is one insp" == str.dropWhile(_ != 'l').take(m) )

  // Starting from a known substring within the string and of m length
  assert("good life is one" == { val i = str.indexOf("good"); str.slice(i, i + m) })
  // Alternatively
  assert("good life is one" == str.drop(str.indexOf("good")).take(m))
}


(define s "Hello, world!")
(define n 5)
(define m (+ n 6))

(display (substring s n m))
(newline)

(display (substring s n))
(newline)

(display (substring s 0 (- (string-length s) 1)))
(newline)

(display (substring s (string-index s #\o) m))
(newline)

(display (substring s (string-contains s "lo") m))
(newline)


# 2 chars starting from 3rd
$ echo string | sed -r 's/.{3}(.{2}).*/\1/'
in
# remove first 3 chars
echo string | sed -r 's/^.{3}//'
# delete last char
$ echo string | sed -r 's/.$//'
strin
# `r' with two following chars
$ echo string | sed -r 's/.*(r.{2}).*/\1/'
rin


$ include "seed7_05.s7i";

const proc: main is func
  local
    const string: stri is "abcdefgh";
    const integer: N is 2;
    const integer: M is 3;
  begin
    writeln(stri[N len M]);
    writeln(stri[N ..]);
    writeln(stri[.. pred(length(stri))]);
    writeln(stri[pos(stri, 'c') len M]);
    writeln(stri[pos(stri, "de") len M]);
  end func;


set mainString to "87654321"
set n to 3
set m to 4
set c to "5"
set sub to "654"

put characters n + 1 to  n + m of mainString

put characters  n + 1 to end of mainString

put characters first to penultimate of mainString

set characterOffset to offset of c in mainString
put characters characterOffset to characterOffset + m - 1 of mainString

set subOffset to offset of sub in mainString
put characters subOffset to subOffset + m - 1 of mainString


var str = 'abcdefgh';
var n = 2;
var m = 3;
say str.substr(n, m);                   #=> cde
say str.substr(n);                      #=> cdefgh
say str.substr(0, -1);                  #=> abcdefg
say str.substr(str.index('d'), m);      #=> def
say str.substr(str.index('de'), m);     #=> def


#s := 'hello world shortest program'.
#n := 13.
#m := 4.
inform: (s copyFrom: n to: n + m).
inform: (s copyFrom: n).
inform: s allButLast.
inform: (s copyFrom: (s indexOf: $w) to: (s indexOf: $w) + m).
inform: (s copyFrom: (s indexOfSubSeq: 'ro') to: (s indexOfSubSeq: 'ro') + m).


|s|
s := 'hello world shortest program'.

(s copyFrom: 13 to: (13+4)) displayNl.
"4 is the length (5) - 1, since we need the index of the
 last char we want, which is included"

(s copyFrom: 7) displayNl.
(s allButLast) displayNl.

(s copyFrom: ((s indexOfRegex: 'w') first)
   to: ( ((s indexOfRegex: 'w') first) + 4) ) displayNl.
(s copyFrom: ((s indexOfRegex: 'ro') first)
   to: ( ((s indexOfRegex: 'ro') first) + 2) ) displayNl.


	string = "abcdefghijklmnopqrstuvwxyz"
	n = 12
	m = 5
	known_char = "q"
	known_str = "pq"
*  starting from n characters in and of m length;
	string len(n - 1) len(m) . output
* starting from n characters in, up to the end of the string;
	string len(n - 1) rem . output
* whole string minus last character;
	string rtab(1) . output
* starting from a known character within the string and of m length;
	string break(known_char) len(m) . output
* starting from a known substring <= m within the string and of m length.
	string (known_str len(m - size(known_str))) . output
end


SELECT 'the quick brown fox jumps over the lazy dog' FROM sysibm.sysdummy1;
SELECT substr('the quick brown fox jumps over the lazy dog', 5, 15) FROM sysibm.sysdummy1;
SELECT substr('the quick brown fox jumps over the lazy dog', 32) FROM sysibm.sysdummy1;
SELECT substr('the quick brown fox jumps over the lazy dog', 1, LENGTH ('the quick brown fox jumps over the lazy dog') - 1) FROM sysibm.sysdummy1;

SELECT locate('j', 'the quick brown fox jumps over the lazy dog') FROM sysibm.sysdummy1;
SELECT locate_in_string('the quick brown fox jumps over the lazy dog', 'j') FROM sysibm.sysdummy1;
SELECT posstr('the quick brown fox jumps over the lazy dog', 'j') FROM sysibm.sysdummy1;
SELECT POSITION('j', 'the quick brown fox jumps over the lazy dog',  OCTETS) FROM sysibm.sysdummy1;

SELECT substr('the quick brown fox jumps over the lazy dog', locate('j', 'the quick brown fox jumps over the lazy dog')) FROM sysibm.sysdummy1;

SELECT locate('fox', 'the quick brown fox jumps over the lazy dog') FROM sysibm.sysdummy1;
SELECT locate_in_string('the quick brown fox jumps over the lazy dog', 'fox') FROM sysibm.sysdummy1;
SELECT posstr('the quick brown fox jumps over the lazy dog', 'fox') FROM sysibm.sysdummy1;
SELECT POSITION('fox', 'the quick brown fox jumps over the lazy dog',  OCTETS) FROM sysibm.sysdummy1;

SELECT substr('the quick brown fox jumps over the lazy dog', locate('fox', 'the quick brown fox jumps over the lazy dog')) FROM sysibm.sysdummy1;


s = "Ἐν ἀρχῇ ἐποίησεν ὁ θεὸς τὸν οὐρανὸν καὶ τὴν γῆν"

usubstr(s, 25, 11)
  τὸν οὐρανὸν

usubstr(s, 25, .)
  τὸν οὐρανὸν καὶ τὴν γῆν

usubstr(s, 1, ustrlen(s)-1)
  Ἐν ἀρχῇ ἐποίησεν ὁ θεὸς τὸν οὐρανὸν καὶ τὴν γῆ

usubstr(s, -3, .)
  γῆν


let string = "Hello, Swift language"
let (n, m) = (5, 4)

// Starting from `n` characters in and of `m` length.
do {
  let start = string.startIndex.advancedBy(n)
  let end = start.advancedBy(m)
  // Pure-Swift (standard library only):
  _ = string[start..<end]
  // With Apple's Foundation framework extensions:
  string.substringWithRange(start..<end)
}

// Starting from `n` characters in, up to the end of the string.
do {
  // Pure-Swift (standard library only):
  _ = String(
    string.characters.suffix(string.characters.count - n)
  )
  // With Apple's Foundation framework extensions:
  _ = string.substringFromIndex(string.startIndex.advancedBy(n))
}

// Whole string minus last character.
do {
  // Pure-Swift (standard library only):
  _ = String(
    string.characters.prefix(
      string.characters.count.predecessor()
    )
  )
  // With Apple's Foundation framework extensions:
  _ = string.substringToIndex(string.endIndex.predecessor())
}

// Starting from a known character within the string and of `m` length.
do {
  // Pure-Swift (standard library only):
  let character = Character("l")
  guard let characterIndex = string.characters.indexOf(character) else {
    fatalError("Index of '\(character)' character not found.")
  }
  let endIndex = characterIndex.advancedBy(m)
  _ = string[characterIndex..<endIndex]
}

// Starting from a known substring within the string and of `m` length.
do {
  // With Apple's Foundation framework extensions:
  let substring = "Swift"
  guard let range = string.rangeOfString(substring) else {
    fatalError("Range of substring \(substring) not found")
  }
  let start = range.startIndex
  let end = start.advancedBy(m)
  string[start..<end]
}


set str "abcdefgh"
set n 2
set m 3

puts [string range $str $n [expr {$n+$m-1}]]
puts [string range $str $n end]
puts [string range $str 0 end-1]
# Because Tcl does substrings with a pair of indices, it is easier to express
# the last two parts of the task as a chained pair of [string range] operations.
# A maximally efficient solution would calculate the indices in full first.
puts [string range [string range $str [string first "d" $str] end] [expr {$m-1}]]
puts [string range [string range $str [string first "de" $str] end] [expr {$m-1}]]

# From Tcl 8.5 onwards, these can be contracted somewhat.
puts [string range [string range $str [string first "d" $str] end] $m-1]
puts [string range [string range $str [string first "de" $str] end] $m-1]


$$ MODE TUSCRIPT
string="abcdefgh", n=4,m=n+2
substring=EXTRACT (string,#n,#m)
  PRINT substring
substring=Extract (string,#n,0)
  PRINT substring
substring=EXTRACT (string,0,-1)
  PRINT substring
n=SEARCH (string,":d:"),m=n+2
substring=EXTRACT (string,#n,#m)
  PRINT substring
substring=EXTRACT (string,":{substring}:"|,0)
  PRINT substring


string s = "Hello, world!";
int n = 1;
int m = 3;
// start at n and go m letters
string s_n_to_m = s[n:n+m];
// start at n and go to end
string s_n_to_end = s[n:s.length];
// start at beginning and show all but last
string s_notlast = s[0:s.length - 1];
// start from known letter and then go m letters
int index_of_l = s.index_of("l");
string s_froml_for_m = s[index_of_l:index_of_l + m];
// start from known substring then go m letters
int index_of_lo = s.index_of("lo");
string s_fromlo_for_m = s[index_of_lo:index_of_lo + m];


Public Sub substring()
'(1) starting from n characters in and of m length;
'(2) starting from n characters in, up to the end of the string;
'(3) whole string minus last character;
'(4) starting from a known character within the string and of m length;
'(5) starting from a known substring within the string and of m length.

    sentence = "the last thing the man said was the"
    n = 10: m = 5

    '(1)
    Debug.Print Mid(sentence, n, 5)
    '(2)
    Debug.Print Right(sentence, Len(sentence) - n + 1)
    '(3)
    Debug.Print Left(sentence, Len(sentence) - 1)
    '(4)
    k = InStr(1, sentence, "m")
    Debug.Print Mid(sentence, k, 5)
    '(5)
    k = InStr(1, sentence, "aid")
    Debug.Print Mid(sentence, k, 5)
End Sub


s = "rosettacode.org"

'starting from n characters in and of m length
WScript.StdOut.WriteLine Mid(s,8,4)

'starting from n characters in, up to the end of the string
WScript.StdOut.WriteLine Mid(s,8,Len(s)-7)

'whole string minus last character
WScript.StdOut.WriteLine Mid(s,1,Len(s)-1)

'starting from a known character within the string and of m length
WScript.StdOut.WriteLine Mid(s,InStr(1,s,"c"),4)

'starting from a known substring within the string and of m length
WScript.StdOut.WriteLine Mid(s,InStr(1,s,"ose"),6)


s <- "abcdefgh"
s.0
=> "a"

# starting from n characters in and of m length;
def (substr s start len)
  (s start start+len)
(substr s 3 2)
=> "de"

# starting from n characters in, up to the end of the string
(s 3 nil)
=> "defgh"

# whole string minus last character;
(s 3 -1)
=> "defg"

# starting from a known character within the string and of <tt>m</tt> length;
# starting from a known substring within the string and of <tt>m</tt> length.
let start (pos s pat)
  (s start start+m)


import "/str" for Str

var s  = "αβγδεζηθ"
var n = 2
var m = 3
var kc = "δ"  // known character
var ks = "δε" // known string
// for reference
System.print("Index of characters:  01234567")
System.print("Complete string:      %(s)")
// starting from n characters in and of m length
System.print("Start %(n), length %(m):    %(Str.sub(s, n...n+m))")
// starting from n characters in, up to the end of the string
System.print("Start %(n), to end:      %(Str.sub(s, n..-1))")
// whole string minus last character
System.print("All but last:         %(Str.sub(s, 0..-2))")
// starting from a known character within the string and of m length
var dx = s.indexOf(kc)
if (dx >= 0) {
    System.print("Start '%(kc)', length %(m):  %(Str.sub(s[dx..-1], 0...m))")
}
// starting from a known substring within the string and of m length
var sx = s.indexOf(ks)
if (sx >= 0) {
    System.print("Start '%(ks)', length %(m): %(Str.sub(s[sx..-1], 0...m))")
}


include xpllib;         \provides StrLen and StrFind

proc PMid(S, N, M);     \Print string at Nth character M chars long
char S, N, M, I;
[for I:= 1 to M do ChOut(0, S(N-2+I));
CrLf(0);
];

char S;
def  N=2, M=3;
[S:= "abcdefgh";
PMid(S, N, M);                  \starting from N chars in and of M length
PMid(S, N, StrLen(S)-N+1);      \starting from N chars in, up to end of string
PMid(S, 1, StrLen(S)-1);        \whole string minus last character
PMid(StrFind(S, "d" ), 1, M);   \starting from known char and of M length
PMid(StrFind(S, "cd"), 1, M);   \starting from known substring and of M length
]


c$ = "abcdefghijklmnopqrstuvwxyz"
n = 12
m = 5
// starting from n characters in and of m length;
print mid$(c$, n, m)
// starting from n characters in, up to the end of the string;
print mid$(c$, n)
// whole string minus last character;
print left$(c$, len(c$) - 1)
// starting from a known character within the string and of m length;
print mid$(c$, instr(c$, "b"), m)
// starting from a known substring within the string and of m length.
f$ = "pq"
print mid$(c$, instr(c$, f$), m)
end


str = "abcdefgh";
n = 2;
m = 3;

// starting from n character in and of m length
write, strpart(str, n:n+m-1);
// starting from n character in, up to the end of the string
write, strpart(str, n:);
// whole string minus last character
write, strpart(str, :-1);
// starting from a known character within the string and of m length
match = strfind("d", str);
write, strpart(str, [match(1), match(1)+m]);
// starting from a known substring within the string and of m length
match = strfind("cd", str);
write, strpart(str, [match(1), match(1)+m]);


var str = "abcdefgh", n = 2, m = 3;
str[n,m]  //-->"cde"
str[n,*]  //-->"cdefgh"
str[0,-1] //-->"abcdefg"
str[str.find("d"),m]  //-->"def"
str[str.find("de"),m] //-->"def"


F primes_upto(limit)
   V is_prime = [0B] * 2 [+] [1B] * (limit - 1)
   L(n) 0 .< Int(limit ^ 0.5 + 1.5)
      I is_prime[n]
         L(i) (n * n .< limit + 1).step(n)
            is_prime[i] = 0B
   R enumerate(is_prime).filter((i, prime) -> prime).map((i, prime) -> i)

V p = primes_upto(10'000'000)
[Int] s, w, b
L(i) 1 .< p.len - 1
   I p[i] > (p[i - 1] + p[i + 1]) * 0.5
      s [+]= p[i]
   E I p[i] < (p[i - 1] + p[i + 1]) * 0.5
      w [+]= p[i]
   E
      b [+]= p[i]

print(‘The first   36   strong primes: ’s[0.<36])
print(‘The   count   of the strong primes below   1,000,000: ’sum(s.filter(p -> p < 1'000'000).map(p -> 1)))
print(‘The   count   of the strong primes below  10,000,000: ’s.len)
print("\nThe first   37   weak primes: "w[0.<37])
print(‘The   count   of the weak   primes below   1,000,000: ’sum(w.filter(p -> p < 1'000'000).map(p -> 1)))
print(‘The   count   of the weak   primes below  10,000,000: ’w.len)
print("\n\nThe first   10 balanced primes: "b[0.<10])
print(‘The   count   of balanced   primes below   1,000,000: ’sum(b.filter(p -> p < 1'000'000).map(p -> 1)))
print(‘The   count   of balanced   primes below  10,000,000: ’b.len)
print("\nTOTAL primes below   1,000,000: "sum(p.filter(pr -> pr < 1'000'000).map(pr -> 1)))
print(‘TOTAL primes below  10,000,000: ’p.len)


# find and count strong and weak primes                                       #
PR heap=128M PR # set heap memory size for Algol 68G                          #
# returns a string representation of n with commas                            #
PROC commatise = ( INT n )STRING:
     BEGIN
        STRING result      := "";
        STRING unformatted  = whole( n, 0 );
        INT    ch count    := 0;
        FOR c FROM UPB unformatted BY -1 TO LWB unformatted DO
            IF   ch count <= 2 THEN ch count +:= 1
            ELSE                    ch count  := 1; "," +=: result
            FI;
            unformatted[ c ] +=: result
        OD;
        result
     END # commatise # ;
# sieve values                                                                #
CHAR prime     = "P"; #  unclassified/average prime                           #
CHAR strong    = "S"; #                strong prime                           #
CHAR weak      = "W"; #                  weak prime                           #
CHAR composite = "C"; #                   non-prime                           #
# sieve of Eratosthenes: sets s[i] to prime if i is a prime,                  #
#                                     composite otherwise                     #
PROC sieve = ( REF[]CHAR s )VOID:
     BEGIN
        # start with everything flagged as prime                              #
        FOR i TO UPB s DO s[ i ] := prime OD;
        # sieve out the non-primes                                            #
        s[ 1 ] := composite;
        FOR i FROM 2 TO ENTIER sqrt( UPB s ) DO
            IF s[ i ] = prime THEN FOR p FROM i * i BY i TO UPB s DO s[ p ] := composite OD FI
        OD
     END # sieve # ;

INT max number = 10 000 000;
# construct a sieve of primes up to slightly more than the maximum number     #
# required for the task, as we may need an extra prime for the classification #
[ 1 : max number + 1 000 ]CHAR primes;
sieve( primes );
# classify the primes                                                         #
# find the first three primes                                                 #
INT prev prime := 0;
INT curr prime := 0;
INT next prime := 0;
FOR p FROM 2 WHILE prev prime = 0 DO
    IF primes[ p ] = prime THEN
        prev prime := curr prime;
        curr prime := next prime;
        next prime := p
    FI
OD;
# 2 is the only even prime so the first three primes are the only case where  #
# the average of prev prime and next prime is not an integer                  #
IF   REAL avg = ( prev prime + next prime ) / 2;
     curr prime > avg THEN primes[ curr prime ] := strong
ELIF curr prime < avg THEN primes[ curr prime ] := weak
FI;
# classify the rest of the primes                                             #
FOR p FROM next prime + 1 WHILE curr prime <= max number DO
    IF primes[ p ] = prime THEN
        prev prime := curr prime;
        curr prime := next prime;
        next prime := p;
        IF   INT avg = ( prev prime + next prime ) OVER 2;
             curr prime > avg THEN primes[ curr prime ] := strong
        ELIF curr prime < avg THEN primes[ curr prime ] := weak
        FI
    FI
OD;
INT strong1 := 0, strong10 := 0;
INT weak1   := 0, weak10   := 0;
FOR p WHILE p < 10 000 000 DO
    IF   primes[ p ] = strong THEN
        strong10 +:= 1;
        IF p < 1 000 000 THEN strong1 +:= 1 FI
    ELIF primes[ p ] = weak   THEN
        weak10   +:= 1;
        IF p < 1 000 000 THEN weak1   +:= 1 FI
    FI
OD;
INT strong count  := 0;
print( ( "first 36 strong primes:", newline ) );
FOR p WHILE strong count < 36 DO IF primes[ p ] = strong THEN print( ( " ", whole( p, 0 ) ) ); strong count +:= 1 FI OD;
print( ( newline ) );
print( ( "strong primes below   1,000,000: ", commatise(  strong1 ), newline ) );
print( ( "strong primes below  10,000,000: ", commatise( strong10 ), newline ) );
print( ( "first 37   weak primes:", newline ) );
INT weak count    := 0;
FOR p WHILE weak count   < 37 DO IF primes[ p ] = weak   THEN print( ( " ", whole( p, 0 ) ) );   weak count +:= 1 FI OD;
print( ( newline ) );
print( ( "  weak primes below   1,000,000: ", commatise(    weak1 ), newline ) );
print( ( "  weak primes below  10,000,000: ", commatise(   weak10 ), newline ) )


# syntax: GAWK -f STRONG_AND_WEAK_PRIMES.AWK
BEGIN {
    for (i=1; i<1E7; i++) {
      if (is_prime(i)) {
        arr[++n] = i
      }
    }
# strong:
    stop1 = 36 ; stop2 = 1E6 ; stop3 = 1E7
    count1 = count2 = count3 = 0
    printf("The first %d strong primes:",stop1)
    for (i=2; count1<stop1; i++) {
      if (arr[i] > (arr[i-1] + arr[i+1]) / 2) {
        count1++
        printf(" %d",arr[i])
      }
    }
    printf("\n")
    for (i=2; i<stop3; i++) {
      if (arr[i] > (arr[i-1] + arr[i+1]) / 2) {
        count3++
        if (arr[i] < stop2) {
          count2++
        }
      }
    }
    printf("Number below %d: %d\n",stop2,count2)
    printf("Number below %d: %d\n",stop3,count3)
# weak:
    stop1 = 37 ; stop2 = 1E6 ; stop3 = 1E7
    count1 = count2 = count3 = 0
    printf("The first %d weak primes:",stop1)
    for (i=2; count1<stop1; i++) {
      if (arr[i] < (arr[i-1] + arr[i+1]) / 2) {
        count1++
        printf(" %d",arr[i])
      }
    }
    printf("\n")
    for (i=2; i<stop3; i++) {
      if (arr[i] < (arr[i-1] + arr[i+1]) / 2) {
        count3++
        if (arr[i] < stop2) {
          count2++
        }
      }
    }
    printf("Number below %d: %d\n",stop2,count2)
    printf("Number below %d: %d\n",stop3,count3)
    exit(0)
}
function is_prime(n,  d) {
    d = 5
    if (n < 2) { return(0) }
    if (n % 2 == 0) { return(n == 2) }
    if (n % 3 == 0) { return(n == 3) }
    while (d*d <= n) {
      if (n % d == 0) { return(0) }
      d += 2
      if (n % d == 0) { return(0) }
      d += 4
    }
    return(1)
}


using static System.Console;
using static System.Linq.Enumerable;
using System;

public static class StrongAndWeakPrimes
{
    public static void Main() {
        var primes = PrimeGenerator(10_000_100).ToList();
        var strongPrimes = from i in Range(1, primes.Count - 2) where primes[i] > (primes[i-1] + primes[i+1]) / 2 select primes[i];
        var weakPrimes = from i in Range(1, primes.Count - 2) where primes[i] < (primes[i-1] + primes[i+1]) / 2.0 select primes[i];
        WriteLine($"First 36 strong primes: {string.Join(", ", strongPrimes.Take(36))}");
        WriteLine($"There are {strongPrimes.TakeWhile(p => p < 1_000_000).Count():N0} strong primes below {1_000_000:N0}");
        WriteLine($"There are {strongPrimes.TakeWhile(p => p < 10_000_000).Count():N0} strong primes below {10_000_000:N0}");
        WriteLine($"First 37 weak primes: {string.Join(", ", weakPrimes.Take(37))}");
        WriteLine($"There are {weakPrimes.TakeWhile(p => p < 1_000_000).Count():N0} weak primes below {1_000_000:N0}");
        WriteLine($"There are {weakPrimes.TakeWhile(p => p < 10_000_000).Count():N0} weak primes below {1_000_000:N0}");
    }

}


#include <algorithm>
#include <iostream>
#include <iterator>
#include <locale>
#include <vector>
#include "prime_sieve.hpp"

const int limit1 = 1000000;
const int limit2 = 10000000;

class prime_info {
public:
    explicit prime_info(int max) : max_print(max) {}
    void add_prime(int prime);
    void print(std::ostream& os, const char* name) const;
private:
    int max_print;
    int count1 = 0;
    int count2 = 0;
    std::vector<int> primes;
};

void prime_info::add_prime(int prime) {
    ++count2;
    if (prime < limit1)
        ++count1;
    if (count2 <= max_print)
        primes.push_back(prime);
}

void prime_info::print(std::ostream& os, const char* name) const {
    os << "First " << max_print << " " << name << " primes: ";
    std::copy(primes.begin(), primes.end(), std::ostream_iterator<int>(os, " "));
    os << '\n';
    os << "Number of " << name << " primes below " << limit1 << ": " << count1 << '\n';
    os << "Number of " << name << " primes below " << limit2 << ": " << count2 << '\n';
}

int main() {
    prime_sieve sieve(limit2 + 100);

    // write numbers with groups of digits separated according to the system default locale
    std::cout.imbue(std::locale(""));

    // count and print strong/weak prime numbers
    prime_info strong_primes(36);
    prime_info weak_primes(37);
    int p1 = 2, p2 = 3;
    for (int p3 = 5; p2 < limit2; ++p3) {
        if (!sieve.is_prime(p3))
            continue;
        int diff = p1 + p3 - 2 * p2;
        if (diff < 0)
            strong_primes.add_prime(p2);
        else if (diff > 0)
            weak_primes.add_prime(p2);
        p1 = p2;
        p2 = p3;
    }
    strong_primes.print(std::cout, "strong");
    weak_primes.print(std::cout, "weak");
    return 0;
}


USING: formatting grouping kernel math math.primes sequences
tools.memory.private ;
IN: rosetta-code.strong-primes

: fn ( p-1 p p+1 -- p sum ) rot + 2 / ;
: strong? ( p-1 p p+1 -- ? ) fn > ;
: weak? ( p-1 p p+1 -- ? ) fn < ;

: swprimes ( seq quot -- seq )
    [ 3 <clumps> ] dip [ first3 ] prepose filter [ second ] map
    ; inline

: stats ( seq n -- firstn count1 count2 )
    [ head ] [ drop [ 1e6 < ] filter length ] [ drop length ]
    2tri [ commas ] [email protected] ;

10,000,019 primes-upto [ strong? ] over [ weak? ]
[ swprimes ] [email protected] [ 36 ] [ 37 ] bi* [ stats ] [email protected]

"First 36 strong primes:\n%[%d, %]
%s strong primes below 1,000,000
%s strong primes below 10,000,000\n
First 37 weak primes:\n%[%d, %]
%s weak primes below 1,000,000
%s weak primes below 10,000,000\n" printf


#include "isprime.bas"

function nextprime( n as uinteger ) as uinteger
    'finds the next prime after n, excluding n if it happens to be prime itself
    if n = 0 then return 2
    if n < 3 then return n + 1
    dim as integer q = n + 2
    while not isprime(q)
        q+=2
    wend
    return q
end function

function lastprime( n as uinteger ) as uinteger
    'finds the last prime before n, excluding n if it happens to be prime itself
    if n = 2 then return 0       'zero isn't prime, but it is a good sentinel value :)
    if n = 3 then return 2
    dim as integer q = n - 2
    while not isprime(q)
        q-=2
    wend
    return q
end function

function isstrong( p as integer ) as boolean
    if nextprime(p) + lastprime(p) >= 2*p then return false else return true
end function

function isweak( p as integer ) as boolean
    if nextprime(p) + lastprime(p) <= 2*p then return false else return true
end function

print "The first 36 strong primes are: "
dim as uinteger c, p=3
while p < 10000000
    if isprime(p) andalso isstrong(p) then
        c += 1
        if c <= 36 then print p;" ";
        if c=37 then print
    end if
    if p = 1000001 then print "There are ";c;" strong primes below one million"
    p+=2
wend
print "There are ";c;" strong primes below ten million"
print

print "The first 37 weak primes are: "
p=3 : c=0
while p < 10000000
    if isprime(p) andalso isweak(p) then
        c += 1
        if c <= 37 then print p;" ";
        if c=38 then print
    end if

    if p = 1000001 then print "There are ";c;" weak primes below one million"
    p+=2
wend
print "There are ";c;" weak primes below ten million"
print


strongPrimes[end=undef] := select[primes[3,end], {|p| p > (previousPrime[p] + nextPrime[p])/2 }]
weakPrimes[end=undef]   := select[primes[3,end], {|p| p < (previousPrime[p] + nextPrime[p])/2 }]

println["First 36 strong primes:  " + first[strongPrimes[], 36]]
println["Strong primes below  1,000,000: " + length[strongPrimes[1_000_000]]]
println["Strong primes below 10,000,000: " + length[strongPrimes[10_000_000]]]

println["First 37 weak primes:  " + first[weakPrimes[], 37]]
println["Weak primes below  1,000,000: " + length[weakPrimes[1_000_000]]]
println["Weak primes below 10,000,000: " + length[weakPrimes[10_000_000]]]


package main

import "fmt"

func sieve(limit int) []bool {
    limit++
    // True denotes composite, false denotes prime.
    // Don't bother marking even numbers >= 4 as composite.
    c := make([]bool, limit)
    c[0] = true
    c[1] = true

    p := 3 // start from 3
    for {
        p2 := p * p
        if p2 >= limit {
            break
        }
        for i := p2; i < limit; i += 2 * p {
            c[i] = true
        }
        for {
            p += 2
            if !c[p] {
                break
            }
        }
    }
    return c
}

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

func main() {
    // sieve up to 10,000,019 - the first prime after 10 million
    const limit = 1e7 + 19
    sieved := sieve(limit)
    // extract primes
    var primes = []int{2}
    for i := 3; i <= limit; i += 2 {
        if !sieved[i] {
            primes = append(primes, i)
        }
    }
    // extract strong and weak primes
    var strong []int
    var weak = []int{3}                  // so can use integer division for rest
    for i := 2; i < len(primes)-1; i++ { // start from 5
        if primes[i] > (primes[i-1]+primes[i+1])/2 {
            strong = append(strong, primes[i])
        } else if primes[i] < (primes[i-1]+primes[i+1])/2 {
            weak = append(weak, primes[i])
        }
    }

    fmt.Println("The first 36 strong primes are:")
    fmt.Println(strong[:36])
    count := 0
    for _, p := range strong {
        if p >= 1e6 {
            break
        }
        count++
    }
    fmt.Println("\nThe number of strong primes below 1,000,000 is", commatize(count))
    fmt.Println("\nThe number of strong primes below 10,000,000 is", commatize(len(strong)))

    fmt.Println("\nThe first 37 weak primes are:")
    fmt.Println(weak[:37])
    count = 0
    for _, p := range weak {
        if p >= 1e6 {
            break
        }
        count++
    }
    fmt.Println("\nThe number of weak primes below 1,000,000 is", commatize(count))
    fmt.Println("\nThe number of weak primes below 10,000,000 is", commatize(len(weak)))
}


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

xPrimes :: (Real a, Fractional b) => (b -> b -> Bool) -> [a] -> [a]
xPrimes op ps@(p1:p2:p3:xs)
  | realToFrac p2 `op` (realToFrac (p1 + p3) / 2) = p2 : xPrimes op (tail ps)
  | otherwise = xPrimes op (tail ps)

main :: IO ()
main = do
  printf "First 36 strong primes: %s\n" . show . take 36 $ strongPrimes
  printf "Strong primes below 1,000,000: %d\n" . length . takeWhile (<1000000) $ strongPrimes
  printf "Strong primes below 10,000,000: %d\n\n" . length . takeWhile (<10000000) $ strongPrimes

  printf "First 37 weak primes: %s\n" . show . take 37 $ weakPrimes
  printf "Weak primes below 1,000,000: %d\n" . length . takeWhile (<1000000) $ weakPrimes
  printf "Weak primes below 10,000,000: %d\n\n" . length . takeWhile (<10000000) $ weakPrimes
  where strongPrimes = xPrimes (>) primes
        weakPrimes   = xPrimes (<) primes


public class StrongAndWeakPrimes {

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

    public static void main(String[] args) {
        sieve();
        System.out.println("First 36 strong primes:");
        displayStrongPrimes(36);
        for ( int n : new int[] {1_000_000, 10_000_000}) {
            System.out.printf("Number of strong primes below %,d = %,d%n", n, strongPrimesBelow(n));
        }
        System.out.println("First 37 weak primes:");
        displayWeakPrimes(37);
        for ( int n : new int[] {1_000_000, 10_000_000}) {
            System.out.printf("Number of weak primes below %,d = %,d%n", n, weakPrimesBelow(n));
        }
    }

    private static int weakPrimesBelow(int maxPrime) {
        int priorPrime = 2;
        int currentPrime = 3;
        int count = 0;
        while ( currentPrime < maxPrime ) {
            int nextPrime = getNextPrime(currentPrime);
            if ( currentPrime * 2 < priorPrime + nextPrime ) {
                count++;
            }
            priorPrime = currentPrime;
            currentPrime = nextPrime;
        }
        return count;
    }

    private static void displayWeakPrimes(int maxCount) {
        int priorPrime = 2;
        int currentPrime = 3;
        int count = 0;
        while ( count < maxCount ) {
            int nextPrime = getNextPrime(currentPrime);
            if ( currentPrime * 2 < priorPrime + nextPrime) {
                count++;
                System.out.printf("%d ", currentPrime);
            }
            priorPrime = currentPrime;
            currentPrime = nextPrime;
        }
        System.out.println();
    }

    private static int getNextPrime(int currentPrime) {
        int nextPrime = currentPrime + 2;
        while ( ! primes[nextPrime] ) {
            nextPrime += 2;
        }
        return nextPrime;
    }

    private static int strongPrimesBelow(int maxPrime) {
        int priorPrime = 2;
        int currentPrime = 3;
        int count = 0;
        while ( currentPrime < maxPrime ) {
            int nextPrime = getNextPrime(currentPrime);
            if ( currentPrime * 2 > priorPrime + nextPrime ) {
                count++;
            }
            priorPrime = currentPrime;
            currentPrime = nextPrime;
        }
        return count;
    }

    private static void displayStrongPrimes(int maxCount) {
        int priorPrime = 2;
        int currentPrime = 3;
        int count = 0;
        while ( count < maxCount ) {
            int nextPrime = getNextPrime(currentPrime);
            if ( currentPrime * 2 > priorPrime + nextPrime) {
                count++;
                System.out.printf("%d ", currentPrime);
            }
            priorPrime = currentPrime;
            currentPrime = nextPrime;
        }
        System.out.println();
    }

    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, Formatting

function parseprimelist()
    primelist = primes(2, 10000019)
    strongs = Vector{Int64}()
    weaks = Vector{Int64}()
    balanceds = Vector{Int64}()
    for (n, p) in enumerate(primelist)
        if n == 1 || n == length(primelist)
            continue
        end
        x = (primelist[n - 1] + primelist[n + 1]) / 2
        if x > p
            push!(weaks, p)
        elseif x < p
            push!(strongs, p)
        else
            push!(balanceds, p)
        end
    end
    println("The first 36 strong primes are: ", strongs[1:36])
    println("There are ", format(sum(map(x -> x < 1000000, strongs)), commas=true), " stromg primes less than 1 million.")
    println("There are ", format(length(strongs), commas=true), " strong primes less than 10 million.")
    println("The first 37 weak primes are: ", weaks[1:37])
    println("There are ", format(sum(map(x -> x < 1000000, weaks)), commas=true), " weak primes less than 1 million.")
    println("There are ", format(length(weaks), commas=true), " weak primes less than 10 million.")
    println("The first 28 balanced primes are: ", balanceds[1:28])
    println("There are ", format(sum(map(x -> x < 1000000, balanceds)), commas=true), " balanced primes less than 1 million.")
    println("There are ", format(length(balanceds), commas=true), " balanced primes less than 10 million.")
end

parseprimelist()


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

fun main() {
    sieve()

    println("First 36 strong primes:")
    displayStrongPrimes(36)
    for (n in intArrayOf(1000000, 10000000)) {
        System.out.printf("Number of strong primes below %,d = %,d%n", n, strongPrimesBelow(n))
    }

    println("First 37 weak primes:")
    displayWeakPrimes(37)
    for (n in intArrayOf(1000000, 10000000)) {
        System.out.printf("Number of weak primes below %,d = %,d%n", n, weakPrimesBelow(n))
    }
}

private fun weakPrimesBelow(maxPrime: Int): Int {
    var priorPrime = 2
    var currentPrime = 3
    var count = 0
    while (currentPrime < maxPrime) {
        val nextPrime = getNextPrime(currentPrime)
        if (currentPrime * 2 < priorPrime + nextPrime) {
            count++
        }
        priorPrime = currentPrime
        currentPrime = nextPrime
    }
    return count
}

private fun displayWeakPrimes(maxCount: Int) {
    var priorPrime = 2
    var currentPrime = 3
    var count = 0
    while (count < maxCount) {
        val nextPrime = getNextPrime(currentPrime)
        if (currentPrime * 2 < priorPrime + nextPrime) {
            count++
            print("$currentPrime ")
        }
        priorPrime = currentPrime
        currentPrime = nextPrime
    }
    println()
}

private fun getNextPrime(currentPrime: Int): Int {
    var nextPrime = currentPrime + 2
    while (!primes[nextPrime]) {
        nextPrime += 2
    }
    return nextPrime
}

private fun strongPrimesBelow(maxPrime: Int): Int {
    var priorPrime = 2
    var currentPrime = 3
    var count = 0
    while (currentPrime < maxPrime) {
        val nextPrime = getNextPrime(currentPrime)
        if (currentPrime * 2 > priorPrime + nextPrime) {
            count++
        }
        priorPrime = currentPrime
        currentPrime = nextPrime
    }
    return count
}

private fun displayStrongPrimes(maxCount: Int) {
    var priorPrime = 2
    var currentPrime = 3
    var count = 0
    while (count < maxCount) {
        val nextPrime = getNextPrime(currentPrime)
        if (currentPrime * 2 > priorPrime + nextPrime) {
            count++
            print("$currentPrime ")
        }
        priorPrime = currentPrime
        currentPrime = nextPrime
    }
    println()
}

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


#!/bin/ksh

# Strong and weak primes
#	# Find and display (on one line) the first   36 strong  primes.
#	# Find and display the count of the strong primes below 1,000,000.
#	# Find and display the count of the strong primes below 10,000,000.
#	# Find and display (on one line) the first   37 weak  primes.
#	# Find and display the count of the weak primes below 1,000,000.
#	# Find and display the count of the weak primes below 10,000,000.
#	# (Optional) display the counts and "below numbers" with commas. ???

#	# A strong prime is when prime[p] > (prime[p-1] + prime[p+1]) ÷ 2
#	# A  weak prime  is when prime[p] < (prime[p-1] + prime[p+1]) ÷ 2
#	# Balanced prime is when prime[p] = (prime[p-1] + prime[p+1]) ÷ 2

#	# Variables:
#
integer  NUM_STRONG=36 NUM_WEAK=37 GOAL1=1000000 MAX_INT=10000000

#	# Functions:
#
#	# Function _isprime(n) return 1 for prime, 0 for not prime
#
function _isprime {
	typeset _n ; integer _n=$1
	typeset _i ; integer _i

	(( _n < 2 )) && return 0
	for (( _i=2 ; _i*_i<=_n ; _i++ )); do
		(( ! ( _n % _i ) )) && return 0
	done
	return 1
}

#	# Function _strength(prime[n], prime[n-1], prime[n+1]) return 1 for strong
#
function _strength {
	typeset _pri ; integer _pri=$1		# PRIme number under consideration
	typeset _pre ; integer _pre=$2		# PREvious prime number
	typeset _nex ; integer _nex=$3		# NEXt prime number
	typeset _result ; typeset -F1 _result

	(( _result = (_pre + _nex) / 2.0 ))
	(( _pri > _result )) && echo STRONG && return 0
	(( _pri < _result )) && echo WEAK   && return 1
	echo BALANCED && return 99
}

 #####
# main #
 ######

integer spcnt=0 wpcnt=0 bpcnt=0 sflg=0 wflg=0 i j k goal1_strong goal1_weak
typeset -C prime	# prime[].val  prime[].typ
	typeset -a prime.val
	typeset -a prime.typ
prime.typ[0]='NA' ; prime.typ[1]='NA'

for (( i=2; i<MAX_INT; i++ )); do
	_isprime ${i} ; (( ! $? )) && continue
	prime.val+=( ${i} )
	(( ${#prime.val[*]} <= 2 )) && continue

	(( j = ${#prime.val[*]} - 2 )) ; (( k = j - 1 ))
	prime.typ+=( $(_strength ${prime.val[${j}]} ${prime.val[k]} ${prime.val[-1]}) )
	case $? in
		 0)	(( spcnt++ ))
			(( spcnt <= NUM_STRONG )) && strbuff+="${prime.val[j]}, "
			(( i >= GOAL1 )) && (( ! sflg )) && (( goal1_strong = spcnt - 1 )) && (( sflg = 1 ))
		 ;;

		 1) (( wpcnt++ ))
			(( wpcnt <= NUM_WEAK )) && weabuff+="${prime.val[j]}, "
			(( i >= GOAL1 )) && (( ! wflg )) && (( goal1_weak = wpcnt - 1 )) && (( wflg = 1 ))
		 ;;

		99)	(( bpcnt++ ))
		 ;;
	esac
done

printf "Total primes under %d = %d\n\n"				$MAX_INT	${#prime.val[*]}
printf "First %d Strong Primes are: %s\n\n"			$NUM_STRONG	"${strbuff%,*}"
printf "Number of Strong Primes under %d  is: %d\n"		$GOAL1		${goal1_strong}
printf "Number of Strong Primes under %d is: %d\n\n\n"		$MAX_INT	${spcnt}
printf "First %d Weak Primes are: %s\n\n"			$NUM_WEAK	"${weabuff%,*}"
printf "Number of Weak Primes under %d  is: %d\n"		$GOAL1		${goal1_weak}
printf "Number of Weak Primes under %d is: %d\n\n\n"		$MAX_INT	${wpcnt}
printf "Number of Balanced Primes under %d is: %d\n\n\n"	$MAX_INT	${bpcnt}


-- Return a table of the primes up to n, then one more
function primeList (n)
  local function isPrime (x)
    for d = 3, math.sqrt(x), 2 do
      if x % d == 0 then return false end
    end
    return true
  end
  local pTable, j = {2, 3}
  for i = 5, n, 2 do
    if isPrime(i) then
      table.insert(pTable, i)
    end
    j = i
  end
  repeat j = j + 2 until isPrime(j)
  table.insert(pTable, j)
  return pTable
end

-- Return a boolean indicating whether prime p is strong
function isStrong (p)
  if p == 1 or p == #prime then return false end
  return prime[p] > (prime[p-1] + prime[p+1]) / 2
end

-- Return a boolean indicating whether prime p is weak
function isWeak (p)
  if p == 1 or p == #prime then return false end
  return prime[p] < (prime[p-1] + prime[p+1]) / 2
end

-- Main procedure
prime = primeList(1e7)
local strong, weak, sCount, wCount = {}, {}, 0, 0
for k, v in pairs(prime) do
  if isStrong(k) then
    table.insert(strong, v)
    if v < 1e6 then sCount = sCount + 1 end
  end
  if isWeak(k) then
    table.insert(weak, v)
    if v < 1e6 then wCount = wCount + 1 end
  end
end
print("The first 36 strong primes are:")
for i = 1, 36 do io.write(strong[i] .. " ") end
print("\n\nThere are " .. sCount .. " strong primes below one million.")
print("\nThere are " .. #strong .. " strong primes below ten million.")
print("\nThe first 37 weak primes are:")
for i = 1, 37 do io.write(weak[i] .. " ") end
print("\n\nThere are " .. wCount .. " weak primes below one million.")
print("\nThere are " .. #weak .. " weak primes below ten million.")


isStrong := proc(n::posint) local holder;
holder := false;
if isprime(n) and 1/2*prevprime(n) + 1/2*nextprime(n) < n then
   holder := true;
end if;
return holder;
end proc:

isWeak := proc(n::posint) local holder;
holder := false;
if isprime(n) and n < 1/2*prevprime(n) + 1/2*nextprime(n) then
   holder := true;
end if;
return holder;
end proc

findStrong := proc(n::posint) local count, list, k;
count := 0; list := [];
for k from 3 while count < n do
  if isStrong(k) then count := count + 1;
    list := [op(list), k];
  end if;
end do;
return list;
end proc:

findWeak := proc(n::posint) local count, list, k;
count := 0;
list := [];
for k from 3 while count < n do
  if isWeak(k) then
     count := count + 1;
     list := [op(list), k];
  end if;
end do;
return list;
end proc:

findStrong(36)
findWeak(37)
countStrong(1000000)
countStrong(10000000)
countWeak(1000000)
countWeak(10000000)


import math, strutils

const
  M = 10_000_000
  N = M + 19      # Maximum value for sieve.

# Fill sieve of Erathosthenes.
var comp: array[2..N, bool]   # True means composite; default is prime.
for n in countup(3, sqrt(N.toFloat).int, 2):
  if not comp[n]:
    for k in countup(n * n, N, 2 * n):
      comp[k] = true

# Build list of primes.
var primes = @[2]
for n in countup(3, N, 2):
  if not comp[n]:
    primes.add n
if primes[^1] < M: quit "Not enough primes: please, increase value of N."

# Build lists of strong and weak primes.
var strongPrimes, weakPrimes: seq[int]
for i in 1..<primes.high:
  let p = primes[i]
  if p shl 1 > primes[i - 1] + primes[i + 1]:
    strongPrimes.add p
  elif p shl 1 < primes[i - 1] + primes[i + 1]:
    weakPrimes.add p

when isMainModule:

  proc count(list: seq[int]; max: int): int =
    ## Return the count of values less than "max".
    for p in list:
      if p >= max: break
      inc result

  echo "First 36 strong primes:"
  echo "  ", strongPrimes[0..35].join(" ")
  echo "Count of strong primes below 1_000_000: ", strongPrimes.count(1_000_000)
  echo "Count of strong primes below 10_000_000: ", strongPrimes.count(10_000_000)
  echo()

  echo "First 37 weak primes:"
  echo "  ", weakPrimes[0..36].join(" ")
  echo "Count of weak primes below 1_000_000: ", weakPrimes.count(1_000_000)
  echo "Count of weak primes below 10_000_000: ", weakPrimes.count(10_000_000)


program WeakPrim;
{$IFNDEF FPC}
  {$AppType CONSOLE}
{$ENDIF}
const
  PrimeLimit = 1000*1000*1000;//must be >= 2*3;
type
  tLimit = 0..(PrimeLimit-1) DIV 2;
  tPrimCnt = 0..51*1000*1000;
  tWeakStrong = record
                   strong,
                   balanced,
                   weak : NativeUint;
                end;
var
  primes: array [tLimit] of byte; //always initialized with 0 at startup
  delta : array [tPrimCnt] of byte;
  cntWS : tWeakStrong;
  deltaCnt :NativeUint;

procedure sieveprimes;
//Only odd numbers, minimal count of strikes
var
  spIdx,sieveprime,sievePos,fact :NativeUInt;
begin
  spIdx := 1;
  repeat
    if primes[spIdx]=0 then
    begin
      sieveprime := 2*spIdx+1;
      fact := PrimeLimit DIV sieveprime;
      if Not(odd(fact)) then
        dec(fact);
      IF fact < sieveprime then
        BREAK;
      sievePos := ((fact*sieveprime)-1) DIV 2;
      fact := (fact-1) DIV 2;
      repeat
        primes[sievePos] := 1;
        repeat
          dec(fact);
          dec(sievePos,sieveprime);
        until primes[fact]= 0;
      until fact < spIdx;
    end;
    inc(spIdx);
  until false;
end;
{ Not neccessary for this small primes.
procedure EmergencyStop(i:NativeInt);
Begin
  Writeln( 'STOP at ',i,'.th prime');
  HALT(i);
end;
}
function GetDeltas:NativeUint;
//Converting prime positions into distance
var
  i,j,last : NativeInt;
Begin
  j :=0;
  i := 1;
  last :=1;
  For i := 1 to High(primes) do
    if primes[i] = 0 then
    Begin
      //IF i-last > 255 {aka delta prim > 512} then  EmergencyStop (j);
      delta[j] := i-last;
      last := i;
      inc(j);
   end;
   GetDeltas := j;
end;

procedure OutHeader;
Begin
  writeln('Limit':12,'Strong':10,'balanced':12,'weak':10);
end;

procedure OutcntWS (const cntWS : tWeakStrong;Lmt:NativeInt);
Begin
  with cntWS do
    writeln(lmt:12,Strong:10,balanced:12,weak:10);
end;

procedure CntWeakStrong10(var Out:tWeakStrong);
// Output a table of values for strang/balanced/weak for 10^n
var
  idx,diff,prime,lmt :NativeInt;
begin
  OutHeader;
  lmt := 10;
  fillchar(Out,SizeOf(Out),#0);
  idx := 0;
  prime:=3;
  repeat
    dec(prime,2*delta[idx]);
    while idx < deltaCnt do
    Begin
      inc(prime,2*delta[idx]);
      IF prime > lmt then
         BREAK;

      diff := delta[idx] - delta[idx+1];
      if diff>0 then
        inc(Out.strong)
      else
        if diff< 0 then
          inc(Out.weak)
        else
          inc(Out.balanced);

      inc(idx);
    end;
    OutcntWS(Out,Lmt);
    lmt := lmt*10;
  until Lmt >  PrimeLimit;
end;

procedure WeakOut(cnt:NativeInt);
var
  idx,prime : NativeInt;
begin
  Writeln('The first ',cnt,' weak primes');
  prime:=3;
  idx := 0;
  repeat
    inc(prime,2*delta[idx]);
    if delta[idx] - delta[idx+1]< 0 then
    Begin
      write(prime,' ');
      dec(cnt);
      IF cnt <=0 then
        BREAK;
    end;
    inc(idx);
  until idx >= deltaCnt;
  Writeln;
end;

procedure StrongOut(cnt:NativeInt);
var
  idx,prime : NativeInt;
begin
  Writeln('The first ',cnt,' strong primes');
  prime:=3;
  idx := 0;
  repeat
    inc(prime,2*delta[idx]);
    if delta[idx] - delta[idx+1]> 0 then
    Begin
      write(prime,' ');
      dec(cnt);
      IF cnt <=0 then
        BREAK;
    end;
    inc(idx);
  until idx >= deltaCnt;
  Writeln;
end;

begin
  sieveprimes;
  deltaCnt := GetDeltas;

  StrongOut(36);
  WeakOut(37);
  CntWeakStrong10(CntWs);
end.


use ntheory qw(primes vecfirst);

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

sub below { my ($m, @a) = @_; vecfirst { $a[$_] > $m } 0..$#a }

my (@strong, @weak, @balanced);
my @primes = @{ primes(10_000_019) };

for my $k (1 .. $#primes - 1) {
    my $x = ($primes[$k - 1] + $primes[$k + 1]) / 2;
    if    ($x > $primes[$k]) { push @weak,     $primes[$k] }
    elsif ($x < $primes[$k]) { push @strong,   $primes[$k] }
    else                     { push @balanced, $primes[$k] }
}

for ([\@strong,   'strong',   36, 1e6, 1e7],
     [\@weak,     'weak',     37, 1e6, 1e7],
     [\@balanced, 'balanced', 28, 1e6, 1e7]) {
    my($pr, $type, $d, $c1, $c2) = @$_;
    print "\nFirst $d $type primes:\n", join ' ', map { comma $_ } @$pr[0..$d-1], "\n";
    print "Count of $type primes <=  @{[comma $c1]}:  " . comma below($c1,@$pr) . "\n";
    print "Count of $type primes <= @{[comma $c2]}: "   . comma scalar @$pr . "\n";
}


with javascript_semantics
sequence strong = {}, weak = {}
for i=2 to get_maxprime(1e14) do -- (ie idx of primes < (sqrt(1e14)==1e7), bar 1st)
    integer p = get_prime(i),
    c = compare(p,(get_prime(i-1)+get_prime(i+1))/2)
    if c=+1 then strong &= p end if
    if c=-1 then weak   &= p end if
end for
printf(1,"The first thirty six strong primes: %s\n",{join(shorten(strong[1..36],"",4,"%2d"),", ")})
printf(1,"The first thirty seven weak primes: %s\n",{join(shorten(  weak[1..37],"",4,"%2d"),", ")})
printf(1,"There are %,d strong primes below %,d and %,d below %,d\n",{abs(binary_search(1e6,strong))-1,1e6,length(strong),1e7})
printf(1,"There are %,d   weak primes below %,d and %,d below %,d\n",{abs(binary_search(1e6,  weak))-1,1e6,length(  weak),1e7})


#MAX=10000000+20
Global Dim P.b(#MAX) : FillMemory(@P(),#MAX,1,#PB_Byte)
Global NewList Primes.i()
Global NewList Strong.i()
Global NewList Weak.i()

For n=2 To Sqr(#MAX)+1 : If P(n) : m=n*n : While m<=#MAX : P(m)=0 : m+n : Wend : EndIf : Next
For i=2 To #MAX : If p(i) : AddElement(Primes()) : Primes()=i : EndIf : Next

If FirstElement(Primes())
  pp=Primes()
  While NextElement(Primes())
    ap=Primes()
    If NextElement(Primes()) : np=Primes() : Else : Break : EndIf
    If ap>(pp+np)/2.0 : AddElement(Strong()) : Strong()=ap : If ap<1000000 : c1+1 : EndIf : EndIf
    If ap<(pp+np)/2.0 : AddElement(Weak()) : Weak()=ap : If ap<1000000 : c2+1 : EndIf : EndIf
    PreviousElement(Primes()) : pp=Primes()
  Wend
EndIf

OpenConsole()
If FirstElement(Strong())
  PrintN("First 36 strong primes:")
  Print(Str(Strong())+" ")
  For i=2 To 36 : If NextElement(Strong()) : Print(Str(Strong())+" ") : Else : Break : EndIf : Next
  PrintN("")
EndIf
PrintN("Number of strong primes below  1'000'000 = "+FormatNumber(c1,0,".","'"))
PrintN("Number of strong primes below 10'000'000 = "+FormatNumber(ListSize(Strong()),0,".","'"))
If FirstElement(Weak())
  PrintN("First 37 weak primes:")
  Print(Str(Weak())+" ")
  For i=2 To 37 : If NextElement(Weak()) : Print(Str(Weak())+" ") : Else : Break : EndIf : Next
  PrintN("")
EndIf
PrintN("Number of weak primes below  1'000'000 = "+FormatNumber(c2,0,".","'"))
PrintN("Number of weak primes below 10'000'000 = "+FormatNumber(ListSize(Weak()),0,".","'"))
Input()


import numpy as np

def primesfrom2to(n):
    # https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Input n>=6, Returns a array of primes, 2 <= p < n """
    sieve = np.ones(n//3 + (n%6==2), dtype=np.bool)
    sieve[0] = False
    for i in range(int(n**0.5)//3+1):
        if sieve[i]:
            k=3*i+1|1
            sieve[      ((k*k)//3)      ::2*k] = False
            sieve[(k*k+4*k-2*k*(i&1))//3::2*k] = False
    return np.r_[2,3,((3*np.nonzero(sieve)[0]+1)|1)]

p = primes10m   = primesfrom2to(10_000_000)
s = strong10m   = [t for s, t, u in zip(p, p[1:], p[2:])
                   if t > (s + u) / 2]
w = weak10m     = [t for s, t, u in zip(p, p[1:], p[2:])
                   if t < (s + u) / 2]
b = balanced10m = [t for s, t, u in zip(p, p[1:], p[2:])
                   if t == (s + u) / 2]

print('The first   36   strong primes:', s[:36])
print('The   count   of the strong primes below   1,000,000:',
      sum(1 for p in s if p < 1_000_000))
print('The   count   of the strong primes below  10,000,000:', len(s))
print('\nThe first   37   weak primes:', w[:37])
print('The   count   of the weak   primes below   1,000,000:',
      sum(1 for p in w if p < 1_000_000))
print('The   count   of the weak   primes below  10,000,000:', len(w))
print('\n\nThe first   10 balanced primes:', b[:10])
print('The   count   of balanced   primes below   1,000,000:',
      sum(1 for p in b if p < 1_000_000))
print('The   count   of balanced   primes below  10,000,000:', len(b))
print('\nTOTAL primes below   1,000,000:',
      sum(1 for pr in p if pr < 1_000_000))
print('TOTAL primes below  10,000,000:', len(p))


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

use Math::Primesieve;

my $sieve = Math::Primesieve.new;

my @primes = $sieve.primes(10_000_019);

my (@weak, @balanced, @strong);

for 1 ..^ @primes - 1 -> $p {
    given (@primes[$p - 1] + @primes[$p + 1]) / 2 {
        when * > @primes[$p] {     @weak.push: @primes[$p] }
        when * < @primes[$p] {   @strong.push: @primes[$p] }
        default              { @balanced.push: @primes[$p] }
    }
}

for @strong,   'strong',   36,
    @weak,     'weak',     37,
    @balanced, 'balanced', 28
  -> @pr, $type, $d {
    say "\nFirst $d $type primes:\n", @pr[^$d]».,
    say "Count of $type primes <=  {comma 1e6}:  ", comma +@pr[^(@pr.first: * > 1e6,:k)];
    say "Count of $type primes <= {comma 1e7}: ", comma +@pr;
}


/*REXX program lists a sequence  (or a count)  of  ──strong──   or   ──weak──   primes. */
parse arg N kind _ . 1 . okind;     upper kind   /*obtain optional arguments from the CL*/
if N=='' | N==","  then N= 36                    /*Not specified?   Then assume default.*/
if kind=='' | kind==","  then kind= 'STRONG'     /* "      "          "     "      "    */
if _\==''                             then call ser 'too many arguments specified.'
if kind\=='WEAK'  &  kind\=='STRONG'  then call ser 'invalid 2nd argument: '   okind
if kind =='WEAK'  then weak= 1;  else weak= 0    /*WEAK  is a binary value for function.*/
w = linesize() - 1                               /*obtain the usable width of the term. */
tell= (N>0);    @.=;    N= abs(N)                /*N is negative?   Then don't display. */
!.=0;   !.1=2;  !.2=3;  !.3=5;  !.4=7;  !.5=11;  !.6=13;  !.7=17;  !.8=19;   !.9=23;  #= 8
@.='';  @.2=1;  @.3=1;  @.5=1;  @.7=1;  @.11=1;  @.13=1;  @.17=1;  @.19=1;   start= # + 1
m= 0;                           lim= 0           /*#  is the number of low primes so far*/
$=;     do i=3  for #-2   while lim<=N           /* [↓]  find primes, and maybe show 'em*/
        call strongWeak i-1;       $= strip($)   /*go see if other part of a KIND prime.*/
        end   /*i*/                              /* [↑]  allows faster loop (below).    */
                                                 /* [↓]  N:  default lists up to 35 #'s.*/
   do j=!.#+2  by 2  while  lim<N                /*continue on with the next odd prime. */
   if j // 3 == 0  then iterate                  /*is this integer a multiple of three? */
   parse var  j    ''  -1  _                     /*obtain the last decimal digit of  J  */
   if _      == 5  then iterate                  /*is this integer a multiple of five?  */
   if j // 7 == 0  then iterate                  /* "   "     "    "     "     " seven? */
   if j //11 == 0  then iterate                  /* "   "     "    "     "     " eleven?*/
   if j //13 == 0  then iterate                  /* "   "     "    "     "     "  13 ?  */
   if j //17 == 0  then iterate                  /* "   "     "    "     "     "  17 ?  */
   if j //19 == 0  then iterate                  /* "   "     "    "     "     "  19 ?  */
                                                 /* [↓]  divide by the primes.   ___    */
            do k=start  to #  while !.k * !.k<=j /*divide  J  by other primes ≤ √ J     */
            if j // !.k ==0   then iterate j     /*÷ by prev. prime?  ¬prime     ___    */
            end   /*k*/                          /* [↑]   only divide up to     √ J     */
   #= # + 1                                      /*bump the count of number of primes.  */
   !.#= j;                     @.j= 1            /*define a prime  and  its index value.*/
   call strongWeak #-1                           /*go see if other part of a KIND prime.*/
   end   /*j*/
                                                 /* [↓]  display number of primes found.*/
if $\==''  then say $                            /*display any residual primes in $ list*/
say
if tell  then say commas(m)' '     kind    "primes found."
         else say commas(m)' '     kind    "primes found below or equal to "    commas(N).
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
add: m= m+1; lim= m; if \tell & y>N  then do; lim= y; m= m-1; end; else call app; return 1
app: if tell  then if length($ y)>w  then do;  say $; $= y;   end; else $= $ y;   return 1
ser: say;  say;  say '***error***' arg(1);  say;  say;  exit 13   /*tell error message. */
commas: parse arg _;  do jc=length(_)-3  to 1  by -3; _=insert(',', _, jc); end;  return _
/*──────────────────────────────────────────────────────────────────────────────────────*/
strongWeak: parse arg x;  Lp= x - 1;     Hp= x + 1;     y=!.x;        s= (!.Lp + !.Hp) / 2
            if weak  then if y<s  then return add()               /*is  a    weak prime.*/
                                  else return 0                   /*not "      "    "   */
                     else if y>s  then return add()               /*is  an strong prime.*/
                                       return 0                   /*not  "   "      "   */


load "stdlib.ring"

see "working..." + nl

p = 0
num = 0
pr1 = 37
pr2 = 38
limit1 = 457
limit2 = 1000000
limit3 = 10000000
primes = []

see "first 36 strong primes:" + nl
while true
      p = p + 1
      if isprime(p)
         if p < limit1
            add(primes,p)
         else
            exit
         ok
      ok
end

ln = len(primes)
for n = 2 to ln-1
    tmp = (primes[n-1] + primes[n+1])/2
    if primes[n] > tmp
       num = num + 1
       if num < pr1
          see " " + primes[n]
       ok
    ok
next

see nl + "first 37 weak primes:" + nl

num = 0
ln = len(primes)
for n = 2 to ln-1
    tmp = (primes[n-1] + primes[n+1])/2
    if primes[n] < tmp
       num = num + 1
       if num < pr2
          see " " + primes[n]
       ok
    ok
next

p = 0
primes = []
while true
      p = p + 1
      if isprime(p)
         if p < limit3
            add(primes,p)
         else
            exit
         ok
      ok
end

primes2 = 0
primes3 = 0
ln = len(primes)
for n = 2 to ln-1
    tmp = (primes[n-1] + primes[n+1])/2
    if primes[n] > tmp
       if primes[n] < limit2
          primes2 = primes2 + 1
       ok
       if primes[n] < limit3
          primes3 = primes3 + 1
       else
          exit
       ok
    ok
next

see nl
see "strong primes below 1,000,000: " + primes2 + nl
see "strong primes below 10,000,000: " + primes3 + nl

primes2 = 0
primes3 = 0
ln = len(primes)
for n = 2 to ln-1
    tmp = (primes[n-1] + primes[n+1])/2
    if primes[n] < tmp
       if primes[n] < limit2
          primes2 = primes2 + 1
       ok
       if primes[n] < limit3
          primes3 = primes3 + 1
       else
          exit
       ok
    ok
next

see nl
see "weak primes below 1,000,000: " + primes2 + nl
see "weak primes below 10,000,000: " + primes3 + nl


require 'prime'

strong_gen = Enumerator.new{|y| Prime.each_cons(3){|a,b,c|y << b if a+c-b<b} }
weak_gen   = Enumerator.new{|y| Prime.each_cons(3){|a,b,c|y << b if a+c-b>b} }

puts "First 36 strong primes:"
puts strong_gen.take(36).join(" "), "\n"
puts "First 37 weak primes:"
puts weak_gen.take(37).join(" "), "\n"

[1_000_000, 10_000_000].each do |limit|
  strongs, weaks = 0, 0
  Prime.each_cons(3) do |a,b,c|
    strongs += 1 if b > a+c-b
    weaks += 1 if b < a+c-b
    break if c > limit
  end
  puts "#{strongs} strong primes and #{weaks} weak primes below #{limit}."
end


fn is_prime(n: i32) -> bool {
	for i in 2..n {
		if i * i > n {
			return true;
		}
		if n % i == 0 {
			return false;
		}
	}
	n > 1
}

fn next_prime(n: i32) -> i32 {
	for i in (n+1).. {
		if is_prime(i) {
			return i;
		}
	}
	0
}

fn main() {
	let mut n = 0;
	let mut prime_q = 5;
	let mut prime_p = 3;
	let mut prime_o = 2;

	print!("First 36 strong primes: ");
	while n < 36 {
		if prime_p > (prime_o + prime_q) / 2 {
			print!("{} ",prime_p);
			n += 1;
		}
		prime_o = prime_p;
		prime_p = prime_q;
		prime_q = next_prime(prime_q);
	}
	println!("");

	while prime_p < 1000000 {
		if prime_p > (prime_o + prime_q) / 2 {
			n += 1;
		}
		prime_o = prime_p;
		prime_p = prime_q;
		prime_q = next_prime(prime_q);
	}
	println!("strong primes below 1,000,000: {}", n);

	while prime_p < 10000000 {
		if prime_p > (prime_o + prime_q) / 2 {
			n += 1;
		}
		prime_o = prime_p;
		prime_p = prime_q;
		prime_q = next_prime(prime_q);
	}
	println!("strong primes below 10,000,000: {}", n);

	n = 0;
	prime_q = 5;
	prime_p = 3;
	prime_o = 2;

	print!("First 36 weak primes: ");
	while n < 36 {
		if prime_p < (prime_o + prime_q) / 2 {
			print!("{} ",prime_p);
			n += 1;
		}
		prime_o = prime_p;
		prime_p = prime_q;
		prime_q = next_prime(prime_q);
	}
	println!("");

	while prime_p < 1000000 {
		if prime_p < (prime_o + prime_q) / 2 {
			n += 1;
		}
		prime_o = prime_p;
		prime_p = prime_q;
		prime_q = next_prime(prime_q);
	}
	println!("weak primes below 1,000,000: {}", n);

	while prime_p < 10000000 {
		if prime_p < (prime_o + prime_q) / 2 {
			n += 1;
		}
		prime_o = prime_p;
		prime_p = prime_q;
		prime_q = next_prime(prime_q);
	}
	println!("weak primes below 10,000,000: {}", n);
}


object StrongWeakPrimes {
  def main(args: Array[String]): Unit = {
    val bnd = 1000000
    println(
      f"""|First 36 Strong Primes: ${strongPrimes.take(36).map(n => f"$n%,d").mkString(", ")}
          |Strong Primes < 1,000,000: ${strongPrimes.takeWhile(_ < bnd).size}%,d
          |Strong Primes < 10,000,000: ${strongPrimes.takeWhile(_ < 10*bnd).size}%,d
          |
          |First 37 Weak Primes: ${weakPrimes.take(37).map(n => f"$n%,d").mkString(", ")}
          |Weak Primes < 1,000,000: ${weakPrimes.takeWhile(_ < bnd).size}%,d
          |Weak Primes < 10,000,000: ${weakPrimes.takeWhile(_ < 10*bnd).size}%,d""".stripMargin)
  }

  def weakPrimes: LazyList[Int] = primeTrips.filter{case a +: b +: c +: _ => b < (a + c)/2.0}.map(_(1)).to(LazyList)
  def strongPrimes: LazyList[Int] = primeTrips.filter{case a +: b +: c +: _ => b > (a + c)/2}.map(_(1)).to(LazyList)
  def primeTrips: Iterator[LazyList[Int]] = primes.sliding(3)
  def primes: LazyList[Int] = 2 #:: LazyList.from(3, 2).filter(n => !Iterator.range(3, math.sqrt(n).toInt + 1, 2).exists(n%_ == 0))
}


var primes = 10_000_019.primes

var (*strong, *weak, *balanced)

for k in (1 ..^ primes.end) {
    var p = primes[k]

    given((primes[k-1] + primes[k+1])/2) { |x|
        case (x > p) {     weak << p }
        case (x < p) {   strong << p }
        else         { balanced << p }
    }
}

for pr, type, d, c1, c2 in [
    [  strong, 'strong',   36, 1e6, 1e7],
    [    weak, 'weak',     37, 1e6, 1e7],
    [balanced, 'balanced', 28, 1e6, 1e7],
] {
    say ("\nFirst #{d} #{type} primes:\n", pr.first(d).map{.commify}.join(' '))
    say ("Count of #{type} primes <= #{c1.commify}:  ", pr.first_index { _ > 1e6 }.commify)
    say ("Count of #{type} primes <= #{c2.commify}: " , pr.len.commify)
}


import Foundation

class PrimeSieve {
    var composite: [Bool]

    init(size: Int) {
        composite = Array(repeating: false, count: size/2)
        var p = 3
        while p * p <= size {
            if !composite[p/2 - 1] {
                let inc = p * 2
                var q = p * p
                while q <= size {
                    composite[q/2 - 1] = true
                    q += inc
                }
            }
            p += 2
        }
    }

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

func commatize(_ number: Int) -> String {
    let n = NSNumber(value: number)
    return NumberFormatter.localizedString(from: n, number: .decimal)
}

let limit1 = 1000000
let limit2 = 10000000

class PrimeInfo {
    let maxPrint: Int
    var count1: Int
    var count2: Int
    var primes: [Int]

    init(maxPrint: Int) {
        self.maxPrint = maxPrint
        count1 = 0
        count2 = 0
        primes = []
    }

    func addPrime(prime: Int) {
        count2 += 1
        if prime < limit1 {
            count1 += 1
        }
        if count2 <= maxPrint {
            primes.append(prime)
        }
    }

    func printInfo(name: String) {
        print("First \(maxPrint) \(name) primes: \(primes)")
        print("Number of \(name) primes below \(commatize(limit1)): \(commatize(count1))")
        print("Number of \(name) primes below \(commatize(limit2)): \(commatize(count2))")
    }
}

var strongPrimes = PrimeInfo(maxPrint: 36)
var weakPrimes = PrimeInfo(maxPrint: 37)

let sieve = PrimeSieve(size: limit2 + 100)

var p1 = 2, p2 = 3, p3 = 5
while p2 < limit2 {
    if sieve.isPrime(number: p3) {
        let diff = p1 + p3 - 2 * p2
        if diff < 0 {
            strongPrimes.addPrime(prime: p2)
        } else if diff > 0 {
            weakPrimes.addPrime(prime: p2)
        }
        p1 = p2
        p2 = p3
    }
    p3 += 2
}

strongPrimes.printInfo(name: "strong")
weakPrimes.printInfo(name: "weak")


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

var primes = Int.primeSieve(1e7 + 19) // next prime above 10 million
var strong = []
var weak = []
for (p in 1...primes.count-1) {
    if (primes[p] > (primes[p-1] + primes[p+1]) / 2) {
        strong.add(primes[p])
    } else if (primes[p] < (primes[p-1] + primes[p+1]) / 2) {
        weak.add(primes[p])
    }
}

System.print("The first 36 strong primes are:")
Fmt.print("$d", strong.take(36))
Fmt.print("\nThe count of the strong primes below $,d is $,d.", 1e6, strong.count{ |n| n < 1e6 })
Fmt.print("\nThe count of the strong primes below $,d is $,d.", 1e7, strong.count{ |n| n < 1e7 })

System.print("\nThe first 37 weak primes are:")
Fmt.print("$d", weak.take(37))
Fmt.print("\nThe count of the weak primes below $,d is $,d.", 1e6, weak.count{ |n| n < 1e6 })
Fmt.print("\nThe count of the weak primes below $,d is $,d.", 1e7, weak.count{ |n| n < 1e7 })