import std.stdio;

void main() {
    auto isins = [
        "US0378331005",
        "US0373831005",
        "U50378331005",
        "US03378331005",
        "AU0000XVGZA3",
        "AU0000VXGZA3",
        "FR0000988040",
    ];
    foreach (isin; isins) {
        writeln(isin, " is ", ISINvalidate(isin) ? "valid" : "not valid");
    }
}

bool ISINvalidate(string isin) {
    import std.array : appender;
    import std.conv : to;
    import std.regex : matchFirst;
    import std.string : strip, toUpper;

    isin = isin.strip.toUpper;

    if (isin.matchFirst(`^[A-Z]{2}[A-Z0-9]{9}\d$`).empty) {
        return false;
    }

    auto sb = appender!string;
    foreach (c; isin[0..12]) {
        sb.put(
            [c].to!int(36)
               .to!string
        );
    }

    import luhn;
    return luhnTest(sb.data);
}


include ..\Utilitys.pmt

( 3 4 5 ) var vectorA
( 4 3 5 ) var vectorB
( -5 -12 -13 ) var vectorC

def dotProduct  /# x y -- n #/
    0 >ps
    len for var i
        i get rot i get rot * ps> + >ps
    endfor
    drop drop
    ps>
enddef

def crossProduct    /# x y -- z #/
    1 get rot 2 get rot * >ps
    1 get rot 2 get rot * >ps
    3 get rot 1 get rot * >ps
    3 get rot 1 get rot * >ps
    2 get rot 3 get rot * >ps
    2 get rot 3 get rot * ps> - ps> ps> - ps> ps> - 3 tolist
    nip nip
enddef

"Dot Product = " print vectorA vectorB dotProduct ?
"Cross Product = " print vectorA vectorB crossProduct ?
"Scalar Triple Product = " print vectorB vectorC crossProduct vectorA swap dotProduct ?
"Vector Triple Product = " print vectorB vectorC crossProduct vectorA swap crossProduct ?


<?php

class Vector
{
	private $values;

	public function setValues(array $values)
	{
		if (count($values) != 3)
			throw new Exception('Values must contain exactly 3 values');
		foreach ($values as $value)
			if (!is_int($value) && !is_float($value))
				throw new Exception('Value "' . $value . '" has an invalid type');
		$this->values = $values;
	}

	public function getValues()
	{
		if ($this->values == null)
			$this->setValues(array (
					0,
					0,
					0
			));
		return $this->values;
	}

	public function Vector(array $values)
	{
		$this->setValues($values);
	}

	public static function dotProduct(Vector $va, Vector $vb)
	{
		$a = $va->getValues();
		$b = $vb->getValues();
		return ($a[0] * $b[0]) + ($a[1] * $b[1]) + ($a[2] * $b[2]);
	}

	public static function crossProduct(Vector $va, Vector $vb)
	{
		$a = $va->getValues();
		$b = $vb->getValues();
		return new Vector(array (
				($a[1] * $b[2]) - ($a[2] * $b[1]),
				($a[2] * $b[0]) - ($a[0] * $b[2]),
				($a[0] * $b[1]) - ($a[1] * $b[0])
		));
	}

	public static function scalarTripleProduct(Vector $va, Vector $vb, Vector $vc)
	{
		return self::dotProduct($va, self::crossProduct($vb, $vc));
	}

	public static function vectorTrippleProduct(Vector $va, Vector $vb, Vector $vc)
	{
		return self::crossProduct($va, self::crossProduct($vb, $vc));
	}
}

class Program
{

	public function Program()
	{
		$a = array (
				3,
				4,
				5
		);
		$b = array (
				4,
				3,
				5
		);
		$c = array (
				-5,
				-12,
				-13
		);
		$va = new Vector($a);
		$vb = new Vector($b);
		$vc = new Vector($c);

		$result1 = Vector::dotProduct($va, $vb);
		$result2 = Vector::crossProduct($va, $vb)->getValues();
		$result3 = Vector::scalarTripleProduct($va, $vb, $vc);
		$result4 = Vector::vectorTrippleProduct($va, $vb, $vc)->getValues();

		printf("\n");
		printf("A = (%0.2f, %0.2f, %0.2f)\n", $a[0], $a[1], $a[2]);
		printf("B = (%0.2f, %0.2f, %0.2f)\n", $b[0], $b[1], $b[2]);
		printf("C = (%0.2f, %0.2f, %0.2f)\n", $c[0], $c[1], $c[2]);
		printf("\n");
		printf("A · B = %0.2f\n", $result1);
		printf("A × B = (%0.2f, %0.2f, %0.2f)\n", $result2[0], $result2[1], $result2[2]);
		printf("A · (B × C) = %0.2f\n", $result3);
		printf("A × (B × C) =(%0.2f, %0.2f, %0.2f)\n", $result4[0], $result4[1], $result4[2]);
	}
}

new Program();
?>


func is_vampire (n) {
    return [] if n.ilog10.is_even

    var l1 = n.isqrt.ilog10.ipow10
    var l2 = n.isqrt

    var s = n.digits.sort.join

    gather {
        n.divisors.each { |d|

            d < l1 && next
            d > l2 && break

            var t = n/d

            next if (d%%10 && t%%10)
            next if ("#{d}#{t}".sort != s)

            take([d, t])
        }
    }
}

say "First 25 Vampire Numbers:"

with (1) { |i|
    for (var n = 1; i <= 25; ++n) {
        var fangs = is_vampire(n)
        printf("%2d. %6s : %s\n", i++, n, fangs.join(' ')) if fangs
    }
}

say "\nIndividual tests:"

[16758243290880, 24959017348650, 14593825548650].each { |n|
    var fangs = is_vampire(n)
    say "#{n}: #{fangs ? fangs.join(', ') : 'is not a vampire number'}"
}


import Foundation

func vampire<T>(n: T) -> [(T, T)] where T: BinaryInteger, T.Stride: SignedInteger {
  let strN = String(n).sorted()
  let fangLength = strN.count / 2
  let start = T(pow(10, Double(fangLength - 1)))
  let end = T(Double(n).squareRoot())

  var fangs = [(T, T)]()

  for i in start...end where n % i == 0 {
    let quot = n / i

    guard i % 10 != 0 || quot % 10 != 0 else {
      continue
    }

    if "\(i)\(quot)".sorted() == strN {
      fangs.append((i, quot))
    }
  }

  return fangs
}

var count = 0
var i = 1.0

while count < 25 {
  let start = Int(pow(10, i))
  let end = start * 10

  for num in start...end {
    let fangs = vampire(n: num)

    guard !fangs.isEmpty else { continue }

    count += 1

    print("\(num) is a vampire number with fangs: \(fangs)")

    guard count != 25 else { break }
  }

  i += 2
}

for (vamp, fangs) in [16758243290880, 24959017348650, 14593825548650].lazy.map({ ($0, vampire(n: $0)) }) {
  if fangs.isEmpty {
    print("\(vamp) is not a vampire number")
  } else {
    print("\(vamp) is a vampire number with fangs: \(fangs)")
  }
}


proc factorPairs {n {from 2}} {
    set result [list 1 $n]
    if {$from<=1} {set from 2}
    for {set i $from} {$i<=sqrt($n)} {incr i} {
	if {$n%$i} {} {lappend result $i [expr {$n/$i}]}
    }
    return $result
}

proc vampireFactors {n} {
    if {[string length $n]%2} return
    set half [expr {[string length $n]/2}]
    set digits [lsort [split $n ""]]
    set result {}
    foreach {a b} [factorPairs $n [expr {10**$half/10}]] {
	if {
	    [string length $a]==$half && [string length $b]==$half &&
	    ($a%10 || $b%10) && $digits eq [lsort [split $a$b ""]]
	} then {
	    lappend result [list $a $b]
	}
    }
    return $result
}


isin? = fn str ->
          if str =~ ~r/\A[A-Z]{2}[A-Z0-9]{9}\d\z/ do
            String.codepoints(str)
            |> Enum.map_join(&String.to_integer(&1, 36))
            |> Luhn.valid?
          else
            false
          end
        end

IO.puts "    ISIN        Valid?"
~w(US0378331005
   US0373831005
   U50378331005
   US03378331005
   AU0000XVGZA3
   AU0000VXGZA3
   FR0000988040)
|> Enum.each(&IO.puts "#{&1}\t#{isin?.(&1)}")


USING: combinators.short-circuit.smart formatting kernel luhn
math math.parser qw sequences strings unicode ;
IN: rosetta-code.isin

CONSTANT: test-cases qw{
    US0378331005 US0373831005 U50378331005 US03378331005
    AU0000XVGZA3 AU0000VXGZA3 FR0000988040
}

: valid-length? ( str -- ? ) length 12 = ;

: valid-country-code? ( str -- ? ) first2 [ Letter? ] both? ;

: valid-security-code? ( str -- ? )
    [ 2 11 ] dip subseq [ alpha? ] all? ;

: valid-checksum-digit? ( str -- ? ) last digit? ;

: valid-format? ( str -- ? ) {
        [ valid-length?         ]
        [ valid-country-code?   ]
        [ valid-security-code?  ]
        [ valid-checksum-digit? ]
    } && ;

: base36>base10 ( str -- n )
    >upper [ dup LETTER? [ 55 - number>string ] [ 1string ] if ]
    { } map-as concat string>number ;

: isin? ( str -- ? )
    { [ valid-format? ] [ base36>base10 luhn? ] } && ;

: main ( -- )
    test-cases [
        dup isin? "" " not" ? "%s is%s valid\n" printf
    ] each ;

MAIN: main


program isin
    use ctype
    implicit none
    character(20) :: test(7) = ["US0378331005        ", &
                                "US0373831005        ", &
                                "U50378331005        ", &
                                "US03378331005       ", &
                                "AU0000XVGZA3        ", &
                                "AU0000VXGZA3        ", &
                                "FR0000988040        "]
    print *, check_isin(test)
contains
    elemental logical function check_isin(a)
        character(*), intent(in) :: a
        integer :: s(24)
        integer :: i, j, k, n, v

        check_isin = .false.

        n = len_trim(a)
        if (n /= 12) return

        ! Convert to an array of digits
        j = 0
        do i = 1, n
            k = iachar(a(i:i))
            if (k >= 48 .and. k <= 57) then
                if (i < 3) return
                k = k - 48
                j = j + 1
                s(j) = k
            else if (k >= 65 .and. k <= 90) then
                if (i == 12) return
                k = k - 65 + 10
                j = j + 1
                s(j) = k / 10
                j = j + 1
                s(j) = mod(k, 10)
            else
                return
            end if
        end do

        ! Compute checksum
        v = 0
        do i = j - 1, 1, -2
            k = 2 * s(i)
            if (k > 9) k = k - 9
            v = v + k
        end do
        do i = j, 1, -2
            v = v + s(i)
        end do

        check_isin = 0 == mod(v, 10)
    end function
end program


go =>
  A = [3, 4, 5],
  B = [4, 3, 5],
  C = [-5, -12, -13],

  println(a=A),
  println(b=B),
  println(c=C),
  println("A . B"=dot(A,B)),
  println("A x B"=cross(A,B)),
  println("A . (B x C)"=scalar_triple(A,B,C)),
  println("A X (B X C)"=vector_triple(A,B,C)),
  nl.

dot(A,B)   = sum([ AA*BB : {AA,BB} in zip(A,B)]).
cross(A,B) = [A[2]*B[3]-A[3]*B[2], A[3]*B[1]-A[1]*B[3], A[1]*B[2]-A[2]*B[1]].

scalar_triple(A,B,C) = dot(A,cross(B,C)).
vector_triple(A,B,C) = cross(A,cross(B,C)).


(de dotProduct (A B)
   (sum * A B) )

(de crossProduct (A B)
   (list
      (- (* (cadr A) (caddr B)) (* (caddr A) (cadr B)))
      (- (* (caddr A) (car B)) (* (car A) (caddr B)))
      (- (* (car A) (cadr B)) (* (cadr A) (car B))) ) )

(de scalarTriple (A B C)
   (dotProduct A (crossProduct B C)) )

(de vectorTriple (A B C)
   (crossProduct A (crossProduct B C)) )


/* dot product, cross product, etc.                  4 June 2011 */

test_products: procedure options (main);

   declare a(3) fixed initial (3, 4, 5);
   declare b(3) fixed initial (4, 3, 5);
   declare c(3) fixed initial (-5, -12, -13);
   declare e(3) fixed;

   put skip list ('a . b =', dot_product(a, b));
   call cross_product(a, b, e);  put skip list ('a x b =', e);
   put skip list ('a . (b x c) =',  scalar_triple_product(a, b, c));
   call vector_triple_product(a, b, c, e); put skip list ('a x (b x c) =', e);

dot_product: procedure (a, b) returns (fixed);
   declare (a, b) (*) fixed;
   return (sum(a*b));
end dot_product;

cross_product: procedure (a, b, c);
   declare (a, b, c) (*) fixed;
   c(1) = a(2)*b(3) - a(3)*b(2);
   c(2) = a(3)*b(1) - a(1)*b(3);
   c(3) = a(1)*b(2) - a(2)*b(1);
end cross_product;

scalar_triple_product: procedure (a, b, c) returns (fixed);
   declare (a, b, c)(*) fixed;
   declare t(hbound(a, 1)) fixed;
   call cross_product(b, c, t);
   return (dot_product(a, t));
end scalar_triple_product;

vector_triple_product: procedure (a, b, c, e);
   declare (a, b, c, e)(*) fixed;
   declare t(hbound(a,1))  fixed;
   call cross_product(b, c, t);
   call cross_product(a, t, e);
end vector_triple_product;

end test_products;


import math
fn max(a u64, b u64) u64 {
    if a > b {
        return a
    }
    return b
}

fn min(a u64, b u64) u64 {
    if a < b {
        return a
    }
    return b
}

fn ndigits(xx u64) int {
    mut n:=0
    mut x := xx
    for ; x > 0; x /= 10 {
        n++
    }
    return n
}

fn dtally(xx u64) u64 {
    mut t := u64(0)
    mut x := xx
    for ; x > 0; x /= 10 {
        t += 1 << (x % 10 * 6)
    }
    return t
}

__global (
    tens [20]u64
)

fn init() {
    tens[0] = 1
    for i := 1; i < 20; i++ {
        tens[i] = tens[i-1] * 10
    }
}

fn fangs(x u64) []u64 {
    mut f := []u64{}
    mut nd := ndigits(x)
    if nd&1 == 1 {
        return f
    }
    nd /= 2
    lo := max(tens[nd-1], (x+tens[nd]-2)/(tens[nd]-1))
    hi := min(x/lo, u64(math.sqrt(f64(x))))
    t := dtally(x)
    for a := lo; a <= hi; a++ {
        b := x / a
        if a*b == x &&
            (a%10 > 0 || b%10 > 0) &&
            t == dtally(a)+dtally(b) {
            f << a
        }
    }
    return f
}

fn show_fangs(x u64, f []u64) {
    print(x)
    if f.len > 1 {
        println('')
    }
    for a in f {
        println(" = $a × ${x/a}")
    }
}

fn main() {
    for x, n := u64(1), 0; n < 26; x++ {
        f := fangs(x)
        if f.len > 0 {
            n++
            print("${n:2}: ")
            show_fangs(x, f)
        }
    }
    println('')
    for x in [u64(16758243290880), 24959017348650, 14593825548650] {
        f := fangs(x)
        if f.len > 0 {
            show_fangs(x, f)
        } else {
            println("$x is not vampiric")
        }
    }
}


import "/fmt" for Fmt

var ndigits = Fn.new { |x|
    var n = 0
    while (x > 0) {
        n = n + 1
        x = (x/10).floor
    }
    return n
}

var dtally = Fn.new { |x|
    var t = 0
    while (x > 0) {
        t = t + 2.pow((x%10) * 6)
        x = (x/10).floor
    }
    return t
}

var tens = List.filled(15, 0)

var init = Fn.new  {
    tens[0] = 1
    for (i in 1..14) tens[i] = tens[i-1] * 10
}

var fangs = Fn.new { |x|
    var f = []
    var nd = ndigits.call(x)
    if ((nd&1) == 1) return f
    nd = (nd/2).floor
    var lo = tens[nd-1].max(((x + tens[nd] - 2) / (tens[nd] - 1)).floor)
    var hi = (x/lo).floor.min(x.sqrt.floor)
    var t = dtally.call(x)
    var a = lo
    while (a <= hi) {
        var b = (x/a).floor
        if (a*b == x && ((a%10) > 0 || (b%10) > 0) && t == dtally.call(a) + dtally.call(b)) {
            f.add(a)
        }
        a = a + 1
    }
    return f
}

var showFangs = Fn.new { |x, f|
    Fmt.write("$6d", x)
    if (f.count > 1) System.print()
    for (a in f) Fmt.print(" = $3d x $3d", a, (x/a).floor)
}

init.call()
var x = 1
var n = 0
while (n < 25) {
    var f = fangs.call(x)
    if (f.count > 0) {
        n = n + 1
        Fmt.write("$2d: ", n)
        showFangs.call(x, f)
    }
    x = x + 1
}
System.print()
for (x in [16758243290880, 24959017348650, 14593825548650]) {
    var f = fangs.call(x)
    if (f.count > 0) {
        showFangs.call(x, f)
    } else {
        Fmt.print("$d is not vampiric", x)
    }
}


' version 27-10-2016
' compile with: fbc -s console

#Ifndef TRUE        ' define true and false for older freebasic versions
    #Define FALSE 0
    #Define TRUE Not FALSE
#EndIf

Function luhntest(cardnr As String) As Long

    cardnr = Trim(cardnr) ' remove spaces

    Dim As String reverse_nr = cardnr
    Dim As Long i, j, s1, s2, l = Len(cardnr) -1

    ' reverse string
    For i = 0 To l
        reverse_nr[i] = cardnr[l - i]
    Next
    ' sum odd numbers
    For i = 0 To l Step 2
        s1 = s1 + (reverse_nr[i] - Asc("0"))
    Next
    ' sum even numbers
    For i = 1 To l Step 2
        j = reverse_nr[i] - Asc("0")
        j = j * 2
        If j > 9 Then j = j Mod 10 +1
        s2 = s2 + j
    Next

    If (s1 + s2) Mod 10 = 0 Then
        Return TRUE
    Else
        Return FALSE
    End If

End Function

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

Dim As String test_str
Dim As String test_set(1 To ...) = { "US0378331005", "US0373831005", _
                    "U50378331005", "US03378331005", "AU0000XVGZA3", _
                                     "AU0000VXGZA3", "FR0000988040" }

Dim As Long i, l, n, x

For i = 1 To UBound(test_set)
    test_str = ""
    l = Len(test_set(i))
    If l <> 12 Then
        Print test_set(i), "Invalid, length <> 12 char."
        Continue For
    End If
    If test_set(i)[0] < Asc("A") Or test_set(i)[1] < Asc("A") Then
        Print test_set(i), "Invalid, number needs to start with 2 characters"
        Continue For
    End If
    For n = 0 To l -1
        x = test_set(i)[n] - Asc("0")
        ' if test_set(i)[i] is a letter we to correct for that
        If x > 9 Then x = x -7
        If x < 10 Then
            test_str = test_str + Str(x)
        Else ' two digest number
            test_str = test_str + Str(x \ 10) + Str(x Mod 10)
        End If
    Next
    Print test_set(i), IIf(luhntest(test_str) = TRUE, "Valid","Invalid, checksum error")
Next

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


package main

import "regexp"

var r = regexp.MustCompile(`^[A-Z]{2}[A-Z0-9]{9}\d$`)

var inc = [2][10]int{
	{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
	{0, 2, 4, 6, 8, 1, 3, 5, 7, 9},
}

func ValidISIN(n string) bool {
	if !r.MatchString(n) {
		return false
	}
	var sum, p int
	for i := 10; i >= 0; i-- {
		p = 1 - p
		if d := n[i]; d < 'A' {
			sum += inc[p][d-'0']
		} else {
			d -= 'A'
			sum += inc[p][d%10]
			p = 1 - p
			sum += inc[p][d/10+1]
		}
	}
	sum += int(n[11] - '0')
	return sum%10 == 0
}


To run:
Start up.
Make a vector from 3 and 4 and 5.
Make another vector from 4 and 3 and 5.
Make a third vector from -5 and -12 and -13.
Write "A vector: " then the vector on the console.
Write "Another vector: " then the other vector on the console.
Write "A third vector: " then the third vector on the console.
Write "" on the console.
Compute a dot product of the vector and the other vector.
Write "Dot product between the vector and the other vector: " then the dot product on the console.
Compute a cross product of the vector and the other vector.
Write "Cross product between the vector and the other vector: " then the cross product on the console.
Compute a scalar triple product of the vector and the other vector and the third vector.
Write "Scalar triple product between the vector and the other vector and the third vector: " then the scalar triple product on the console.
Compute a vector triple product of the vector and the other vector and the third vector.
Write "Vector triple product between the vector and the other vector and the third vector: " then the vector triple product on the console.
Wait for the escape key.
Shut down.

A vector has a first number, a second number, and a third number.

To make a vector from a first number and a second number and a third number:
Put the first into the vector's first.
Put the second into the vector's second.
Put the third into the vector's third.

To put a vector into another vector:
Put the vector's first into the other vector's first.
Put the vector's second into the other vector's second.
Put the vector's third into the other vector's third.

To convert a vector into a string:
Append "(" then the vector's first then ", " then the vector's second then ", " then the vector's third then ")" to the string.

A dot product is a number.

To compute a dot product of a vector and another vector:
Put the vector's first times the other vector's first into a first number.
Put the vector's second times the other vector's second into a second number.
Put the vector's third times the other vector's third into a third number.
Put the first plus the second plus the third into the dot product.

A cross product is a vector.

To compute a cross product of a vector and another vector:
Put the vector's second times the other vector's third into a first number.
Put the vector's third times the other vector's second into a second number.
Put the vector's third times the other vector's first into a third number.
Put the vector's first times the other vector's third into a fourth number.
Put the vector's first times the other vector's second into a fifth number.
Put the vector's second times the other vector's first into a sixth number.
Make a result vector from the first minus the second and the third minus the fourth and the fifth minus the sixth.
Put the result into the cross product.

A scalar triple product is a number.

To compute a scalar triple product of a vector and another vector and a third vector:
Compute a cross product of the other vector and the third vector.
Compute a dot product of the vector and the cross product.
Put the dot product into the scalar triple product.

A vector triple product is a vector.

To compute a vector triple product of a vector and another vector and a third vector:
Compute a cross product of the other vector and the third vector.
Compute another cross product of the vector and the cross product.
Put the other cross product into the vector triple product.


function dot-product($a,$b) {
    $a[0]*$b[0] +  $a[1]*$b[1] +  $a[2]*$b[2]
}

function cross-product($a,$b) {
    $v1 = $a[1]*$b[2] - $a[2]*$b[1]
    $v2 = $a[2]*$b[0] - $a[0]*$b[2]
    $v3 = $a[0]*$b[1] - $a[1]*$b[0]
    @($v1,$v2,$v3)
}

function scalar-triple-product($a,$b,$c) {
    dot-product $a (cross-product $b $c)
}

function vector-triple-product($a,$b) {
    cross-product $a (cross-product $b $c)
}

$a = @(3, 4, 5)
$b = @(4, 3, 5)
$c = @(-5, -12, -13)

"a.b = $(dot-product $a $b)"
"axb = $(cross-product $a $b)"
"a.(bxc) = $(scalar-triple-product $a $b $c)"
"ax(bxc) = $(vector-triple-product $a $b $c)"


fcn fangs(N){ //-->if Vampire number: (N,(a,b,c,...)), where a*x==N
   var [const] tens=[0 .. 18].pump(List,(10.0).pow,"toInt");

   (half:=N.numDigits) : if (_.isOdd) return(T);;
   half/=2; digits:=N.toString().sort();
   lo:=tens[half-1].max((N+tens[half])/(tens[half]));
   hi:=(N/lo).min(N.toFloat().sqrt());
   fs:=[lo .. hi].filter('wrap(n){
      N%n==0 and (n%10!=0 or (N/n)%10!=0) and
      (n.toString()+(N/n).toString()).sort()==digits
   });
   fs and T(N,fs) or T;
}


CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'

int checksum(String prefix) {
    def digits = prefix.toUpperCase().collect { CHARS.indexOf(it).toString() }.sum()
    def groups = digits.collect { CHARS.indexOf(it) }.inject([[], []]) { acc, i -> [acc[1], acc[0] + i] }
    def ds = groups[1].collect { (2 * it).toString() }.sum().collect { CHARS.indexOf(it) } + groups[0]
    (10 - ds.sum() % 10) % 10
}

assert checksum('AU0000VXGZA') == 3
assert checksum('GB000263494') == 6
assert checksum('US037833100') == 5
assert checksum('US037833107') == 0


module ISINVerification2 where

import Data.Char (isUpper, isDigit, digitToInt)

verifyISIN :: String -> Bool
verifyISIN isin =
  correctFormat isin && mod (oddsum + multiplied_even_sum) 10 == 0
  where
    reverted = reverse $ convertToNumber isin
    theOdds = fst $ collectOddandEven reverted
    theEvens = snd $ collectOddandEven reverted
    oddsum = sum $ map digitToInt theOdds
    multiplied_even_sum = addUpDigits $ map ((* 2) . digitToInt) theEvens

capitalLetters :: String
capitalLetters = ['A','B' .. 'Z']

numbers :: String
numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

correctFormat :: String -> Bool
correctFormat isin =
  (length isin == 12) &&
  all (`elem` capitalLetters) (take 2 isin) &&
  all (\c -> elem c capitalLetters || elem c numbers) (drop 2 $ take 11 isin) &&
  elem (last isin) numbers

convertToNumber :: String -> String
convertToNumber = concatMap convert
  where
    convert :: Char -> String
    convert c =
      if isDigit c
        then show $ digitToInt c
        else show (fromEnum c - 55)

collectOddandEven :: String -> (String, String)
collectOddandEven term
  | odd $ length term =
    ( concat
        [ take 1 $ drop n term
        | n <- [0,2 .. length term - 1] ]
    , concat
        [ take 1 $ drop d term
        | d <- [1,3 .. length term - 2] ])
  | otherwise =
    ( concat
        [ take 1 $ drop n term
        | n <- [0,2 .. length term - 2] ]
    , concat
        [ take 1 $ drop d term
        | d <- [1,3 .. length term - 1] ])

addUpDigits :: [Int] -> Int
addUpDigits list =
  sum $
  map
    (\d ->
        if d > 9
          then sum $ map digitToInt $ show d
          else d)
    list

printSolution :: String -> IO ()
printSolution str = do
  putStr $ str ++ " is"
  if verifyISIN str
    then putStrLn " valid"
    else putStrLn " not valid"

main :: IO ()
main = do
  let isinnumbers =
        [ "US0378331005"
        , "US0373831005"
        , "U50378331005"
        , "US03378331005"
        , "AU0000XVGZA3"
        , "AU0000VXGZA3"
        , "FR0000988040"
        ]
  mapM_ printSolution isinnumbers


dot_product([A1, A2, A3], [B1, B2, B3], Ans) :-
    Ans is A1 * B1 + A2 * B2 + A3 * B3.

cross_product([A1, A2, A3], [B1, B2, B3], Ans) :-
    T1 is A2 * B3 - A3 * B2,
    T2 is A3 * B1 - A1 * B3,
    T3 is A1 * B2 - A2 * B1,
    Ans = [T1, T2, T3].

scala_triple(A, B, C, Ans) :-
    cross_product(B, C, Temp),
    dot_product(A, Temp, Ans).

vector_triple(A, B, C, Ans) :-
    cross_product(B, C, Temp),
    cross_product(A, Temp, Ans).


Structure vector
  x.f
  y.f
  z.f
EndStructure

;convert vector to a string for display
Procedure.s toString(*v.vector)
  ProcedureReturn "[" + StrF(*v\x, 2) + ", " + StrF(*v\y, 2) + ", " + StrF(*v\z, 2) + "]"
EndProcedure

Procedure.f dotProduct(*a.vector, *b.vector)
  ProcedureReturn *a\x * *b\x + *a\y * *b\y + *a\z * *b\z
EndProcedure

Procedure crossProduct(*a.vector, *b.vector, *r.vector)
  *r\x = *a\y * *b\z - *a\z * *b\y
  *r\y = *a\z * *b\x - *a\x * *b\z
  *r\z = *a\x * *b\y - *a\y * *b\x
EndProcedure

Procedure.f scalarTriple(*a.vector, *b.vector, *c.vector)
  Protected r.vector
  crossProduct(*b, *c, r)
  ProcedureReturn dotProduct(*a, r)
EndProcedure

Procedure vectorTriple(*a.vector, *b.vector, *c.vector, *r.vector)
  Protected r.vector
  crossProduct(*b, *c, r)
  crossProduct(*a, r, *r)
EndProcedure

If OpenConsole()
  Define.vector a, b, c, r
  a\x = 3: a\y = 4: a\z = 5
  b\x = 4: b\y = 3: b\z = 5
  c\x = -5: c\y = -12: c\z = -13

  PrintN("a = " + toString(a) + ", b = " + toString(b) + ", c = " + toString(c))
  PrintN("a . b = " + StrF(dotProduct(a, b), 2))
  crossProduct(a, b, r)
  PrintN("a x b = " + toString(r))
  PrintN("a . b x c  = " + StrF(scalarTriple(a, b, c), 2))
  vectorTriple(a, b, c, r)
  PrintN("a x b x c = " + toString(r))

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


require'regex'
validFmt=: 0 -: '^[A-Z]{2}[A-Z0-9]{9}[0-9]{1}$'&rxindex

df36=: ;@([: <@":"0 '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'&i.)  NB. decimal from base 36
luhn=: 0 = 10 (| +/@,) 10 #.inv 1 2 *&|: _2 "."0\ |.            NB. as per task Luhn_test_of_credit_card_numbers#J

validISIN=: validFmt *. [email protected]


public class ISIN {

    public static void main(String[] args) {
        String[] isins = {
            "US0378331005",
            "US0373831005",
            "U50378331005",
            "US03378331005",
            "AU0000XVGZA3",
            "AU0000VXGZA3",
            "FR0000988040"
        };
        for (String isin : isins)
            System.out.printf("%s is %s\n", isin, ISINtest(isin) ? "valid" : "not valid");
    }

    static boolean ISINtest(String isin) {
        isin = isin.trim().toUpperCase();

        if (!isin.matches("^[A-Z]{2}[A-Z0-9]{9}\\d$"))
            return false;

        StringBuilder sb = new StringBuilder();
        for (char c : isin.substring(0, 12).toCharArray())
            sb.append(Character.digit(c, 36));

        return luhnTest(sb.toString());
    }

    static boolean luhnTest(String number) {
        int s1 = 0, s2 = 0;
        String reverse = new StringBuffer(number).reverse().toString();
        for (int i = 0; i < reverse.length(); i++){
            int digit = Character.digit(reverse.charAt(i), 10);
            //This is for odd digits, they are 1-indexed in the algorithm.
            if (i % 2 == 0){
                s1 += digit;
            } else { // Add 2 * digit for 0-4, add 2 * digit - 9 for 5-9.
                s2 += 2 * digit;
                if(digit >= 5){
                    s2 -= 9;
                }
            }
        }
        return (s1 + s2) % 10 == 0;
    }
}


def crossp(a, b):
    '''Cross product of two 3D vectors'''
    assert len(a) == len(b) == 3, 'For 3D vectors only'
    a1, a2, a3 = a
    b1, b2, b3 = b
    return (a2*b3 - a3*b2, a3*b1 - a1*b3, a1*b2 - a2*b1)

def dotp(a,b):
    '''Dot product of two eqi-dimensioned vectors'''
    assert len(a) == len(b), 'Vector sizes must match'
    return sum(aterm * bterm for aterm,bterm in zip(a, b))

def scalartriplep(a, b, c):
    '''Scalar triple product of three vectors: "a . (b x c)"'''
    return dotp(a, crossp(b, c))

def vectortriplep(a, b, c):
    '''Vector triple product of three vectors: "a x (b x c)"'''
    return crossp(a, crossp(b, c))

if __name__ == '__main__':
    a, b, c = (3, 4, 5), (4, 3, 5), (-5, -12, -13)
    print("a = %r;  b = %r;  c = %r" % (a, b, c))
    print("a . b = %r" % dotp(a,b))
    print("a x b = %r"  % (crossp(a,b),))
    print("a . (b x c) = %r" % scalartriplep(a, b, c))
    print("a x (b x c) = %r" % (vectortriplep(a, b, c),))


  [ 0 unrot witheach
      [ over i^ peek *
        rot + swap ]
    drop ]                      is dotproduct   (   [ [ --> n )

  [ join
    dup 1 peek over 5 peek *
    swap
    dup 2 peek over 4 peek *
    swap dip -
    dup 2 peek over 3 peek *
    swap
    dup 0 peek over 5 peek *
    swap dip -
    dup 0 peek over 4 peek *
    swap
    dup 1 peek swap 3 peek *
    - join join ]               is crossproduct (   [ [ --> [ )

  [ crossproduct dotproduct ]   is scalartriple ( [ [ [ --> n )

  [ crossproduct crossproduct ] is vectortriple ( [ [ [ --> [ )

  [ ' [  3   4   5 ] ]          is a            (       --> [ )
  [ ' [  4   3   5 ] ]          is b            (       --> [ )
  [ ' [ -5 -12 -13 ] ]          is c            (       --> [ )

  a b   dotproduct   echo cr
  a b   crossproduct echo cr
  a b c scalartriple echo cr
  a b c vectortriple echo cr


# This filter may be applied to integers or integer-valued strings
def luhntest:
  def digits: tostring | explode | map([.]|implode|tonumber);
  (digits | reverse)
  | ( [.[range(0;length;2)]] | add ) as $sum1
  | [.[range(1;length;2)]]
  | (map( (2 * .) | if . > 9 then (digits|add) else . end) | add) as $sum2
  | ($sum1 + $sum2) % 10 == 0;

def decodeBase36:
  # decode a single character
  def d1:
    explode[0]
    # "0" is 48; "A" is 65
    | if . < 65 then . - 48
      else . - 55
      end;
  def chars: explode | map([.]|implode);
  chars | map(d1) | join("");

def is_ISIN:
  type == "string"
  and test("^(?<cc>[A-Z][A-Z])(?<sc>[0-9A-Z]{9})(?<cs>[0-9])$")
  and (decodeBase36 | luhntest);


using Printf

luhntest(x) = luhntest(parse(Int, x))

function checkISIN(inum::AbstractString)
    if length(inum) != 12 || !all(isalpha, inum[1:2]) return false end
    return parse.(Int, collect(inum), 36) |> join |> luhntest
end

for inum in ["US0378331005", "US0373831005", "U50378331005",
    "US03378331005", "AU0000XVGZA3", "AU0000VXGZA3", "FR0000988040"]
    @printf("%-15s %5s\n", inum, ifelse(checkISIN(inum), "pass", "fail"))
end


// version 1.1

object Isin {
    val r = Regex("^[A-Z]{2}[A-Z0-9]{9}[0-9]$")

    fun isValid(s: String): Boolean {
        // check format
        if (!s.matches(r)) return false
        // validate checksum
        val sb = StringBuilder()
        for (c in s) {
            when (c) {
                in '0'..'9' -> sb.append(c)
                in 'A'..'Z' -> sb.append((c.toInt() - 55).toString().padStart(2, '0'))
            }
        }
        return luhn(sb.toString())
    }

    private fun luhn(s: String): Boolean {
        fun sumDigits(n: Int) = n / 10 + n % 10
        val t = s.reversed()
        val s1 = t.filterIndexed { i, _ -> i % 2 == 0 }.sumBy { it - '0' }
        val s2 = t.filterIndexed { i, _ -> i % 2 == 1 }.map { sumDigits((it - '0') * 2) }.sum()
        return (s1 + s2) % 10 == 0
    }
}

fun main(args: Array<String>) {
    val isins = arrayOf(
        "US0378331005", "US0373831005", "U50378331005", "US03378331005",
        "AU0000XVGZA3", "AU0000VXGZA3", "FR0000988040"
    )
    for (isin in isins) {
        println("$isin\t -> ${if (Isin.isValid(isin)) "valid" else "not valid"}")
    }
}


val .luhntest = f(.s) {
    val .t = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
    val .numbers = s2n .s
    val .oddeven = len(.numbers) rem 2

    for[=0] .i of .numbers {
        _for += if(.i rem 2 == .oddeven: .numbers[.i]; .t[.numbers[.i]+1])
    } div 10
}

val .isintest = f(.s) {
    matching(re/^[A-Z][A-Z][0-9A-Z]{9}[0-9]$/, .s) and
        .luhntest(join s2n .s)
}

val .tests = h{
    "US0378331005":  true,
    "US0373831005": false,
    "U50378331005": false,
    "AU0000XVGZA3": true,
    "AU0000VXGZA3": true,
    "FR0000988040": true,
    "US03378331005": false,
}

for .key in sort(keys .tests) {
    val .pass = .isintest(.key)
    write .key, ": ", .pass
    writeln if(.pass == .tests[.key]: ""; " (ISIN TEST FAILED)")
}


function luhn (n)
    local revStr, s1, s2, digit, mod = n:reverse(), 0, 0
    for pos = 1, #revStr do
        digit = tonumber(revStr:sub(pos, pos))
        if pos % 2 == 1 then
            s1 = s1 + digit
        else
            digit = digit * 2
            if digit > 9 then
                mod = digit % 10
                digit = mod + ((digit - mod) / 10)
            end
            s2 = s2 + digit
        end
    end
    return (s1 + s2) % 10 == 0
end

function checkISIN (inStr)
    if #inStr ~= 12 then return false end
    local numStr = ""
    for pos = 1, #inStr do
        numStr = numStr .. tonumber(inStr:sub(pos, pos), 36)
    end
    return luhn(numStr)
end

local testCases = {
    "US0378331005",
    "US0373831005",
    "US0373831005",
    "US03378331005",
    "AU0000XVGZA3",
    "AU0000VXGZA3",
    "FR0000988040"
}
for _, ISIN in pairs(testCases) do print(ISIN, checkISIN(ISIN)) end


ClearAll[LuhnQ, VakudISINQ]
LuhnQ[n_Integer] := Block[{digits = [email protected]@n}, Mod[Total[{digits[[;; ;; 2]], IntegerDigits[2 #] & /@ digits[[2 ;; ;; 2]]}, -1], 10] == 0]
VakudISINQ[sin_String] := Module[{s = ToUpperCase[sin]},
  If[StringMatchQ[s,
    LetterCharacter ~~ LetterCharacter ~~
     Repeated[DigitCharacter | LetterCharacter, {9}] ~~
     DigitCharacter],
   s = StringJoin[
     Characters[s] /.
      Thread[CharacterRange["A", "Z"] -> ToString /@ Range[10, 35]]];
   LuhnQ[ToExpression[s]]
   ,
   False
   ]
  ]
VakudISINQ /@ {"US0378331005", "US0373831005", "U50378331005", "US03378331005", "AU0000XVGZA3", "AU0000VXGZA3", "FR0000988040"}


#lang racket

(define (dot-product X Y)
  (for/sum ([x (in-vector X)] [y (in-vector Y)]) (* x y)))

(define (cross-product X Y)
  (define len (vector-length X))
  (for/vector ([n len])
    (define (ref V i) (vector-ref V (modulo (+ n i) len)))
    (- (* (ref X 1) (ref Y 2)) (* (ref X 2) (ref Y 1)))))

(define (scalar-triple-product X Y Z)
  (dot-product X (cross-product Y Z)))

(define (vector-triple-product X Y Z)
  (cross-product X (cross-product Y Z)))

(define A '#(3 4 5))
(define B '#(4 3 5))
(define C '#(-5 -12 -13))

(printf "A = ~s\n" A)
(printf "B = ~s\n" B)
(printf "C = ~s\n" C)
(newline)

(printf "A . B = ~s\n" (dot-product A B))
(printf "A x B = ~s\n" (cross-product A B))
(printf "A . B x C = ~s\n" (scalar-triple-product A B C))
(printf "A x B x C = ~s\n" (vector-triple-product A B C))


import strformat

const
  DigitRange = '0'..'9'
  UpperCaseRange = 'A'..'Z'

type ISINError = object of ValueError

proc luhn(s: string): bool =
  const m = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
  var sum = 0
  var odd = true
  for i in countdown(s.high, 0):
    let digit = ord(s[i]) - ord('0')
    sum += (if odd: digit else: m[digit])
    odd = not odd
  result = sum mod 10 == 0

proc validateISIN(s: string) =
  if s.len != 12:
    raise newException(ISINError, "wrong length")
  if s[0] notin UpperCaseRange or s[1] notin UpperCaseRange:
    raise newException(ISINError, "wrong country code")
  if s[11] notin DigitRange:
    raise newException(ISINError, "wrong checksum character")
  var t: string
  for ch in s:
    case ch
    of '0'..'9': t.add ch
    of 'A'..'Z': t.addInt ord(ch) - ord('A') + 10
    else: raise newException(ISINError, "invalid characters in code")
  if not t.luhn():
    raise newException(ISINError, "checksum error")

when isMainModule:

  for isin in ["US0378331005", "US0373831005", "U50378331005",
               "US03378331005", "AU0000XVGZA3", "AU0000VXGZA3", "FR0000988040"]:
    try:
      isin.validateISIN()
      echo &"{isin} is valid."
    except ISINError:
      echo &"{isin} is not valid: {getCurrentExceptionMsg()}."


use strict;
use English;
use POSIX;
use Test::Simple tests => 7;

ok(   validate_isin('US0378331005'),  'Test 1');
ok( ! validate_isin('US0373831005'),  'Test 2');
ok( ! validate_isin('U50378331005'),  'Test 3');
ok( ! validate_isin('US03378331005'), 'Test 4');
ok(   validate_isin('AU0000XVGZA3'),  'Test 5');
ok(   validate_isin('AU0000VXGZA3'),  'Test 6');
ok(   validate_isin('FR0000988040'),  'Test 7');
exit 0;

sub validate_isin {
    my $isin = shift;
    $isin =~ /\A[A-Z]{2}[A-Z\d]{9}\d\z/s or return 0;
    my $base10 = join(q{}, map {scalar(POSIX::strtol($ARG, 36))}
                               split(//s, $isin));
    return luhn_test($base10);
}


with javascript_semantics
function Luhn(string st)
    integer s = 0, d
    st = reverse(st)
    for i=1 to length(st) do
        d = st[i]-'0'
        s += iff(mod(i,2)?d,d*2-(d>4)*9)
    end for
    return remainder(s,10)=0
end function

function valid_ISIN(string st)
-- returns 1 if valid, else 0/2/3/4.
-- (feel free to return 0 instead of 2/3/4)
    if length(st)!=12 then return 2 end if
    for i=length(st) to 1 by -1 do
        integer ch = st[i]
        if ch>='A' then
            if ch>'Z' then return 3 end if
            st[i..i] = sprintf("%d",ch-55)
        elsif i<=2 then
            return 4
        elsif ch<'0' or ch>'9' then
            return 3
        end if
    end for
    return Luhn(st)
end function

constant tests = {"US0378331005",   --  valid
                  "US0373831005",   --  not valid       The transposition typo is caught by the checksum constraint.
                  "U50378331005",   --  not valid       The substitution typo is caught by the format constraint.
                  "US03378331005",  --  not valid       The duplication typo is caught by the format constraint.
                  "AU0000XVGZA3",   --  valid
                  "AU0000VXGZA3",   --  valid   Unfortunately, not all transposition typos are caught by the checksum constraint.
                  "FR0000988040"},  --  valid

        reasons = {"wrong checksum","valid","wrong length","bad char","wrong country"}

for i=1 to length(tests) do
    printf(1,"%s : %s\n",{tests[i],reasons[valid_ISIN(tests[i])+1]})
end for


/*REXX program computes the products:  dot,  cross,  scalar triple,  and  vector triple.*/
                             a=   3   4   5
                             b=   4   3   5      /*(positive numbers don't need quotes.)*/
                             c= "-5 -12 -13"
call tellV  'vector A =', a                      /*show the  A  vector, aligned numbers.*/
call tellV  'vector B =', b                      /*  "   "   B     "        "      "    */
call tellV  'vector C =', c                      /*  "   "   C     "        "      "    */
     say
call tellV  '  dot product [A∙B] =',                 dot(a, b)
call tellV  'cross product [AxB] =',               cross(a, b)
call tellV  'scalar triple product [A∙(BxC)] =',     dot(a, cross(b, c) )
call tellV  'vector triple product [Ax(BxC)] =',   cross(a, cross(b, c) )
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
cross: procedure; arg $1 $2 $3,@1 @2 @3;  return  $2*@3 -$3*@2  $3*@1 -$1*@3  $1*@2 -$2*@1
dot:   procedure; arg $1 $2 $3,@1 @2 @3;  return  $1*@1        +   $2*@2     +   $3*@3
/*──────────────────────────────────────────────────────────────────────────────────────*/
tellV: procedure; parse arg name,x y z;   w=max(4,length(x),length(y),length(z)) /*max W*/
       say right(name,40)  right(x,w)  right(y,w)  right(z,w); /*show vector.*/    return


# Project : Vector products

d = list(3)
e = list(3)
a = [3, 4, 5]
b = [4, 3, 5]
c = [-5, -12, -13]

see "a . b = " + dot(a,b) + nl
cross(a,b,d)
see "a x b = (" + d[1] + ", " + d[2] + ", " + d[3] + ")" + nl
see "a . (b x c) = " + scalartriple(a,b,c) + nl
vectortriple(a,b,c,d)

def dot(a,b)
    sum = 0
    for n=1 to len(a)
        sum = sum + a[n]*b[n]
    next
    return sum

func cross(a,b,d)
     d = [a[2]*b[3]-a[3]*b[2], a[3]*b[1]-a[1]*b[3], a[1]*b[2]-a[2]*b[1]]

func scalartriple(a,b,c)
     cross(b,c,d)
     return dot(a,d)

func vectortriple(a,b,c,d)
     cross(b,c,d)
     cross(a,d,e)
     see "a x (b x c) = (" + e[1] + ", " +e[2] + ", " + e[3] + ")"


function Test-ISIN
{
    [CmdletBinding()]
    [OutputType([bool])]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [ValidatePattern("[A-Z]{2}\w{9}\d")]
        [ValidateScript({$_.Length -eq 12})]
        [string]
        $Number
    )

    function Split-Array
    {
        $array = @(), @()
        $input | ForEach-Object {$array[($index = -not $index)] += $_}
        $array[1], $array[0]
    }

    filter ConvertTo-Digit
    {
        if ($_ -gt 9)
        {
            $_.ToString().ToCharArray() | ForEach-Object -Begin {$n = 0} -Process {$n += [Char]::GetNumericValue($_)} -End {$n}
        }
        else
        {
            $_
        }
    }

    $checkDigit = $Number[-1]

    $digits = ($Number -replace ".$").ToCharArray() | ForEach-Object {
        if ([Char]::IsDigit($_))
        {
            [Char]::GetNumericValue($_)
        }
        else
        {
            [int][char]$_ - 55
        }
    }

    $odds, $evens = ($digits -join "").ToCharArray() | Split-Array

    if ($odds.Count -gt $evens.Count)
    {
        $odds  = $odds  | ForEach-Object {[Char]::GetNumericValue($_) * 2} | ConvertTo-Digit
        $evens = $evens | ForEach-Object {[Char]::GetNumericValue($_)}
    }
    else
    {
        $odds  = $odds  | ForEach-Object {[Char]::GetNumericValue($_)}
        $evens = $evens | ForEach-Object {[Char]::GetNumericValue($_) * 2} | ConvertTo-Digit
    }

    $sum = ($odds  | Measure-Object -Sum).Sum + ($evens | Measure-Object -Sum).Sum

    (10 - ($sum % 10)) % 10 -match $checkDigit
}


require 'matrix'

class Vector
  def scalar_triple_product(b, c)
    self.inner_product(b.cross_product c)
  end

  def vector_triple_product(b, c)
    self.cross_product(b.cross_product c)
  end
end

a = Vector[3, 4, 5]
b = Vector[4, 3, 5]
c = Vector[-5, -12, -13]

puts "a dot b = #{a.inner_product b}"
puts "a cross b = #{a.cross_product b}"
puts "a dot (b cross c) = #{a.scalar_triple_product b, c}"
puts "a cross (b cross c) = #{a.vector_triple_product b, c}"


#[derive(Debug)]
struct Vector {
    x: f64,
    y: f64,
    z: f64,
}

impl Vector {
    fn new(x: f64, y: f64, z: f64) -> Self {
        Vector {
            x: x,
            y: y,
            z: z,
        }
    }

    fn dot_product(&self, other: &Vector) -> f64 {
        (self.x * other.x) + (self.y * other.y) + (self.z * other.z)
    }

    fn cross_product(&self, other: &Vector) -> Vector {
        Vector::new(self.y * other.z - self.z * other.y,
                    self.z * other.x - self.x * other.z,
                    self.x * other.y - self.y * other.x)
    }

    fn scalar_triple_product(&self, b: &Vector, c: &Vector) -> f64 {
        self.dot_product(&b.cross_product(&c))
    }

    fn vector_triple_product(&self, b: &Vector, c: &Vector) -> Vector {
        self.cross_product(&b.cross_product(&c))
    }
}

fn main(){
    let a = Vector::new(3.0, 4.0, 5.0);
    let b = Vector::new(4.0, 3.0, 5.0);
    let c = Vector::new(-5.0, -12.0, -13.0);

    println!("a . b = {}", a.dot_product(&b));
    println!("a x b = {:?}", a.cross_product(&b));
    println!("a . (b x c) = {}", a.scalar_triple_product(&b, &c));
    println!("a x (b x c) = {:?}", a.vector_triple_product(&b, &c));
}


case class Vector3D(x:Double, y:Double, z:Double) {
  def dot(v:Vector3D):Double=x*v.x + y*v.y + z*v.z;
  def cross(v:Vector3D)=Vector3D(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x)
  def scalarTriple(v1:Vector3D, v2:Vector3D)=this dot (v1 cross v2)
  def vectorTriple(v1:Vector3D, v2:Vector3D)=this cross (v1 cross v2)
}

object VectorTest {
  def main(args:Array[String])={
    val a=Vector3D(3,4,5)
    val b=Vector3D(4,3,5)
    val c=Vector3D(-5,-12,-13)

    println("      a . b : " + (a dot b))
    println("      a x b : " + (a cross b))
    println("a . (b x c) : " + (a scalarTriple(b, c)))
    println("a x (b x c) : " + (a vectorTriple(b, c)))
  }
}


EnableExplicit

Procedure.b Check_ISIN(*c.Character)
  Define count.i=0, Idx.i=1, v.i=0, i.i
  Dim s.i(24)

  If MemoryStringLength(*c) > 12 : ProcedureReturn #False : EndIf

  While *c\c
    count+1
    If *c\c>='0' And *c\c<='9'
      If count<=2 : ProcedureReturn #False : EndIf
      s(Idx)= *c\c - '0'
      Idx+1
    ElseIf *c\c>='A' And *c\c<='Z'
      s(Idx)= (*c\c - ('A'-10)) / 10
      Idx+1
      s(Idx)= (*c\c - ('A'-10)) % 10
      Idx+1
    Else
      ProcedureReturn #False
    EndIf
    *c + SizeOf(Character)
  Wend

  For i=Idx-2 To 0 Step -2
    If s(i)*2 > 9
      v+ s(i)*2 -9
    Else
      v+ s(i)*2
    EndIf
    v+s(i+1)
  Next

  ProcedureReturn Bool(v%10=0)
EndProcedure

Define.s s
OpenConsole("Validate_International_Securities_Identification_Number (ISIN)")

If ReadFile(0,"c:\code_pb\rosettacode\data\isin.txt")
  While Not Eof(0)
    s=ReadString(0)
    Print(s+~"\t")
    If Check_ISIN(@s) : PrintN("TRUE") : Else : PrintN("FALSE") : EndIf
  Wend
  CloseFile(0)
EndIf
Input()


def check_isin(a):
    if len(a) != 12 or not all(c.isalpha() for c in a[:2]) or not all(c.isalnum() for c in a[2:]):
        return False
    s = "".join(str(int(c, 36)) for c in a)
    return 0 == (sum(sum(divmod(2 * (ord(c) - 48), 10)) for c in s[-2::-2]) +
                 sum(ord(c) - 48 for c in s[::-2])) % 10

# A more readable version
def check_isin_alt(a):
    if len(a) != 12:
        return False
    s = []
    for i, c in enumerate(a):
        if c.isdigit():
            if i < 2:
                return False
            s.append(ord(c) - 48)
        elif c.isupper():
            if i == 11:
                return False
            s += divmod(ord(c) - 55, 10)
        else:
            return False
    v = sum(s[::-2])
    for k in s[-2::-2]:
        k = 2 * k
        v += k - 9 if k > 9 else k
    return v % 10 == 0

[check_isin(s) for s in ["US0378331005", "US0373831005", "U50378331005", "US03378331005",
                         "AU0000XVGZA3", "AU0000VXGZA3", "FR0000988040"]]

# [True, False, False, False, True, True, True]


(define (dot-product A B)
    (apply + (map * (vector->list A) (vector->list B))))

(define (cross-product A B)
	(define len (vector-length A))
	(define xp (make-vector (vector-length A) #f))
	(let loop ((n 0))
		(vector-set! xp n (-
			(* (vector-ref A (modulo (+ n 1) len))
				(vector-ref B (modulo (+ n 2) len)))
			(* (vector-ref A (modulo (+ n 2) len))
				(vector-ref B (modulo (+ n 1) len)))))
		(if (eqv? len (+ n 1))
			xp
			(loop (+ n 1)))))

(define (scalar-triple-product A B C)
	(dot-product A (cross-product B C)))

(define (vector-triple-product A B C)
	(cross-product A (cross-product B C)))

(define A #( 3 4 5))
(define B #(4 3 5))
(define C #(-5 -12 -13))

(display "A = ")(display A)(newline)
(display "B = ")(display B)(newline)
(display "C = ")(display C)(newline)
(newline)
(display "A . B = ")(display (dot-product A B))(newline)
(display "A x B = ")(display (cross-product A B))(newline)
(display "A . B x C = ")(display (scalar-triple-product A B C))(newline)
(display "A x B x C = ") (display (vector-triple-product A B C))(newline)


  [ 2 split drop do
    char A char z 1+ within
    swap
    char A char z 1+ within
    and ]                   is 2chars ( $ --> b )

  [ dup size 12 != iff
      [ drop false ] done
    dup 2chars not iff
      [ drop false ] done
    [] swap
    witheach
      [ 36 base put
        char->n
        base release
        number$ join ]
    $->n drop luhn ]        is isin   ( n --> b )

  [ dup echo$
    say " is "
    isin not if
      [ say "not " ]
    say "valid." cr ]       is task   ( n -->   )

  $ "US0378331005"  task
  $ "US0373831005"  task
  $ "U50378331005"  task
  $ "US03378331005" task
  $ "AU0000XVGZA3"  task
  $ "AU0000VXGZA3"  task
  $ "FR0000988040"  task


#lang racket

;; convert a base36 character (#\0 - #\Z) to its equivalent
;; in base 10 as a string ("0" - "35")
(define (base36-char->base10-string c)
  (let ([char-int (char->integer (char-upcase c))]
        [zero-int (char->integer #\0)]
        [nine-int (char->integer #\9)]
        [A-int (char->integer #\A)]
        [Z-int (char->integer #\Z)])
    (cond [(and (>= char-int zero-int) (<= char-int nine-int)) (~a c)]
          [(and (>= char-int A-int) (<= char-int Z-int)) (~a (+ (- char-int A-int) 10))]
          [else null])))

;; substitute equivalent base 10 numbers for base 36 characters in string
;; this is a character-by-character substitution not a conversion
;; of a base36 number to a base10 number
(define (base36-string-characters->base10-string-characters s)
  (for/fold ([joined ""])
            ([tenstr (map base36-char->base10-string (string->list (string-upcase s)))])
    (values (string-append joined tenstr))))

;; This uses the Racket Luhn solution
(define [isin-test? s]
  (let ([RE (pregexp "^[A-Z]{2}[A-Z0-9]{9}[0-9]{1}$")])
    (and
     (regexp-match? RE s)
     (luhn-test (string->number (base36-string-characters->base10-string-characters s))))))

(define test-cases '("US0378331005" "US0373831005" "U50378331005" "US03378331005" "AU0000XVGZA3" "AU0000VXGZA3" "FR0000988040"))

(map isin-test? test-cases)
;; -> '(#t #f #f #f #t #t #t)


/*REXX program validates the  checksum digit for an  International Securities ID number.*/
parse arg z                                      /*obtain optional  ISINs  from the C.L.*/
if z=''  then z= "US0378331005 US0373831005 U50378331005 US03378331005 AU0000XVGZA3" ,
                 'AU0000VXGZA3 FR0000988040'     /* [↑]  use the default list of  ISINs.*/
                                                 /* [↓]  process  all  specified  ISINs.*/
     do n=1  for words(z);  x=word(z, n);  y= x  /*obtain an  ISIN  from the  Z  list.  */
     $=                                          /* [↓]  construct list of ISIN digits. */
        do k=1  for length(x);  _= substr(x,k,1) /*the ISIN may contain alphabetic chars*/
        p= pos(_, 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ)   /*X must contain A──►Z, 0──►9.*/
        if p==0  then y=                                  /*trigger  "not"  valid below.*/
                 else $= $ || p-1                /*convert  X  string (base 36 ──► dec).*/
        end   /*k*/                              /* [↑]  convert  alphabetic ──► digits.*/
     @=                                          /*placeholder for the "not" in message.*/
     if length(y)\==12             then @= "not" /*see if the ISIN is exactly 12 chars. */
     if \datatype( left(x,2),'U')  then @= "not" /* "   "  "    "  1st 2 chars cap. let.*/
     if \datatype(right(x,1),'W')  then @= "not" /* "   "  "    "  last char not a digit*/
     if @==''  then  if \luhn($)   then @= "not" /* "   "  "    "  passed the Luhn test.*/
     say right(x, 30)   right(@, 5)   "valid"    /*display the   yea  or  nay   message.*/
     end   /*n*/                                 /* [↑] 1st 3 IFs could've been combined*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
Luhn: procedure;  parse arg x;           $= 0    /*get credit card number;  zero $ sum. */
      y= reverse( left(0, length(x) // 2)x)      /*add leading zero if needed, & reverse*/
                            do j=1  to length(y)-1  by 2;    _= 2  *  substr(y, j+1, 1)
                            $= $ + substr(y, j, 1)  +  left(_, 1)  +  substr(_, 2  , 1, 0)
                            end   /*j*/          /* [↑]   sum the  odd and even  digits.*/
      return right($, 1)==0                      /*return "1" if number passed Luhn test*/


$ include "seed7_05.s7i";
  include "float.s7i";

const type: vec3 is new struct
    var float: x is 0.0;
    var float: y is 0.0;
    var float: z is 0.0;
  end struct;

const func vec3: vec3 (in float: x, in float: y, in float: z) is func
  result
    var vec3: aVector is vec3.value;
  begin
    aVector.x := x;
    aVector.y := y;
    aVector.z := z;
  end func;

$ syntax expr: .(). dot .() is -> 6;
const func float: (in vec3: a) dot (in vec3: b) is
  return a.x*b.x + a.y*b.y + a.z*b.z;

$ syntax expr: .(). X .() is -> 6;
const func vec3: (in vec3: a) X (in vec3: b) is
  return vec3(a.y*b.z - a.z*b.y,
              a.z*b.x - a.x*b.z,
              a.x*b.y - a.y*b.x);

const func string: str (in vec3: v) is
  return "(" <& v.x <& ", " <& v.y <& ", " <& v.z <& ")";

enable_output(vec3);

const func float: scalarTriple (in vec3: a, in vec3: b, in vec3: c) is
  return a dot (b X c);

const func vec3: vectorTriple (in vec3: a, in vec3: b, in vec3: c) is
  return a X (b X c);

const proc: main is func
  local
    const vec3: a is vec3(3.0, 4.0, 5.0);
    const vec3: b is vec3(4.0, 3.0, 5.0);
    const vec3: c is vec3(-5.0, -12.0, -13.0);
  begin
    writeln("a = " <& a <& ", b = " <& b <& ", c = " <& c);
    writeln("a . b      = " <& a dot b);
    writeln("a x b      = " <& a X b);
    writeln("a .(b x c) = " <& scalarTriple(a, b, c));
    writeln("a x(b x c) = " <& vectorTriple(a, b, c));
  end func;


class MyVector(x, y, z) {
    method ∙(vec) {
        [self{:x,:y,:z}] »*« [vec{:x,:y,:z}] «+»
    }

    method ⨉(vec) {
        MyVector(self.y*vec.z - self.z*vec.y,
               self.z*vec.x - self.x*vec.z,
               self.x*vec.y - self.y*vec.x)
    }

    method to_s {
        "(#{x}, #{y}, #{z})"
    }
}

var a = MyVector(3, 4, 5)
var b = MyVector(4, 3, 5)
var c = MyVector(-5, -12, -13)

say "a=#{a}; b=#{b}; c=#{c};"
say "a ∙ b = #{a ∙ b}"
say "a ⨉ b = #{a ⨉ b}"
say "a ∙ (b ⨉ c) = #{a ∙ (b ⨉ c)}"
say "a ⨉ (b ⨉ c) = #{a ⨉ (b ⨉ c)}"


# Project : Validate International Securities Identification Number

decimals(0)

test = ["US0378331005",
           "US0373831005",
           "U50378331005",
           "US03378331005",
           "AU0000XVGZA3",
           "AU0000VXGZA3",
           "FR0000988040"]

for n = 1 to len(test)
      testold = test[n]
      ascii1 = ascii(left(test[n],1))
      ascii2 = ascii(substr(test[n],2,1))
      if len(test[n]) != 12 or (ascii1 < 65 or ascii1 > 90) or (ascii2 < 65 or ascii2 > 90)
         see test[n] + " -> Invalid" + nl
         loop
      ok
      for m = 1 to len(test[n])
           if ascii(test[n][m]) > 64 and ascii(test[n][m]) < 91
              asc = ascii(test[n][m]) - 55
              test[n] = left(test[n],m-1) + string(asc) + right(test[n],len(test[n])-m)
           ok
      next
      see testold + " -> " + cardtest(test[n]) + nl
next

func cardtest(numstr)
        revstring = revstr(numstr)
        s1 = revodd(revstring)
        s2 = reveven(revstring)
        s3 =right(string(s1+s2), 1)
        if s3 = "0"
           return "Valid"
        else
           return "Invalid"
        ok

func revstr(str)
      strnew = ""
      for nr = len(str) to 1 step -1
           strnew = strnew + str[nr]
      next
      return strnew

func revodd(str)
        strnew = ""
        for nr = 1 to len(str) step 2
             strnew = strnew + str[nr]
        next
        sumodd = 0
        for p = 1 to len(strnew)
              sumodd = sumodd + number(strnew[p])
        next
        return sumodd

func reveven(str)
        strnew = ""
        for nr = 2 to len(str) step 2
             strnew = strnew + str[nr]
        next
        lsteven = []
        for p = 1 to len(strnew)
             add(lsteven, string(2*number(strnew[p])))
        next
        arreven = list(len(lsteven))
        for q = 1 to len(lsteven)
              sum = 0
              for w = 1 to len(lsteven[q])
                    sum = sum + lsteven[q][w]
              next
              arreven[q] = sum
        next
        sumarr = 0
        for x = 1 to len(arreven)
             sumarr = sumarr + arreven[x]
        next
        return sumarr


RE = /\A[A-Z]{2}[A-Z0-9]{9}[0-9]{1}\z/

def valid_isin?(str)
  return false unless str =~ RE
  luhn(str.chars.map{|c| c.to_i(36)}.join)
end

p %w(US0378331005
US0373831005
U50378331005
US03378331005
AU0000XVGZA3
AU0000VXGZA3
FR0000988040).map{|tc| valid_isin?(tc) }

# => [true, false, false, false, true, true, true]


extern crate luhn_cc;

use luhn_cc::compute_luhn;

fn main() {
    assert_eq!(validate_isin("US0378331005"), true);
    assert_eq!(validate_isin("US0373831005"), false);
    assert_eq!(validate_isin("U50378331005"), false);
    assert_eq!(validate_isin("US03378331005"), false);
    assert_eq!(validate_isin("AU0000XVGZA3"), true);
    assert_eq!(validate_isin("AU0000VXGZA3"), true);
    assert_eq!(validate_isin("FR0000988040"), true);
}

fn validate_isin(isin: &str) -> bool {
    // Preliminary checks to avoid working on non-ASCII stuff
    if !isin.chars().all(|x| x.is_alphanumeric()) || isin.len() != 12 {
        return false;
    }
    if !isin[..2].chars().all(|x| x.is_alphabetic())
        || !isin[2..12].chars().all(|x| x.is_alphanumeric())
        || !isin.chars().last().unwrap().is_numeric()
    {
        return false;
    }

    // Converts the alphanumeric string in a numeric-only string
    let bytes = isin.as_bytes();

    let s2 = bytes.iter()
        .flat_map(|&c| {
            if c.is_ascii_digit() {
                vec![c]
            }
            else {
                (c + 10 - ('A' as u8)).to_string().into_bytes()
            }
        }).collect::<Vec<u8>>();

    let string = std::str::from_utf8(&s2).unwrap();
    let number = string.parse::<usize>().unwrap();

    return compute_luhn(number);
}


data test;
length isin $20 ok $1;
input isin;
keep isin ok;
array s{24};
link isin;
return;
isin:
ok="N";
n=length(isin);
if n=12 then do;
    j=0;
    do i=1 to n;
        k=rank(substr(isin,i,1));
        if k>=48 & k<=57 then do;
            if i<3 then return;
            j+1;
            s{j}=k-48;
        end;
        else if k>=65 & k<=90 then do;
            if i=12 then return;
            k+-55;
            j+1;
            s{j}=int(k/10);
            j+1;
            s{j}=mod(k,10);
        end;
        else return;
    end;

    v=sum(of s{*});
    do i=j-1 to 1 by -2;
        v+s{i}-9*(s{i}>4);
    end;

if mod(v,10)=0 then ok="Y";
end;
return;
cards;
US0378331005
US0373831005
U50378331005
US03378331005
AU0000XVGZA3
AU0000VXGZA3
FR0000988040
;
run;


F vdc(=n, base = 2)
   V (vdc, denom) = (0.0, 1)
   L n != 0
      denom *= base
      (n, V remainder) = divmod(n, base)
      vdc += Float(remainder) / denom
   R vdc

print((0.<10).map(i -> vdc(i)))
print((0.<10).map(i -> vdc(i, 3)))


BEGIN

    CLASS VECTOR(I,J,K); REAL I,J,K;;

    REAL PROCEDURE DOTPRODUCT(A,B); REF(VECTOR) A,B;
        DOTPRODUCT := A.I*B.I+A.J*B.J+A.K*B.K;

    REF(VECTOR) PROCEDURE CROSSPRODUCT(A,B); REF(VECTOR) A,B;
        CROSSPRODUCT :- NEW VECTOR(A.J*B.K - A.K*B.J,
                                   A.K*B.I - A.I*B.K,
                                   A.I*B.J - A.J*B.I);

    REAL PROCEDURE SCALARTRIPLEPRODUCT(A,B,C); REF(VECTOR) A,B,C;
        SCALARTRIPLEPRODUCT := DOTPRODUCT(A,CROSSPRODUCT(B,C));

    REF(VECTOR) PROCEDURE VECTORTRIPLEPRODUCT(A,B,C); REF(VECTOR) A,B,C;
        VECTORTRIPLEPRODUCT :- CROSSPRODUCT(A,CROSSPRODUCT(B,C));

    PROCEDURE OUTR(X); REAL X;
        OUTFIX(X,6,0);

    PROCEDURE OUTVECTOR(A); REF(VECTOR) A;
    BEGIN
        OUTTEXT("(");  OUTR(A.I);
        OUTTEXT(", "); OUTR(A.J);
        OUTTEXT(", "); OUTR(A.K); OUTTEXT(")");
    END;

    BEGIN
        REF(VECTOR) A,B,C;

        A :- NEW VECTOR(3, 4, 5);
        B :- NEW VECTOR(4, 3, 5);
        C :- NEW VECTOR(-5, -12, -13);

        OUTTEXT("A           = "); OUTVECTOR(A);
        OUTIMAGE;
        OUTTEXT("B           = "); OUTVECTOR(B);
        OUTIMAGE;
        OUTTEXT("C           = "); OUTVECTOR(C);
        OUTIMAGE;
        OUTTEXT("A . B       = "); OUTR(DOTPRODUCT(A,B));
        OUTIMAGE;
        OUTTEXT("A X B       = "); OUTVECTOR(CROSSPRODUCT(A,B));
        OUTIMAGE;
        OUTTEXT("A . (B X C) = "); OUTR(SCALARTRIPLEPRODUCT(A,B,C));
        OUTIMAGE;
        OUTTEXT("A X (B X C) = "); OUTVECTOR(VECTORTRIPLEPRODUCT(A,B,C));
        OUTIMAGE;
    END;
END;


mata
real scalar sprod(real colvector u, real colvector v) {
	return(u[1]*v[1] + u[2]*v[2] + u[3]*v[3])
}

real colvector vprod(real colvector u, real colvector v) {
	return(u[2]*v[3]-u[3]*v[2]\u[3]*v[1]-u[1]*v[3]\u[1]*v[2]-u[2]*v[1])
}

real scalar striple(real colvector u, real colvector v, real colvector w) {
	return(sprod(u, vprod(v, w)))
}

real colvector vtriple(real colvector u, real colvector v, real colvector w) {
	return(vprod(u, vprod(v, w)))
}

a = 3\4\5
b = 4\3\5
c = -5\-12\-13

sprod(a, b)
  49

vprod(a, b)
        1
    +------+
  1 |   5  |
  2 |   5  |
  3 |  -7  |
    +------+

striple(a, b, c)
  6

vtriple(a, b, c)
          1
    +--------+
  1 |  -267  |
  2 |   204  |
  3 |    -3  |
    +--------+
end


import Foundation

infix operator • : MultiplicationPrecedence
infix operator × : MultiplicationPrecedence

public struct Vector {
  public var x = 0.0
  public var y = 0.0
  public var z = 0.0

  public init(x: Double, y: Double, z: Double) {
    (self.x, self.y, self.z) = (x, y, z)
  }

  public static func • (lhs: Vector, rhs: Vector) -> Double {
    return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z
  }

  public static func × (lhs: Vector, rhs: Vector) -> Vector {
    return Vector(
      x: lhs.y * rhs.z - lhs.z * rhs.y,
      y: lhs.z * rhs.x - lhs.x * rhs.z,
      z: lhs.x * rhs.y - lhs.y * rhs.x
    )
  }
}

let a = Vector(x: 3, y: 4, z: 5)
let b = Vector(x: 4, y: 3, z: 5)
let c = Vector(x: -5, y: -12, z: -13)

print("a: \(a)")
print("b: \(b)")
print("c: \(c)")
print()
print("a • b = \(a • b)")
print("a × b = \(a × b)")
print("a • (b × c) = \(a • (b × c))")
print("a × (b × c) = \(a × (b × c))")


object Isin extends App {
  val isins = Seq("US0378331005", "US0373831005", "U50378331005",
    "US03378331005", "AU0000XVGZA3","AU0000VXGZA3", "FR0000988040")

  private def ISINtest(isin: String): Boolean = {
    val isin0 = isin.trim.toUpperCase

    def luhnTestS(number: String): Boolean = {

      def luhnTestN(digits: Seq[Int]): Boolean = {

        def checksum(digits: Seq[Int]): Int = {
          digits.reverse.zipWithIndex
            .foldLeft(0) {
              case (sum, (digit, i)) =>
                if (i % 2 == 0) sum + digit
                else sum + (digit * 2) / 10 + (digit * 2) % 10
            } % 10
        }

        checksum(digits) == 0
      }

      luhnTestN(number.map { c =>
        assert(c.isDigit, s"$number has a non-digit error")
        c.asDigit
      })
    }

    if (!isin0.matches("^[A-Z]{2}[A-Z0-9]{9}\\d$")) false
    else {
      val sb = new StringBuilder
      for (c <- isin0.substring(0, 12)) sb.append(Character.digit(c, 36))
      luhnTestS(sb.toString)
    }
  }

  isins.foreach(isin => println(f"$isin is ${if (ISINtest(isin)) "" else "not"}%s valid"))

}


--#SET TERMINATOR @

SET SERVEROUTPUT ON @

CREATE OR REPLACE FUNCTION VALIDATE_ISIN (
  IN IDENTIFIER VARCHAR(12)
 ) RETURNS SMALLINT
 -- ) RETURNS BOOLEAN
 BEGIN
  DECLARE CHECKSUM_FUNC CHAR(1);
  DECLARE CONVERTED VARCHAR(24);
  DECLARE I SMALLINT;
  DECLARE LENGTH SMALLINT;
  DECLARE RET SMALLINT DEFAULT 1;
  --DECLARE RET BOOLEAN DEFAULT FALSE;
  DECLARE CHAR_AT CHAR(1);
  DECLARE INVALID_CHAR CONDITION FOR SQLSTATE 'ISIN1';

  SET CHAR_AT = SUBSTR(IDENTIFIER, 1, 1);
  IF (ASCII(CHAR_AT) < 65 OR 90 < ASCII(CHAR_AT)) THEN
   SIGNAL INVALID_CHAR SET MESSAGE_TEXT = 'Country code with invalid characters';
  END IF;
  SET CHAR_AT = SUBSTR(IDENTIFIER, 2, 1);
  IF (ASCII(CHAR_AT) < 65 OR 90 < ASCII(CHAR_AT)) THEN
   SIGNAL INVALID_CHAR SET MESSAGE_TEXT = 'Country code with invalid characters';
  END IF;

  -- Convert letters to numbers.
  SET I = 1;
  SET CONVERTED = '';
  SET LENGTH = LENGTH(IDENTIFIER);
  WHILE (I <= LENGTH) DO
   SET CHAR_AT = SUBSTR(IDENTIFIER, I, 1);
   IF (48 <= ASCII(CHAR_AT) AND ASCII(CHAR_AT) <= 57) THEN
    SET CONVERTED = CONVERTED || CHAR_AT;
   ELSE
    SET CONVERTED = CONVERTED || (ASCII(CHAR_AT) - 55);
   END IF;
   SET I = I + 1;
  END WHILE;

  CALL DBMS_OUTPUT.PUT_LINE(CONVERTED);

  -- This function is implemented in Rosetta code.
  SET CHECKSUM_FUNC = LUHN_TEST(CONVERTED);
  IF (CHECKSUM_FUNC = 0) THEN
   SET RET = 0;
   --SET RET = TRUE;
  END IF;

  RETURN RET;
 END @


*        Van der Corput sequence   31/01/2017
VDCS     CSECT
         USING  VDCS,R13           base register
         B      72(R15)            skip savearea
         DC     17F'0'             savearea
         STM    R14,R12,12(R13)    prolog
         ST     R13,4(R15)         " <-
         ST     R15,8(R13)         " ->
         LR     R13,R15            " addressability
         ZAP    B,=P'2'            b=2  (base)
         ZAP    M,=P'-1'           m=-1
         SR     R6,R6              i=0
LOOPI    CH     R6,=H'10'          do i=0 to 10
         BH     ELOOPI
         AP     M,=P'1'            w=m+1
         ZAP    V,=P'0'            v=0
         ZAP    S,=P'1'            s=1
         ZAP    N,M                n=m
WHILE    CP     N,=P'0'            do while n<>0
         BE     EWHILE
         MP     S,B                s=s*b
         ZAP    PL16,N             n
         DP     PL16,B             n/b
         ZAP    W,PL16+8(8)        w=n mod b
         MP     W,=P'100000'       *100000
         ZAP    PL16,W             w
         DP     PL16,S             w/s
         ZAP    W,PL16(8)          w=w/s
         AP     V,W                v=v+(n mod b)*100000/s
         ZAP    PL16,N             n
         DP     PL16,B             n/b
         ZAP    N,PL16(8)          n=n/b
         B      WHILE
EWHILE   XDECO  R6,XDEC            edit i
         MVC    PG+0(3),XDEC+9     output i
         MVC    PG+3(3),=C' 0.'
         UNPK   Z,V                unpack v
         OI     Z+L'Z-1,X'F0'      edit v
         MVC    PG+6(5),Z+11       output v  (v/100000)
         XPRNT  PG,L'PG            print buffer
         LA     R6,1(R6)           i=i+1
         B      LOOPI
ELOOPI   L      R13,4(0,R13)       epilog
         LM     R14,R12,12(R13)    " restore
         XR     R15,R15            " rc=0
         BR     R14                exit
B        DS     PL8
M        DS     PL8
V        DS     PL8
S        DS     PL8
N        DS     PL8
W        DS     PL8                packed
Z        DS     ZL16               zoned
PL16     DS     PL16               packed max
PG       DC     CL80' '            buffer
XDEC     DS     CL12               work area for xdeco
         YREGS
         END    VDCS


INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit

PROC Generate(INT value,base REAL POINTER res)
  REAL denom,rbase,r1,r2

  IntToReal(0,res)
  IntToReal(1,denom)
  IntToReal(base,rbase)
  WHILE value#0
  DO
    RealMult(denom,rbase,r1)
    RealAssign(r1,denom)
    IntToReal(value MOD base,r1)
    RealDiv(r1,denom,r2)
    RealAdd(res,r2,r1)
    RealAssign(r1,res)
    value==/base
  OD
RETURN

PROC Main()
  INT value,base
  REAL res

  Put(125) PutE() ;clear the screen
  FOR base=2 TO 5
  DO
    PrintF("Base %I:%E",base)
    FOR value=0 TO 9
    DO
      Generate(value,base,res)
      PrintR(res) Put(32)
    OD
    PutE() PutE()
  OD
RETURN


package {

    import flash.display.Sprite;
    import flash.events.Event;

    public class VanDerCorput extends Sprite {

        public function VanDerCorput():void {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event = null):void {

            removeEventListener(Event.ADDED_TO_STAGE, init);

            var base2:Vector.<Number> = new Vector.<Number>(10, true);
            var base3:Vector.<Number> = new Vector.<Number>(10, true);
            var base4:Vector.<Number> = new Vector.<Number>(10, true);
            var base5:Vector.<Number> = new Vector.<Number>(10, true);
            var base6:Vector.<Number> = new Vector.<Number>(10, true);
            var base7:Vector.<Number> = new Vector.<Number>(10, true);
            var base8:Vector.<Number> = new Vector.<Number>(10, true);

            var i:uint;

            for ( i = 0; i < 10; i++ ) {
                base2[i] = Math.round( _getTerm(i, 2) * 1000000 ) / 1000000;
                base3[i] = Math.round( _getTerm(i, 3) * 1000000 ) / 1000000;
                base4[i] = Math.round( _getTerm(i, 4) * 1000000 ) / 1000000;
                base5[i] = Math.round( _getTerm(i, 5) * 1000000 ) / 1000000;
                base6[i] = Math.round( _getTerm(i, 6) * 1000000 ) / 1000000;
                base7[i] = Math.round( _getTerm(i, 7) * 1000000 ) / 1000000;
                base8[i] = Math.round( _getTerm(i, 8) * 1000000 ) / 1000000;
            }

            trace("Base 2: " + base2.join(', '));
            trace("Base 3: " + base3.join(', '));
            trace("Base 4: " + base4.join(', '));
            trace("Base 5: " + base5.join(', '));
            trace("Base 6: " + base6.join(', '));
            trace("Base 7: " + base7.join(', '));
            trace("Base 8: " + base8.join(', '));

        }

        private function _getTerm(n:uint, base:uint = 2):Number {

            var r:Number = 0, p:uint, digit:uint;
            var baseLog:Number = Math.log(base);

            while ( n > 0 ) {
                p = Math.pow( base, uint(Math.log(n) / baseLog) );

                digit = n / p;
                n %= p;
                r += digit / (p * base);
            }

            return r;

        }

    }

}


proc dot {A B} {
    lassign $A a1 a2 a3
    lassign $B b1 b2 b3
    expr {$a1*$b1 + $a2*$b2 + $a3*$b3}
}
proc cross {A B} {
    lassign $A a1 a2 a3
    lassign $B b1 b2 b3
    list [expr {$a2*$b3 - $a3*$b2}] \
	 [expr {$a3*$b1 - $a1*$b3}] \
	 [expr {$a1*$b2 - $a2*$b1}]
}
proc scalarTriple {A B C} {
    dot $A [cross $B $C]
}
proc vectorTriple {A B C} {
    cross $A [cross $B $C]
}


a = 0                                  ' use variables for vector addresses
b = a + 3
c = b + 3
d = c + 3

Proc _Vector (a, 3, 4, 5)              ' initialize the vectors
Proc _Vector (b, 4, 3, 5)
Proc _Vector (c, -5, -12, -13)

Print "a . b = "; FUNC(_FNdot(a, b))
Proc _Cross (a, b, d)
Print "a x b = (";@(d+0);", ";@(d+1);", ";@(d+2);")"
Print "a . (b x c) = "; FUNC(_FNscalarTriple(a, b, c))
Proc _VectorTriple (a, b, c, d)
Print "a x (b x c) = (";@(d+0);", ";@(d+1);", ";@(d+2);")"
End

_FNdot Param (2)
Return ((@([email protected]+0)*@([email protected]+0))+(@([email protected]+1)*@([email protected]+1))+(@([email protected]+2)*@([email protected]+2)))

_Vector Param (4)                      ' initialize a vector
  @([email protected] + 0) = [email protected]
  @([email protected] + 1) = [email protected]
  @([email protected] + 2) = [email protected]
Return

_Cross Param (3)
  @([email protected]+0) = @([email protected] + 1) * @([email protected] + 2) - @([email protected] + 2) * @([email protected] + 1)
  @([email protected]+1) = @([email protected] + 2) * @([email protected] + 0) - @([email protected] + 0) * @([email protected] + 2)
  @([email protected]+2) = @([email protected] + 0) * @([email protected] + 1) - @([email protected] + 1) * @([email protected] + 0)
Return

_FNscalarTriple Param (3)
  Local (1)                            ' a "local" vector
  [email protected] = d + 3                           ' (best effort) ;-)
  Proc _Cross([email protected], [email protected], [email protected])
Return (FUNC(_FNdot([email protected], [email protected])))

_VectorTriple Param(4)
  Local (1)                            ' a "local" vector
  [email protected] = d + 3                           ' (best effort) ;-)
  Proc _Cross ([email protected], [email protected], [email protected])
  Proc _Cross ([email protected], [email protected], [email protected])
Return


package require Tcl 8.6   ;# mostly needed for [assert].  Substitute a simpler one or a NOP if required.


CREATE FUNCTION dbo._ISINCheck( @strISIN VarChar(40) )
RETURNS bit
AS
BEGIN
--*** Test an ISIN code and return 1 if it is valid, 0 if invalid.
DECLARE @bValid	 bit;

SET @bValid = CASE WHEN @strISIN LIKE '[A-Z][A-Z][A-Z,0-9][A-Z,0-9][A-Z,0-9][A-Z,0-9][A-Z,0-9][A-Z,0-9][A-Z,0-9][A-Z,0-9][A-Z,0-9][0-9]' THEN 1 ELSE 0 END
IF @bValid = 1
	BEGIN
		DECLARE @strTest VarChar(40) = '';
		DECLARE @strAdd  VarChar(2);
		DECLARE @p INT = 0;
		WHILE @p < LEN(@strISIN)
			BEGIN
				SET @p = @p+1;
				SET @strAdd = SUBSTRING(@strISIN,@p,1);
				IF @strAdd LIKE '[A-Z]' SET @strAdd = CONVERT(VarChar(2),ASCII(UPPER(@strAdd))-55);
				SET @strTest = @strTest + @strAdd;
			END;

		-- Proceed with Luhn test
		DECLARE @strLuhn VarChar(40) = REVERSE(@strTest); -- usage: set once, never changed
		DECLARE @strS2Values VarChar(10) = '0246813579';  -- constant: maps digits to their S2 summed values
		SET @p = 0; -- reset loop counter
		DECLARE @intValue INT;
		DECLARE @intSum	INT = 0;
		-- loop through the reversed string, get the value (even-positioned digits are mapped) and add it to @intSum
		WHILE @p < LEN(@strLuhn)
			BEGIN
				SET @p = @p+1;
				SET @intValue = CONVERT(INT, SUBSTRING(@strLuhn,@p,1) ) -- value of the digit at position @p in the string
				IF @p % 2 = 0	SET @intValue = CONVERT(INT,SUBSTRING(@strS2Values,@intValue+1,1))
				SET @intSum = @intSum + @intValue
			END
		-- If the of the digits' mapped values ends in 0 (modulo 10 = 0) then the Luhn test succeeds
		SET @bValid = CASE WHEN @intSum % 10 = 0 THEN 1 ELSE 0 END
	END;

RETURN @bValid
END


' Validate International Securities Identification Number - 03/03/2019

buf=buf&test("US0378331005")&vbCrLf
buf=buf&test("US0373831005")&vbCrLf
buf=buf&test("U50378331005")&vbCrLf
buf=buf&test("US03378331005")&vbCrLf
buf=buf&test("AU0000XVGZA3")&vbCrLf
buf=buf&test("AU0000VXGZA3")&vbCrLf
buf=buf&test("FR0000988040")&vbCrLf
msgbox buf,,"Validate International Securities Identification Number"

function test(cc)
	dim err,c,r,s,i1,i2
	if len(cc)=12 then
		for i=1 to len(cc)
			p=instr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",mid(cc,i,1))
			if p<>0 then c=c&(p-1) else err=1
		next 'i
		for i=1 to 2
			if instr("ABCDEFGHIJKLMNOPQRSTUVWXYZ",mid(cc,i,1))=0 then err=1
		next 'i
		if err=0 then
			for i=len(c) to 1 step -1
				r=r&mid(c,i,1)
			next 'i
			for i=1 to len(r) step 2
				i1=i1+cint(mid(r,i,1))
			next 'i
			for i=2 to len(r) step 2
				ii=cint(mid(r,i,1))*2
				if ii>=10 then ii=ii-9
				i2=i2+ii
			next 'i
			s=cstr(i1+i2)
			if mid(s,len(s),1)="0" then
				msg="valid"
			else
				msg="invalid ??1"
			end if
		else
			msg="invalid ??2"
		end if
	else
		msg="invalid ??3"
	end if
	test=cc&" "&msg
end function 'test


Function IsValidISIN(ByVal ISIN As String) As Boolean
Dim s As String, c As String
Dim i As Long
  If Len(ISIN) = 12 Then
    For i = 1 To Len(ISIN)
      c = UCase$(Mid(ISIN, i, 1))
        Select Case c
        Case "A" To "Z"
          If i = 12 Then Exit Function
          s = s & CStr(Asc(c) - 55)
        Case "0" To "9"
          If i < 3 Then Exit Function
          s = s & c
        Case Else
          Exit Function
        End Select
   Next i
  IsValidISIN = LuhnCheckPassed(s)
  End If
End Function


with Ada.Text_IO;

procedure Main is
   package Float_IO is new Ada.Text_IO.Float_IO (Float);
   function Van_Der_Corput (N : Natural; Base : Positive := 2) return Float is
      Value    : Natural  := N;
      Result   : Float    := 0.0;
      Exponent : Positive := 1;
   begin
      while Value > 0 loop
         Result   := Result +
                     Float (Value mod Base) / Float (Base ** Exponent);
         Value    := Value / Base;
         Exponent := Exponent + 1;
      end loop;
      return Result;
   end Van_Der_Corput;
begin
   for Base in 2 .. 5 loop
      Ada.Text_IO.Put ("Base" & Integer'Image (Base) & ":");
      for N in 1 .. 10 loop
         Ada.Text_IO.Put (' ');
         Float_IO.Put (Item => Van_Der_Corput (N, Base), Exp => 0);
      end loop;
      Ada.Text_IO.New_Line;
   end loop;
end Main;


SetFormat, FloatFast, 0.5
for i, v in [2, 3, 4, 5, 6] {
    seq .= "Base " v ": "
    Loop, 10
        seq .= VanDerCorput(A_Index - 1, v) (A_Index = 10 ? "`n" : ", ")
}
MsgBox, % seq

VanDerCorput(n, b, r=0) {
    while n
        r += Mod(n, b) * b ** -A_Index, n := n // b
    return, r
}


Option Base 1
Function dot_product(a As Variant, b As Variant) As Variant
    dot_product = WorksheetFunction.SumProduct(a, b)
End Function

Function cross_product(a As Variant, b As Variant) As Variant
    cross_product = Array(a(2) * b(3) - a(3) * b(2), a(3) * b(1) - a(1) * b(3), a(1) * b(2) - a(2) * b(1))
End Function

Function scalar_triple_product(a As Variant, b As Variant, c As Variant) As Variant
    scalar_triple_product = dot_product(a, cross_product(b, c))
End Function

Function vector_triple_product(a As Variant, b As Variant, c As Variant) As Variant
    vector_triple_product = cross_product(a, cross_product(b, c))
End Function

Public Sub main()
    a = [{3, 4, 5}]
    b = [{4, 3, 5}]
    c = [{-5, -12, -13}]
    Debug.Print "      a . b = "; dot_product(a, b)
    Debug.Print "      a x b = "; "("; Join(cross_product(a, b), ", "); ")"
    Debug.Print "a . (b x c) = "; scalar_triple_product(a, b, c)
    Debug.Print "a x (b x c) = "; "("; Join(vector_triple_product(a, b, c), ", "); ")"
End Sub


Public Class Vector3D
    Private _x, _y, _z As Double

    Public Sub New(ByVal X As Double, ByVal Y As Double, ByVal Z As Double)
        _x = X
        _y = Y
        _z = Z
    End Sub

    Public Property X() As Double
        Get
            Return _x
        End Get
        Set(ByVal value As Double)
            _x = value
        End Set
    End Property

    Public Property Y() As Double
        Get
            Return _y
        End Get
        Set(ByVal value As Double)
            _y = value
        End Set
    End Property

    Public Property Z() As Double
        Get
            Return _z
        End Get
        Set(ByVal value As Double)
            _z = value
        End Set
    End Property

    Public Function Dot(ByVal v2 As Vector3D) As Double
        Return (X * v2.X) + (Y * v2.Y) + (Z * v2.Z)
    End Function

    Public Function Cross(ByVal v2 As Vector3D) As Vector3D
        Return New Vector3D((Y * v2.Z) - (Z * v2.Y), _
                            (Z * v2.X) - (X * v2.Z), _
                            (X * v2.Y) - (Y * v2.X))
    End Function

    Public Function ScalarTriple(ByVal v2 As Vector3D, ByVal v3 As Vector3D) As Double
        Return Me.Dot(v2.Cross(v3))
    End Function

    Public Function VectorTriple(ByRef v2 As Vector3D, ByVal v3 As Vector3D) As Vector3D
        Return Me.Cross(v2.Cross(v3))
    End Function

    Public Overrides Function ToString() As String
        Return String.Format("({0}, {1}, {2})", _x, _y, _z)
    End Function
End Class


Option Strict On
Imports System.Text.RegularExpressions

Module Module1
    ReadOnly IsinRegex As New Regex("^[A-Z]{2}[A-Z0-9]{9}\d$", RegexOptions.Compiled)

    Function DigitValue(c As Char) As Integer
        Dim temp As Integer
        If Asc(c) >= Asc("0"c) AndAlso Asc(c) <= Asc("9"c) Then
            temp = Asc(c) - Asc("0"c)
        Else
            temp = Asc(c) - Asc("A"c) + 10
        End If
        Return temp
    End Function

    Function LuhnTest(number As String) As Boolean
        Return number.Select(Function(c, i) (AscW(c) - 48) << ((number.Length - i - 1) And 1)).Sum(Function(n) If(n > 9, n - 9, n)) Mod 10 = 0
    End Function

    Function Digitize(isin As String) As String
        Return String.Join("", isin.Select(Function(c) $"{DigitValue(c)}"))
    End Function

    Function IsValidIsin(isin As String) As Boolean
        Return IsinRegex.IsMatch(isin) AndAlso LuhnTest(Digitize(isin))
    End Function

    Sub Main()
        Dim isins() = {
            "US0378331005",
            "US0373831005",
            "U50378331005",
            "US03378331005",
            "AU0000XVGZA3",
            "AU0000VXGZA3",
            "FR0000988040"
        }

        For Each isin In isins
            If IsValidIsin(isin) Then
                Console.WriteLine("{0} is valid", isin)
            Else
                Console.WriteLine("{0} is not valid", isin)
            End If
        Next
    End Sub

End Module


import regex

const (
    inc = [
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        [0, 2, 4, 6, 8, 1, 3, 5, 7, 9],
    ]
)

fn valid_isin(n string) bool {
    mut r,_,_ := regex.regex_base('^[A-Z]{2}[A-Z0-9]{9}\d$')
    if !r.matches_string(n) {
        return false
    }
    mut sum := 0
    mut p := 0
    for i := 10; i >= 0; i-- {
        p = 1 - p
        mut d := n[i..i+1].int()
        if d < 'A'.int() {
            sum += inc[p][d-'0'.int()]
        } else {
            d -= 'A'.int()
            sum += inc[p][d%10]
            p = 1 - p
            sum += inc[p][d/10+1]
        }
    }
    sum += n[11..12].int() - '0'.int()
    return sum%10 == 0
}

struct Testcases {
    isin string
    valid bool
}

fn main(){
    testcases := [
        Testcases{"US0378331005", true},
        Testcases{"US0373831005", false},
        Testcases{"U50378331005", false},
        Testcases{"US03378331005", false},
        Testcases{"AU0000XVGZA3", true},
        Testcases{"AU0000VXGZA3", true},
        Testcases{"FR0000988040", true},
    ]

    for testcase in testcases {
        actual := valid_isin(testcase.isin)
        if actual != testcase.valid {
            println("expected ${testcase.valid} for ${testcase.isin}, got $actual")
        }
    }
}


V string = input(‘Input a string: ’)
V number = Float(input(‘Input a number: ’))


# syntax: GAWK -f VAN_DER_CORPUT_SEQUENCE.AWK
# converted from BBC BASIC
BEGIN {
    printf("base")
    for (i=0; i<=9; i++) {
      printf(" %7d",i)
    }
    printf("\n")
    for (base=2; base<=5; base++) {
      printf("%-4s",base)
      for (i=0; i<=9; i++) {
        printf(" %7.5f",vdc(i,base))
      }
      printf("\n")
    }
    exit(0)
}
function vdc(n,b,  s,v) {
    s = 1
    while (n) {
      s *= b
      v += (n % b) / s
      n /= b
      n = int(n)
    }
    return(v)
}


10 DEFINT A-Z
20 FOR B=2 TO 5
30 PRINT USING "BASE #:";B;
40 FOR I=0 TO 9
50 P=0: Q=1: N=I
60 IF N=0 GOTO 110
70 P=P*B+N MOD B
80 Q=Q*B
90 N=N\B
100 GOTO 60
110 X=P: Y=Q
120 IF P=0 GOTO 150
130 N=P: P=Q MOD P: Q=N
140 GOTO 120
150 X=X\Q
160 Y=Y\Q
170 IF X=0 THEN PRINT "   0"; ELSE PRINT USING "  ##/##";X;Y;
180 NEXT I
190 PRINT
200 NEXT B


struct Vector {
    x f64
    y f64
    z f64
}

const (
    a = Vector{3, 4, 5}
    b = Vector{4, 3, 5}
    c = Vector{-5, -12, -13}
)

fn dot(a Vector, b Vector) f64 {
    return a.x*b.x + a.y*b.y + a.z*b.z
}

fn cross(a Vector, b Vector) Vector {
    return Vector{a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}
}

fn s3(a Vector, b Vector, c Vector) f64 {
    return dot(a, cross(b, c))
}

fn v3(a Vector, b Vector, c Vector) Vector {
    return cross(a, cross(b, c))
}

fn main() {
    println(dot(a, b))
    println(cross(a, b))
    println(s3(a, b, c))
    println(v3(a, b, c))
}


@let {
  dot &[a b] @sum @mapm ^* [a b]
  cross &[a b] [[
    -*a.1 b.2 *a.2 b.1
    -*a.2 b.0 *a.0 b.2
    -*a.0 b.1 *a.1 b.0
  ]]
  scalarTripleProduct &[a b c] !!dot a !!cross b c
  vectorTripleProduct &[a b c] !!cross a !!cross b c

  a [3 4 5]
  b [4 3 5]
  c [5N 12N 13N]

  [[
    !!dot a b
    !!cross a b
    @!scalarTripleProduct [a b c]
    @!vectorTripleProduct [a b c]
  ]]
}


class Vector3D {
    construct new(x, y, z) {
        if (x.type != Num  || y.type != Num || z.type != Num)  Fiber.abort("Arguments must be numbers.")
        _x = x
        _y = y
        _z = z
    }

    x { _x }
    y { _y }
    z { _z }

    dot(v) {
        if (v.type != Vector3D) Fiber.abort("Argument must be a Vector3D.")
        return _x * v.x + _y * v.y + _z * v.z
    }

    cross(v) {
        if (v.type != Vector3D) Fiber.abort("Argument must be a Vector3D.")
        return Vector3D.new(_y*v.z - _z*v.y, _z*v.x - _x*v.z, _x*v.y - _y*v.x)
    }

    scalarTriple(v, w) {
        if ((v.type != Vector3D) || (w.type != Vector3D)) Fiber.abort("Arguments must be Vector3Ds.")
        return this.dot(v.cross(w))
    }

    vectorTriple(v, w) {
        if ((v.type != Vector3D) || (w.type != Vector3D)) Fiber.abort("Arguments must be Vector3Ds.")
        return this.cross(v.cross(w))
    }

    toString { [_x, _y, _z].toString }
}

var a = Vector3D.new(3, 4, 5)
var b = Vector3D.new(4, 3, 5)
var c = Vector3D.new(-5, -12, -13)
System.print("a = %(a)")
System.print("b = %(b)")
System.print("c = %(c)")
System.print()
System.print("a . b     = %(a.dot(b))")
System.print("a x b     = %(a.cross(b))")
System.print("a . b x c = %(a.scalarTriple(b, c))")
System.print("a x b x c = %(a.vectorTriple(b, c))")


import "/str" for Char
import "/trait" for Stepped
import "/fmt" for Conv, Fmt

var luhn = Fn.new { |s|
    s = s[-1..0]
    var s1 = Stepped.new(s, 2).reduce(0) { |sum, d| sum + d.bytes[0] - 48 }
    var s2 = Stepped.new(s[1..-1], 2).reduce(0) { |sum, d|
        var d2 = (d.bytes[0] - 48) * 2
        return sum  + ((d2 > 9) ?  d2%10 + 1 : d2)
    }
    return (s1 + s2)%10 == 0
}

var isin = Fn.new { |s|
    if (!(s is String && s.count == 12)) return false
    for (i in 0..11) {
        var c = s[i]
        if (i <= 1) {
            if (!Char.isUpper(c)) return false
        } else if (i >= 2 && i <= 10) {
            if (!Char.isUpper(c) && !Char.isDigit(c)) return false
        } else {
            if (!Char.isDigit(c)) return false
        }
    }
    var dec = ""
    for (i in 0...s.count) dec = dec + "%(Conv.atoi(s[i], 36))"
    return luhn.call(dec)
}

var tests = [
    "US0378331005", "US0373831005", "U50378331005", "US03378331005",
    "AU0000XVGZA3", "AU0000VXGZA3", "FR0000988040"
]

for (test in tests) {
    var ans = (isin.call(test)) ? "valid" : "not valid"
    System.print("%(Fmt.s(-13, test)) -> %(ans)")
}


//Consts
.equ BUFFERSIZE,   100
.equ STDIN,  0                // linux input console
.equ STDOUT, 1                // linux output console
.equ READ,   63
.equ WRITE,  64
.equ EXIT,   93

.data
enterText:		.asciz "Enter text: "
carriageReturn:  	.asciz "\n"

//Read Buffer
.bss
buffer:    .skip    BUFFERSIZE

.text
.global _start

quadEnterText:        	.quad  enterText
quadBuffer:          	.quad  buffer
quadCarriageReturn:	.quad  carriageReturn

writeMessage:
    mov x2,0                   // reset size counter to 0

checkSize:                     // get size of input
    ldrb w1,[x0,x2]            // load char with offset of x2
    add x2,x2,#1               // add 1 char read legnth
    cbz w1,output              // if char found
    b checkSize                // loop

output:
    mov x1,x0                  // move string address into system call func parm
    mov x0,STDOUT
    mov x8,WRITE
    svc 0                      // trigger system write
    ret

_start:
    //Output enter text
    ldr x0,quadEnterText	// load enter message
    bl writeMessage		// output enter message

    //Read User Input
    mov x0,STDIN           	// linux input console
    ldr x1,quadBuffer      	// load buffer address
    mov x2,BUFFERSIZE      	// load buffer size
    mov x8,READ            	// request to read data
    svc 0                  	// trigger system read input

    //Output User Message
    mov x2, #0			// prep end of string
    ldr x1,quadBuffer      	// load buffer address
    strb w2,[x1, x0]        	// store x2 0 byte at the end of input string, offset x0
    ldr x0,quadBuffer      	// load buffer address
    bl writeMessage

    //Output newline
    ldr x0,quadCarriageReturn
    bl writeMessage

    //End Program
    mov x0, #0             	// return code
    mov x8, #EXIT          	// request to exit program
    svc 0                 	// trigger end of program


INCLUDE "H6:REALMATH.ACT"

PROC Main()
  CHAR ARRAY sUser(255)
  REAL r75000,rUser

  Put(125) PutE() ;clear the screen
  ValR("75000",r75000)

  Print("Please enter a text: ")
  InputS(sUser)

  DO
    Print("Please enter number ")
    PrintR(r75000) Print(": ")
    InputR(rUser)
  UNTIL RealEqual(rUser,r75000)
  OD

  PutE()
  Print("Text: ") PrintE(sUser)
  Print("Number: ") PrintRE(rUser)
RETURN


function Get_String return String is
  Line : String (1 .. 1_000);
  Last : Natural;
begin
  Get_Line (Line, Last);
  return Line (1 .. Last);
end Get_String;

function Get_Integer return Integer is
  S : constant String := Get_String;
begin
  return Integer'Value (S);
  --  may raise exception Constraint_Error if value entered is not a well-formed integer
end Get_Integer;


print("Enter a string: ");
STRING s := read string;
print("Enter a number: ");
INT i := read int;
~


      @% = &20509
      FOR base% = 2 TO 5
        PRINT "Base " ; STR$(base%) ":"
        FOR number% = 0 TO 9
          PRINT FNvdc(number%, base%);
        NEXT
        PRINT
      NEXT
      END

      DEF FNvdc(n%, b%)
      LOCAL v, s%
      s% = 1
      WHILE n%
        s% *= b%
        v += (n% MOD b%) / s%
        n% DIV= b%
      ENDWHILE
      = v


/*
 * Return the _n_th term of the van der Corput sequence.
 * Uses the current _ibase_.
 */
define v(n) {
	auto c, r, s

	s = scale
	scale = 0  /* to use integer division */

	/*
	 * c = count digits of n
	 * r = reverse the digits of n
	 */
	for (0; n != 0; n /= 10) {
		c += 1
		r = (10 * r) + (n % 10)
	}

	/* move radix point to left of digits */
	scale = length(r) + 6
	r /= 10 ^ c

	scale = s
	return r
}

t = 10
for (b = 2; b <= 4; b++) {
	"base "; b
	obase = b
	for (i = 0; i < 10; i++) {
		ibase = b
		"  "; v(i)
		ibase = t
	}
	obase = t
}
quit


get "libhdr"

let corput(n, base, num, denom) be
$(  let p = 0 and q = 1
    until n=0
    $(  p := p * base + n rem base
        q := q * base
        n := n / base
    $)

    !num := p
    !denom := q

    until p=0
    $(  n := p
        p := q rem p
        q := n
    $)

    !num := !num / q
    !denom := !denom / q
$)

let writefrac(num, denom) be
    test num=0
        do writes("  0")
        or writef("  %N/%N", num, denom)

let start() be
$(  let num = ? and denom = ?
    for base=2 to 5
    $(  writef("base %N:", base)
        for i=0 to 9
        $(  corput(i, base, @num, @denom)
            writefrac(num, denom)
        $)
        wrch('*N')
    $)
$)


#> Vector3 Class <#
class Vector3 {
	construct=func(self,x,y,z){
		self:x=x;
		self:y=y;
		self:z=z;
	};
	ToString=func(self){
		send self.x+", "+self.y+", "+self.z;
	};
	Magnitude=func(self){
		send math.sqrt((self.x^2)+(self.y^2)+(self.z^2));
	};
	Normalize=func(self){
		set Mag = self::Magnitude();
		send new Vector3 with [self.x/Mag,self.y/Mag,self.z/Mag];
	};
	Dot=func(self,v2){
		send (self.x*v2.x)+(self.y*v2.y)+(self.z*v2.z);
	};
	__add=func(self,x){
		if (type(x)=="object"){
			send new Vector3 with [self.x+x.x,self.y+x.y,self.z+x.z];
		} else {
			send new Vector3 with [self.x+x,self.y+x,self.z+x];
		}
	};
	__sub=func(self,x){
		if (type(x)=="object"){
			send new Vector3 with [self.x-x.x,self.y-x.y,self.z-x.z];
		} else {
			send new Vector3 with [self.x-x,self.y-x,self.z-x];
		}
	};
	__mul=func(self,x){
		if (type(x)=="object"){
			send new Vector3 with [self.x*x.x,self.y*x.y,self.z*x.z];
		} else {
			send new Vector3 with [self.x*x,self.y*x,self.z*x];
		}
	};
	__div=func(self,x){
		if (type(x)=="object"){
			send new Vector3 with [self.x/x.x,self.y/x.y,self.z/x.z];
		} else {
			send new Vector3 with [self.x/x,self.y/x,self.z/x];
		}
	};
	__pow=func(self,x){
		if (type(x)=="object"){
			send new Vector3 with [self.x^x.x,self.y^x.y,self.z^x.z];
		} else {
			send new Vector3 with [self.x^x,self.y^x,self.z^x];
		}
	};
	__mod=func(self,x){
		if (type(x)=="object"){
			send new Vector3 with [self.x%x.x,self.y%x.y,self.z%x.z];
		} else {
			send new Vector3 with [self.x%x,self.y%x,self.z%x];
		}
	};
	Reflect=func(self,v2){
		set Normal = self::Normalize();
		set Direction = v2::Normalize();
		send (Normal*(2*Normal::Dot(Direction)))-Direction;
	};
	Cross=func(self,v2){
		send new Vector3 with [(self.y*v2.z)-(self.z*v2.y),(self.z*v2.x)-(self.x*v2.z),(self.x*v2.y)-(self.y*v2.x)];
	};
}

math:deg=func(x){
	send x*(180/math.PI);
}

math:rad=func(x){
	send x*(math.PI/180);
}

set a = new Vector3 with [3,4,5];
set b = new Vector3 with [4,3,5];
set c = new Vector3 with [-5,-12,-13];

log("Dot: ",a::Dot(b));
log("Cross: ",a::Cross(b)::ToString());
log("Scalar Triple: ",a::Dot(b::Cross(c)));
log("Vector Triple: ",a::Cross(b::Cross(c))::ToString());


include c:\cxpl\codes;          \intrinsic 'code' declarations

func DotProd(A, B);             \Return the dot product of two 3D vectors
int A, B;                       \A ù B
return A(0)*B(0) + A(1)*B(1) + A(2)*B(2);

proc CrossProd(A, B, C);        \Calculate the cross product of two 3D vectors
int A, B, C;                    \C:= A x B
[C(0):= A(1)*B(2) - A(2)*B(1);
 C(1):= A(2)*B(0) - A(0)*B(2);
 C(2):= A(0)*B(1) - A(1)*B(0);
]; \CrossProd

func ScalarTriProd(A, B, C);    \Return the scalar triple product
int A, B, C;                    \A ù (B x C)
int D(3);
[CrossProd(B, C, D);
return DotProd(A, D);
]; \ScalarTriProd

proc VectTriProd(A, B, C, D);   \Calculate the vector triple product
int A, B, C, D;                 \D:= A x (B x C)
int E(3);
[CrossProd(B, C, E);
 CrossProd(A, E, D);
]; \CrossProd

int A, B, C, D(3);
[A:= [3, 4, 5];  B:= [4, 3, 5];  C:= [-5, -12, -13];

IntOut(0, DotProd(A,B));  CrLf(0);

CrossProd(A, B, D);
IntOut(0, D(0));  ChOut(0, 9\tab\);
IntOut(0, D(1));  ChOut(0, 9\tab\);
IntOut(0, D(2));  CrLf(0);

IntOut(0, ScalarTriProd(A,B,C)); CrLf(0);

VectTriProd(A, B, C, D);
IntOut(0, D(0));  ChOut(0, 9\tab\);
IntOut(0, D(1));  ChOut(0, 9\tab\);
IntOut(0, D(2));  CrLf(0);
]


string 0;               \use zero-terminated strings

func    Luhn(Str);      \Return 'true' if digits in Str pass Luhn test
char    Str;
int     Len, Sum, I, Dig;
[Len:= 0;               \find length of Str
while Str(Len) do Len:= Len+1;
Sum:= 0;                \sum even and odd digits
for I:= 0 to Len-1 do   \(no need to reverse)
        [if (I xor Len) & 1 then
                Sum:= Sum + Str(I) - ^0
        else    [Dig:= Str(I) - ^0;
                Dig:= Dig*2;
                Sum:= Sum + Dig/10 + rem(0);
                ];
        ];
return rem(Sum/10) = 0;
];      \Luhn

func    Valid(Str);     \Return 'true' if valid ISIN code
char    Str, Str2(100);
int     Sum, I, J, C, V;
[J:= 0;
for I:= 0 to 12-1 do    \convert letters in Str to digits in Str2
        [C:= Str(I);
        case of
          C>=^0 & C<=^9: [Str2(J):= C;  J:= J+1];
          C>=^A & C<=^Z: [Str2(J):= (C-^A+10)/10 + ^0;  J:= J+1;
                          Str2(J):= rem(0) + ^0;  J:= J+1]
        other return false;
        if I=1 & J#4 then return false; \first two chars not letters
        ];
if Str(I) # 0 then return false;        \too long
Str2(J):= 0;            \terminate string
return Luhn(Str2);
];      \Valid

int     ISIN, N;
[ISIN:= ["US0378331005",
         "US0373831005",
         "U50378331005",
         "US03378331005",
         "AU0000XVGZA3",
         "AU0000VXGZA3",
         "FR0000988040"];
for N:= 0 to 7-1 do
        [Text(0, ISIN(N));
         Text(0, if Valid(ISIN(N))
                then " is valid"
                else " is not valid");
        CrLf(0);
        ];
]


sub luhntest(cardnr$)
    local i, j, s1, s2, l

    cardnr$ = Trim$(cardnr$) // remove spaces

    l = Len(cardnr$)

    // sum odd numbers
    For i = l To 1 Step -2
        s1 = s1 + (asc(mid$(cardnr$, i, 1)) - Asc("0"))
    Next
    // sum even numbers
    For i = l-1 To 1 Step -2
        j = asc(mid$(cardnr$, i, 1)) - Asc("0")
        j = j * 2
        If j > 9 j = mod(j, 10) + 1
        s2 = s2 + j
    Next

    return mod(s1 + s2, 10) = 0
End sub

// ------=< MAIN >=-----

data "US0378331005", "US0373831005", "U50378331005", "US03378331005", "AU0000XVGZA3", "AU0000VXGZA3", "FR0000988040", ""

do
    read test_item$
    if test_item$ = "" break

    l = Len(test_item$)
    If l <> 12 Then
        Print test_item$, " Invalid, length <> 12 char."
        Continue
    End If
    c1$ = mid$(test_item$, 1, 1) : c2$ = mid$(test_item$, 2, 1)
    If c1$ < "A" Or c1$ > "Z" or c2$ < "A" or c2$ > "Z" Then
        Print test_item$, " Invalid, number needs to start with 2 characters"
        Continue
    End If
    test_str$ = ""
    For n = 1 To l
        x = asc(mid$(test_item$, n, 1)) - Asc("0")
        // if is a letter we to correct for that
        If x > 9 x = x - 7
        If x < 10 Then
            test_str$ = test_str$ + Str$(x)
        Else // two digest number
            test_str$ = test_str$ + Str$(int(x / 10)) + Str$(mod(x, 10))
        End If
    Next
    Print test_item$;
    if luhntest(test_str$) then print " Valid" else print " Invalid, checksum error" end if
loop


fcn validateISIN(isin){
   RegExp(String("^","[A-Z]"*2,"[A-Z0-9]"*9,"[0-9]$")).matches(isin) and
      luhnTest(isin.split("").apply("toInt",36).concat().toInt())
}
fcn luhnTest(n){
   0 == (n.split().reverse().reduce(fcn(s,n,clk){
      s + if(clk.inc()%2) n else 2*n%10 + n/5 },0,Ref(1)) %10)
}


begin
    string(80) s;
    integer    n;
    write( "Enter a string  > " );
    read( s );
    write( "Enter an integer> " );
    read( n )
end.


#include <flow.h>

#import lib/input.bas.lib
#include include/flow-input.h

DEF-MAIN(argv,argc)
   CLR-SCR
   MSET( número, cadena )
   LOCATE(2,2), PRNL( "Input an string : "), LOC-COL(20), LET( cadena := READ-STRING( cadena ) )
   LOCATE(3,2), PRNL( "Input an integer: "), LOC-COL(20), LET( número := INT( VAL(READ-NUMBER( número )) ) )
   LOCATE(5,2), PRNL( cadena, "\n ",número )
END