#11 = 400		// Width of the image
#12 = 300		// Height of the image

// Create an empty RGB image and fill it with black color
//
File_Open("|(VEDIT_TEMP)\pixel.data", OVERWRITE+NOEVENT)
BOF
Del_Char(ALL)
#10 = Buf_Num
Repeat(#11 * #12) {
    Ins_Char(0, COUNT, 3)
}

// Fill the image with dark blue color
//
#5 = 0				// Red
#6 = 0				// Green
#7 = 64				// Blue
Call("FILL_IMAGE")

// Draw one pixel in orange color
//
#1 = 100			// x
#2 = 50				// y
#5 = 255 #6 = 128 #7 = 0	// Orange color
Call("DRAW_PIXEL")

// Get the color of a pixel
//
#1 = 10
#2 = 3
Call("GET_COLOR")

Buf_Switch(#10) Buf_Quit(OK)
Return

/////////////////////////////////////////////////////////////////////
//
//  Fill image with given color: #5 = Red, #6 = Green, #7 = Blue
//
:FILL_IMAGE:
BOF
Repeat (File_Size/3) {
    IC(#5,OVERWRITE) IC(#6,OVERWRITE) IC(#7,OVERWRITE)
}
Return

/////////////////////////////////////////////////////////////////////
//
//  Daw a pixel. #1 = x, #2 = y
//
:DRAW_PIXEL:
Goto_Pos((#1 + #2*#11)*3)
IC(#5,OVERWRITE) IC(#6,OVERWRITE) IC(#7,OVERWRITE)
Return

/////////////////////////////////////////////////////////////////////
//
//  Get color of a pixel. #1 = x, #2 = y
//  Return: #5 = Red, #6 = Green, #7 = Blue
//
:GET_COLOR:
Goto_Pos((#1 + #2*#11)*3)
#5 = Cur_Char
#6 = Cur_Char(1)
#7 = Cur_Char(2)
Return


' The StructLayout attribute allows fields to overlap in memory.
<System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)> _
Public Structure Rgb

    <FieldOffset(0)> _
    Public Rgb As Integer

    <FieldOffset(0)> _
    Public B As Byte

    <FieldOffset(1)> _
    Public G As Byte

    <FieldOffset(2)> _
    Public R As Byte

    Public Sub New(ByVal r As Byte, ByVal g As Byte, ByVal b As Byte)
        Me.R = r
        Me.G = g
        Me.B = b
    End Sub

End Structure


import "graphics" for Canvas, ImageData, Color
import "dome" for Window

class Game {
    static bmpCreate(name, w, h) { ImageData.create(name, w, h) }

    static bmpFill(name, col) {
        var image = ImageData[name]
        for (x in 0...image.width) {
            for (y in 0...image.height) image.pset(x, y, col)
        }
    }

    static bmpPset(name, x, y, col) { ImageData[name].pset(x, y, col) }

    static bmpPget(name, x, y) { ImageData[name].pget(x, y) }

    static init() {
        Window.title = "Bitmap"
        var size = 600
        Window.resize(size, size)
        Canvas.resize(size, size)
        var bmp = bmpCreate("rcbmp", size/2, size/2)
        bmpFill("rcbmp", Color.yellow)
        bmpPset("rcbmp", size/4, size/4, Color.blue) // 'blue' is #29ADFF on the default palette
        var col = bmpPget("rcbmp", size/4, size/4)
        System.print(col.toString) // check it's blue - alpha component (FF) will also be shown
        bmp.draw(150, 150)
    }

    static update() {}

    static draw(alpha) {}
}


Function CreatePicture(width As Integer, height As Integer) As Picture
  Return New Picture(width, height)
End Function

Sub FillPicture(ByRef p As Picture, FillColor As Color)
  p.Graphics.ForeColor = FillColor
  p.Graphics.FillRect(0, 0, p.Width, p.Height)
End Sub

Function GetPixelColor(p As Picture, x As Integer, y As Integer) As Color
  Return p.RGBSurface.Pixel(x, y)
End Function

Sub SetPixelColor(p As Picture, x As Integer, y As Integer, pColor As Color)
  p.RGBSurface.Pixel(x, y) = pColor
End Sub


include c:\cxpl\codes;  \include 'code' declarations
def Width=180, Height=135, Color=$123456;
int X, Y;
[SetVid($112);  \set display for 640x480 graphics in 24-bit RGB color
for Y:= 0 to Height-1 do    \fill area with Color one pixel at a time
    for X:= 0 to Width-1 do \(this takes 4.12 ms on a Duron 850)
        Point(X, Y, Color);
Move(60, 60); HexOut(6, ReadPix(0,0));  \show color of pixel at 0,0
X:= ChIn(1);            \wait for keystroke
SetVid(3);              \restore display to normal text mode
]


class PPM{	// (0,0) is logically bottom left
   fcn init(width,height){
      sz:=width*height*3;
      var [const]
         data=sz.pump(Data(sz),0),  // initialize to Black (RGB=000)
	 w=width, h=height;
   }
   fcn fill(rgb){
      sz:=data.len()/3;
      data.clear(); sz.pump(data,T(Void,rgb.toBigEndian(3)));
   }
   fcn __sGet(x,y)    { data.toBigEndian(3*y*w + 3*x,3);        } //ppm[x,y]
   fcn __sSet(rbg,x,y){	data[3*y*w + 3*x,3]=rbg.toBigEndian(3); } //ppm[x,y]=rgb
   fcn write(out){   // write bottom to top to move (0,0) from bottom left to bottom left
      out.write("P6\n#rosettacode PPM\n%d %d\n255\n".fmt(w,h));
      [h-1..0, -1].pump(out,'wrap(h){ data.seek(3*h*w); data.read(3*w) });
      out.close();
   }
}


;this code assumes that both DS and ES point to the correct segments.
cld
mov si,offset TestMessage
mov di,offset EmptyRam
mov cx,5  ;length of the source string, you'll need to either know this
          ;ahead of time or calculate it.
rep movsb
ret

;there is no buffer overflow protection built into these functions so be careful!
TestMessage byte "Hello"
EmptyRam byte 0,0,0,0,0


declare
   Data : Storage_Array (1..20); -- Data created
begin
   Data := (others => 0); -- Assign all zeros
   if Data = (1..10 => 0) then -- Compare with 10 zeros
      declare
         Copy : Storage_Array := Data; -- Copy Data
      begin
         if Data'Length = 0 then -- If empty
            ...
         end if;
      end;
   end if;
   ... Data & 1 ...         -- The result is Data with byte 1 appended
   ... Data & (1,2,3,4) ... -- The result is Data with bytes 1,2,3,4 appended
   ... Data (3..5) ...      -- The result the substring of Data from 3 to 5
end; -- Data destructed


# String creation #
STRING a,b,c,d,e,f,g,h,i,j,l,r;
a := "hello world";
print((a, new line));

# String destruction (for garbage collection) #
b := ();
BEGIN
  LOC STRING lb := "hello earth";  # allocate off the LOC stack  #
  HEAP STRING hb := "hello moon"; # allocate out of the HEAP space #
  ~
END; # local variable "lb" has LOC stack space recovered at END #

# String assignment #
c := "a"+REPR 0+"b";
print (("string length c:", UPB c, new line));# ==> 3 #

# String comparison #
l := "ab"; r := "CD";

BOOL result;
FORMAT summary = $""""g""" is "b("","NOT ")"lexicographically "g" """g""""l$ ;

result := l <  r OR l LT r;              printf((summary, l, result, "less than", r));
result := l <= r OR l LE r # OR l ≤ r #; printf((summary, l, result, "less than or equal to", r));
result := l  = r OR l EQ r;              printf((summary, l, result, "equal to", r));
result := l /= r OR l NE r # OR l ≠ r #; printf((summary, l, result, "not equal to", r));
result := l >= r OR l GE r # OR l ≥ r #; printf((summary, l, result, "greater than or equal to", r));
result := l >  r OR l GT r;              printf((summary, l, result, "greater than", r));

# String cloning and copying #
e := f;

# Check if a string is empty #
IF g = "" THEN print(("g is empty", new line)) FI;
IF UPB g = 0 THEN print(("g is empty", new line)) FI;

# Append a byte to a string #
h +:= "A";

# Append a string to a string #
h +:= "BCD";
h PLUSAB "EFG";

# Prepend a string to a string - because STRING addition isn't communitive #
"789" +=: h;
"456" PLUSTO h;
print(("The result of prepends and appends: ", h, new line));

# Extract a substring from a string #
i := h[2:3];
print(("Substring 2:3 of ",h," is ",i, new line));

# Replace every occurrences of a byte (or a string) in a string with another string #
PROC replace = (STRING string, old, new, INT count)STRING: (
  INT pos;
  STRING tail := string, out;
  TO count WHILE string in string(old, pos, tail) DO
    out +:= tail[:pos-1]+new;
    tail := tail[pos+UPB old:]
  OD;
  out+tail
);

j := replace("hello world", "world", "planet", max int);
print(("After replace string: ", j, new line));

INT offset = 7;
# Replace a character at an offset in the string #
j[offset] := "P";
print(("After replace 7th character: ", j, new line));

# Replace a substring at an offset in the string #
j[offset:offset+3] := "PlAN";
print(("After replace 7:10th characters: ", j, new line));

# Insert a string before an offset in the string #
j := j[:offset-1]+"INSERTED "+j[offset:];
print(("Insert string before 7th character: ", j, new line));

# Join strings  #
a := "hel";
b := "lo w";
c := "orld";
d := a+b+c;

print(("a+b+c is ",d, new line));

# Pack a string into the target CPU's word #
BYTES word := bytes pack(d);

# Extract a CHAR from a CPU word #
print(("7th byte in CPU word is: ", offset ELEM word, new line))


; creation
x: "this is a string"
y: "this is another string"
z: "this is a string"

; comparison
if x = z -> print "x is z"

; assignment
z: "now this is another string too"

; copying reference
y: z

; copying value
y: new z

; check if empty
if? empty? x -> print "empty"
else         -> print "not empty"

; append a string
'x ++ "!"

print x

; substrings
print slice x 5 8

; join strings
z: x ++ y
print z

; replace occurrences of substring
print replace z "t" "T"


#!/usr/bin/awk -f

BEGIN {
	# string creation
	a="123\0 abc ";
	b="456\x09";
	c="789";
	printf("abc=<%s><%s><%s>\n",a,b,c);

	# string comparison
	printf("(a==b) is %i\n",a==b)

	# string copying
	A = a;
	B = b;
	C = c;
	printf("ABC=<%s><%s><%s>\n",A,B,C);

	# check if string is empty
	if (length(a)==0) {
		printf("string a is empty\n");
	} else {
		printf("string a is not empty\n");
	}

	# append a byte to a string
	a=a"\x40";
	printf("abc=<%s><%s><%s>\n",a,b,c);

	# substring
	e = substr(a,1,6);
	printf("substr(a,1,6)=<%s>\n",e);

	# join strings
	d=a""b""c;
	printf("d=<%s>\n",d);
}


REM STRING CREATION AND DESTRUCTION (WHEN NEEDED AND IF THERE'S NO GARBAGE COLLECTION OR SIMILAR MECHANISM)
A$ = "STRING" : REM CREATION
A$ = "" : REM DESTRUCTION
PRINT FRE(0) : REM GARBAGE COLLECTION

REM STRING ASSIGNMENT
A$ = "STRING" : R$ = "DEUX"

REM STRING COMPARISON
PRINT A$ = B$; A$ <> B$; A$ < B$; A$ > B$; A$ <= B$; A$ >= B$

REM STRING CLONING AND COPYING
B$ = A$

REM CHECK IF A STRING IS EMPTY
PRINT LEN(A$) = 0

REM APPEND A BYTE TO A STRING
A$ = A$ + CHR$(0)

REM EXTRACT A SUBSTRING FROM A STRING
S$ = MID$(A$, 2, 3)

REM REPLACE EVERY OCCURRENCE OF A BYTE (OR A STRING) IN A STRING WITH ANOTHER STRING
S = LEN(S$) : R = LEN(R$) : A = LEN(A$) : IF A > S THEN B$ = "" : FOR I = 1 TO A : F = MID$(A$, I, S) = S$ : B$ = B$ + MID$(R$, 1, R * F) + MID$(A$, I, F = 0) : NEXT I : A$ = B$ : PRINT A$

REM JOIN STRINGS
J$ = A$ + STR$(42) + " PUDDLES " + B$ + CHR$(255) : REM USE +


      A$ = CHR$(0) + CHR$(1) + CHR$(254) + CHR$(255) : REM assignment
      B$ = A$                                        : REM clone / copy
      IF A$ = B$ THEN PRINT "Strings are equal"      : REM comparison
      IF A$ = "" THEN PRINT "String is empty"        : REM Check if empty
      A$ += CHR$(128)                                : REM Append a byte
      S$ = MID$(A$, S%, L%)                          : REM Extract a substring
      C$ = A$ + B$                                   : REM Join strings

      REM To replace every occurrence of a byte:
      old$ = CHR$(1)
      new$ = CHR$(5)
      REPEAT
        I% = INSTR(A$, old$)
        IF I% MID$(A$, I%, 1) = new$
      UNTIL I% = 0


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

typedef struct str_t {
	size_t len, alloc;
	unsigned char *s;
} bstr_t, *bstr;

#define str_len(s) ((s)->len)
bstr str_new(size_t len)
{
	bstr s = malloc(sizeof(bstr_t));
	if (len < 8) len = 8;
	s->alloc = len;
	s->s = malloc(len);
	s->len = 0;
	return s;
}

void str_extend(bstr s)
{
	size_t ns = s->alloc * 2;
	if (ns - s->alloc > 1024) ns = s->alloc + 1024;
	s->s = realloc(s->s, ns);
	s->alloc = ns;
}

void str_del(bstr s)
{
	free(s->s), free(s);
}

int str_cmp(bstr l, bstr r)
{
	int res, len = l->len;
	if (len > r->len) len = r->len;

	if ((res = memcmp(l->s, r->s, len))) return res;
	return l->len > r->len ? 1 : -1;
}

bstr str_dup(bstr src)
{
	bstr x = str_new(src->len);
	memcpy(x->s, src->s, src->len);
	x->len = src->len;
	return x;
}

bstr str_from_chars(const char *t)
{
	if (!t) return str_new(0);
	size_t l = strlen(t);
	bstr x = str_new(l + 1);
	x->len = l;
	memcpy(x->s, t, l);
	return x;
}

void str_append(bstr s, unsigned char b)
{
	if (s->len >= s->alloc) str_extend(s);
	s->s[s->len++] = b;
}

bstr str_substr(bstr s, int from, int to)
{
	if (!to) to = s->len;
	if (from < 0) from += s->len;
	if (from < 0 || from >= s->len)
		return 0;
	if (to < from) to = from + 1;
	bstr x = str_new(to - from);
	x->len = to - from;
	memcpy(x->s, s->s + from, x->len);
	return x;
}

bstr str_cat(bstr s, bstr s2)
{
	while (s->alloc < s->len + s2->len) str_extend(s);
	memcpy(s->s + s->len, s2->s, s2->len);
	s->len += s2->len;
	return s;
}

void str_swap(bstr a, bstr b)
{
	size_t tz;
	unsigned char *ts;
	tz = a->alloc; a->alloc = b->alloc; b->alloc = tz;
	tz = a->len; a->len = b->len; b->len = tz;
	ts = a->s; a->s = b->s; b->s = ts;
}

bstr str_subst(bstr tgt, bstr pat, bstr repl)
{
	bstr tmp = str_new(0);
	int i;
	for (i = 0; i + pat->len <= tgt->len;) {
		if (memcmp(tgt->s + i, pat->s, pat->len)) {
			str_append(tmp, tgt->s[i]);
			i++;
		} else {
			str_cat(tmp, repl);
			i += pat->len;
			if (!pat->len) str_append(tmp, tgt->s[i++]);
		}
	}
	while (i < tgt->len) str_append(tmp, tgt->s[i++]);
	str_swap(tmp, tgt);
	str_del(tmp);
	return tgt;
}

void str_set(bstr dest, bstr src)
{
	while (dest->len < src->len) str_extend(dest);
	memcpy(dest->s, src->s, src->len);
	dest->len = src->len;
}

int main()
{
	bstr s = str_from_chars("aaaaHaaaaaFaaaaHa");
	bstr s2 = str_from_chars("___.");
	bstr s3 = str_from_chars("");

	str_subst(s, s3, s2);
	printf("%.*s\n", s->len, s->s);

	str_del(s);
	str_del(s2);
	str_del(s3);

	return 0;
}


#include <iomanip>
#include <iostream>

using namespace std;

string replaceFirst(string &s, const string &target, const string &replace) {
    auto pos = s.find(target);
    if (pos == string::npos) return s;
    return s.replace(pos, target.length(), replace);
}

int main() {

    // string creation
    string x = "hello world";

    // reassign string (no garbage collection)
    x = "";

    // string assignment with a null byte
    x = "ab\0";
    cout << x << '\n';
    cout << x.length() << '\n';

    // string comparison
    if (x == "hello") {
        cout << "equal\n";
    } else {
        cout << "not equal\n";
    }
    if (x < "bc") {
        cout << "x is lexigraphically less than 'bc'\n";
    }

    // string cloning
    auto y = x;
    cout << boolalpha << (x == y) << '\n';
    cout << boolalpha << (&x == &y) << '\n';

    // check if empty
    string empty = "";
    if (empty.empty()) {
        cout << "String is empty\n";
    }

    // append a byte
    x = "helloworld";
    x += (char)83;
    cout << x << '\n';

    // substring
    auto slice = x.substr(5, 5);
    cout << slice << '\n';

    // replace bytes
    auto greeting = replaceFirst(x, "worldS", "");
    cout << greeting << '\n';

    // join strings
    auto join = greeting + ' ' + slice;
    cout << join << '\n';

    return 0;
}


using System;

class Program
{
    static void Main()
    {
        //string creation
        var x = "hello world";

        //# mark string for garbage collection
        x = null;

        //# string assignment with a null byte
        x = "ab\0";
        Console.WriteLine(x);
        Console.WriteLine(x.Length); // 3

        //# string comparison
        if (x == "hello")
            Console.WriteLine("equal");
        else
            Console.WriteLine("not equal");

        if (x.CompareTo("bc") == -1)
            Console.WriteLine("x is lexicographically less than 'bc'");

        //# string cloning
        var c = new char[3];
        x.CopyTo(0, c, 0, 3);
        object objecty = new string(c);
        var y = new string(c);

        Console.WriteLine(x == y);      //same as string.equals
        Console.WriteLine(x.Equals(y)); //it overrides object.Equals

        Console.WriteLine(x == objecty); //uses object.Equals, return false

        //# check if empty
        var empty = "";
        string nullString = null;
        var whitespace = "   ";
        if (nullString == null && empty == string.Empty &&
            string.IsNullOrEmpty(nullString) && string.IsNullOrEmpty(empty) &&
            string.IsNullOrWhiteSpace(nullString) && string.IsNullOrWhiteSpace(empty) &&
            string.IsNullOrWhiteSpace(whitespace))
            Console.WriteLine("Strings are null, empty or whitespace");

        //# append a byte
        x = "helloworld";
        x += (char)83;
        Console.WriteLine(x);

        //# substring
        var slice = x.Substring(5, 5);
        Console.WriteLine(slice);

        //# replace bytes
        var greeting = x.Replace("worldS", "");
        Console.WriteLine(greeting);

        //# join strings
        var join = greeting + " " + slice;
        Console.WriteLine(join);
    }
}


"string"
(coerce '(#\s #\t #\r #\i #\n #\g) 'string)


MODULE NpctBinaryString;
IMPORT StdLog,Strings;

PROCEDURE Do*;
VAR
	str: ARRAY 256 OF CHAR;
	pStr,pAux: POINTER TO ARRAY OF CHAR;
	b: BYTE;
	pIni: INTEGER;
BEGIN
	(* String creation, on heap *)
	NEW(pStr,256); (* Garbage collectable *)
	NEW(pAux,256);

	(* String assingment *)
	pStr^ := "This is a string on a heap";
	pAux^ := "This is a string on a heap";
	str := "This is other string";

	(* String comparision *)
	StdLog.String("pStr = str:> ");StdLog.Bool(pStr$ = str$);StdLog.Ln;
	StdLog.String("pStr = pAux:> ");StdLog.Bool(pStr$ = pAux$);StdLog.Ln;

	(* String cloning and copying *)
	NEW(pAux,LEN(pStr$) + 1);pAux^ := pStr$;

	(* Check if a string is empty *)
	(* version 1 *)
	pAux^ := "";
	StdLog.String("is empty pAux?(1):> ");StdLog.Bool(pAux$ = "");StdLog.Ln;
	(* version 2 *)
	pAux[0] := 0X;
	StdLog.String("is empty pAux?(2):> ");StdLog.Bool(pAux$ = "");StdLog.Ln;
	(* version 3 *)
	pAux[0] := 0X;
	StdLog.String("is empty pAux?(3):> ");StdLog.Bool(pAux[0] = 0X);StdLog.Ln;
	(* version 4 *)
	pAux^ := "";
	StdLog.String("is empty pAux?(4):> ");StdLog.Bool(pAux[0] = 0X);StdLog.Ln;

	(* Append a byte to a string *)
	NEW(pAux,256);pAux^ := "BBBBBBBBBBBBBBBBBBBBB";
	b := 65;pAux[LEN(pAux$)] := CHR(b);
	StdLog.String("pAux:> ");StdLog.String(pAux);StdLog.Ln;

	(* Extract a substring from a string *)
	Strings.Extract(pStr,0,16,pAux);
	StdLog.String("pAux:> ");StdLog.String(pAux);StdLog.Ln;

	(* Replace a every ocurrence of a string with another string *)
	pAux^ := "a"; (* Pattern *)
	Strings.Find(pStr,pAux,0,pIni);
	WHILE pIni > 0 DO
		Strings.Replace(pStr,pIni,LEN(pAux$),"one");
		Strings.Find(pStr,pAux,pIni + 1,pIni);
	END;
	StdLog.String("pStr:> ");StdLog.String(pStr);StdLog.Ln;

	(* Join strings *)
	pStr^ := "First string";pAux^ := "Second String";
	str := pStr$ + "." + pAux$;
	StdLog.String("pStr + '.' + pAux:>");StdLog.String(str);StdLog.Ln
END Do;
END NpctBinaryString.


void main() /*@safe*/ {
    import std.array: empty, replace;
    import std.string: representation, assumeUTF;

    // String creation (destruction is usually handled by
    // the garbage collector).
    ubyte[] str1;

    // String assignments.
    str1 = "blah".dup.representation;
    // Hex string, same as "\x00\xFB\xCD\x32\xFD\x0A"
    // whitespace and newlines are ignored.
    str1 = cast(ubyte[])x"00 FBCD 32FD 0A";

    // String comparison.
    ubyte[] str2;
    if (str1 == str2) {} // Strings equal.

    // String cloning and copying.
    str2 = str1.dup; // Copy entire string or array.

    // Check if a string is empty
    if (str1.empty) {} // String empty.
    if (str1.length) {} // String not empty.
    if (!str1.length) {} // String empty.

    // Append a ubyte to a string.
    str1 ~= x"0A";
    str1 ~= 'a';

    // Extract a substring from a string.
    str1 = "blork".dup.representation;
    // This takes off the first and last bytes and
    // assigns them to the new ubyte string.
    // This is just a light slice, no string data copied.
    ubyte[] substr = str1[1 .. $ - 1];

    // Replace every occurrence of a ubyte (or a string)
    // in a string with another string.
    str1 = "blah".dup.representation;
    replace(str1.assumeUTF, "la", "al");

    // Join two strings.
    ubyte[] str3 = str1 ~ str2;
}


local :b make-blob 10 #ten bytes of initial size
set-to b 0 255
!. get-from b 0 #prints 255
!. b #prints (blob:ff000000000000000000)
local :b2 make-blob 3
set-to b2 0 97
set-to b2 1 98
set-to b2 2 99
!. b #prints (blob:"abc")
!. !encode!utf-8 b #prints "abc"


program Binary_strings;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

var
  x          : string;
  c          : TArray<Byte>;
  objecty,
  y          : string;
  empty      : string;
  nullString : string;
  whitespace,
  slice,
  greeting,
  join       : string;
begin
        //string creation
        x:= String.create(['1','2','3']);
        x:= String.create('*',8);
        x := 'hello world';

        //# string assignment with a hex byte
        x := 'ab'#10;
        writeln(x);
        writeln(x.Length); // 3

        //# string comparison
        if x = 'hello' then
            writeln('equal')
        else
            writeln('not equal');
        if x.CompareTo('bc') = -1 then
            writeln('x is lexicographically less than "bc"');

        //# string cloning
        y := x; // string is not object is delphi (are imutables)
        writeln(x = y);      //same as string.equals
        writeln(x.Equals(y)); //it overrides object.Equals

        //# check if empty
        // Strings can't be null (nil), just Pchar can be
        // IsNullOrEmpty and  IsNullOrWhiteSpace, check only for
        // Empty and Whitespace respectively.
        empty := '';
        whitespace := '   ';
        if (empty = string.Empty)  and
            string.IsNullOrEmpty(empty)  and
            string.IsNullOrWhiteSpace(empty)  and
            string.IsNullOrWhiteSpace(whitespace) then
            writeln('Strings are empty or whitespace');

        //# append a byte
        x := 'helloworld';
        x  := x + Chr(83);
//        x  := x + #83;    // the same of above line
        writeln(x);

        //# substring
        slice := x.Substring(5, 5);
        writeln(slice);

        //# replace bytes
        greeting := x.Replace('worldS', '');
        writeln(greeting);

        //# join strings
        join := greeting + ' ' + slice;
        writeln(join);

        Readln;
end.


? def int8 := <type:java.lang.Byte>
# value: int8


# String creation
x = "hello world"

# String destruction
x = nil

# String assignment with a null byte
x = "a\0b"
IO.inspect x                  #=> <<97, 0, 98>>
IO.puts String.length(x)      #=> 3

# string comparison
if x == "hello" do
  IO.puts "equal"
else
  IO.puts "not equal"         #=> not equal
end
y = "bc"
if x < y do
  IO.puts "#{x} is lexicographically less than #{y}"  #=> a b is lexicographically less than bc
end

# string cloning
xx = x
IO.puts x == xx               #=> true  （same length and content)

# check if empty
if x=="" do
  IO.puts "is empty"
end
if String.length(x)==0 do
  IO.puts "is empty"
end

# append a byte
IO.puts x <> "\07"            #=> a b 7
IO.inspect x <> "\07"         #=> <<97, 0, 98, 0, 55>>

# substring
IO.puts String.slice("elixir", 1..3)          #=> lix
IO.puts String.slice("elixir", 2, 3)          #=> ixi

# replace bytes
IO.puts String.replace("a,b,c", ",", "-")     #=> a-b-c

# string interpolation
a = "abc"
n = 100
IO.puts "#{a} : #{n}"         #=> abc : 100

# join strings
a = "hel"
b = "lo w"
c = "orld"
IO.puts a <> b <> c           #=> hello world


-module(binary_string).
-compile([export_all]).

%% Erlang has very easy handling of binary strings. Using
%% binary/bitstring syntax the various task features will be
%% demonstrated.

%% Erlang has GC so destruction is not shown.
test() ->
    Binary = <<0,1,1,2,3,5,8,13>>, % binaries can be created directly
    io:format("Creation: ~p~n",[Binary]),
    Copy = binary:copy(Binary), % They can also be copied
    io:format("Copy: ~p~n",[Copy]),
    Compared = Binary =:= Copy, % They can be compared directly
    io:format("Equal: ~p = ~p ? ~p~n",[Binary,Copy,Compared]),
    Empty1 = size(Binary) =:= 0, % The empty binary would have size 0
    io:format("Empty: ~p ? ~p~n",[Binary,Empty1]),
    Empty2 = size(<<>>) =:= 0, % The empty binary would have size 0
    io:format("Empty: ~p ? ~p~n",[<<>>,Empty2]),
    Substring = binary:part(Binary,3,3),
    io:format("Substring: ~p [~b..~b] => ~p~n",[Binary,3,5,Substring]),
    Replace = binary:replace(Binary,[<<1>>],<<42>>,[global]),
    io:format("Replacement: ~p~n",[Replace]),
    Append = <<Binary/binary,21>>,
    io:format("Append: ~p~n",[Append]),
    Join = <<Binary/binary,<<21,34,55>>/binary>>,
    io:format("Join: ~p~n",[Join]).

%% Since the task also asks that we show how these can be reproduced
%% rather than just using BIFs, the following are some example
%% recursive functions reimplementing some of the above.

%% Empty string
is_empty(<<>>) ->
    true;
is_empty(_) ->
    false.

%% Replacement:
replace(Binary,Value,Replacement) ->
    replace(Binary,Value,Replacement,<<>>).

replace(<<>>,_,_,Acc) ->
    Acc;
replace(<<Value,Rest/binary>>,Value,Replacement,Acc) ->
    replace(Rest,Value,Replacement,<< Acc/binary, Replacement >>);
replace(<<Keep,Rest/binary>>,Value,Replacement,Acc) ->
    replace(Rest,Value,Replacement,<< Acc/binary, Keep >>).


\ Rosetta Code Binary Strings Demo in Forth
\ Portions of this code are found at http://forth.sourceforge.net/mirror/toolbelt-ext/index.html

\ String words created in this code:
\       STR<    STR>    STR=    COMPARESTR      SUBSTR  STRPAD  CLEARSTR
\       =""     ="      STRING: MAXLEN  REPLACE-CHAR    COPYSTR WRITESTR
\       ,"      APPEND-CHAR     STRING, PLACE   CONCAT  APPEND  C+!  ENDSTR
\       COUNT   STRLEN

: STRLEN  ( addr -- length)  [email protected] ;        \ alias the "character fetch" operator

: COUNT   ( addr --  addr+1 length)      \ Standard word. Shown for explanation
          dup  strlen swap 1+ swap ;     \ returns the address+1 and the length byte on the stack

: ENDSTR  ( str -- addr)                 \ calculate the address at the end of a string
          COUNT + ;

: C+!     ( n addr -- )                  \ primitive: increment a byte at addr by n
          DUP [email protected] ROT + SWAP C! ;

: APPEND  ( addr1 length addr2 -- )      \ Append addr1 length to addr2
          2dup 2>r  endstr swap move 2r> c+! ;

: CONCAT  ( string1 string2 -- )          \ concatenate counted string1 to counted string2
           >r  COUNT  R> APPEND ;

: PLACE  ( addr1 len addr2 -- )           \ addr1 and length, placed at addr2 as counted string
           2dup 2>r  char+  swap  move  2r> c! ;

: STRING, ( addr len -- )                 \ compile a string at the next available memory (called 'HERE')
            here  over char+  allot  place ;

: APPEND-CHAR  ( char string -- )         \ append char to string
           dup >r  count dup 1+ r> c! + c! ;

: ,"       [CHAR] " PARSE  STRING, ;      \ Parse input stream until '"' and compile into memory

: WRITESTR ( string -- )                  \ output a counted string with a carriage return
           count  type CR ;

: COPYSTR  ( string1 string3 -- )         \ String cloning and copying COPYSTR
           >r  count  r> PLACE ;

: REPLACE-CHAR ( char1 char2 string -- )  \ replace all char2 with char1 in string
          count                           \ get string's address and length
          BOUNDS                          \ calc start and end addr of string for do-loop
          DO                              \ do a loop from start address to end address
             I [email protected] OVER =                  \ fetch the char at loop index compare to CHAR2
             IF
                OVER I C!                 \ if its equal, store CHAR1 into the index address
             THEN
          LOOP
          2drop ;                         \ drop the chars off the stack

 256 constant maxlen                      \ max size of byte counted string in this example

: string:   CREATE    maxlen ALLOT ;      \ simple string variable constructor

: ="      ( string -- )                   \ String variable assignment operator (compile time only)
          [char] " PARSE  ROT  PLACE ;

: =""     ( string -- )  0 swap c! ;      \ empty a string, set count to zero

: clearstr ( string -- )                  \ erase a string variables contents, fill with 0
           maxlen erase ;

  string: strpad                           \ general purpose storage buffer

: substr  ( string1 start length -- strpad) \ Extract a substring of string and return an output string
          >r >r                             \ push start,length
          count                             \ compute addr,len
          r> 1- /string                     \ pop start, subtract 1, cut string
          drop r>                           \ drop existing length, pop new length
          strpad place                      \ place new stack string in strpad
          strpad ;                          \ return address of strpad

\ COMPARE takes the 4 inputs from the stack (addr1 len1  addr2 len2 )
\ and returns a flag for equal (0) , less-than (1)  or greater-than (-1) on the stack

  : comparestr ( string1 string2 -- flag)  \ adapt for use with counted strings
              count rot count compare ;

\ now it's simple to make new operators
  : STR=   ( string1 string2 -- flag)
             comparestr  0= ;

  : STR>   ( string1 string2 -- flag)
             comparestr -1 = ;

  : STR<   ( string1 string2 -- flag)
             comparestr 1 = ;


Dim As String cad, cad2
'creación de cadenas
cad = "¡Hola Mundo!"

'destrucción de cadenas: no es necesario debido a la recolección de basura
cad = ""

'clonación/copia de cadena
cad2 = cad

'comparación de cadenas
If cad = cad2 Then Print "Las cadenas son iguales"

'comprobar si está vacío
If cad = "" Then Print "Cadena vac¡a"

'agregar un byte
cad += Chr(33)

'extraer una subcadena
cad2 = Mid(cad, 1, 5)

'reemplazar bytes
cad2 = "Hola mundo!"
For i As Integer = 1 To Len(cad2)
    If Mid(cad2,i,1) = "l" Then
        cad2 = Left(cad2,i-1) + "L" + Mid(cad2,i+1)
    End If
Next
Print cad2

'unir cadenas
cad = "Hasta " + "pronto " + "de momento."

'imprimir caracteres 2 a 4 de una cadena (una subcadena)
For i As Integer = 2 To 4
    Print Chr(cad[i])
Next i
Sleep


package main

import (
    "bytes"
    "fmt"
)

// Strings in Go allow arbitrary bytes.  They are implemented basically as
// immutable byte slices and syntactic sugar.  This program shows functions
// required by the task on byte slices, thus it mostly highlights what
// happens behind the syntactic sugar.  The program does not attempt to
// reproduce the immutability property of strings, as that does not seem
// to be the intent of the task.

func main() {
    // Task point: String creation and destruction.
    // Strings are most often constructed from literals as in s := "binary"
    // With byte slices,
    b := []byte{'b', 'i', 'n', 'a', 'r', 'y'}
    fmt.Println(b) // output shows numeric form of bytes.
    // Go is garbage collected.  There are no destruction operations.

    // Task point: String assignment.
    // t = s assigns strings.  Since strings are immutable, it is irrelevant
    // whether the string is copied or not.
    // With byte slices, the same works,
    var c []byte
    c = b
    fmt.Println(c)

    // Task point: String comparison.
    // operators <, <=, ==, >=, and > work directly on strings comparing them
    // by lexicographic order.
    // With byte slices, there are standard library functions, bytes.Equal
    // and bytes.Compare.
    fmt.Println(bytes.Equal(b, c)) // prints true

    // Task point: String cloning and copying.
    // The immutable property of Go strings makes cloning and copying
    // meaningless for strings.
    // With byte slices though, it is relevant.  The assignment c = b shown
    // above does a reference copy, leaving both c and b based on the same
    // underlying data.  To clone or copy the underlying data,
    d := make([]byte, len(b)) // allocate new space
    copy(d, b)                // copy the data
    // The data can be manipulated independently now:
    d[1] = 'a'
    d[4] = 'n'
    fmt.Println(string(b)) // convert to string for readable output
    fmt.Println(string(d))

    // Task point: Check if a string is empty.
    // Most typical for strings is s == "", but len(s) == 0 works too.
    // For byte slices, "" does not work, len(b) == 0 is correct.
    fmt.Println(len(b) == 0)

    // Task point: Append a byte to a string.
    // The language does not provide a way to do this directly with strings.
    // Instead, the byte must be converted to a one-byte string first, as in,
    // s += string('z')
    // For byte slices, the language provides the append function,
    z := append(b, 'z')
    fmt.Printf("%s\n", z) // another way to get readable output

    // Task point: Extract a substring from a string.
    // Slicing syntax is the for both strings and slices.
    sub := b[1:3]
    fmt.Println(string(sub))

    // Task point: Replace every occurrence of a byte (or a string)
    // in a string with another string.
    // Go supports this with similar library functions for strings and
    // byte slices.  Strings:  t = strings.Replace(s, "n", "m", -1).
    // The byte slice equivalent returns a modified copy, leaving the
    // original byte slice untouched,
    f := bytes.Replace(d, []byte{'n'}, []byte{'m'}, -1)
    fmt.Printf("%s -> %s\n", d, f)

    // Task point: Join strings.
    // Using slicing syntax again, with strings,
    // rem := s[:1] + s[3:] leaves rem == "bary".
    // Only the concatenation of the parts is different with byte slices,
    rem := append(append([]byte{}, b[:1]...), b[3:]...)
    fmt.Println(string(rem))
}


import java.nio.charset.StandardCharsets

class MutableByteString {
    private byte[] bytes
    private int length

    MutableByteString(byte... bytes) {
        setInternal(bytes)
    }

    int length() {
        return length
    }

    boolean isEmpty() {
        return length == 0
    }

    byte get(int index) {
        return bytes[check(index)]
    }

    void set(byte[] bytes) {
        setInternal(bytes)
    }

    void set(int index, byte b) {
        bytes[check(index)] = b
    }

    void append(byte b) {
        if (length >= bytes.length) {
            int len = 2 * bytes.length
            if (len < 0) {
                len = Integer.MAX_VALUE
            }
            bytes = Arrays.copyOf(bytes, len)
        }
        bytes[length] = b
        length++
    }

    MutableByteString substring(int from, int to) {
        return new MutableByteString(Arrays.copyOfRange(bytes, from, to))
    }

    void replace(byte[] from, byte[] to) {
        ByteArrayOutputStream copy = new ByteArrayOutputStream()
        if (from.length == 0) {
            for (byte b : bytes) {
                copy.write(to, 0, to.length)
                copy.write(b)
            }
            copy.write(to, 0, to.length)
        } else {
            for (int i = 0; i < length; i++) {
                if (regionEqualsImpl(i, from)) {
                    copy.write(to, 0, to.length)
                    i += from.length - 1
                } else {
                    copy.write(bytes[i])
                }
            }
        }
        set(copy.toByteArray())
    }

    boolean regionEquals(int offset, MutableByteString other, int otherOffset, int len) {
        if (Math.max(offset, otherOffset) + len < 0) {
            return false
        }
        if (offset + len > length || otherOffset + len > other.length()) {
            return false
        }
        for (int i = 0; i < len; i++) {
            if (bytes[offset + i] != other.get(otherOffset + i)) {
                return false
            }
        }
        return true
    }

    String toHexString() {
        char[] hex = new char[2 * length]
        for (int i = 0; i < length; i++) {
            hex[2 * i] = "0123456789abcdef".charAt(bytes[i] >> 4 & 0x0F)
            hex[2 * i + 1] = "0123456789abcdef".charAt(bytes[i] & 0x0F)
        }
        return new String(hex)
    }

    String toStringUtf8() {
        return new String(bytes, 0, length, StandardCharsets.UTF_8)
    }

    private void setInternal(byte[] bytes) {
        this.bytes = bytes.clone()
        this.length = bytes.length
    }

    private boolean regionEqualsImpl(int offset, byte[] other) {
        int len = other.length
        if (offset < 0 || offset + len < 0)
            return false
        if (offset + len > length)
            return false
        for (int i = 0; i < len; i++) {
            if (bytes[offset + i] != other[i])
                return false
        }
        return true
    }

    private int check(int index) {
        if (index < 0 || index >= length)
            throw new IndexOutOfBoundsException(String.valueOf(index))
        return index
    }
}


import Text.Regex
{- The above import is needed only for the last function.
It is used there purely for readability and conciseness -}

{- Assigning a string to a 'variable'.
We're being explicit about it just for show.
Haskell would be able to figure out the type
of "world" -}
string = "world" :: String


s := "\x00" # strings can contain any value, even nulls
s := "abc"             # create a string
s := &null             # destroy a string (garbage collect value of s; set new value to &null)
v := s                 # assignment
s == t                 # expression s equals t
s << t                 # expression s less than t
s <<= t                # expression s less than or equal to t
v := s                 # strings are immutable, no copying or cloning are needed
s == ""                # equal empty string
*s = 0                 # string length is zero
s ||:= "a"             # append a byte "a" to s via concatenation
t := s[2+:3]           # t is set to position 2 for 3 characters
s := replace(s,s2,s3)  # IPL replace function
s := s1 || s2          # concatenation (joining) of strings


import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class MutableByteString {

    private byte[] bytes;
    private int length;

    public MutableByteString(byte... bytes) {
        setInternal(bytes);
    }

    public int length() {
        return length;
    }

    public boolean isEmpty() {
        return length == 0;
    }

    public byte get(int index) {
        return bytes[check(index)];
    }

    public void set(byte[] bytes) {
        setInternal(bytes);
    }

    public void set(int index, byte b) {
        bytes[check(index)] = b;
    }

    public void append(byte b) {
        if (length >= bytes.length) {
            int len = 2 * bytes.length;
            if (len < 0)
                len = Integer.MAX_VALUE;
            bytes = Arrays.copyOf(bytes, len);
        }
        bytes[length] = b;
        length++;
    }

    public MutableByteString substring(int from, int to) {
        return new MutableByteString(Arrays.copyOfRange(bytes, from, to));
    }

    public void replace(byte[] from, byte[] to) {
        ByteArrayOutputStream copy = new ByteArrayOutputStream();
        if (from.length == 0) {
            for (byte b : bytes) {
                copy.write(to, 0, to.length);
                copy.write(b);
            }
            copy.write(to, 0, to.length);
        } else {
            for (int i = 0; i < length; i++) {
                if (regionEquals(i, from)) {
                    copy.write(to, 0, to.length);
                    i += from.length - 1;
                } else {
                    copy.write(bytes[i]);
                }
            }
        }
        set(copy.toByteArray());
    }

    public boolean regionEquals(int offset, MutableByteString other, int otherOffset, int len) {
        if (Math.max(offset, otherOffset) + len < 0)
            return false;
        if (offset + len > length || otherOffset + len > other.length())
            return false;
        for (int i = 0; i < len; i++) {
            if (bytes[offset + i] != other.get(otherOffset + i))
                return false;
        }
        return true;
    }

    public String toHexString() {
        char[] hex = new char[2 * length];
        for (int i = 0; i < length; i++) {
            hex[2 * i] = "0123456789abcdef".charAt(bytes[i] >> 4 & 0x0F);
            hex[2 * i + 1] = "0123456789abcdef".charAt(bytes[i] & 0x0F);
        }
        return new String(hex);
    }

    public String toStringUtf8() {
        return new String(bytes, 0, length, StandardCharsets.UTF_8);
    }

    private void setInternal(byte[] bytes) {
        this.bytes = bytes.clone();
        this.length = bytes.length;
    }

    private boolean regionEquals(int offset, byte[] other) {
        int len = other.length;
        if (offset < 0 || offset + len < 0)
            return false;
        if (offset + len > length)
            return false;
        for (int i = 0; i < len; i++) {
            if (bytes[offset + i] != other[i])
                return false;
        }
        return true;
    }

    private int check(int index) {
        if (index < 0 || index >= length)
            throw new IndexOutOfBoundsException(String.valueOf(index));
        return index;
    }
}


//String creation
var str='';
//or
str2=new String();

//String assignment
str="Hello";
//or
str2=', Hey there'; //can use " or '
str=str+str2;//concantenates
//string deletion
delete str2;//this will return true or false, true when it has been successfully deleted, it shouldn't/won't work when the variable has been declared with the keyword 'var', you don't have to initialize variables with the var keyword in JavaScript, but when you do, you cannot 'delete' them. However JavaScript garbage collects, so when the function returns, the variable declared on the function is erased.

//String comparison
str!=="Hello"; //!== not equal-> returns true there's also !===
str=="Hello, Hey there"; //returns true
//compares 'byte' by 'byte'
"Character Z">"Character A"; //returns true, when using > or < operators it converts the string to an array and evalues the first index that is higher than another. (using unicode values) in this case 'Z' char code is 90 (decimal) and 'A' char code is 65, therefore making one string "larger" than the other.

//String cloning and copying
string=str;//Strings are immutable therefore when you assign a string to a variable another one is created. So for two variables to have the 'same' string you have to add that string to an object, and get/set the string from that object

//Check if a string is empty
Boolean(''); //returns false
''[0]; //returns undefined
''.charCodeAt(); //returns NaN
''==0; //returns true
''===0; //returns false
''==false; //returns true

//Append byte to String
str+="\x40";//using + operator before the equal sign on a string makes it equal to str=str+"\x40"

//Extract a substring from a string
//str is "Hello, Hey [email protected]"
str.substr(3); //returns "lo, Hey [email protected]"
str.substr(-5); //returns "[email protected]" negative values just go to the end
str.substr(7,9); //returns "Hey there" index of 7 + 9 characters after the 7
str.substring(3); //same as substr
str.substring(-5); //negative values don't work on substring same as substr(0)
str.substring(7,9); //returns "He" that is, whatever is between index 7 and index 9, same as substring(9,7)

//Replace every occurence of x byte with another string
str3="url,url,url,url,url";
str3.replace(/,/g,'\n') //Regex ,returns the same string with the , replaced by \n
str4=str3.replace(/./g,function(index){//it also supports callback functions, the function will be called when a match has been found..
return index==','?'\n':index;//returns replacement
})

//Join Strings
[str," ",str3].join(" "/*this is the character that will glue the strings*/)//we can join an array of strings
str3+str4;
str.concat('\n',str4); //concantenate them


# If the input is a valid representation of a binary string
# then pass it along:
def check_binary:
  . as $a
  | reduce .[] as $x
    ($a;
     if $x | (type == "number" and . == floor
              and 0 <= . and . <= 255) then $a
     else error("\(.) is an invalid representation of a byte")
     end );


# String assignment. Creation and garbage collection are automatic.
a = "123\x00 abc "  # strings can contain bytes that are not printable in the local font
b = "456" * '\x09'
c = "789"
println(a)
println(b)
println(c)

# string comparison
println("(a == b) is $(a == b)")

# String copying.
A = a
B = b
C = c
println(A)
println(B)
println(C)

# check if string is empty
if length(a) == 0
println("string a is empty")
else
println("string a is not empty")
end

# append a byte (actually this is a Char in Julia, and may also be up to 32 bit Unicode) to a string
a= a * '\x64'
println(a)

# extract a substring from string
e = a[1:6]
println(e)

# repeat strings with ^
b4 = b ^ 4
println(b4)

# Replace every occurrence of a string in another string with third string
r = replace(b4, "456" => "xyz")
println(r)

# join strings with *
d = a * b * c
println(d)


class ByteString(private val bytes: ByteArray) : Comparable<ByteString> {
    val length get() = bytes.size

    fun isEmpty() = bytes.isEmpty()

    operator fun plus(other: ByteString): ByteString = ByteString(bytes + other.bytes)

    operator fun plus(byte: Byte) = ByteString(bytes + byte)

    operator fun get(index: Int): Byte {
        require (index in 0 until length)
        return bytes[index]
    }

    fun toByteArray() = bytes

    fun copy() = ByteString(bytes.copyOf())

    override fun compareTo(other: ByteString) = this.toString().compareTo(other.toString())

    override fun equals(other: Any?): Boolean {
        if (other == null || other !is ByteString) return false
        return compareTo(other) == 0
    }

    override fun hashCode() = this.toString().hashCode()

    fun substring(startIndex: Int) = ByteString(bytes.sliceArray(startIndex until length))

    fun substring(startIndex: Int, endIndex: Int) =
        ByteString(bytes.sliceArray(startIndex until endIndex))

    fun replace(oldByte: Byte, newByte: Byte): ByteString {
        val ba = ByteArray(length) { if (bytes[it] == oldByte) newByte else bytes[it] }
        return ByteString(ba)
    }

    fun replace(oldValue: ByteString, newValue: ByteString) =
        this.toString().replace(oldValue.toString(), newValue.toString()).toByteString()

    override fun toString(): String {
        val chars = CharArray(length)
        for (i in 0 until length) {
            chars[i] = when (bytes[i]) {
                in 0..127  -> bytes[i].toChar()
                else       -> (256 + bytes[i]).toChar()
            }
        }
        return chars.joinToString("")
    }
}

fun String.toByteString(): ByteString {
    val bytes = ByteArray(this.length)
    for (i in 0 until this.length) {
        bytes[i] = when (this[i].toInt()) {
            in 0..127   -> this[i].toByte()
            in 128..255 -> (this[i] - 256).toByte()
            else        -> '?'.toByte()  // say
        }
    }
    return ByteString(bytes)
}

/* property to be used as an abbreviation for String.toByteString() */
val String.bs get() = this.toByteString()

fun main(args: Array<String>) {
    val ba  = byteArrayOf(65, 66, 67)
    val ba2 = byteArrayOf(68, 69, 70)
    val bs  = ByteString(ba)
    val bs2 = ByteString(ba2)
    val bs3 = bs + bs2
    val bs4 = "GHI£€".toByteString()
    println("The length of $bs is ${bs.length}")
    println("$bs + $bs2 = $bs3")
    println("$bs + D = ${bs + 68}")
    println("$bs == ABC is ${bs == bs.copy()}")
    println("$bs != ABC is ${bs != bs.copy()}")
    println("$bs >= $bs2 is ${bs > bs2}")
    println("$bs <= $bs2 is ${bs < bs2}")
    println("$bs is ${if (bs.isEmpty()) "empty" else "not empty"}")
    println("ABC[1] = ${bs[1].toChar()}")
    println("ABC as a byte array is ${bs.toByteArray().contentToString()}")
    println("ABCDEF(1..5) = ${bs3.substring(1)}")
    println("ABCDEF(2..4) = ${bs3.substring(2,5)}")
    println("ABCDEF with C replaced by G is ${bs3.replace(67, 71)}")
    println("ABCDEF with CD replaced by GH is ${bs3.replace("CD".bs, "GH".bs)}")
    println("GHI£€ as a ByteString is $bs4")
}


'string creation
s$ = "Hello, world!"

'string destruction - not needed because of garbage collection
s$ = ""

'string comparison
s$ = "Hello, world!"
If s$ = "Hello, world!" then print "Equal Strings"

'string copying
a$ = s$

'check If empty
If s$ = "" then print "Empty String"

'append a byte
s$ = s$ + Chr$(33)

'extract a substring
a$ = Mid$(s$, 1, 5)

'replace bytes
a$ = "Hello, world!"
for i = 1 to len(a$)
    if mid$(a$,i,1)="l" then
        a$=left$(a$,i-1)+"L"+mid$(a$,i+1)
    end if
next
print a$

'join strings
s$ = "Good" + "bye" + " for now."


-- String creation and destruction
foo = "Hello world!" -- created by assignment; destruction via garbage collection

-- Strings are binary safe
put numtochar(0) into char 6 of foo
put chartonum(foo.char[6])
-- 0
put str.char[7..foo.length]
-- "world!"

-- String cloning and copying
bar = foo -- copies foo contents to bar

-- String comparison
put (foo=bar) -- TRUE
put (foo<>bar) -- FALSE

-- Check if a string is empty
put (foo=EMPTY)
put (foo="")
put (foo.length=0)

-- Append a byte to a string
put "X" after foo
put chartonum(88) after foo

-- Extract a substring from a string
put foo.char[3..5]

-- Replace every occurrence of a byte (or a string) in a string with another string

----------------------------------------
-- Replace in string
-- @param {string} stringToFind
-- @param {string} stringToInsert
-- @param {string} input
-- @return {string}
----------------------------------------
on replaceAll (stringToFind, stringToInsert, input)
    output = ""
    findLen = stringToFind.length - 1
    repeat while TRUE
        currOffset = offset(stringToFind, input)
        if currOffset=0 then exit repeat
        put input.char[1..currOffset] after output
        delete the last char of output
        put stringToInsert after output
        delete input.char[1..(currOffset + findLen)]
    end repeat
    put input after output
    return output
end

put replaceAll("o", "X", foo)

-- Join strings (4x the same result)
foo = "Hello " & "world!"
foo = "Hello" & numtochar(32) & "world!"
foo = "Hello" & SPACE & "world!"
foo = "Hello" && "world!"


foo = 'foo'             -- Ducktyping foo to be string 'foo'
bar = 'bar'
assert (foo == "foo")   -- Comparing string var to string literal
assert (foo ~= bar)
str = foo               -- Copy foo contents to str
if #str == 0 then       -- # operator returns string length
    print 'str is empty'
end
str=str..string.char(50)-- Char concatenated with .. operator
substr = str:sub(1,3)   -- Extract substring from index 1 to 3, inclusively

str = "string string string string"
-- This function will replace all occurances of 'replaced' in a string with 'replacement'
function replaceAll(str,replaced,replacement)
    local function sub (a,b)
        if b > a then
            return str:sub(a,b)
        end
        return nil
    end
    a,b = str:find(replaced)
    while a do
        str = str:sub(1,a-1) .. replacement .. str:sub(b+1,#str)
        a,b = str:find(replaced)
    end
    return str
end
str = replaceAll (str, 'ing', 'ong')
print (str)

str = foo .. bar -- Strings concatenate with .. operator


(* String creation and destruction *)  BinaryString = {}; BinaryString = . ;
(* String assignment *)   BinaryString1 = {12,56,82,65} ,  BinaryString2 = {83,12,56,65}
-> {12,56,82,65}
-> {83,12,56,65}
(* String comparison *)   BinaryString1 === BinaryString2
-> False
(* String cloning and copying *)  BinaryString3 = BinaryString1
-> {12,56,82,65}
(* Check if a string is empty *)  BinaryString3 === {}
-> False
(* Append a byte to a string *)   AppendTo[BinaryString3, 22]
-> {12,56,82,65,22}
(* Extract a substring from a string *)  Take[BinaryString3, {2, 5}]
-> {56,82,65,22}
(* Replace every occurrence of a byte (or a string) in a string with another string *)
BinaryString3 /. {22 -> Sequence[33, 44]}
-> {12,56,82,65,33,44}
(* Join strings *)  BinaryString4 = Join[BinaryString1 , BinaryString2]
-> {12,56,82,65,83,12,56,65}


	a=['123',0,' abc '];
	b=['456',9];
	c='789';
	disp(a);
	disp(b);
	disp(c);

	% string comparison
	printf('(a==b) is %i\n',strcmp(a,b));

	% string copying
	A = a;
	B = b;
	C = c;
	disp(A);
	disp(B);
	disp(C);

	% check if string is empty
	if (length(a)==0)
		printf('\nstring a is empty\n');
	else
		printf('\nstring a is not empty\n');
	end

	% append a byte to a string
	a=[a,64];
        disp(a);

	% substring
	e = a(1:6);
        disp(e);

	% join strings
	d=[a,b,c];
	disp(d);


var # creation
  x = "this is a string"
  y = "this is another string"
  z = "this is a string"

if x == z: echo "x is z" # comparison

z = "now this is another string too" # assignment

y = z # copying

if x.len == 0: echo "empty" # check if empty

x.add('!') # append a byte

echo x[5..8] # substring
echo x[8 .. ^1] # substring

z = x & y # join strings

import strutils

echo z.replace('t', 'T') # replace occurences of t with T


cmp_str(u,v)=u==v
copy_str(v)=v \\ Creates a copy, not a pointer
append_str(v,n)=concat(v,n)
replace_str(source, n, replacement)=my(v=[]);for(i=1,#source,v=concat(v,if(source[i]==n,replacement,source[i]))); v

u=[72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100];
v=[];
cmp_str(u,v)
w=copy_str(v)
#w==0
append_str(u,33)
u[8..12]
replace_str(u,108,[121])
concat(v,w)


const
  greeting = 'Hello';
var
  s1: string;
  s2: ansistring;
  s3: pchar;
begin
{ Assignments }
  s1 := 'Mister Presiden';  (* typo is on purpose. See below! *)
{ Comparisons }
  if s2 > 'a' then
    writeln ('The first letter of ', s1, ' is later than a');
{ Cloning and copying }
  s2 := greeting;
{ Check if a string is empty }
  if s1 = '' then
    writeln('This string is empty!');
{ Append a byte to a string }
  s1 := s1 + 't';
{ Extract a substring from a string }
  s3 := copy(S2, 2, 4);  (* s3 receives ello *)
{ String replacement }  (* the unit StrUtils of the FreePascal rtl has AnsiReplaceStr *)
  s1 := AnsiReplaceStr('Thees ees a text weeth typos', 'ee', 'i');
{ Join strings}
  s3 := greeting + ' and how are you, ' + s1 + '?';
end.


$s = undef;
say 'Nothing to see here' if ! defined $s;  # 'Nothing to see here'
say $s = '';                                # ''
say 'Empty string' if $s eq '';             # 'Empty string'
say $s = 'be';                              # 'be'
say $t = $s;                                # 'be'
say 'Same' if $t eq $s;                     # 'Same'
say $t = $t .'e'                            # 'bee'
say $t .= 'keeper';                         # 'beekeeper'
$t =~ s/ee/ook/; say $t;                    # 'bookkeeper'
say $u = substr $t, 2, 2;                   # 'ok'
say 'Oklahoma' . ' is ' . uc $u;            # 'Oklahoma is OK'


with javascript_semantics
string s = "abc"
s = x"ef bb bf" -- explicit binary string (the utf8 BOM)
s[2] = 0
s[3] = 'z'
if s="\#EF\0z" then puts(1,"ok\n") end if
string t = s
t[1..2] = "xy"  -- s remains unaltered
?t              -- "xyz"
t = "food"      ?t
t[2..3] = 'e'   ?t -- "feed"
t[3..2] = "ast" ?t -- "feasted"
t[3..-2] = ""   ?t -- "fed"
if length(t)=0 then puts(1,"t is empty\n") end if
if t!="" then puts(1,"t is not empty\n") end if
t = "be"
t &= 't'        ?t  -- bet
t = 'a'&t       ?t  -- abet
?t[2..3]            -- be
?substitute(t,"be","bbo")   -- abbot
?substitute(t,"be","dep")   -- adept
t = substitute(t,"be","dep") -- to actually modify t
?join({"abc","def","ghi"})  -- "abc def ghi"
?join({"abc","def","ghi"},"")   -- "abcdefghi"
?join({"abc","def","ghi"},"\n") -- "abc\ndef\nghi"


main =>  % - String assignment
  S1 = "binary_string",
  println(s1=S1),

  % Picat has re-assignments (:=/2) as well,
  S1 := "another string",
  println(s1=S1),

  % - String comparison
  if S1 == "another string" then
    println(same)
  else
    println(not_same)
  end,

  % - String cloning and copying
  S2 = S1,
  println(s2=S2),

  S3 = copy_term(S1), % for strings it's the same as =/2
  println(s3=S3),

  % - Check if a string is empty
  if S3 == "" then
    println(is_empty)
  else
    println(not_empty)
  end,

  % - Append a byte to a string
  S3 := S3 ++ "s",
  println(s3=S3),

  % - Extract a substring from a string
  println(substring=S3[5..7]),
  println(slice=slice(S1,5,7)),
  println(slice=slice(S1,5)),

  % - Replace every occurrence of a byte (or a string) in a string with another string
  S4 = replace(S3,'s','x'),
  println(s4=S4),

  % - Join strings
  S5 = S1 ++ " " ++ S2,
  println(s5=S5),

  % using append/4
  append(S1," ", S2,S6),
  println(s6=S6),

  % find positions of substrings
  println(find=findall([From,To],find(S5,"str",From,To))),

  % split a string
  println(split=split(S1," st"))


: (out "rawfile"
   (mapc wr (range 0 255)) )


/* PL/I has immediate facilities for all those operations except for */
/* replace. */
s = t;                     /* assignment */
s = t || u;                /* catenation - append one or more bytes. */
if length(s) = 0 then ...  /* test for an empty string.              */
if s = t then ...          /* compare strings.                       */
u = substr(t, i, j);       /* take a substring of t beginning at the */
                           /* i-th character andcontinuing for j     */
                           /* characters.                            */
substr(u, i, j) = t;       /* replace j characters in u, beginning   */
                           /* with the i-th character.               */

/* In string t, replace every occurrence of string u with string v.  */
replace: procedure (t, u, v);
   declare (t, u, v) character (*) varying;

   do until (k = 0);
      k = index(t, u);
      if k > 0 then
         t = substr(t, 1, k-1) || v || substr(t, k+length(u));
   end;
end replace;


Clear-Host

## String creation (which is string assignment):
Write-Host "`nString creation (which is string assignment):" -ForegroundColor Cyan
Write-Host '[string]$s = "Hello cruel world"' -ForegroundColor Yellow
[string]$s = "Hello cruel world"

## String (or any variable) destruction:
Write-Host "`nString (or any variable) destruction:" -ForegroundColor Cyan
Write-Host 'Remove-Variable -Name s -Force' -ForegroundColor Yellow
Remove-Variable -Name s -Force

## Now reassign the variable:
Write-Host "`nNow reassign the variable:" -ForegroundColor Cyan
Write-Host '[string]$s = "Hello cruel world"' -ForegroundColor Yellow
[string]$s = "Hello cruel world"

Write-Host "`nString comparison -- default is case insensitive:" -ForegroundColor Cyan
Write-Host '$s -eq "HELLO CRUEL WORLD"' -ForegroundColor Yellow
$s -eq "HELLO CRUEL WORLD"
Write-Host '$s -match "HELLO CRUEL WORLD"' -ForegroundColor Yellow
$s -match "HELLO CRUEL WORLD"
Write-Host '$s -cmatch "HELLO CRUEL WORLD"' -ForegroundColor Yellow
$s -cmatch "HELLO CRUEL WORLD"

## Copy a string:
Write-Host "`nCopy a string:" -ForegroundColor Cyan
Write-Host '$t = $s' -ForegroundColor Yellow
$t = $s

## Check if a string is empty:
Write-Host "`nCheck if a string is empty:" -ForegroundColor Cyan
Write-Host 'if ($s -eq "") {"String is empty."} else {"String = $s"}' -ForegroundColor Yellow
if ($s -eq "") {"String is empty."} else {"String = $s"}

## Append a byte to a string:
Write-Host "`nAppend a byte to a string:" -ForegroundColor Cyan
Write-Host "`$s += [char]46`n`$s" -ForegroundColor Yellow
$s += [char]46
$s

## Extract (and display) substring from a string:
Write-Host "`nExtract (and display) substring from a string:" -ForegroundColor Cyan
Write-Host '"Is the world $($s.Substring($s.IndexOf("c"),5))?"' -ForegroundColor Yellow
"Is the world $($s.Substring($s.IndexOf("c"),5))?"

## Replace every occurrence of a byte (or a string) in a string with another string:
Write-Host "`nReplace every occurrence of a byte (or a string) in a string with another string:" -ForegroundColor Cyan
Write-Host "`$t = `$s -replace `"cruel`", `"beautiful`"`n`$t" -ForegroundColor Yellow
$t = $s -replace "cruel", "beautiful"
$t

## Join strings:
Write-Host "`nJoin strings [1]:" -ForegroundColor Cyan
Write-Host '"Is the world $($s.Split()[1]) or $($t.Split()[1])?"' -ForegroundColor Yellow
"Is the world $($s.Split()[1]) or $($t.Split()[1])?"
Write-Host "`nJoin strings [2]:" -ForegroundColor Cyan
Write-Host '"{0} or {1}... I don''t care." -f (Get-Culture).TextInfo.ToTitleCase($s.Split()[1]), $t.Split()[1]' -ForegroundColor Yellow
"{0} or {1}... I don't care." -f (Get-Culture).TextInfo.ToTitleCase($s.Split()[1]), $t.Split()[1]
Write-Host "`nJoin strings [3] (display an integer array using the -join operater):" -ForegroundColor Cyan
Write-Host '1..12 -join ", "' -ForegroundColor Yellow
1..12 -join ", "

## Display an integer array in a tablular format:
Write-Host "`nMore string madness... display an integer array in a tablular format:" -ForegroundColor Cyan
Write-Host '1..12 | Format-Wide {$_.ToString().PadLeft(2)}-Column 3 -Force' -NoNewline -ForegroundColor Yellow
1..12 | Format-Wide {$_.ToString().PadLeft(2)} -Column 3 -Force


% Create a string (no destruction necessary)
?- X = "a test string".
X = "a test string".

% String assignment, there is no assignment but you can unify between variables, also 'String cloning and copying'
?- X = "a test string", X = Y.
X = Y, Y = "a test string".

% String comparison
?- X = "a test string", Y = "a test string", X = Y.
X = Y, Y = "a test string".

?- X = "a test string", Y = "a different string", X = Y.
false.

% Test for empty string, this is the same as string comparison.
?- X = "a test string", Y = "", X = Y.
false.

?- X = "", Y = "", X = Y.
false.

% Append a byte to a string
?- X = "a test string", string_concat(X, "!", Y).
X = "a test string",
Y = "a test string!".

% Extract a substring from a string
?- X = "a test string", sub_string(X, 2, 4, _, Y).
X = "a test string",
Y = "test".

?- X = "a test string", sub_string(X, Before, Len, After, test).
X = "a test string",
Before = 2,
Len = 4,
After = 7 ;
false.

% Replace every occurrence of a byte (or a string) in a string with another string
?- X = "a test string", re_replace('t'/g, 'o', X, Y).
X = "a test string",
Y = "a oeso soring".

% Join strings
?- X = "a test string", Y = " with extra!", string_concat(X, Y, Z).
X = "a test string",
Y = " with extra!",
Z = "a test string with extra!".


;string creation
x$ = "hello world"

;string destruction
x$ = ""

;string comparison
If x$ = "hello world" : PrintN("String is equal") : EndIf

;string copying;
y$ = x$

; check If empty
If x$ = "" : PrintN("String is empty") : EndIf

; append a byte
x$ = x$ + Chr(41)

; extract a substring
x$ = Mid(x$, 1, 5)

; replace bytes
x$ = ReplaceString(x$, "world", "earth")

; join strings
x$ = "hel" + "lo w" + "orld"


s1 = "A 'string' literal \n"
s2 = 'You may use any of \' or " as delimiter'
s3 = """This text
   goes over several lines
       up to the closing triple quote"""


#lang racket

;; Byte strings can be created either by a function (b1)
;; or as a literal string (b2). No operation is needed for
;; destruction due to garbage collection.

(define b1 (make-bytes 5 65))  ; b1 -> #"AAAAA"
(define b2 #"BBBBB")           ; b2 -> #"BBBBB"

;; String assignment. Note that b2 cannot be
;; mutated since literal byte strings are immutable.

(bytes-set! b1 0 66)           ; b1 -> #"BAAAA"

;; Comparison. Less than & greater than are
;; lexicographic comparison.

(bytes=? b1 b2)                ; -> #f
(bytes<? b1 b2)                ; -> #t
(bytes>? b1 b2)                ; -> #f

;; Byte strings can be cloned by copying to a
;; new one or by overwriting an existing one.

(define b3 (bytes-copy b1))    ; b3 -> #"BAAAA"
(bytes-copy! b1 0 b2)          ; b1 -> #"BBBBB"

;; Byte strings can be appended to one another. A
;; single byte is appended as a length 1 string.

(bytes-append b1 b2)           ; -> #"BBBBBBBBBB"
(bytes-append b3 #"B")         ; -> #"BAAAAB"

;; Substring

(subbytes b3 0)                ; -> #"BAAAA"
(subbytes b3 0 2)              ; -> #"BA"

;; Regular expressions can be used to do replacements
;; in a byte string (or ordinary strings)

(regexp-replace #"B" b1 #"A")  ; -> #"ABBBB" (only the first one)
(regexp-replace* #"B" b1 #"A") ; -> #"AAAAA"

;; Joining strings

(bytes-join (list b2 b3) #" ") ; -> #"BBBBB BAAAA"


# Raku is perfectly fine with NUL *characters* in strings:
my Str $s = 'nema' ~ 0.chr ~ 'problema!';
say $s;

# However, Raku makes a clear distinction between strings
# (i.e. sequences of characters), like your name, or …
my Str $str = "My God, it's full of chars!";
# … and sequences of bytes (called Bufs), for example a PNG image, or …
my Buf $buf = Buf.new(255, 0, 1, 2, 3);
say $buf;

# Strs can be encoded into Blobs …
my Blob $this = 'round-trip'.encode('ascii');
# … and Blobs can be decoded into Strs …
my Str $that = $this.decode('ascii');

# So it's all there. Nevertheless, let's solve this task explicitly
# in order to see some nice language features:

# We define a class …
class ByteStr {
    # … that keeps an array of bytes, and we delegate some
    # straight-forward stuff directly to this attribute:
    # (Note: "has byte @.bytes" would be nicer, but that is
    # not yet implemented in Rakudo.)
    has Int @.bytes handles(< Bool elems gist push >);

    # A handful of methods …
    method clone() {
        self.new(:@.bytes);
    }

    method substr(Int $pos, Int $length) {
        self.new(:bytes(@.bytes[$pos .. $pos + $length - 1]));
    }

    method replace(*@substitutions) {
        my %h = @substitutions;
        @.bytes.=map: { %h{$_} // $_ }
    }
}

# A couple of operators for our new type:
multi infix:<cmp>(ByteStr $x, ByteStr $y) { $x.bytes.join cmp $y.bytes.join }
multi infix:<~>  (ByteStr $x, ByteStr $y) { ByteStr.new(:bytes(|$x.bytes, |$y.bytes)) }

# create some byte strings (destruction not needed due to garbage collection)
my ByteStr $b0 = ByteStr.new;
my ByteStr $b1 = ByteStr.new(:bytes( |'foo'.ords, 0, 10, |'bar'.ords ));

# assignment ($b1 and $b2 contain the same ByteStr object afterwards):
my ByteStr $b2 = $b1;

# comparing:
say 'b0 cmp b1 = ', $b0 cmp $b1;
say 'b1 cmp b2 = ', $b1 cmp $b2;

# cloning:
my $clone = $b1.clone;
$b1.replace('o'.ord => 0);
say 'b1 = ', $b1;
say 'b2 = ', $b2;
say 'clone = ', $clone;

# to check for (non-)emptiness we evaluate the ByteStr in boolean context:
say 'b0 is ', $b0 ?? 'not empty' !! 'empty';
say 'b1 is ', $b1 ?? 'not empty' !! 'empty';

# appending a byte:
$b1.push: 123;
say 'appended = ', $b1;

# extracting a substring:
my $sub = $b1.substr(2, 4);
say 'substr = ', $sub;

# replacing a byte:
$b2.replace(102 => 103);
say 'replaced = ', $b2;

# joining:
my ByteStr $b3 = $b1 ~ $sub;
say 'joined = ', $b3;


Red []
s: copy "abc"   ;; string creation

s: none ;; destruction
t: "Abc"
if t == "abc" [print "equal case"]              ;; comparison , case sensitive
if t = "abc" [print "equal (case insensitive)"]  ;; comparison , case insensitive
s: copy ""                                        ;; copying string
if empty? s [print "string is empty "]          ;; check if string is empty
append s #"a"                                    ;; append byte
substr: copy/part at "1234" 3 2               ;; ~ substr ("1234" ,3,2) , red has 1 based indices !
?? substr
s: replace/all "abcabcabc" "bc" "x"             ;; replace all "bc" by "x"
?? s
s: append "hello " "world"                        ;; join 2 strings
?? s
s: rejoin ["hello " "world" " !"]                   ;; join multiple strings
?? s


/*REXX program demonstrates methods (code examples)  to use and express  binary strings.*/
dingsta= '11110101'b                             /*four versions, bit string assignment.*/
dingsta= "11110101"b                             /*this is the same assignment as above.*/
dingsta= '11110101'B                             /*  "   "  "    "      "       "   "   */
dingsta= '1111 0101'B                            /*  "   "  "    "      "       "       */

dingsta2= dingsta                                /*clone one string to another (a copy).*/
other= '1001 0101 1111 0111'b                    /*another binary  (or bit)  string.    */
if dingsta= other    then say 'they are equal'   /*compare the two  (binary)  strings.  */
if other== ''        then say "OTHER is empty."  /*see if the   OTHER   string is empty.*/
otherA= other || '$'                             /*append a dollar sign ($)  to  OTHER. */
otherB= other'$'                                 /*same as above,  but with less fuss.  */
  guts= substr(c2b(other), 10, 3)                /*obtain the  10th  through  12th bits.*/
   new= changeStr('A' , other, "Z")              /*change the upper  letter  A  ──►  Z. */
    tt= changeStr('~~', other, ";")              /*change two tildes ──►  one semicolon.*/
joined= dingsta || dingsta2                      /*join two strings together (concat).  */
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
c2b:       return x2b( c2x( arg(1) ) )           /*return the string as a binary string.*/


# string creation
x = "hello world"

# string destruction
x = NULL

# string assignment with a null byte
x = "a"+char(0)+"b"
see len(x)  # ==> 3

# string comparison
if x = "hello"
  See "equal"
else
  See "not equal"
ok
y = 'bc'
if strcmp(x,y) < 0
  See x + " is lexicographically less than " + y
ok

# string cloning
xx = x
See x = xx       # true, same length and content

# check if empty
if x = NULL
  See "is empty"
ok

# append a byte
x += char(7)

# substring
x = "hello"
x[1] = "H"
See x + nl

# join strings
a = "hel"
b = "lo w"
c = "orld"
See a + b + c


# string creation
x = "hello world"

# string destruction
x = nil

# string assignment with a null byte
x = "a\0b"
x.length  # ==> 3

# string comparison
if x == "hello"
  puts "equal"
else
  puts "not equal"
end
y = 'bc'
if x < y
  puts "#{x} is lexicographically less than #{y}"
end

# string cloning
xx = x.dup
x == xx       # true, same length and content
x.equal?(xx)  # false, different objects

# check if empty
if x.empty?
  puts "is empty"
end

# append a byte
p x << "\07"

# substring
p xx = x[0..-2]
x[1,2] = "XYZ"
p x

# replace bytes
p y = "hello world".tr("l", "L")

# join strings
a = "hel"
b = "lo w"
c = "orld"
p d = a + b + c


' Create string
s$ = "Hello, world"

' String destruction
s$ = ""

' String comparison
If s$ = "Hello, world" then print "Equal String"

' Copying string
a$ = s$

' Check If empty
If s$ = "" then print "String is MT"

' Append a byte
s$ = s$ + Chr$(65)

' Extract a substring
a$ = Mid$(s$, 1, 5)   ' bytes 1 -> 5

'substitute string "world" with "universe"
a$ = "Hello, world"
for i = 1 to len(a$)
    if mid$(a$,i,5)="world" then
        a$=left$(a$,i-1)+"universe"+mid$(a$,i+5)
    end if
next
print a$

'join strings
s$ = "See " + "you " + "later."
print s$


use std::str;

fn main() {
    // Create new string
    let string = String::from("Hello world!");
    println!("{}", string);
    assert_eq!(string, "Hello world!", "Incorrect string text");

    // Create and assign value to string
    let mut assigned_str = String::new();
    assert_eq!(assigned_str, "", "Incorrect string creation");
    assigned_str += "Text has been assigned!";
    println!("{}", assigned_str);
    assert_eq!(assigned_str, "Text has been assigned!","Incorrect string text");

    // String comparison, compared lexicographically byte-wise same as the asserts above
    if string == "Hello world!" && assigned_str == "Text has been assigned!" {
        println!("Strings are equal");
    }

    // Cloning -> string can still be used after cloning
    let clone_str = string.clone();
    println!("String is:{}  and  Clone string is: {}", string, clone_str);
    assert_eq!(clone_str, string, "Incorrect string creation");

    // Copying, string won't be usable anymore, accessing it will cause compiler failure
    let copy_str = string;
    println!("String copied now: {}", copy_str);

    // Check if string is empty
    let empty_str = String::new();
    assert!(empty_str.is_empty(), "Error, string should be empty");

    // Append byte, Rust strings are a stream of UTF-8 bytes
    let byte_vec = [65]; // contains A
    let byte_str = str::from_utf8(&byte_vec).unwrap();
    assert_eq!(byte_str, "A", "Incorrect byte append");

    // Substrings can be accessed through slices
    let test_str = "Blah String";
    let mut sub_str = &test_str[0..11];
    assert_eq!(sub_str, "Blah String", "Error in slicing");
    sub_str = &test_str[1..5];
    assert_eq!(sub_str, "lah ", "Error in slicing");
    sub_str = &test_str[3..];
    assert_eq!(sub_str, "h String", "Error in slicing");
    sub_str = &test_str[..2];
    assert_eq!(sub_str, "Bl", "Error in slicing");

    // String replace, note string is immutable
    let org_str = "Hello";
    assert_eq!(org_str.replace("l", "a"), "Heaao", "Error in replacement");
    assert_eq!(org_str.replace("ll", "r"), "Hero", "Error in replacement");

    // Joining strings requires a `String` and an &str or a two `String`s one of which needs an & for coercion
    let str1 = "Hi";
    let str2 = " There";
    let fin_str = str1.to_string() + str2;
    assert_eq!(fin_str, "Hi There", "Error in concatenation");

    // Joining strings requires a `String` and an &str or two `Strings`s, one of which needs an & for coercion
    let str1 = "Hi";
    let str2 = " There";
    let fin_str = str1.to_string() + str2;
    assert_eq!(fin_str, "Hi There", "Error in concatenation");

    // Splits -- note Rust supports passing patterns to splits
    let f_str = "Pooja and Sundar are up in Tumkur";
    let split_str: Vec<_> = f_str.split(' ').collect();
    assert_eq!(split_str, ["Pooja", "and", "Sundar", "are", "up", "in", "Tumkur"], "Error in string split");
}


var string: stri is "asdf";   # variable declaration
const string: stri is "jkl";  # constant declaration


s := "abc"             # create a string (immutable if its a literal constant in the program)
s := #[16r01 16r02 16r00 16r03] asString # strings can contain any value, even nulls
s := String new:3.     # a mutable string
v := s                 # assignment
s = t                  # same contents
s < t                  # less
s <= t                 # less or equal
s = ''                 # equal empty string
s isEmpty              # ditto
s size                 # string length
t := s copy            # a copy
t := s copyFrom:2 to:3 # a substring
t := s copyReplaceFrom:2 to:3 with:'**'  # a copy with some replacements
s replaceFrom:2 to:3 with:'**'           # inplace replace (must be mutable)
s replaceAll:$x with:$y                  # destructive replace of characters
s copyReplaceAll:$x with:$y              # non-destructive replace
s replaceString:s1 withString:s2         # substring replace
s3 := s1 , s2          # concatenation of strings
s2 := s1 , $x          # append a character
s2 := s1 , 123 asCharacter # append an arbitrary byte
s := 'Hello / 今日は'   # they support unicode (at least up to 16rFFFF, some more)


# string creation
set x "hello world"

# string destruction
unset x

# string assignment with a null byte
set x a\0b
string length $x ;# ==> 3

# string comparison
if {$x eq "hello"} {puts equal} else {puts "not equal"}
set y bc
if {$x < $y} {puts "$x is lexicographically less than $y"}

# string copying; cloning happens automatically behind the scenes
set xx $x

# check if empty
if {$x eq ""} {puts "is empty"}
if {[string length $x] == 0} {puts "is empty"}

# append a byte
append x \07

# substring
set xx [string range $x 0 end-1]

# replace bytes
set y [string map {l L} "hello world"]

# join strings
set a "hel"
set b "lo w"
set c "orld"
set d $a$b$c


The Option Compare instruction is used at module level to declare the default comparison method to use when string data is compared.
The default text comparison method is Binary.


Module Module1

    Sub Main()
        'string creation
        Dim x = "hello world"

        ' mark string for garbage collection
        x = Nothing

        ' string assignment with a null byte
        x = "ab" + Chr(0)
        Console.WriteLine(x)
        Console.WriteLine(x.Length)

        'string comparison
        If x = "hello" Then
            Console.WriteLine("equal")
        Else
            Console.WriteLine("not equal")
        End If

        If x.CompareTo("bc") = -1 Then
            Console.WriteLine("x is lexicographically less than 'bc'")
        End If

        'string cloning
        Dim c(3) As Char
        x.CopyTo(0, c, 0, 3)
        Dim objecty As New String(c)
        Dim y As New String(c)

        Console.WriteLine(x = y)        'same as string.equals
        Console.WriteLine(x.Equals(y))  'it overrides object.equals

        Console.WriteLine(x = objecty)  'uses object.equals, return false

        'check if empty
        Dim empty = ""
        Dim nullString As String = Nothing
        Dim whitespace = "    "
        If IsNothing(nullString) AndAlso empty = String.Empty _
            AndAlso String.IsNullOrEmpty(nullString) AndAlso String.IsNullOrEmpty(empty) _
            AndAlso String.IsNullOrWhiteSpace(nullString) AndAlso String.IsNullOrWhiteSpace(empty) _
            AndAlso String.IsNullOrWhiteSpace(whitespace) Then
            Console.WriteLine("Strings are null, empty or whitespace")
        End If

        'append a byte
        x = "helloworld"
        x += Chr(83)
        Console.WriteLine(x)

        'substring
        Dim slice = x.Substring(5, 5)
        Console.WriteLine(slice)

        'replace bytes
        Dim greeting = x.Replace("worldS", "")
        Console.WriteLine(greeting)

        'join strings
        Dim join = greeting + " " + slice
        Console.WriteLine(join)
    End Sub

End Module


// create string
var s = "abc"

// destroy string (not really see notes above)
s = null

// (re)assignment
s = "def"

// comparison (only == && != supported directly)
var b = (s == "abc")  // false

// cloning/copying
var t = s

// check if empty
s = ""
b = (s != "")  // false
b = s.isEmpty  // true

// append a byte
s = s + "b"

// extract a substring
s = "ghijkl"
t = s[1..4]   // "hijk"

// replace a byte or string
s = "abracadabra"
s = s.replace("a", "z")  // "zbrzczdzbrz"

// join strings
s = "abc"
t = "def"
var u = s + t  // "abcdef"


Data(0,.Int,1,2,3) // bytes
Data(0,String,1,2,3) // same
Data(0,Int,"foo","bar") //-->foobar\0
d:=Data(0,String,"foo","bar") //-->foo\0bar\0\0
d==d // -->True: byte by byte comparison
d.copy()  //-->clone
d.len()  //-->8, 0 if empty

d.append("1").len(); //-->10  // or d+"1"
Data(0,Int,"foo","bar").len() //-->6
Data(0,Int,"foo","bar").append("1").len() //-->7

d.readString(4)    //-->"bar"
d.readNthString(2) //-->"1"
d[2,4]             //-->"o", really "o\0ba" but String sees the null

while(Void!=(n:=d.findString("bar"))){ d[n,4]="hoho" }
d.bytes() //-->L(102,111,111,0,104,111,104,111,0,49,0)

d2:=Data(0,Int,"sam");
d.append(d2).text // or d+d2


WITH GMP.Rationals, GMP.Integers, Ada.Text_IO, Ada.Strings.Fixed, Ada.Strings;
USE GMP.Rationals, GMP.Integers, Ada.Text_IO, Ada.Strings.Fixed, Ada.Strings;

PROCEDURE Main IS

   FUNCTION Bernoulli_Number (N : Natural) RETURN Unbounded_Fraction IS
      FUNCTION "/" (Left, Right : Natural) RETURN Unbounded_Fraction IS
        (To_Unbounded_Integer (Left) / To_Unbounded_Integer (Right));
      A : ARRAY (0 .. N) OF Unbounded_Fraction;
   BEGIN
      FOR M IN 0 .. N LOOP
         A (M) := 1 / (M + 1);
         FOR J IN REVERSE 1 .. M LOOP
            A (J - 1) := (J / 1 ) * (A (J - 1) - A (J));
         END LOOP;
      END LOOP;
      RETURN A (0);
   END Bernoulli_Number;

BEGIN
   FOR I IN 0 .. 60 LOOP
      IF I MOD 2 = 0 OR I = 1 THEN
         DECLARE
            B : Unbounded_Fraction := Bernoulli_Number (I);
            S : String := Image (GMP.Rationals.Numerator (B));
         BEGIN
            Put_Line ("B (" & (IF I < 10 THEN " " ELSE "") &  Trim (I'Img, Left)
                      & ")=" & (44 - S'Length) * " " & Image (B));
         END;
      END IF;
   END LOOP;
END Main;


BEGIN
    # Show Bernoulli numbers B0 to B60 as rational numbers           #

    # Uses code from the Arithmetic/Rational task modified to use    #
    # LONG LONG INT to allow for the large number of digits requried #

    PR precision 100 PR # sets the precision of LONG LONG INT        #

    # Code from the Arithmetic/Rational task                         #
    # ============================================================== #

    MODE FRAC = STRUCT( LONG LONG INT num #erator#,  den #ominator#);

    PROC gcd = (LONG LONG INT a, b) LONG LONG INT: # greatest common divisor #
       (a = 0 | b |: b = 0 | a |: ABS a > ABS b  | gcd(b, a MOD b) | gcd(a, b MOD a));

    PROC lcm = (LONG LONG INT a, b)LONG LONG INT: # least common multiple #
       a OVER gcd(a, b) * b;

    PRIO // = 9; # higher then the ** operator #
    OP // = (LONG LONG INT num, den)FRAC: ( # initialise and normalise #
       LONG LONG INT common = gcd(num, den);
       IF den < 0 THEN
         ( -num OVER common, -den OVER common)
       ELSE
         ( num OVER common, den OVER common)
       FI
     );

    OP + = (FRAC a, b)FRAC: (
       LONG LONG INT common = lcm(den OF a, den OF b);
       FRAC result := ( common OVER den OF a * num OF a + common OVER den OF b * num OF b, common );
       num OF result//den OF result
    );

    OP - = (FRAC a, b)FRAC: a + -b,
       * = (FRAC a, b)FRAC: (
           LONG LONG INT num = num OF a * num OF b,
           den = den OF a * den OF b;
           LONG LONG INT common = gcd(num, den);
           (num OVER common) // (den OVER common)
         );

    OP - = (FRAC frac)FRAC: (-num OF frac, den OF frac);

    # ============================================================== #
    # end code from the Arithmetic/Rational task                     #

    # Additional FRACrelated operators                               #
    OP *  = ( INT a, FRAC b )FRAC: ( num OF b * a ) // den OF b;
    OP // = ( INT a, INT  b )FRAC: LONG LONG INT( a ) // LONG LONG INT( b );

    # returns the nth Bernoulli number, n must be >= 0               #
    # Uses the algorithm suggested by the task, so B(1) is +1/2      #
    PROC bernoulli = ( INT n )FRAC:
         IF n < 0
         THEN # n is out of range # 0 // 1
         ELSE # n is valid        #
            [ 0 : n ]FRAC a;
            FOR i FROM LWB a TO UPB a DO a[ i ] := 0 // 1 OD;
            FOR m FROM 0 TO n DO
                a[ m ] := 1 // ( m + 1 );
                FOR j FROM m BY -1 TO 1 DO
                    a[ j - 1 ] := j * ( a[ j - 1 ] - a[ j ] )
                OD
            OD;
            a[ 0 ]
         FI # bernoulli # ;

    FOR n FROM 0 TO 60 DO
        FRAC bn := bernoulli( n );
        IF num OF bn /= 0 THEN
            # have a non-0 Bn #
            print( ( "B(", whole( n, -2 ), ") ", whole( num OF bn, -50 ), " / ", whole( den OF bn, 0 ), newline ) )
        FI
    OD
END


  ( BernoulliList
  =     B Bs answer indLn indexLen indexPadding
      , n numberPadding p solPos solidusPos sp
    .   ( B
        =   m A a j b
          .   -1:?m
            & :?A
            &   whl
              ' ( 1+!m:~>!arg:?m
                &     ((!m+1:?j)^-1:?a)
                        map
                      $ ( (
                          = .(-1+!j:?j)*(!arg+-1*!a):?a
                          )
                        . !A
                        )
                  : ?A
                )
            & !A:? @?b
            & !b
        )
      & -1:?n
      & :?Bs
      &   whl
        ' ( 1+!n:~>!arg:?n
          & B$!n !Bs:?Bs
          )
      & @(!arg:? [?indexLen)
      & 1+!indexLen:?indexLen
      & !Bs:%@(?:? "/" [?solidusPos ?) ?
      & 1+!solidusPos:?solidusPos:?p
      & :?sp
      &   whl
        ' (!p+-1:~<0:?p&" " !sp:?sp)
      & :?answer
      &   whl
        ' ( !Bs:%?B ?Bs
          & ( !B:0
            |   (!B:/|str$(!B "/1"):?B)
              & @(!B:? "/" [?solPos ?)
              & @(!arg:? [?indLn)
              &   !sp
                : ? [(-1*!indexLen+!indLn) ?indexPadding
                : ? [(-1*!solidusPos+!solPos) ?numberPadding
              &     "B("
                    !arg
                    ")="
                    !indexPadding
                    !numberPadding
                    (!B:>0&" "|)
                    !B
                    \n
                    !answer
                : ?answer
            )
          & -1+!arg:?arg
          )
      & str$!answer
  )
& BernoulliList$60;


#include <stdlib.h>
#include <gmp.h>

#define mpq_for(buf, op, n)\
    do {\
        size_t i;\
        for (i = 0; i < (n); ++i)\
            mpq_##op(buf[i]);\
    } while (0)

void bernoulli(mpq_t rop, unsigned int n)
{
    unsigned int m, j;
    mpq_t *a = malloc(sizeof(mpq_t) * (n + 1));
    mpq_for(a, init, n + 1);

    for (m = 0; m <= n; ++m) {
        mpq_set_ui(a[m], 1, m + 1);
        for (j = m; j > 0; --j) {
            mpq_sub(a[j-1], a[j], a[j-1]);
            mpq_set_ui(rop, j, 1);
            mpq_mul(a[j-1], a[j-1], rop);
        }
    }

    mpq_set(rop, a[0]);
    mpq_for(a, clear, n + 1);
    free(a);
}

int main(void)
{
    mpq_t rop;
    mpz_t n, d;
    mpq_init(rop);
    mpz_inits(n, d, NULL);

    unsigned int i;
    for (i = 0; i <= 60; ++i) {
        bernoulli(rop, i);
        if (mpq_cmp_ui(rop, 0, 1)) {
            mpq_get_num(n, rop);
            mpq_get_den(d, rop);
            gmp_printf("B(%-2u) = %44Zd / %Zd\n", i, n, d);
        }
    }

    mpz_clears(n, d, NULL);
    mpq_clear(rop);
    return 0;
}


using Mpir.NET;
using System;

namespace Bernoulli
{
    class Program
    {
        private static void bernoulli(mpq_t rop, uint n)
        {
            mpq_t[] a = new mpq_t[n + 1];

            for (uint i = 0; i < n + 1; i++)
            {
                a[i] = new mpq_t();
            }

            for (uint m = 0; m <= n; ++m)
            {
                mpir.mpq_set_ui(a[m], 1, m + 1);

                for (uint j = m; j > 0; --j)
                {
                    mpir.mpq_sub(a[j - 1], a[j], a[j - 1]);
                    mpir.mpq_set_ui(rop, j, 1);
                    mpir.mpq_mul(a[j - 1], a[j - 1], rop);
                }

                mpir.mpq_set(rop, a[0]);
            }
        }

        static void Main(string[] args)
        {
            mpq_t rop = new mpq_t();
            mpz_t n = new mpz_t();
            mpz_t d = new mpz_t();

            for (uint  i = 0; i <= 60; ++i)
            {
                bernoulli(rop, i);

                if (mpir.mpq_cmp_ui(rop, 0, 1) != 0)
                {
                    mpir.mpq_get_num(n, rop);
                    mpir.mpq_get_den(d, rop);
                    Console.WriteLine(string.Format("B({0, 2}) = {1, 44} / {2}", i, n, d));
                }
            }

            Console.ReadKey();
        }
    }
}


/**
 * Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
 * Apple LLVM version 9.1.0 (clang-902.0.39.1)
 * Target: x86_64-apple-darwin17.5.0
 * Thread model: posix
*/

#include <boost/multiprecision/cpp_int.hpp>  // 1024bit precision
#include <boost/rational.hpp>                // Rationals
#include <iostream>                          // formatting with std::cout
#include <vector>                            // Container

typedef boost::rational<boost::multiprecision::int1024_t> rational;  // reduce boilerplate

rational bernoulli(size_t n) {
    auto out = std::vector<rational>();

    for (size_t m = 0; m <= n; m++) {
        out.emplace_back(1, (m + 1));  // automatically constructs object
        for (size_t j = m; j >= 1; j--) {
            out[j - 1] = rational(j) * (out[j - 1] - out[j]);
        }
    }
    return out[0];
}

int main() {
    for (size_t n = 0; n <= 60; n += n >= 2 ? 2 : 1) {
        auto b = bernoulli(n);
        std::cout << "B(" << std::right << std::setw(2) << n << ") = ";
        std::cout << std::right << std::setw(44) << b.numerator();
        std::cout << " / " << b.denominator() << std::endl;
    }

    return 0;
}


ns test-project-intellij.core
  (:gen-class))

(defn a-t [n]
  " Used Akiyama-Tanigawa algorithm with a single loop rather than double nested loop "
  " Clojure does fractional arithmetic automatically so that part is easy "
  (loop [m 0
         j m
         A (vec (map #(/ 1 %) (range 1 (+ n 2))))] ; Prefil A(m) with 1/(m+1), for m = 1 to n
    (cond                                          ; Three way conditional allows single loop
      (>= j 1) (recur m (dec j) (assoc A (dec j) (* j (- (nth A (dec j)) (nth A j))))) ; A[j-1] ← j×(A[j-1] - A[j]) ;
      (< m n) (recur (inc m) (inc m) A)                                                 ; increment m, reset j = m
      :else (nth A 0))))

(defn format-ans [ans]
  " Formats answer so that '/' is aligned for all answers "
  (if (= ans 1)
  (format "%50d / %8d" 1 1)
  (format "%50d / %8d" (numerator ans) (denominator ans))))

;; Generate a set of results for [0 1 2 4 ... 60]
(doseq [q (flatten [0 1 (range 2 62 2)])
        :let [ans (a-t q)]]
  (println q ":" (format-ans ans)))


(defun bernouilli (n)
  (loop with a = (make-array (list (1+ n)))
     for m from 0 to n do
       (setf (aref a m) (/ 1 (+ m 1)))
       (loop for j from m downto 1 do
            (setf (aref a (- j 1))
                  (* j (- (aref a j) (aref a (- j 1))))))
     finally (return (aref a 0))))

;;Print outputs to stdout:

(loop for n from 0 to 60 do
     (let ((b (bernouilli n)))
       (when (not (zerop b))
         (format t "~a: ~a~%" n b))))

;;For the "extra credit" challenge, we need to align the slashes.

(let (results)
  ;;collect the results
  (loop for n from 0 to 60 do
       (let ((b (bernouilli n)))
         (when (not (zerop b)) (push (cons b n) results))))
  ;;parse the numerators into strings; save the greatest length in max-length
  (let ((max-length (apply #'max (mapcar (lambda (r)
                                           (length (format nil "~a" (numerator r))))
                                         (mapcar #'car results)))))
    ;;Print the numbers with using the fixed-width formatter: ~Nd, where N is
    ;;the number of leading spaces. We can't just pass in the width variable
    ;;but we can splice together a formatting string that includes it.

    ;;We also can't use the fixed-width formatter on a ratio, so we have to split
    ;;the ratio and splice it back together like idiots.
    (loop for n in (mapcar #'cdr (reverse results))
          for r in (mapcar #'car (reverse results)) do
         (format t (concatenate 'string
                                "B(~2d): ~"
                                (format nil "~a" max-length)
                                "d/~a~%")
                 n
                 (numerator r)
                 (denominator r)))))


require "big"

class Bernoulli
  include Iterator(Tuple(Int32, BigRational))

  def initialize
    @a = [] of BigRational
    @m = 0
  end

  def next
    @a << BigRational.new(1, @m+1)
    @m.downto(1) { |j| @a[j-1] = j*(@a[j-1] - @a[j]) }
    v = @m.odd? && @m != 1 ? BigRational.new(0, 1) : @a.first
    return {@m, v}
  ensure
    @m += 1
  end
end

b = Bernoulli.new
bn = b.first(61).to_a

max_width = bn.map { |_, v| v.numerator.to_s.size }.max
bn.reject { |i, v| v.zero? }.each do |i, v|
  puts "B(%2i) = %*i/%i" % [i, max_width, v.numerator, v.denominator]
end


import std.stdio, std.range, std.algorithm, std.conv, arithmetic_rational;

auto bernoulli(in uint n) pure nothrow /*@safe*/ {
    auto A = new Rational[n + 1];
    foreach (immutable m; 0 .. n + 1) {
        A[m] = Rational(1, m + 1);
        foreach_reverse (immutable j; 1 .. m + 1)
            A[j - 1] = j * (A[j - 1] - A[j]);
    }
    return A[0];
}

void main() {
    immutable berns = 61.iota.map!bernoulli.enumerate.filter!(t => t[1]).array;
    immutable width = berns.map!(b => b[1].numerator.text.length).reduce!max;
    foreach (immutable b; berns)
        writefln("B(%2d) = %*d/%d", b[0], width, b[1].tupleof);
}


program Bernoulli_numbers;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  Velthuis.BigRationals;

function b(n: Integer): BigRational;
begin
  var a: TArray<BigRational>;
  SetLength(a, n + 1);
  for var m := 0 to High(a) do
  begin
    a[m] := BigRational.Create(1, m + 1);
    for var j := m downto 1 do
    begin
      a[j - 1] := (a[j - 1] - a[j]) * j;
    end;
  end;
  Result := a[0];
end;

begin
  for var n := 0 to 60 do
  begin
    var bb := b(n);
    if bb.Numerator.BitLength > 0 then
      writeln(format('B(%2d) =%45s/%s', [n, bb.Numerator.ToString, bb.Denominator.ToString]));
  end;
  readln;
end.


(lib 'bigint) ;; lerge numbers
(lib 'gloops) ;; classes

(define-class Rational null ((a :initform #0) (b :initform #1)))
(define-method tostring  (Rational) (lambda (r) (format "%50d / %d" r.a r.b)))
(define-method normalize (Rational) (lambda (r) ;; divide a and b by gcd
		 (let ((g (gcd r.a r.b)))
		 (set! r.a (/ r.a g)) (set! r.b (/ r.b g))
 		 (when (< r.b 0) (set! r.a ( - r.a)) (set! r.b (- r.b))) ;; denominator > 0
 		r)))

(define-method initialize (Rational) (lambda (r) (normalize r)))
(define-method add (Rational) (lambda (r n)  ;; + Rational any number
			(normalize (Rational (+ (* (+ #0 n) r.b) r.a) r.b))))
(define-method add (Rational Rational) (lambda (r q) ;;; + Rational Rational
			(normalize (Rational (+ (* r.a q.b) (* r.b q.a)) (* r.b q.b)))))
(define-method sub (Rational Rational) (lambda (r q)
			(normalize (Rational (- (* r.a q.b) (* r.b q.a)) (* r.b q.b)))))
(define-method mul (Rational Rational) (lambda (r q)
			(normalize (Rational  (* r.a q.a)  (* r.b q.b)))))
(define-method mul (Rational) (lambda (r n)
			(normalize (Rational  (* r.a (+ #0 n))  r.b ))))
(define-method div (Rational Rational) (lambda (r q)
			(normalize (Rational  (* r.a q.b)  (* r.b q.a)))))


defmodule Bernoulli do
  defmodule Rational do
    import Kernel, except: [div: 2]

    defstruct numerator: 0, denominator: 1

    def new(numerator, denominator\\1) do
      sign = if numerator * denominator < 0, do: -1, else: 1
      {numerator, denominator} = {abs(numerator), abs(denominator)}
      gcd = gcd(numerator, denominator)
      %Rational{numerator: sign * Kernel.div(numerator, gcd),
                denominator: Kernel.div(denominator, gcd)}
    end

    def sub(a, b) do
      new(a.numerator * b.denominator - b.numerator * a.denominator,
          a.denominator * b.denominator)
    end

    def mul(a, b) when is_integer(a) do
      new(a * b.numerator, b.denominator)
    end

    defp gcd(a,0), do: a
    defp gcd(a,b), do: gcd(b, rem(a,b))
  end

  def numbers(n) do
    Stream.transform(0..n, {}, fn m,acc ->
      acc = Tuple.append(acc, Rational.new(1,m+1))
      if m>0 do
        new =
          Enum.reduce(m..1, acc, fn j,ar ->
            put_elem(ar, j-1, Rational.mul(j, Rational.sub(elem(ar,j-1), elem(ar,j))))
          end)
        {[elem(new,0)], new}
      else
        {[elem(acc,0)], acc}
      end
    end) |> Enum.to_list
  end

  def task(n \\ 61) do
    b_nums = numbers(n)
    width  = Enum.map(b_nums, fn b -> b.numerator |> to_string |> String.length end)
             |> Enum.max
    format = 'B(~2w) = ~#{width}w / ~w~n'
    Enum.with_index(b_nums)
    |> Enum.each(fn {b,i} ->
         if b.numerator != 0, do: :io.fwrite format, [i, b.numerator, b.denominator]
       end)
  end
end

Bernoulli.task


open MathNet.Numerics
open System
open System.Collections.Generic

let calculateBernoulli n =
    let ℚ(x) = BigRational.FromInt x
    let A = Array.init<BigRational> (n+1) (fun x -> ℚ(x+1))

    for m in [1..n] do
        A.[m] <- ℚ(1) / (ℚ(m) + ℚ(1))
        for j in [m..(-1)..1] do
            A.[j-1] <- ℚ(j) * (A.[j-1] - A.[j])
    A.[0]

[<EntryPoint>]
let main argv =
    for n in [0..60] do
        let bernoulliNumber = calculateBernoulli n
        match bernoulliNumber.Numerator.IsZero with
        | false ->
            let formatedString = String.Format("B({0, 2}) = {1, 44} / {2}", n, bernoulliNumber.Numerator, bernoulliNumber.Denominator)
            printfn "%s" formatedString
        | true ->
            printf ""
    0


Func Bern(m) = Sigma<k=0,m>[Sigma<v=0,k>[(-1)^v*Bin(k,v)*(v+1)^m/(k+1)]].;
for i=0, 60 do b:=Bern(i); if b<>0 then !!(i,b) fi od;


' version 08-10-2016
' compile with: fbc -s console
' uses gmp

#Include Once "gmp.bi"

#Define max 60

Dim As Long n
Dim As ZString Ptr gmp_str :gmp_str = Allocate(1000) ' 1000 char
Dim Shared As Mpq_ptr tmp, big_j
tmp = Allocate(Len(__mpq_struct)) :Mpq_init(tmp)
big_j = Allocate(Len(__mpq_struct)) :Mpq_init(big_j)

Dim Shared As Mpq_ptr a(max), b(max)
For n = 0 To max
  A(n) = Allocate(Len(__mpq_struct)) :Mpq_init(A(n))
  B(n) = Allocate(Len(__mpq_struct)) :Mpq_init(B(n))
Next

Function Bernoulli(n As Integer) As Mpq_ptr

  Dim As Long m, j

  For m = 0 To n
    Mpq_set_ui(A(m), 1, m + 1)
    For j = m To 1 Step - 1
      Mpq_sub(tmp, A(j - 1), A(j))
      Mpq_set_ui(big_j, j, 1)                 'big_j = j
      Mpq_mul(A(j - 1), big_j, tmp)
    Next
  Next

  Return A(0)
End Function

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

For n = 0 To max
  Mpq_set(B(n), Bernoulli(n))
  Mpq_get_str(gmp_str, 10, B(n))
  If *gmp_str <> "0" Then
    If *gmp_str = "1" Then *gmp_str = "1/1"
    Print Using "B(##) = "; n;
    Print Space(45 - InStr(*gmp_str, "/")); *gmp_str
  End If
Next

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


BernoulliNumber[n] :=
{
   a = new array
   for m = 0 to n
   {
      [email protected] = 1/(m+1)
      for j = m to 1 step -1
         [email protected](j-1) = j * ([email protected](j-1) - [email protected])
   }

   return [email protected]
}

result = new array
for n=0 to 60
{
   b = BernoulliNumber[n]
   if b != 0
   {
      [num,den] = numeratorDenominator[b]
      result.push[[n, num, "/", den]]
   }
}

println[formatTable[result, "right"]]


import integers.choose

def B( n ) = sum( 1/(k + 1)*sum((if 2|r then 1 else -1)*choose(k, r)*(r^n) | r <- 0..k) | k <- 0..n )

for i <- 0..60 if i == 1 or 2|i
  printf( "B(%2d) = %s\n", i, B(i) )


package main

import (
	"fmt"
	"math/big"
)

func b(n int) *big.Rat {
	var f big.Rat
	a := make([]big.Rat, n+1)
	for m := range a {
		a[m].SetFrac64(1, int64(m+1))
		for j := m; j >= 1; j-- {
			d := &a[j-1]
			d.Mul(f.SetInt64(int64(j)), d.Sub(d, &a[j]))
		}
	}
	return f.Set(&a[0])
}

func main() {
	for n := 0; n <= 60; n++ {
		if b := b(n); b.Num().BitLen() > 0 {
			fmt.Printf("B(%2d) =%45s/%s\n", n, b.Num(), b.Denom())
		}
	}
}


import Data.Ratio
import System.Environment

main = getArgs >>= printM . defaultArg
  where
    defaultArg as =
      if null as
        then 60
        else read (head as)

printM m =
  mapM_ (putStrLn . printP) .
  takeWhile ((<= m) . fst) . filter (\(_, b) -> b /= 0 % 1) . zip [0 ..] $
  bernoullis

printP (i, r) =
  "B(" ++ show i ++ ") = " ++ show (numerator r) ++ "/" ++ show (denominator r)

bernoullis = map head . iterate (ulli 1) . map berno $ enumFrom 0
  where
    berno i = 1 % (i + 1)
    ulli _ [_] = []
    ulli i (x:y:xs) = (i % 1) * (x - y) : ulli (i + 1) (y : xs)


link "rational"

procedure main(args)
    limit := integer(!args) | 60
    every b := bernoulli(i := 0 to limit) do
        if b.numer > 0 then write(right(i,3),": ",align(rat2str(b),60))
end

procedure bernoulli(n)
    (A := table(0))[0] := rational(1,1,1)
    every m := 1 to n do {
        A[m] := rational(1,m+1,1)
        every j := m to 1 by -1 do A[j-1] := mpyrat(rational(j,1,1), subrat(A[j-1],A[j]))
        }
    return A[0]
end

procedure align(r,n)
    return repl(" ",n-find("/",r))||r
end