module Bitmap.Line(line) where

import Bitmap
import Control.Monad
import Control.Monad.ST
import qualified Data.STRef

var = Data.STRef.newSTRef
get = Data.STRef.readSTRef
mutate = Data.STRef.modifySTRef

line :: Color c => Image s c -> Pixel -> Pixel -> c -> ST s ()
line i (Pixel (xa, ya)) (Pixel (xb, yb)) c = do
    yV <- var y1
    errorV <- var $ deltax `div` 2
    forM_ [x1 .. x2] (\x -> do
        y <- get yV
        setPix i (Pixel $ if steep then (y, x) else (x, y)) c
        mutate errorV $ subtract deltay
        error <- get errorV
        when (error < 0) (do
            mutate yV (+ ystep)
            mutate errorV (+ deltax)))
  where steep = abs (yb - ya) > abs (xb - xa)
        (xa', ya', xb', yb') = if steep
          then (ya, xa, yb, xb)
          else (xa, ya, xb, yb)
        (x1, y1, x2, y2) = if xa' > xb'
          then (xb', yb', xa', ya')
          else (xa', ya', xb', yb')
        deltax = x2 - x1
        deltay = abs $ y2 - y1
        ystep = if y1 < y2 then 1 else -1


thru=: <./ + -~ [email protected]+ _1 ^ >        NB. integers from x through y

NB.*getBresenhamLine v Returns points for a line given start and end points
NB. y is: y0 x0 ,: y1 x1
getBresenhamLine=: monad define
  steep=. ([: </ |@-~/) y
  points=. |."1^:steep y
  slope=. %~/ -~/ points
  ypts=. thru/ {."1 points
  xpts=. ({: + 0.5 <[email protected]:+ slope * ypts - {.) {.points
  |."1^:steep ypts,.xpts
)

NB.*drawLines v Draws lines (x) on image (y)
NB. x is: 2-item list (start and end points) ; (color)
drawLines=: (1&{:: ;~ [: ; [: <@getBresenhamLine"2 (0&{::))@[ setPixels ]


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class Bresenham {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Bresenham::run);
    }

    private static void run() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        f.setTitle("Bresenham");

        f.getContentPane().add(new BresenhamPanel());
        f.pack();

        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class BresenhamPanel extends JPanel {

    private final int pixelSize = 10;

    BresenhamPanel() {
        setPreferredSize(new Dimension(600, 500));
        setBackground(Color.WHITE);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        int w = (getWidth() - 1) / pixelSize;
        int h = (getHeight() - 1) / pixelSize;
        int maxX = (w - 1) / 2;
        int maxY = (h - 1) / 2;
        int x1 = -maxX, x2 = maxX * -2 / 3, x3 = maxX * 2 / 3, x4 = maxX;
        int y1 = -maxY, y2 = maxY * -2 / 3, y3 = maxY * 2 / 3, y4 = maxY;

        drawLine(g, 0, 0, x3, y1); // NNE
        drawLine(g, 0, 0, x4, y2); // ENE
        drawLine(g, 0, 0, x4, y3); // ESE
        drawLine(g, 0, 0, x3, y4); // SSE
        drawLine(g, 0, 0, x2, y4); // SSW
        drawLine(g, 0, 0, x1, y3); // WSW
        drawLine(g, 0, 0, x1, y2); // WNW
        drawLine(g, 0, 0, x2, y1); // NNW
    }

    private void plot(Graphics g, int x, int y) {
        int w = (getWidth() - 1) / pixelSize;
        int h = (getHeight() - 1) / pixelSize;
        int maxX = (w - 1) / 2;
        int maxY = (h - 1) / 2;

        int borderX = getWidth() - ((2 * maxX + 1) * pixelSize + 1);
        int borderY = getHeight() - ((2 * maxY + 1) * pixelSize + 1);
        int left = (x + maxX) * pixelSize + borderX / 2;
        int top = (y + maxY) * pixelSize + borderY / 2;

        g.setColor(Color.black);
        g.drawOval(left, top, pixelSize, pixelSize);
    }

    private void drawLine(Graphics g, int x1, int y1, int x2, int y2) {
        // delta of exact value and rounded value of the dependent variable
        int d = 0;

        int dx = Math.abs(x2 - x1);
        int dy = Math.abs(y2 - y1);

        int dx2 = 2 * dx; // slope scaling factors to
        int dy2 = 2 * dy; // avoid floating point

        int ix = x1 < x2 ? 1 : -1; // increment direction
        int iy = y1 < y2 ? 1 : -1;

        int x = x1;
        int y = y1;

        if (dx >= dy) {
            while (true) {
                plot(g, x, y);
                if (x == x2)
                    break;
                x += ix;
                d += dy2;
                if (d > dx) {
                    y += iy;
                    d -= dx2;
                }
            }
        } else {
            while (true) {
                plot(g, x, y);
                if (y == y2)
                    break;
                y += iy;
                d += dx2;
                if (d > dy) {
                    x += ix;
                    d -= dy2;
                }
            }
        }
    }
}


function bline(x0, y0, x1, y1) {

  var dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
  var dy = Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
  var err = (dx>dy ? dx : -dy)/2;

  while (true) {
    setPixel(x0,y0);
    if (x0 === x1 && y0 === y1) break;
    var e2 = err;
    if (e2 > -dx) { err -= dy; x0 += sx; }
    if (e2 < dy) { err += dx; y0 += sy; }
  }
}


function drawline!(img::Matrix{T}, x0::Int, y0::Int, x1::Int, y1::Int, col::T) where T
    δx = abs(x1 - x0)
    δy = abs(y1 - y0)
    δe = abs(δy / δx)
    er = 0.0

    y = y0
    for x in x0:x1
        img[x, y] = col
        er += δe
        if er > 0.5
            y  += 1
            er -= 1.0
        end
    end

    return img
end

using Images

img = fill(Gray(255.0), 5, 5);
println("\nImage:")
display(img); println()
drawline!(img, 1, 1, 5, 5, Gray(0.0));
println("\nModified image:")
display(img); println()


with Ada.Exceptions, Interfaces;
with Ada.Streams;
use Ada.Exceptions, Interfaces;
use Ada.Streams;

package Bitcoin is
    subtype BT_Raw_Addr is Stream_Element_Array(1..25);
    subtype BT_Checksum is Stream_Element_Array(1..4);
    subtype BT_Addr is String(1..34);
    subtype Sha256String is String(1..64);
    Invalid_Address_Error : Exception;

    function Double_Sha256(S : Stream_Element_Array) return BT_Checksum;
    function Is_Valid(A : BT_Raw_Addr) return Boolean;
    procedure Base58_Decode(S : BT_Addr; A : out BT_Raw_Addr) ;
private
    Base58 : constant String := "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
    function Hex_Val (C, C2 : Character) return Stream_Element;
end Bitcoin;

with GNAT.SHA256, Ada.Strings.Fixed;
use  GNAT.SHA256, Ada.Strings.Fixed;

package body Bitcoin is

function Hex_Val (C, C2 : Character) return Stream_Element is
    subtype Nibble is Integer range 0..15;
    HEX : array (0..255) of Nibble := (
          48=>0, 49=>1, 50=>2, 51=>3, 52=>4, 53=>5, 54=>6, 55=>7, 56=>8, 57=>9
        , 65=>10, 66=>11, 67=>12, 68 =>13, 69 =>14, 70 =>15
        , 97=>10, 98=>11, 99=>12, 100=>13, 101=>14, 102=>15
        , Others=>0
    );
begin
    return Stream_Element(HEX(Character'Pos(C)) * 16 + HEX(Character'Pos(C2)));
end Hex_Val;

function Double_Sha256(S : Stream_Element_Array) return BT_Checksum is
    Ctx  : Context := Initial_Context;
    D : Message_Digest;
    S2 : Stream_Element_Array(1..32);
    Ctx2 : Context := Initial_Context;
    C : BT_Checksum;
begin
    Update(Ctx, S);
    D := Digest(Ctx);
    for I in S2'Range loop
        S2(I) := Hex_Val(D(Integer(I)*2-1), D(Integer(I)*2));
    end loop;
    Update(Ctx2, S2);
    D := Digest(Ctx2);
    for I in C'Range loop
        C(I) := Hex_Val(D(Integer(I)*2-1), D(Integer(I)*2));
    end loop;
    return C;

end Double_Sha256;

--------------------------------------------------------------------------------
-- Summary of Base58:                                                         --
-- We decode S into a 200 bit unsigned integer.                               --
-- We could use a BigNum library, but choose to go without.                   --
--------------------------------------------------------------------------------
procedure Base58_Decode(S : BT_Addr; A : out BT_Raw_Addr) is
begin
    A := (Others => 0);
    for I in S'Range loop
        declare
            P : Natural := Index(Base58, String(S(I..I)));
            C : Natural;
        begin
            if P = 0 then
                raise Invalid_Address_Error;
            end if;
            C := P - 1;
            for J in reverse A'Range loop
                C    := C + Natural(A(J)) * 58;
                A(J) := Stream_Element(Unsigned_32(C) and 255);         -- 0x00FF
                C    := Natural(Shift_Right(Unsigned_32(C),8) and 255); -- 0xFF00
            end loop;
            if C /= 0 then
                raise Invalid_Address_Error;
            end if;
        end;
    end loop;
end Base58_Decode;

function Is_Valid(A : BT_Raw_Addr) return Boolean is
begin
    return A(1) = 0 and A(22..25) = Double_Sha256(A(1..21));
end Is_Valid;

end Bitcoin;

with Ada.Text_IO, Bitcoin;
use Ada.Text_IO, Bitcoin;

procedure Bitcoin_Addr_Validate is
begin
    declare
        BTs : array (positive range <>) of BT_Addr := (
              "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"  -- VALID
            , "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9"  -- VALID
            , "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X"  -- checksum changed, original data.
            , "1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"  -- data changed, original checksum.
            , "1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"  -- invalid chars
        );
    begin
        for I in Bts'Range loop
            declare
                A : BT_Raw_Addr;
                Valid : Boolean;
            begin
                Put(BTs(I) & " validity: ");
                Base58_Decode(BTs(I), A);
                Valid := Is_Valid(A);
                Put_Line(Boolean'Image(Valid));
            exception
                when E : Invalid_Address_Error  =>
                    Put_Line ("*** Error: Invalid BT address.");
            end;
        end loop;
    end;
end Bitcoin_Addr_Validate;


-----------------------------------------------
-- Bitmap replacement
-- (why? current Lua impl lacks a "set" method)
-----------------------------------------------
local Bitmap = {
  new = function(self, width, height)
    local instance = setmetatable({ width=width, height=height }, self)
    instance:alloc()
    return instance
  end,
  alloc = function(self)
   self.pixels = {}
    for y = 1, self.height do
      self.pixels[y] = {}
      for x = 1, self.width do
        self.pixels[y][x] = 0x00000000
      end
    end
  end,
  clear = function(self, c)
    for y = 1, self.height do
      for x = 1, self.width do
        self.pixels[y][x] = c or 0x00000000
      end
    end
  end,
  get = function(self, x, y)
    x, y = math.floor(x+1), math.floor(y+1)
    if ((x>=1) and (x<=self.width) and (y>=1) and (y<=self.height)) then
      return self.pixels[y][x]
    else
      return nil
    end
  end,
  set = function(self, x, y, c)
    x, y = math.floor(x+1), math.floor(y+1)
    if ((x>=1) and (x<=self.width) and (y>=1) and (y<=self.height)) then
      self.pixels[y][x] = c or 0x00000000
    end
  end,
}
Bitmap.__index = Bitmap
setmetatable(Bitmap, { __call = function (t, ...) return t:new(...) end })

------------------------------
-- Bresenham's Line Algorithm:
------------------------------
Bitmap.line = function(self, x1, y1, x2, y2, c)
  local dx, sx = math.abs(x2-x1), x1<x2 and 1 or -1
  local dy, sy = math.abs(y2-y1), y1<y2 and 1 or -1
  local err = math.floor((dx>dy and dx or -dy)/2)
  while(true) do
    self:set(x1, y1, c or 0xFFFFFFFF)
    if (x1==x2 and y1==y2) then break end
    if (err > -dx) then
      err, x1 = err-dy, x1+sx
      if (x1==x2 and y1==y2) then
        self:set(x1, y1, c or 0xFFFFFFFF)
        break
      end
    end
    if (err < dy) then
      err, y1 = err+dx, y1+sy
    end
  end
end

--------
-- Demo:
--------
Bitmap.render = function(self, charmap)
  for y = 1, self.height do
    local rowtab = {}
    for x = 1, self.width do
      rowtab[x] = charmap[self.pixels[y][x]]
    end
    print(table.concat(rowtab))
  end
end
local bitmap = Bitmap(61,21)
bitmap:clear()
bitmap:line(0,10,30,0)
bitmap:line(30,0,60,10)
bitmap:line(60,10,30,20)
bitmap:line(30,20,0,10)
bitmap:render({[0x000000]='.', [0xFFFFFFFF]='X'})


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

const char *coin_err;
#define bail(s) { coin_err = s; return 0; }

int unbase58(const char *s, unsigned char *out) {
	static const char *tmpl = "123456789"
		"ABCDEFGHJKLMNPQRSTUVWXYZ"
		"abcdefghijkmnopqrstuvwxyz";
	int i, j, c;
	const char *p;

	memset(out, 0, 25);
	for (i = 0; s[i]; i++) {
		if (!(p = strchr(tmpl, s[i])))
			bail("bad char");

		c = p - tmpl;
		for (j = 25; j--; ) {
			c += 58 * out[j];
			out[j] = c % 256;
			c /= 256;
		}

		if (c) bail("address too long");
	}

	return 1;
}

int valid(const char *s) {
	unsigned char dec[32], d1[SHA256_DIGEST_LENGTH], d2[SHA256_DIGEST_LENGTH];

	coin_err = "";
	if (!unbase58(s, dec)) return 0;

	SHA256(SHA256(dec, 21, d1), SHA256_DIGEST_LENGTH, d2);

	if (memcmp(dec + 21, d2, 4))
		bail("bad digest");

	return 1;
}

int main (void) {
	const char *s[] = {
		"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9",
		"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
		"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9",
		"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I",
		0 };
	int i;
	for (i = 0; s[i]; i++) {
		int status = valid(s[i]);
		printf("%s: %s\n", s[i], status ? "Ok" : coin_err);
	}

	return 0;
}


SegmentBresenham := proc (img, x0, y0, x1, y1)
    local deltax, deltay, x, y, ystep, steep, err, img2, x02, y02, x12, y12;
    x02, x12, y02, y12 := y0, y1, x0, x1;
    steep := abs(x12 - x02) < abs(y12 - y02);
    img2 := copy(img);
    if steep then
        x02, y02 := y02, x02;
        x12, y12 := y12, x12;
    end if;
    if x12 < x02 then
        x02, x12 := x12, x02;
        y02, y12 := y12, y02;
    end if;
    deltax := x12 - x02;
    deltay := abs(y12 - y02);
    err := deltax / 2;
    y := y02;
    if y02 < y12 then
        ystep := 1
    else
        ystep := -1
    end if;
    for x from x02 to x12 do
        if steep then
            img2[y, x] := 0
        else
            img2[x, y] := 0
        end if;
        err := err - deltay;
        if err < 0 then
            y := y + ystep;
            err := err + deltax
        end if;
    end do;
    return img2;
end proc:


Rasterize[Style[Graphics[Line[{{0, 0}, {20, 10}}]], Antialiasing -> False]]


%screen     = Bitmap object
%startPoint = [x0,y0]
%endPoint   = [x1,y1]
%color      = [red,green,blue]

function bresenhamLine(screen,startPoint,endPoint,color)

  if( any(color > 255) )
      error 'RGB colors must be between 0 and 255';
  end

  %Check for vertical line, x0 == x1
  if( startPoint(1) == endPoint(1) )
      %Draw vertical line
      for i = (startPoint(2):endPoint(2))
          setPixel(screen,[startPoint(1) i],color);
      end
  end

  %Simplified Bresenham algorithm
  dx = abs(endPoint(1) - startPoint(1));
  dy = abs(endPoint(2) - startPoint(2));

  if(startPoint(1) < endPoint(1))
      sx = 1;
  else
      sx = -1;
  end

  if(startPoint(2) < endPoint(2))
      sy = 1;
  else
      sy = -1;
  end

  err = dx - dy;
  pixel = startPoint;

  while(true)

      screen.setPixel(pixel,color); %setPixel(x0,y0)

      if( pixel == endPoint )
          break;
      end

      e2 = 2*err;

      if( e2 > -dy )
          err = err - dy;
          pixel(1) = pixel(1) + sx;
      end

      if( e2 < dx )
          err = err + dx;
          pixel(2) = pixel(2) + sy;
      end
  end

  assignin('caller',inputname(1),screen); %saves the changes to the object
end


using System;
using System.Linq;
using System.Security.Cryptography;
using NUnit.Framework;

namespace BitcoinValidator
{
    public class ValidateTest
    {
        [TestCase]
        public void ValidateBitcoinAddressTest()
        {
            Assert.IsTrue(ValidateBitcoinAddress("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i")); // VALID
            Assert.IsTrue(ValidateBitcoinAddress("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9")); // VALID
            Assert.Throws<Exception>(() => ValidateBitcoinAddress("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X")); // checksum changed, original data
            Assert.Throws<Exception>(() => ValidateBitcoinAddress("1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i")); // data changed, original checksum
            Assert.Throws<Exception>(() => ValidateBitcoinAddress("1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i")); // invalid chars
            Assert.Throws<Exception>(() => ValidateBitcoinAddress("BZbvjr")); // checksum is fine, address too short
        }

        public static bool ValidateBitcoinAddress(string address)
        {
            if (address.Length < 26 || address.Length > 35) throw new Exception("wrong length");
            var decoded = DecodeBase58(address);
            var d1 = Hash(decoded.SubArray(0, 21));
            var d2 = Hash(d1);
            if (!decoded.SubArray(21, 4).SequenceEqual(d2.SubArray(0, 4))) throw new Exception("bad digest");
            return true;
        }

        const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
        const int Size = 25;

        private static byte[] DecodeBase58(string input)
        {
            var output = new byte[Size];
            foreach (var t in input)
            {
                var p = Alphabet.IndexOf(t);
                if (p == -1) throw new Exception("invalid character found");
                var j = Size;
                while (--j > 0)
                {
                    p += 58 * output[j];
                    output[j] = (byte)(p % 256);
                    p /= 256;
                }
                if (p != 0) throw new Exception("address too long");
            }
            return output;
        }

        private static byte[] Hash(byte[] bytes)
        {
            var hasher = new SHA256Managed();
            return hasher.ComputeHash(bytes);
        }
    }

    public static class ArrayExtensions
    {
        public static T[] SubArray<T>(this T[] data, int index, int length)
        {
            var result = new T[length];
            Array.Copy(data, index, result, 0, length);
            return result;
        }
    }
}


fn plot img coord steep col =
(
    if steep then
    (
        swap coord[1] coord[2]
    )
    setPixels img coord col
)

fn drawLine img start end col =
(
    local steep = (abs (end.y - start.y)) > (abs (end.x - start.x))

    if steep then
    (
        swap start.x start.y
        swap end.x end.y
    )

    if start.x > end.x then
    (
        swap start.x end.x
        swap start.y end.y
    )

    local deltaX = end.x - start.x
    local deltaY = abs (end.y - start.y)
    local error = deltaX / 2.0
    local yStep = -1
    local y = start.y

    if start.y < end.y then
    (
        yStep = 1
    )

    for x in start.x to end.x do
    (
        plot img [x, y] steep col
        error -= deltaY
        if error < 0 then
        (
            y += yStep
            error += deltaX
        )
    )
    img
)

myBitmap = bitmap 512 512 color:(color 0 0 0)
myBitmap = drawLine myBitmap [0, 511] [511, 0] #((color 255 255 255))
display myBitmap


void drawLine(texture2d<float, access::write> targetTexture, uint2 start, uint2 end);

void drawLine(texture2d<float, access::write> targetTexture, uint2 start, uint2 end)
{
    int x = int(start.x);
    int y = int(start.y);

    int dx = abs(x - int(end.x));
    int dy = abs(y - int(end.y));

    int sx = start.x < end.x ? 1 : -1;
    int sy = start.y < end.y ? 1 : -1;

    int err = (dx > dy ? dx : -dy) / 2;

    while (true)
    {
        targetTexture.write(float4(1.0), uint2(x, y));

        if (x == int(end.x) && y == int(end.y))
        {
            break;
        }

        int e2 = err;

        if (e2 > -dx)
        {
            err -= dy;
            x += sx;
        }

        if (e2 < dy)
        {
            err += dx;
            y += sy;
        }
    }
}


import bitmap

proc drawLine*(img: Image; p, q: Point; color: Color) =
  let
    dx = abs(q.x - p.x)
    sx = if p.x < q.x: 1 else: -1
    dy = abs(q.y - p.y)
    sy = if p.y < q.y: 1 else: -1

  var
    p = p
    q = q
    err = (if dx > dy: dx else: -dy) div 2
    e2 = 0

  while true:
    img[p.x, p.y] = color
    if p == q:
      break
    e2 = err
    if e2 > -dx:
      err -= dy
      p.x += sx
    if e2 < dy:
      err += dx
      p.y += sy

when isMainModule:
  var img = newImage(16, 16)
  img.fill(White)
  img.drawLine((0, 7), (7, 15), Black)
  img.drawLine((7, 15), (15, 7), Black)
  img.drawLine((15, 7), (7, 0), Black)
  img.drawLine((7, 0), (0, 7), Black)
  img.print()


let draw_line ~img ~color ~p0:(x0,y0) ~p1:(x1,y1) =

  let steep = abs(y1 - y0) > abs(x1 - x0) in

  let plot =
    if steep
    then (fun x y -> put_pixel img color y x)
    else (fun x y -> put_pixel img color x y)
  in

  let x0, y0, x1, y1 =
    if steep
    then y0, x0, y1, x1
    else x0, y0, x1, y1
  in
  let x0, x1, y0, y1 =
    if x0 > x1
    then x1, x0, y1, y0
    else x0, x1, y0, y1
  in

  let delta_x = x1 - x0
  and delta_y = abs(y1 - y0) in
  let error = -delta_x / 2
  and y_step =
    if y0 < y1 then 1 else -1
  in
  let rec loop x y error =
    plot x y;
    if x <= x1 then
      let error = error + delta_y in
      let y, error =
        if error > 0
        then (y + y_step), (error - delta_x)
        else y, error
      in
      loop (succ x) y error
  in
  loop x0 y0 error
;;


import std.stdio, std.algorithm, std.array, std.string, sha_256_2;

struct A25 {
    // Type for a 25 ubyte (not base58 encoded) bitcoin address.
    ubyte[25] enc;

    ubyte bitcoinVersion() const pure nothrow @safe @nogc {
        return enc[0];
    }

    ubyte[4] embeddedChecksum() return const pure nothrow @safe @nogc {
        return enc[$ - 4 .. $];
    }

    /** Computes a double sha256 hash of the first 21 bytes of
    the address. Returns the full 32 ubyte sha256 hash. */
    ubyte[32] doubleSHA256() const pure nothrow @nogc {
        return SHA256.digest(SHA256.digest(enc[0 .. 21]));
    }

    /** Returns a four ubyte checksum computed from the first 21
    bytes of the address. */
    ubyte[4] computeChecksum() const pure nothrow @nogc {
        return doubleSHA256[0 .. 4];
    }

    /** Takes a base58 encoded address and decodes it into the
    receiver. Errors are returned if the argument is not valid base58
    or if the decoded value does not fit in the 25 ubyte address.
    The address is not otherwise checked for validity. */
    string set58(in ubyte[] s) pure nothrow @safe @nogc {
        static immutable digits =
        "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
        .representation;
        static assert(digits.length == 58);

        foreach (immutable char s1; s) {
            immutable c = digits.countUntil(s1);
            if (c < 0)
                return "found a bad char in the Bitcoin address.";

            // Currently the D type system can't see c as nonegative.
            uint uc = (c < 0) ? 0 : c;

            foreach_reverse (ref aj; enc) {
                uc += digits.length * aj;
                aj = uc % 256;
                uc /= 256;
            }
            if (uc > 0)
                return "too long Bitcoin address.";
        }

        return null;
    }
}

/** Validates a base58 encoded bitcoin address.  An address is valid
if it can be decoded into a 25 ubyte address, the Version number is 0,
and the checksum validates.  Return value ok will be true for valid
addresses.  If ok is false, the address is invalid and the error value
may indicate why. */
string isValidA58(in ubyte[] a58) pure nothrow @nogc {
    A25 a;
    immutable err = a.set58(a58);
    if (!err.empty)
        return err;
    if (a.bitcoinVersion != 0)
        return "not Bitcoin version 0.";
    return (a.embeddedChecksum == a.computeChecksum) ? null :
           "checksums don't match.";
}

void main() {
    immutable tests = ["1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
                       "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j",
                       "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!",
                       "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz",
                       "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz"];

    foreach (immutable test; tests) {
        immutable err = test.representation.isValidA58;
        writefln(`"%s": %s`, test, err.empty ? "OK." : err);
    }
}


import 'package:crypto/crypto.dart';

class Bitcoin {
  final String ALPHABET =
      "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

  List<int> bigIntToByteArray(BigInt data) {
    String str;
    bool neg = false;
    if (data < BigInt.zero) {
      str = (~data).toRadixString(16);
      neg = true;
    } else str = data.toRadixString(16);
    int p = 0;
    int len = str.length;

    int blen = (len + 1) ~/ 2;
    int boff = 0;
    List bytes;
    if (neg) {
      if (len & 1 == 1) {
        p = -1;
      }
      int byte0 = ~int.parse(str.substring(0, p + 2), radix: 16);
      if (byte0 < -128) byte0 += 256;
      if (byte0 >= 0) {
        boff = 1;
        bytes = new List<int>(blen + 1);
        bytes[0] = -1;
        bytes[1] = byte0;
      } else {
        bytes = new List<int>(blen);
        bytes[0] = byte0;
      }
      for (int i = 1; i < blen; ++i) {
        int byte = ~int.parse(str.substring(p + (i << 1), p + (i << 1) + 2),
            radix: 16);
        if (byte < -128) byte += 256;
        bytes[i + boff] = byte;
      }
    } else {
      if (len & 1 == 1) {
        p = -1;
      }
      int byte0 = int.parse(str.substring(0, p + 2), radix: 16);
      if (byte0 > 127) byte0 -= 256;
      if (byte0 < 0) {
        boff = 1;
        bytes = new List<int>(blen + 1);
        bytes[0] = 0;
        bytes[1] = byte0;
      } else {
        bytes = new List<int>(blen);
        bytes[0] = byte0;
      }
      for (int i = 1; i < blen; ++i) {
        int byte =
            int.parse(str.substring(p + (i << 1), p + (i << 1) + 2), radix: 16);
        if (byte > 127) byte -= 256;
        bytes[i + boff] = byte;
      }
    }
    return bytes;
  }

  List<int> arrayCopy(bytes, srcOffset, result, destOffset, bytesLength) {
    for (int i = srcOffset; i < bytesLength; i++) {
      result[destOffset + i] = bytes[i];
    }
    return result;
  }

  List<int> decodeBase58To25Bytes(String input) {
    BigInt number = BigInt.zero;
    for (String t in input.split('')) {
      int p = ALPHABET.indexOf(t);
      if (p == (-1))
        return null;
      number = number * (BigInt.from(58)) + (BigInt.from(p));
    }
    List<int> result = new List<int>(24);
    List<int> numBytes = bigIntToByteArray(number);
    return arrayCopy(
        numBytes, 0, result, result.length - numBytes.length, numBytes.length);
  }

  validateAddress(String address) {
    List<int> decoded = new List.from(decodeBase58To25Bytes(address));
    List<int> temp = new List<int>.from(decoded);
    temp.insert(0, 0);
    List<int> hash1 = sha256.convert(temp.sublist(0, 21)).bytes;
    List<int> hash2 = sha256.convert(hash1).bytes;
    if (hash2[0] != decoded[20] ||
        hash2[1] != decoded[21] ||
        hash2[2] != decoded[22] ||
        hash2[3] != decoded[23]) return false;
    return true;
  }
}


uses
  DCPsha256;

type
  TByteArray = array of Byte;

function HashSHA256(const Input: TByteArray): TByteArray;
var
  Hasher: TDCP_sha256;
begin
  Hasher := TDCP_sha256.Create(nil);
  try
    Hasher.Init;
    Hasher.Update(Input[0], Length(Input));
    SetLength(Result, Hasher.HashSize div 8);
    Hasher.Final(Result[0]);
  finally
    Hasher.Free;
  end;
end;

function DecodeBase58(const Input: string): TByteArray;
const
  Size = 25;
  Alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
var
  C: Char;
  I, J: Integer;
begin
  SetLength(Result, Size);

  for C in Input do
  begin
    I := Pos(C, Alphabet) - 1;

    if I = -1 then
      raise Exception.CreateFmt('Invalid character found: %s', [C]);

    for J := High(Result) downto 0 do
    begin
      I := I + (58 * Result[J]);
      Result[J] := I mod 256;
      I := I div 256;
    end;

    if I <> 0 then
      raise Exception.Create('Address too long');
  end;
end;

procedure ValidateBitcoinAddress(const Address: string);
var
  Hashed: TByteArray;
  Decoded: TByteArray;
begin
  if (Length(Address) < 26) or (Length(Address) > 35) then
    raise Exception.Create('Wrong length');

  Decoded := DecodeBase58(Address);
  Hashed := HashSHA256(HashSHA256(Copy(Decoded, 0, 21)));

  if not CompareMem(@Decoded[21], @Hashed[0], 4) then
    raise Exception.Create('Bad digest');
end;


-module( bitcoin_address ).

-export( [task/0, validate/1] ).

task() ->
	io:fwrite( "Validate ~p~n", ["1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"] ),
	io:fwrite( "~p~n", [validate("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i")] ),
	io:fwrite( "Validate ~p~n", ["1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW622"] ),
	io:fwrite( "~p~n", [validate("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW622")] ).

validate( String ) ->
	{length_25, <<Address:21/binary, Checksum:4/binary>>} = {length_25, base58:base58_to_binary( String )},
	<<Version:1/binary, _/binary>> = Address,
	{version_0, <<0>>} = {version_0, Version},
	<<Four_bytes:4/binary, _T/binary>> = crypto:hash( sha256, crypto:hash(sha256, Address) ),
	{checksum, Checksum} = {checksum, Four_bytes},
	ok.


USING: byte-arrays checksums checksums.sha io.binary kernel math
math.parser sequences ;
IN: rosetta-code.bitcoin.validation

CONSTANT: ALPHABET "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

: base58>bigint ( str -- n )
  [ ALPHABET index ]
  [ [ 58 * ] [ + ] bi* ] map-reduce ;

: base58> ( str -- bytes ) base58>bigint 25 >be ;

: btc-checksum ( bytes -- checksum-bytes )
  21 head 2 [ sha-256 checksum-bytes ] times 4 head ;

: btc-valid? ( str -- ? ) base58> [ btc-checksum ] [ 4 tail* ] bi = ;


-- demo\rosetta\Bresenham_line.exw (runnable version)

global function bresLine(sequence image, integer x0, y0, x1, y1, colour)
    -- The line algorithm
    integer dimx = length(image),
            dimy = length(image[1]),
            deltaX = abs(x1-x0),
            deltaY = abs(y1-y0),
            stepX = iff(x0<x1,1,-1),
            stepY = iff(y0<y1,1,-1),
            lineError = iff(deltaX>deltaY,deltaX,-deltaY),
            prevle
    lineError = round(lineError/2, 1)
    while true do
        if  x0>=1 and x0<=dimx
        and y0>=1 and y0<=dimy then
            image[x0][y0] = colour
        end if
        if x0=x1 and y0=y1 then exit end if
        prevle = lineError
        if prevle>-deltaX then
            lineError -= deltaY
            x0 += stepX
        end if
        if prevle<deltaY then
            lineError += deltaX
            y0 += stepY
        end if
    end while
    return image
end function

--include ppm.e   -- red, green, blue, white, new_image(), write_ppm(), bresLine()  (as distributed, instead of the above)

sequence screenData = new_image(400,300,black)
screenData = bresLine(screenData,100,1,50,300,red)
screenData = bresLine(screenData,1,180,400,240,green)
screenData = bresLine(screenData,200,1,400,150,white)
screenData = bresLine(screenData,195,1,205,300,blue)
write_ppm("bresenham.ppm",screenData)


(de brez (Img X Y DX DY)
   (let SX
      (cond
         ((=0 DX) 0)
         ((gt0 DX) 1)
         (T (setq DX (- DX)) -1) )
      (let SY
         (cond
            ((=0 DY) 0)
            ((gt0 DY) 1)
            (T (setq DY (- DY)) -1) )
         (if (>= DX DY)
            (let E (- (* 2 DY) DX)
               (do DX
                  (set (nth Img Y X) 1)
                  (when (ge0 E)
                     (inc 'Y SY)
                     (dec 'E (* 2 DX)) )
                  (inc 'X SX)
                  (inc 'E (* 2 DY)) ) )
            (let E (- (* 2 DX) DY)
               (do DY
                  (set (nth Img Y X) 1)
                  (when (ge0 E)
                     (inc 'X SX)
                     (dec 'E (* 2 DY)) )
                  (inc 'Y SY)
                  (inc 'E (* 2 DX)) ) ) ) ) ) )

(let Img (make (do 90 (link (need 120 0))))        # Create image 120 x 90
   (brez Img 10 10 100 30)                         # Draw five lines
   (brez Img 10 10 100 50)
   (brez Img 10 10 100 70)
   (brez Img 10 10 60 70)
   (brez Img 10 10 20 70)
   (out "img.pbm"                                  # Write to bitmap file
      (prinl "P1")
      (prinl 120 " " 90)
      (mapc prinl Img) ) )


/* Draw a line from (x0, y0) to (x1, y1).   13 May 2010 */
/* Based on Rosetta code proforma. */

   /* Declarations for image and selected color, for 4-bit colors. */
   declare image(40,40) bit (4), color bit (4) static initial ('1000'b);

draw_line: procedure (xi, yi, xf, yf );
   declare (xi, yi, xf, yf) fixed binary (31) nonassignable;
   declare (x0, y0, x1, y1) fixed binary (31);
   declare (deltax, deltay, x, y, ystep) fixed binary;
   declare (error initial (0), delta_error) float;
   declare steep bit (1);

   x0 = xi; y = YI; y0 = yi; x1 = xf; y1 = yf;
   steep = abs(y1 - y0) > abs (x1 - x0);
   if steep then
      do; call swap (x0, y0); call swap (x1, y1); end;
   if x0 > x1 then
      do; call swap (x0, x1); call swap (y0, y1); end;
   deltax = x1 - x0; deltay = abs(y1 - y0);
   delta_error = deltay/deltax;
   if y0 < y1 then ystep = 1; else ystep = -1;
   do x = x0 to x1;
       if steep then image(y, x) = color; else image(x, y) = color;
       if steep then put skip list (y, x); else put skip list (x, y);
       error = error + delta_error;
       if error >= 0.5 then do; y = y + ystep; error = error - 1; end;
   end;

swap: procedure (a, b);
   declare (a, b) fixed binary (31);
   declare t fixed binary (31);
   t = a; a = b; b = t;
end swap;

end draw_line;


:- use_module(bitmap).
:- use_module(bitmapIO).
:- use_module(library(clpfd)).

% ends when X1 = X2 and Y1 = Y2
draw_recursive_line(NPict,Pict,Color,X,X,_DX,_DY,Y,Y,_E,_Sx,_Sy):-
	set_pixel0(NPict,Pict,[X,Y],Color).
draw_recursive_line(NPict,Pict,Color,X,X2,DX,DY,Y,Y2,E,Sx,Sy):-
	set_pixel0(TPict,Pict,[X,Y],Color),
	E2 #= 2*E,
	% because we can't accumulate error we set Ey or Ex to 1 or 0
	% depending on whether we need to add dY or dX to the error term
	(   E2 >= DY ->
	        Ey = 1, NX #= X + Sx;
	        Ey = 0, NX = X),
	(   E2 =< DX ->
	        Ex = 1, NY #= Y + Sy;
		Ex = 0, NY = Y),
	NE #= E + DX*Ex + DY*Ey,
	draw_recursive_line(NPict,TPict,Color,NX,X2,DX,DY,NY,Y2,NE,Sx,Sy).

draw_line(NPict,Pict,Color,X1,Y1,X2,Y2):-
	DeltaY #= Y2-Y1,
	DeltaX #= X2-X1,
	(   DeltaY < 0 -> Sy = -1; Sy = 1),
	(   DeltaX < 0 -> Sx = -1; Sx = 1),
	DX #= abs(DeltaX),
	DY #= -1*abs(DeltaY),
	E #= DY+DX,
	draw_recursive_line(NPict,Pict,Color,X1,X2,DX,DY,Y1,Y2,E,Sx,Sy).

 init:-
	new_bitmap(B,[100,100],[255,255,255]),
	draw_line(NB,B,[0,0,0],2,2,10,90),
	write_ppm_p6('line.ppm',NB).


' version 05-04-2017
' compile with: fbc -s console

' function adapted from the SHA-256 task
Function SHA_256(test_str As String, bitcoin As ULong = 0) As String

    #Macro Ch (x, y, z)
        (((x) And (y)) Xor ((Not (x)) And z))
    #EndMacro

    #Macro Maj (x, y, z)
        (((x) And (y)) Xor ((x) And (z)) Xor ((y) And (z)))
    #EndMacro

    #Macro sigma0 (x)
        (((x) Shr 2 Or (x) Shl 30) Xor ((x) Shr 13 Or (x) Shl 19) Xor ((x) Shr 22 Or (x) Shl 10))
    #EndMacro

    #Macro sigma1 (x)
        (((x) Shr 6 Or (x) Shl 26) Xor ((x) Shr 11 Or (x) Shl 21) Xor ((x) Shr 25 Or (x) Shl 7))
    #EndMacro

    #Macro sigma2 (x)
        (((x) Shr 7 Or (x) Shl 25) Xor ((x) Shr 18 Or (x) Shl 14) Xor ((x) Shr 3))
    #EndMacro

    #Macro sigma3 (x)
        (((x) Shr 17 Or (x) Shl 15) Xor ((x) Shr 19 Or (x) Shl 13) Xor ((x) Shr 10))
    #EndMacro

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

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

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

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

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

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

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

        'table of constants
        Dim As UInteger<32> K(0 To ...) = _
        { &H428a2f98, &H71374491, &Hb5c0fbcf, &He9b5dba5, &H3956c25b, &H59f111f1, _
          &H923f82a4, &Hab1c5ed5, &Hd807aa98, &H12835b01, &H243185be, &H550c7dc3, _
          &H72be5d74, &H80deb1fe, &H9bdc06a7, &Hc19bf174, &He49b69c1, &Hefbe4786, _
          &H0fc19dc6, &H240ca1cc, &H2de92c6f, &H4a7484aa, &H5cb0a9dc, &H76f988da, _
          &H983e5152, &Ha831c66d, &Hb00327c8, &Hbf597fc7, &Hc6e00bf3, &Hd5a79147, _
          &H06ca6351, &H14292967, &H27b70a85, &H2e1b2138, &H4d2c6dfc, &H53380d13, _
          &H650a7354, &H766a0abb, &H81c2c92e, &H92722c85, &Ha2bfe8a1, &Ha81a664b, _
          &Hc24b8b70, &Hc76c51a3, &Hd192e819, &Hd6990624, &Hf40e3585, &H106aa070, _
          &H19a4c116, &H1e376c08, &H2748774c, &H34b0bcb5, &H391c0cb3, &H4ed8aa4a, _
          &H5b9cca4f, &H682e6ff3, &H748f82ee, &H78a5636f, &H84c87814, &H8cc70208, _
          &H90befffa, &Ha4506ceb, &Hbef9a3f7, &Hc67178f2 }

        Dim As UInteger<32> h0 = &H6a09e667
        Dim As UInteger<32> h1 = &Hbb67ae85
        Dim As UInteger<32> h2 = &H3c6ef372
        Dim As UInteger<32> h3 = &Ha54ff53a
        Dim As UInteger<32> h4 = &H510e527f
        Dim As UInteger<32> h5 = &H9b05688c
        Dim As UInteger<32> h6 = &H1f83d9ab
        Dim As UInteger<32> h7 = &H5be0cd19
        Dim As UInteger<32> a, b, c, d, e, f, g, h
        Dim As UInteger<32> t1, t2, w(0 To 63)

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

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

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

            For i = 16 To 63   ' fill the rest of the array
                w(i) = sigma3(W(i -2)) + W(i -7) + sigma2(W(i -15)) + W(i -16)
            Next

            a = h0 : b = h1 : c = h2 : d = h3 : e = h4 : f = h5 : g = h6 : h = h7

            For i = 0 To 63
                t1 = h + sigma1(e) + Ch(e, f, g) + K(i) + W(i)
                t2 = sigma0(a) + Maj(a, b, c)
                h = g : g = f : f = e
                e = d + t1
                d = c : c = b : b = a
                a = t1 + t2
            Next

            h0 += a : h1 += b : h2 += c : h3 += d
            h4 += e : h5 += f : h6 += g : h7 += h

        Next j

        Dim As String answer  = Hex(h0, 8) + Hex(h1, 8) + Hex(h2, 8) + Hex(h3, 8) _
        + Hex(h4, 8) + Hex(h5, 8) + Hex(h6, 8) + Hex(h7, 8)

        If bitcoin = 0 Then
            Return LCase(answer)
        Else 'conver hex value's to integer value's
            message = String(32,0)
            For i = 0 To 31
                message[i] = Val("&h" + Mid(answer, i * 2 + 1, 2))
            Next
            bitcoin = 0
        End If

    Loop

End Function

Function conv_base58(bitcoin_address As String) As String

    Dim As String base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
    Dim As String tmp = String(24, 0)
    Dim As Long x, y, z

    For x = 1 To Len(bitcoin_address) -1
        z = InStr(base58, Chr(bitcoin_address[x])) -1
        If z = -1 Then
            Print " bitcoin address contains illegal character"
            Return ""
        End If
        For y = 23 To 0 Step -1
            z = z + tmp[y] * 58
            tmp[y] = z And 255       ' test_str[y] = z Mod 256
            z Shr= 8                 ' z \= 256
        Next
        If z <> 0 Then
            Print " bitcoin address is to long"
            Return ""
        End If
    Next

    z = InStr(base58, Chr(bitcoin_address[0])) -1
    Return Chr(z) + tmp

End Function

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

Data "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" ' original
Data "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j" ' checksum changed
Data "1NAGa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" ' address changed
Data "0AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" ' only 1 or 3 as first char. allowed
Data "1AGNa15ZQXAZUgFlqJ2i7Z2DPU2J6hW62i" ' illegal character in address

Dim As String tmp, result, checksum, bitcoin_address
Dim As Long i, j

For i = 1 To 5

    Read bitcoin_address
    Print "Bitcoin address: "; bitcoin_address;
    tmp = Left(bitcoin_address,1)

    If tmp <> "1" And tmp <> "3" Then
        Print " first character is not 1 or 3"
        Continue For
    End If

    ' convert bitcoinaddress
    tmp = conv_base58(bitcoin_address)
    If tmp = "" Then Continue For
    ' get the checksum, last 4 digits
    For j As Long = 21 To 24
        checksum = checksum + LCase(Hex(tmp[j], 2))
    Next

    ' send the first 21 characters to the SHA 256 routine
    result = SHA_256(Left(tmp, 21), 2)
    result = Left(result, 8) ' get the checksum (the first 8 digits (hex))
    If checksum = result Then          ' test the found checksum against
        Print " is valid"              ' the one from the address
    Else
        Print " is not valid, checksum fails"
    End If

Next

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


Procedure BresenhamLine(x0 ,y0 ,x1 ,y1)
     If Abs(y1 - y0) > Abs(x1 - x0);
        steep =#True
        Swap x0, y0
        Swap x1, y1
     EndIf
     If x0 > x1
         Swap x0, x1
         Swap y0, y1
     EndIf
     deltax = x1 - x0
     deltay = Abs(y1 - y0)
     error = deltax / 2
     y = y0
     If y0 < y1
        ystep = 1
     Else
        ystep = -1
     EndIf
     For x = x0 To x1
         If steep
           Plot(y,x)
         Else
           Plot(x,y)
         EndIf
         error - deltay
         If error < 0
             y + ystep
             error + deltax
         EndIf
     Next
EndProcedure

#Window1   = 0
#Image1    = 0
#ImgGadget = 0
#width     = 300
#height    = 300

Define.i Event
Define.f Angle

If OpenWindow(#Window1, 0, 0, #width, #height, "Bresenham's Line PureBasic Example", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
   If CreateImage(#Image1, #width, #height)
      ImageGadget(#ImgGadget, 0, 0, #width, #height, ImageID(#Image1))
      StartDrawing(ImageOutput(#Image1))
      FillArea(0,0,-1,$FFFFFF) :FrontColor(0)
      While Angle < 2*#PI
        BresenhamLine(150,150,150+Cos(Angle)*120,150+Sin(Angle)*120)
        Angle + #PI/60
      Wend

      StopDrawing()
      SetGadgetState(#ImgGadget, ImageID(#Image1))
      Repeat
        Event = WaitWindowEvent()
      Until Event = #PB_Event_CloseWindow
   EndIf
EndIf


def line(self, x0, y0, x1, y1):
    "Bresenham's line algorithm"
    dx = abs(x1 - x0)
    dy = abs(y1 - y0)
    x, y = x0, y0
    sx = -1 if x0 > x1 else 1
    sy = -1 if y0 > y1 else 1
    if dx > dy:
        err = dx / 2.0
        while x != x1:
            self.set(x, y)
            err -= dy
            if err < 0:
                y += sy
                err += dx
            x += sx
    else:
        err = dy / 2.0
        while y != y1:
            self.set(x, y)
            err -= dx
            if err < 0:
                x += sx
                err += dy
            y += sy
    self.set(x, y)
Bitmap.line = line

bitmap = Bitmap(17,17)
for points in ((1,8,8,16),(8,16,16,8),(16,8,8,1),(8,1,1,8)):
    bitmap.line(*points)
bitmap.chardisplay()

'''
The origin, 0,0; is the lower left, with x increasing to the right,
and Y increasing upwards.

The chardisplay above produces the following output :
+-----------------+
|        @        |
|       @ @       |
|      @   @      |
|     @     @     |
|    @       @    |
|    @        @   |
|   @          @  |
|  @            @ |
| @              @|
|  @            @ |
|   @          @  |
|    @       @@   |
|     @     @     |
|      @   @      |
|       @ @       |
|        @        |
|                 |
+-----------------+
'''


package main

import (
    "bytes"
    "crypto/sha256"
    "errors"
    "os"
)

// With at least one other bitcoin RC task, this source is styled more like
// a package to show how functions of the two tasks might be combined into
// a single package.  It turns out there's not really that much shared code,
// just the A25 type and doubleSHA256 method, but it's enough to suggest how
// the code might be organized.  Types, methods, and functions are capitalized
// where they might be exported from a package.

// A25 is a type for a 25 byte (not base58 encoded) bitcoin address.
type A25 [25]byte

func (a *A25) Version() byte {
    return a[0]
}

func (a *A25) EmbeddedChecksum() (c [4]byte) {
    copy(c[:], a[21:])
    return
}

// DoubleSHA256 computes a double sha256 hash of the first 21 bytes of the
// address.  This is the one function shared with the other bitcoin RC task.
// Returned is the full 32 byte sha256 hash.  (The bitcoin checksum will be
// the first four bytes of the slice.)
func (a *A25) doubleSHA256() []byte {
    h := sha256.New()
    h.Write(a[:21])
    d := h.Sum([]byte{})
    h = sha256.New()
    h.Write(d)
    return h.Sum(d[:0])
}

// ComputeChecksum returns a four byte checksum computed from the first 21
// bytes of the address.  The embedded checksum is not updated.
func (a *A25) ComputeChecksum() (c [4]byte) {
    copy(c[:], a.doubleSHA256())
    return
}/* {{header|Go}} */

// Tmpl and Set58 are adapted from the C solution.
// Go has big integers but this techinique seems better.
var tmpl = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")

// Set58 takes a base58 encoded address and decodes it into the receiver.
// Errors are returned if the argument is not valid base58 or if the decoded
// value does not fit in the 25 byte address.  The address is not otherwise
// checked for validity.
func (a *A25) Set58(s []byte) error {
    for _, s1 := range s {
        c := bytes.IndexByte(tmpl, s1)
        if c < 0 {
            return errors.New("bad char")
        }
        for j := 24; j >= 0; j-- {
            c += 58 * int(a[j])
            a[j] = byte(c % 256)
            c /= 256
        }
        if c > 0 {
            return errors.New("too long")
        }
    }
    return nil
}

// ValidA58 validates a base58 encoded bitcoin address.  An address is valid
// if it can be decoded into a 25 byte address, the version number is 0,
// and the checksum validates.  Return value ok will be true for valid
// addresses.  If ok is false, the address is invalid and the error value
// may indicate why.
func ValidA58(a58 []byte) (ok bool, err error) {
    var a A25
    if err := a.Set58(a58); err != nil {
        return false, err
    }
    if a.Version() != 0 {
        return false, errors.New("not version 0")
    }
    return a.EmbeddedChecksum() == a.ComputeChecksum(), nil
}

// Program returns exit code 0 with valid address and produces no output.
// Otherwise exit code is 1 and a message is written to stderr.
func main() {
    if len(os.Args) != 2 {
        errorExit("Usage: valid <base58 address>")
    }
    switch ok, err := ValidA58([]byte(os.Args[1])); {
    case ok:
    case err == nil:
        errorExit("Invalid")
    default:
        errorExit(err.Error())
    }
}

func errorExit(m string) {
    os.Stderr.WriteString(m + "\n")
    os.Exit(1)
}


#lang racket
(require racket/draw)

(define (draw-line dc x0 y0 x1 y1)
  (define dx (abs (- x1 x0)))
  (define dy (abs (- y1 y0)))
  (define sx (if (> x0 x1) -1 1))
  (define sy (if (> y0 y1) -1 1))
  (cond
    [(> dx dy)
     (let loop ([x x0] [y y0] [err (/ dx 2.0)])
       (unless (= x x1)
         (send dc draw-point x y)
         (define newerr (- err dy))
         (if (< newerr 0)
             (loop (+ x sx) (+ y sy) (+ newerr dx))
             (loop (+ x sx)    y        newerr))))]
    [else
     (let loop ([x x0] [y y0] [err (/ dy 2.0)])
       (unless (= y y1)
         (send dc draw-point x y)
         (define newerr (- err dy))
         (if (< newerr 0)
             (loop (+ x sx) (+ y sy)    newerr)
             (loop    x     (+ y sy) (+ newerr dy)))))]))

(define bm (make-object bitmap% 17 17))
(define dc (new bitmap-dc% [bitmap bm]))
(send dc set-smoothing 'unsmoothed)
(send dc set-pen "red" 1 'solid)
(for ([points '((1 8 8 16) (8 16 16 8) (16 8 8 1) (8 1 1 8))])
  (apply draw-line  (cons dc points)))
bm


class Pixel { has UInt ($.R, $.G, $.B) }
class Bitmap {
    has UInt ($.width, $.height);
    has Pixel @!data;

    method fill(Pixel $p) {
        @!data = $p.clone xx ($!width*$!height)
    }
    method pixel(
	$i where ^$!width,
	$j where ^$!height
	--> Pixel
    ) is rw { @!data[$i + $j * $!width] }

    method set-pixel ($i, $j, Pixel $p) {
	self.pixel($i, $j) = $p.clone;
    }
    method get-pixel ($i, $j) returns Pixel {
	self.pixel($i, $j);
    }
}

sub line(Bitmap $bitmap, $x0 is copy, $x1 is copy, $y0 is copy, $y1 is copy) {
    my $steep = abs($y1 - $y0) > abs($x1 - $x0);
    if $steep {
        ($x0, $y0) = ($y0, $x0);
        ($x1, $y1) = ($y1, $x1);
    }
    if $x0 > $x1 {
        ($x0, $x1) = ($x1, $x0);
        ($y0, $y1) = ($y1, $y0);
    }
    my $Δx = $x1 - $x0;
    my $Δy = abs($y1 - $y0);
    my $error = 0;
    my $Δerror = $Δy / $Δx;
    my $y-step = $y0 < $y1 ?? 1 !! -1;
    my $y = $y0;
    for $x0 .. $x1 -> $x {
        my $pix = Pixel.new(R => 100, G => 200, B => 0);
        if $steep {
            $bitmap.set-pixel($y, $x, $pix);
        } else {
            $bitmap.set-pixel($x, $y, $pix);
        }
        $error += $Δerror;
        if $error >= 0.5 {
            $y += $y-step;
            $error -= 1.0;
        }
    }
}


import           Control.Monad      (when)
import           Data.List          (elemIndex)
import           Data.Monoid        ((<>))
import qualified Data.ByteString    as BS
import           Data.ByteString    (ByteString)

import           Crypto.Hash.SHA256 (hash)  -- from package cryptohash

-- Convert from base58 encoded value to Integer
decode58 :: String -> Maybe Integer
decode58 = fmap combine . traverse parseDigit
  where
    combine = foldl (\acc digit -> 58 * acc + digit) 0  -- should be foldl', but this trips up the highlighting
    parseDigit char = toInteger <$> elemIndex char c58
    c58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

-- Convert from base58 encoded value to bytes
toBytes :: Integer -> ByteString
toBytes = BS.reverse . BS.pack . map (fromIntegral . (`mod` 256)) . takeWhile (> 0) . iterate (`div` 256)

-- Check if the hash of the first 21 (padded) bytes matches the last 4 bytes
checksumValid :: ByteString -> Bool
checksumValid address =
  let (value, checksum) = BS.splitAt 21 $ leftPad address
  in and $ BS.zipWith (==) checksum $ hash $ hash $ value
  where
    leftPad bs = BS.replicate (25 - BS.length bs) 0 <> bs

-- utility
withError :: e -> Maybe a -> Either e a
withError e = maybe (Left e) Right

-- Check validity of base58 encoded bitcoin address.
-- Result is either an error string (Left) or unit (Right ()).
validityCheck :: String -> Either String ()
validityCheck encoded = do
  num <- withError "Invalid base 58 encoding" $ decode58 encoded
  let address = toBytes num
  when (BS.length address > 25) $ Left "Address length exceeds 25 bytes"
  when (BS.length address <  4) $ Left "Address length less than 4 bytes"
  when (not $ checksumValid address) $ Left "Invalid checksum"

-- Run one validity check and display results.
validate :: String -> IO ()
validate encodedAddress = do
  let result = either show (const "Valid") $ validityCheck encodedAddress
  putStrLn $ show encodedAddress ++ " -> " ++ result

-- Run some validity check tests.
main :: IO ()
main  = do
  validate "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"     -- VALID
  validate "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9"     -- VALID
  validate "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X"     -- checksum changed, original data.
  validate "1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"     -- data changed, original checksum.
  validate "1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"     -- invalid chars
  validate "1ANa55215ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"   -- too long
  validate "i55j"                                   -- too short


SUB draw_line(x1, y1, x2, y2, colour)
    x_dist = abs(x2-x1)
    y_dist = abs(y2-y1)
    IF y2-y1 < -x_dist OR x2-x1 <= -y_dist THEN
        SWAP x1, x2       ' Swap start and end points
  SWAP y1, y2
    END IF
    IF x1 < x2 THEN x_step = 1 ELSE x_step = -1
    IF y1 < y2 THEN y_step = 1 ELSE y_step = -1

    IF y_dist > x_dist THEN     ' steep angle, step by y
  error = y_dist/2
  x = x1
  FOR y = y1 TO y2
      canvas.Pset(x, y, colour)
      error = error - x_dist
      IF error < 0 THEN
          x = x + x_step
    error = error + y_dist
      END IF
  NEXT y
    ELSE          ' not steep, step by x
        error = x_dist/2
  y = y1
  FOR x = x1 TO x2
      canvas.Pset(x, y, colour)
      error = error - y_dist
      IF error < 0 THEN
          y = y + y_step
    error = error + x_dist
      END IF
  NEXT y
    END IF

END SUB


/*REXX program  plots/draws line segments  using the  Bresenham's line  (2D) algorithm. */
parse arg data                                   /*obtain optional arguments from the CL*/
if data=''  then data= "(1,8)  (8,16)  (16,8)  (8,1)  (1,8)"         /* ◄──── a rhombus.*/
data= translate(data, , '()[]{}/,:;')            /*elide chaff from the data points.    */
@.= '·'                                          /*use mid─dots chars (plot background).*/
           do points=1  while data\=''           /*put the data points into an array (!)*/
           parse var data x y data; !.points=x y /*extract the line segments.           */
           if points==1  then do;  minX= x;  maxX= x;  minY= y;  maxY= y     /*1st case.*/
                              end
           minX= min(minX,x);   maxX= max(maxX,x);   minY= min(minY,y);  maxY= max(maxY,y)
           end   /*points*/                      /* [↑]  data points pairs in array  !. */
border= 2                                        /*border:  is extra space around plot. */
minX= minX - border*2;    maxX= maxX + border*2  /*min and max  X  for the plot display.*/
minY= minY - border  ;    maxY= maxY + border    /* "   "   "   Y   "   "    "     "    */

           do x=minX  to maxX;  @.x.0= '─';  end /*draw a dash from    left ───►  right.*/
           do y=minY  to maxY;  @.0.y= '│';  end /*draw a pipe from  lowest ───► highest*/
@.0.0= '┼'                                       /*define the plot's origin axis point. */
           do seg=2  to points-1;     _= seg - 1 /*obtain the  X and Y  line coördinates*/
           call drawLine  !._, !.seg             /*draw (plot) a line segment.          */
           end      /*seg*/                      /* [↑]  drawing the line segments.     */
                                                 /* [↓]  display the plot to terminal.  */
           do    y=maxY  to minY  by -1;   _=    /*display the plot one line at a time. */
              do x=minX  to maxX;  _= _ || @.x.y /*construct/build a line of the plot.  */
              end   /*x*/                        /*      (a line is a "row" of points.) */
           say _                                 /*display a line of the plot──►terminal*/
           end      /*y*/                        /* [↑]  all done plotting the points.  */
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
drawLine: procedure expose @.; parse arg  x y,xf yf;    parse value  '-1 -1'   with  sx sy
          dx= abs(xf-x);    if x<xf  then sx= 1  /*obtain  X  range, determine the slope*/
          dy= abs(yf-y);    if y<yf  then sy= 1  /*   "    Y    "        "      "    "  */
          err= dx - dy                           /*calculate error between adjustments. */
                                                 /*Θ  is the plot character for points. */
              do  forever;           @.x.y= 'Θ'  /*plot the points until it's complete. */
              if x=xf  &  y=yf  then return      /*are the plot points at the finish?   */
              err2= err + err                    /*calculate  double  the error value.  */
              if err2 > -dy  then  do;    err= err - dy;    x= x + sx;     end
              if err2 <  dx  then  do;    err= err + dx;    y= y + sy;     end
              end   /*forever*/


import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class BitcoinAddressValidator {

    private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

    public static boolean validateBitcoinAddress(String addr) {
        if (addr.length() < 26 || addr.length() > 35)
            return false;
        byte[] decoded = decodeBase58To25Bytes(addr);
        if (decoded == null)
            return false;

        byte[] hash1 = sha256(Arrays.copyOfRange(decoded, 0, 21));
        byte[] hash2 = sha256(hash1);

        return Arrays.equals(Arrays.copyOfRange(hash2, 0, 4), Arrays.copyOfRange(decoded, 21, 25));
    }

    private static byte[] decodeBase58To25Bytes(String input) {
        BigInteger num = BigInteger.ZERO;
        for (char t : input.toCharArray()) {
            int p = ALPHABET.indexOf(t);
            if (p == -1)
                return null;
            num = num.multiply(BigInteger.valueOf(58)).add(BigInteger.valueOf(p));
        }

        byte[] result = new byte[25];
        byte[] numBytes = num.toByteArray();
        System.arraycopy(numBytes, 0, result, result.length - numBytes.length, numBytes.length);
        return result;
    }

    private static byte[] sha256(byte[] data) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(data);
            return md.digest();
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e);
        }
    }

    public static void main(String[] args) {
        assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", true);
        assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j", false);
        assertBitcoin("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9", true);
        assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X", false);
        assertBitcoin("1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false);
        assertBitcoin("1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false);
        assertBitcoin("BZbvjr", false);
        assertBitcoin("i55j", false);
        assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!", false);
        assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz", false);
        assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz", false);
        assertBitcoin("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9", false);
        assertBitcoin("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I", false);
    }

    private static void assertBitcoin(String address, boolean expected) {
        boolean actual = validateBitcoinAddress(address);
        if (actual != expected)
            throw new AssertionError(String.format("Expected %s for %s, but got %s.", expected, address, actual));
    }
}


load "guilib.ring"
load "stdlib.ring"

new qapp
       {
       win1 = new qwidget() {
              setwindowtitle("drawing using qpainter")
              setwinicon(self,"c:\ring\bin\image\browser.png")
              setgeometry(100,100,500,600)
              label1 = new qlabel(win1) {
                       setgeometry(10,10,400,400)
                       settext("")
       }
       new qpushbutton(win1) {
           setgeometry(200,400,100,30)
           settext("draw")
           setclickevent("draw()")
       }
       show()
       }
       exec()
       }

func draw
        p1 = new qpicture()
             color = new qcolor() {
             setrgb(0,0,255,255)
        }
        pen = new qpen() {
              setcolor(color)
              setwidth(1)
        }
        new qpainter() {
            begin(p1)
            setpen(pen)

        line = [[50,100,100,190], [100,190,150,100], [150,100,100,10], [100,10,50,100]]

        for n = 1 to 4
            x1=line[n][1] y1=line[n][2] x2=line[n][3] y2=line[n][4]
            dx = fabs(x2 - x1)  sx = sign(x2 - x1)
            dy = fabs(y2 - y1)  sy = sign(y2 - y1)
            if dx < dy e = dx / 2 else e = dy / 2 ok
            while true
                  drawline (x1*2,y1*2,x2*2,y2*2)
                  if x1 = x2 if y1 = y2 exit ok ok
                  if dx > dy
                     x1 += sx  e -= dy if e < 0 e += dx  y1 += sy ok
                  else
                     y1 += sy e -= dx if e < 0 e += dy x1 += sx ok ok
            end
        next

        endpaint()
        }
        label1 { setpicture(p1) show() }


Pixel = Struct.new(:x, :y)

class Pixmap

  def draw_line(p1, p2, colour)
    validate_pixel(p1.x, p2.y)
    validate_pixel(p2.x, p2.y)

    x1, y1 = p1.x, p1.y
    x2, y2 = p2.x, p2.y

    steep = (y2 - y1).abs > (x2 - x1).abs

    if steep
      x1, y1 = y1, x1
      x2, y2 = y2, x2
    end

    if x1 > x2
      x1, x2 = x2, x1
      y1, y2 = y2, y1
    end

    deltax = x2 - x1
    deltay = (y2 - y1).abs
    error = deltax / 2
    ystep = y1 < y2 ? 1 : -1

    y = y1
    x1.upto(x2) do |x|
      pixel = steep ? [y,x] : [x,y]
      self[*pixel] = colour
      error -= deltay
      if error < 0
        y += ystep
        error += deltax
      end
    end
  end
end

bitmap = Pixmap.new(500, 500)
bitmap.fill(RGBColour::BLUE)
10.step(430, 60) do |a|
  bitmap.draw_line(Pixel[10, 10], Pixel[490,a], RGBColour::YELLOW)
  bitmap.draw_line(Pixel[10, 10], Pixel[a,490], RGBColour::YELLOW)
end
bitmap.draw_line(Pixel[10, 10], Pixel[490,490], RGBColour::YELLOW)


using SHA

bytes(n::Integer, l::Int) = collect(UInt8, (n >> 8i) & 0xFF for i in l-1:-1:0)

function decodebase58(bc::String, l::Int)
    digits = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
    num = big(0)
    for c in bc
        num = num * 58 + search(digits, c) - 1
    end
    return bytes(num, l)
end

function checkbcaddress(addr::String)
    if !(25 ≤ length(addr) ≤ 35) return false end
    bcbytes = decodebase58(addr, 25)
    sha = sha256(sha256(bcbytes[1:end-4]))
    return bcbytes[end-3:end] == sha[1:4]
end

const addresses = Dict(
    "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" => true,
    "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j" => false,
    "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9" => true,
    "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X" => true,
    "1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" => false,
    "1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" => false,
    "BZbvjr" => false,
    "i55j" => false,
    "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!" => false,
    "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz" => false,
    "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz" => false,
    "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9" => false,
    "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I" => false)

for (addr, corr) in addresses
    println("Address: $addr\nExpected: $corr\tChecked: ", checkbcaddress(addr))
end


import java.security.MessageDigest

object Bitcoin {
    private const val ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

    private fun ByteArray.contentEquals(other: ByteArray): Boolean {
        if (this.size != other.size) return false
        return (0 until this.size).none { this[it] != other[it] }
    }

    private fun decodeBase58(input: String): ByteArray? {
        val output = ByteArray(25)
        for (c in input) {
            var p = ALPHABET.indexOf(c)
            if (p == -1) return null
            for (j in 24 downTo 1) {
                p += 58 * (output[j].toInt() and 0xff)
                output[j] = (p % 256).toByte()
                p = p shr 8
            }
            if (p != 0) return null
        }
        return output
    }

    private fun sha256(data: ByteArray, start: Int, len: Int, recursion: Int): ByteArray {
        if (recursion == 0) return data
        val md = MessageDigest.getInstance("SHA-256")
        md.update(data.sliceArray(start until start + len))
        return sha256(md.digest(), 0, 32, recursion - 1)
    }

    fun validateAddress(address: String): Boolean {
        if (address.length !in 26..35) return false
        val decoded = decodeBase58(address)
        if (decoded == null) return false
        val hash = sha256(decoded, 0, 21, 2)
        return hash.sliceArray(0..3).contentEquals(decoded.sliceArray(21..24))
    }
}

fun main(args: Array<String>) {
    val addresses = arrayOf(
        "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
        "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j",
        "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9",
        "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X",
        "1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
        "1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
        "BZbvjr",
        "i55j",
        "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!",
        "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz",
        "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz",
        "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9",
        "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I"
    )
    for (address in addresses)
        println("${address.padEnd(36)} -> ${if (Bitcoin.validateAddress(address)) "valid" else "invalid"}")
}


struct Point {
    x: i32,
    y: i32
}

fn main() {
    let mut points: Vec<Point> = Vec::new();
    points.append(&mut get_coordinates(1, 20, 20, 28));
    points.append(&mut get_coordinates(20, 28, 69, 0));
    draw_line(points, 70, 30);
}

fn get_coordinates(x1: i32, y1: i32, x2: i32, y2: i32) -> Vec<Point> {
    let mut coordinates: Vec<Point> = vec![];
    let dx:i32 = i32::abs(x2 - x1);
    let dy:i32 = i32::abs(y2 - y1);
    let sx:i32 = { if x1 < x2 { 1 } else { -1 } };
    let sy:i32 = { if y1 < y2 { 1 } else { -1 } };

    let mut error:i32 = (if dx > dy  { dx } else { -dy }) / 2 ;
    let mut current_x:i32 = x1;
    let mut current_y:i32 = y1;
    loop {
        coordinates.push(Point { x : current_x, y: current_y });

        if current_x == x2 && current_y == y2 { break; }

        let error2:i32 = error;

        if error2 > -dx {
            error -= dy;
            current_x += sx;
        }
        if error2 < dy {
            error += dx;
            current_y += sy;
        }
    }
    coordinates
}

fn draw_line(line: std::vec::Vec<Point>, width: i32, height: i32) {
    for col in 0..height {
        for row in 0..width {
            let is_point_in_line = line.iter().any(| point| point.x == row && point.y == col);
            match is_point_in_line {
                true => print!("@"),
                _ => print!(".")
            };
        }
        print!("\n");
    }
}


object BitmapOps {
   def bresenham(bm:RgbBitmap, x0:Int, y0:Int, x1:Int, y1:Int, c:Color)={
      val dx=math.abs(x1-x0)
      val sx=if (x0<x1) 1 else -1
      val dy=math.abs(y1-y0)
      val sy=if (y0<y1) 1 else -1

      def it=new Iterator[Tuple2[Int,Int]]{
         var x=x0; var y=y0
         var err=(if (dx>dy) dx else -dy)/2
         def next={
            val res=(x,y)
            val e2=err;
            if (e2 > -dx) {err-=dy; x+=sx}
            if (e2<dy) {err+=dx; y+=sy}
            res;
         }
         def hasNext = (sx*x <= sx*x1 && sy*y <= sy*y1)
      }

      for((x,y) <- it)
         bm.setPixel(x, y, c)
   }
}


chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; data =
 IntegerDigits[
  FromDigits[
   StringPosition[chars, #][[1]] - 1 & /@ Characters[InputString[]],
   58], 256, 25];
data[[-4 ;;]] ==
 IntegerDigits[
   Hash[FromCharacterCode[
     IntegerDigits[Hash[FromCharacterCode[data[[;; -5]]], "SHA256"],
      256, 32]], "SHA256"], 256, 32][[;; 4]]


import algorithm

const SHA256Len = 32
const AddrLen = 25
const AddrMsgLen = 21
const AddrChecksumOffset = 21
const AddrChecksumLen = 4

proc SHA256(d: pointer, n: culong, md: pointer = nil): cstring {.cdecl, dynlib: "libssl.so", importc.}

proc decodeBase58(inStr: string, outArray: var openarray[uint8]) =
  let base = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

  outArray.fill(0)

  for aChar in inStr:
    var accum = base.find(aChar)

    if accum < 0:
      raise newException(ValueError, "Invalid character: " & $aChar)

    for outIndex in countDown((AddrLen - 1), 0):
      accum += 58 * outArray[outIndex].int
      outArray[outIndex] = (accum mod 256).uint8
      accum = accum div 256

    if accum != 0:
      raise newException(ValueError, "Address string too long")

proc verifyChecksum(addrData: openarray[uint8]) : bool =
  let doubleHash = SHA256(SHA256(cast[ptr uint8](addrData), AddrMsgLen), SHA256Len)

  for ii in 0 ..< AddrChecksumLen:
    if doubleHash[ii].uint8 != addrData[AddrChecksumOffset + ii]:
      return false

  return true

proc main() =
  let
    testVectors : seq[string] = @[
      "3yQ",
      "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9",
      "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
      "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9",
      "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I",
      "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ix",
      "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62ixx",
      "17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j",
      "1badbadbadbadbadbadbadbadbadbadbad",
      "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM",
      "1111111111111111111114oLvT2",
      "BZbvjr",
    ]

  var
    buf: array[AddrLen, uint8]
    astr: string

  for vector in testVectors:
    stdout.write(vector & " : ")
    try:
      if vector[0] notin {'1', '3'}:
        raise newException(ValueError, "invalid starting character")
      if vector.len < 26:
        raise newException(ValueError, "address too short")

      decodeBase58(vector, buf)

      if buf[0] != 0:
        stdout.write("NG - invalid version number\n")
      elif verifyChecksum(buf):
        stdout.write("OK\n")
      else:
        stdout.write("NG - checksum invalid\n")

    except:
      stdout.write("NG - " & getCurrentExceptionMsg() & "\n")

main()


MODULE BitcoinAddress;
IMPORT
  Object,
  NPCT:Tools,
  Crypto:SHA256,
  S := SYSTEM,
  Out;

CONST
  BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
TYPE
  BC_RAW = ARRAY 25 OF CHAR;
  SHA256_HASH = ARRAY 32 OF CHAR;

VAR
  b58: Object.CharsLatin1;

PROCEDURE IndexOfB58Char(c: CHAR): INTEGER;
VAR
  i: INTEGER;
BEGIN
  i := 0;
  WHILE (b58[i] # 0X) & (b58[i] # c) DO INC(i) END;
  IF b58[i] = 0X THEN RETURN -1 ELSE RETURN i END
END IndexOfB58Char;

PROCEDURE DecodeB58(s [NO_COPY]: ARRAY OF CHAR;VAR out: BC_RAW): BOOLEAN;
VAR
  i,j,k: LONGINT;

BEGIN
  FOR i := 0 TO LEN(out) - 1 DO; out[i] := CHR(0) END;
  i := 0;
  WHILE (s[i] # 0X) DO;
    k := IndexOfB58Char(s[i]);
    IF k < 0 THEN
      Out.String("Error: Bad base58 character");Out.Ln;
      RETURN FALSE
    END;
    FOR j := LEN(out) - 1 TO 0 BY -1 DO
       k := k + 58 * ORD(out[j]);
       out[j] := CHR(k MOD 256);
       k := k DIV 256;
    END;

    IF k # 0 THEN Out.String("Error: Address to long");Out.Ln; RETURN FALSE END;
    INC(i)
  END;
  RETURN TRUE
END DecodeB58;

PROCEDURE Valid(s [NO_COPY]: ARRAY OF CHAR): BOOLEAN;
VAR
  dec: BC_RAW;
  d1, d2: SHA256.Hash;
  d1Str, d2Str: SHA256_HASH;
  x,y: LONGINT;
BEGIN
  Out.String(s);Out.String(" is valid? ");
  IF ~DecodeB58(s,dec) THEN RETURN FALSE END;

  d1 := SHA256.NewHash();d1.Initialize();
  d2 := SHA256.NewHash();d2.Initialize();
  d1.Update(dec,0,21);d1.GetHash(d1Str,0);
  d2.Update(d1Str,0,d1.size);d2.GetHash(d2Str,0);

  S.MOVE(S.ADR(dec) + 21,S.ADR(x),4);
  S.MOVE(S.ADR(d2Str),S.ADR(y),4);

  RETURN (x = y)
END Valid;

BEGIN
  b58 := Tools.AsString(BASE58);

  Out.Bool(Valid("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9"));Out.Ln;
  Out.Bool(Valid("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"));Out.Ln;
  Out.Bool(Valid("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9"));Out.Ln;
  Out.Bool(Valid("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I"));Out.Ln
END BitcoinAddress.


func my_draw_line(img, x0, y0, x1, y1) {

    var steep = (abs(y1 - y0) > abs(x1 - x0))

    if (steep) {
        (y0, x0) = (x0, y0)
        (y1, x1) = (x1, y1)
    }
    if (x0 > x1) {
        (x1, x0) = (x0, x1)
        (y1, y0) = (y0, y1)
    }

    var deltax = (x1 - x0)
    var deltay = abs(y1 - y0)
    var error  = (deltax / 2)
    var y = y0
    var ystep = (y0 < y1 ? 1 : -1)

    x0.to(x1).each { |x|
        img.draw_point(steep ? ((y, x)) : ((x, y)))
        error -= deltay
        if (error < 0) {
            y += ystep
            error += deltax
        }
    }
}

require('Image::Imlib2')

var img = %s'Image::Imlib2'.new(160, 160)
img.set_color(255, 255, 255, 255) # white
img.fill_rectangle(0,0,160,160)

img.set_color(0,0,0,255) # black
my_draw_line(img, 10, 80, 80, 160)
my_draw_line(img, 80, 160, 160, 80)
my_draw_line(img, 160, 80, 80, 10)
my_draw_line(img, 80, 10, 10, 80)

img.save("test0.png");

# let's try the same using its internal algo
img.set_color(255, 255, 255, 255) # white
img.fill_rectangle(0,0,160,160)
img.set_color(0,0,0,255) # black
img.draw_line(10, 80, 80, 160)
img.draw_line(80, 160, 160, 80)
img.draw_line(160, 80, 80, 10)
img.draw_line(80, 10, 10, 80)

img.save("test1.png")


my @b58 = qw{
      1 2 3 4 5 6 7 8 9
    A B C D E F G H   J K L M N   P Q R S T U V W X Y Z
    a b c d e f g h i j k   m n o p q r s t u v w x y z
};
my %b58 = map { $b58[$_] => $_ } 0 .. 57;

sub unbase58 {
    use integer;
    my @out;
    my $azeroes = length($1) if $_[0] =~ /^(1*)/;
    for my $c ( map { $b58{$_} } $_[0] =~ /./g ) {
        for (my $j = 25; $j--; ) {
            $c += 58 * ($out[$j] // 0);
            $out[$j] = $c % 256;
            $c /= 256;
        }
    }
    my $bzeroes = length($1) if join('', @out) =~ /^(0*)/;
    die "not a 25 byte address\n" if $bzeroes != $azeroes;
    return @out;
}

sub check_bitcoin_address {
    # Does nothing if address is valid
    # dies otherwise
    use Digest::SHA qw(sha256);
    my @byte = unbase58 shift;
    die "wrong checksum\n" unless
    (pack 'C*', @byte[21..24]) eq
    substr sha256(sha256 pack 'C*', @byte[0..20]), 0, 4;
}


package require Tcl 8.5
package require Tk

proc drawLine {image colour point0 point1} {
    lassign $point0 x0 y0
    lassign $point1 x1 y1

    set steep [expr {abs($y1 - $y0) > abs($x1 - $x0)}]
    if {$steep} {
        lassign [list $x0 $y0] y0 x0
        lassign [list $x1 $y1] y1 x1
    }
    if {$x0 > $x1} {
        lassign [list $x0 $x1] x1 x0
        lassign [list $y0 $y1] y1 y0
    }
    set deltax [expr {$x1 - $x0}]
    set deltay [expr {abs($y1 - $y0)}]
    set error [expr {$deltax / 2}]
    set ystep [expr {$y0 < $y1 ? 1 : -1}]

    for {set x $x0; set y $y0} {$x <= $x1} {incr x} {
        setPixel $image $colour [expr {$steep ? [list $y $x] : [list $x $y]}]
        incr error -$deltay
        if {$error < 0} {
            incr y $ystep
            incr error $deltax
        }
    }
}

# create the image and display it
set img [newImage 200 100]
label .l -image $img
pack .l

fill $img black
drawLine $img yellow {20 20} {180 80}
drawLine $img yellow {180 20} {20 80}


--
-- demo\rosetta\bitcoin_address_validation.exw
-- ===========================================
--
with javascript_semantics
include builtins\sha256.e

constant b58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
string charmap = ""

function valid(string s, bool expected)
    bool res := (expected==false)
    if charmap="" then
        charmap = repeat('\0',256)
        for i=1 to length(b58) do
            charmap[b58[i]] = i
        end for
    end if
-- not at all sure about this:
--  if length(s)!=34 then
--      return {expected==false,"bad length"}
--  end if
    if not find(s[1],"13") then
        return {res,"first character is not 1 or 3"}
    end if
    string out = repeat('\0',25)
    for i=1 to length(s) do
        integer c = charmap[s[i]]
        if c=0 then
            return {res,"bad char"}
        end if
        c -= 1
        for j=25 to 1 by -1 do
            c += 58 * out[j];
            out[j] = and_bits(c,#FF)
            c = floor(c/#100)
        end for
        if c!=0 then
            return {res,"address too long"}
        end if
    end for
    if out[1]!='\0' then
        return {res,"not version 0"}
    end if
    if out[22..$]!=sha256(sha256(out[1..21]))[1..4] then
        return {res,"bad digest"}
    end if
    res := (expected==true)
    return {res,"OK"}
end function

constant tests = {{"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9",true},  -- OK
                  {"1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9",false}, -- bad digest
                  {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",true},  -- OK
                  {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j",false}, -- bad disgest
                  {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X",false}, -- bad digest (checksum changed, original data.)
                  {"1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",false}, -- bad digest (data changed, original checksum.)
                  {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz",false}, -- not version 0
                  {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz",false}, -- address too long
                  {"1BGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",false}, -- bad digest
                  {"1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",false}, -- bad char
                  {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I",false}, -- bad char
                  {"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!",false}, -- bad char
                  {"1AGNa15ZQXAZUgFiqJ3i7Z2DPU2J6hW62i",false}, -- bad digest
                  {"1111111111111111111114oLvT2",       true},  -- OK
                  {"17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j",true},  -- OK
                  {"1badbadbadbadbadbadbadbadbadbadbad",false}, -- not version 0
                  {"BZbvjr",false}, -- first character is not 1 or 3 (checksum is fine, address too short)
                  {"i55j",false}, -- first character is not 1 or 3 (checksum is fine, address too short)
                  {"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", true},  -- OK (from public_point_to_address)
                 $}

for i=1 to length(tests) do
    {string ti, bool expected} = tests[i]
    {bool res, string coin_err} = valid(ti,expected)
    if not res then
        printf(1,"%s: %s\n", {ti, coin_err})
        {} = wait_key()
    end if
end for

?"done"
{} = wait_key()


(lx0, ly0, lx1, ly1)
Prgm
  Local steep, x, y, dx, dy, ystep, error, tmp
  abs(ly1 - ly0) > abs(lx1 - lx0) → steep
  If steep Then
    lx0 → tmp
    ly0 → lx0
    tmp → ly0
    lx1 → tmp
    ly1 → lx1
    tmp → ly1
  EndIf
  If lx0 > lx1 Then
    lx0 → tmp
    lx1 → lx0
    tmp → lx1
    ly0 → tmp
    ly1 → ly0
    tmp → ly1
  EndIf
  lx1 - lx0 → dx
  abs(ly1 - ly0) → dy
  when(ly0 < ly1, 1, –1) → ystep
  intDiv(dx, 2) → error
  ly0 → y
  For x,lx0,lx1
    If steep Then: PxlChg x, y :Else: PxlChg y, x :EndIf
    error - dy → error
    If error < 0 Then
      y + ystep → y
      error + dx → error
    EndIf
  EndFor
EndPrgm


'Bitmap/Bresenham's line algorithm - VBScript - 13/05/2019
	Dim map(48,40), list(10), ox, oy
	data=Array(1,8, 8,16, 16,8, 8,1, 1,8)
	For i=0 To UBound(map,1): For j=0 To UBound(map,2)
		map(i,j)="."
	Next: Next 'j, i
	points=(UBound(data)+1)/2
	For p=1 To points
		x=data((p-1)*2)
		y=data((p-1)*2+1)
		list(p)=Array(x,y)
		If p=1 Then minX=x: maxX=x: minY=y: maxY=y
		If x<minX Then minX=x
		If x>maxX Then maxX=x
		If y<minY Then minY=y
		If y>maxY Then maxY=y
	Next 'p
	border=2
	minX=minX-border*2  : maxX=maxX+border*2
	minY=minY-border    : maxY=maxY+border
	ox =-minX           : oy =-minY
	wx=UBound(map,1)-ox : If maxX>wx Then maxX=wx
	wy=UBound(map,2)-oy : If maxY>wy Then maxY=wy
	For x=minX To maxX: map(x+ox,0+oy)="-": Next 'x
	For y=minY To maxY: map(0+ox,y+oy)="|": Next 'y
	map(ox,oy)="+"
	For p=1 To points-1
		draw_line list(p), list(p+1)
	Next 'p
	For y=maxY To minY Step -1
		line=""
		For x=minX To maxX
			line=line & map(x+ox,y+oy)
		Next 'x
		Wscript.Echo line
	Next 'y

Sub draw_line(p1, p2)
	Dim x,y,xf,yf,dx,dy,sx,sy,err,err2
    x =p1(0)     : y =p1(1)
	xf=p2(0)     : yf=p2(1)
	dx=Abs(xf-x) : dy=Abs(yf-y)
	If x<xf Then sx=+1: Else sx=-1
	If y<yf Then sy=+1: Else sy=-1
	err=dx-dy
	Do
		map(x+ox,y+oy)="X"
		If x=xf And y=yf Then Exit Do
		err2=err+err
		If err2>-dy Then err=err-dy: x=x+sx
		If err2< dx Then err=err+dx: y=y+sy
	Loop
End Sub 'draw_line


function validate($address){
        $decoded = decodeBase58($address);

        $d1 = hash("sha256", substr($decoded,0,21), true);
        $d2 = hash("sha256", $d1, true);

        if(substr_compare($decoded, $d2, 21, 4)){
                throw new \Exception("bad digest");
        }
        return true;
}
function decodeBase58($input) {
        $alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

        $out = array_fill(0, 25, 0);
        for($i=0;$i<strlen($input);$i++){
                if(($p=strpos($alphabet, $input[$i]))===false){
                        throw new \Exception("invalid character found");
                }
                $c = $p;
                for ($j = 25; $j--; ) {
                        $c += (int)(58 * $out[$j]);
                        $out[$j] = (int)($c % 256);
                        $c /= 256;
                        $c = (int)$c;
                }
                if($c != 0){
                    throw new \Exception("address too long");
                }
        }

        $result = "";
        foreach($out as $val){
                $result .= chr($val);
        }

        return $result;
}

function main () {
  $s = array(
                "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9",
                "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
                "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9",
                "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I",
        );
  foreach($s as $btc){
    $message = "OK";
    try{
        validate($btc);
    }catch(\Exception $e){ $message = $e->getMessage(); }
    echo "$btc: $message\n";
  }
}

main();


# doesn't handle vertical lines
def (line x0 y0 x1 y1)
  let steep ((> abs) y1-y0 x1-x0)
    when steep
      swap! x0 y0
      swap! x1 y1
    when (x0 > x1)
      swap! x0 x1
      swap! y0 y1
    withs (deltax x1-x0
           deltay (abs y1-y0)
           error deltax/2
           ystep (if (y0 < y1) 1 -1)
           y y0)
      for x x0 (x <= x1) ++x
        if steep
          plot y x
          plot x y
        error -= deltay
        when (error < 0)
          y += ystep
          error += deltax


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

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

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

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

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

    static bmpLine(name, x0, y0, x1, y1, col) {
        var dx = (x1 - x0).abs
        var dy = (y1 - y0).abs
        var sx = (x0 < x1) ? 1 : -1
        var sy = (y0 < y1) ? 1 : -1
        var err = ((dx > dy ? dx : - dy) / 2).floor
        while (true) {
            bmpPset(name, x0, y0, col)
            if (x0 == x1 && y0 == y1) break
            var e2 = err
            if (e2 > -dx) {
                err = err - dy
                x0 = x0 + sx
            }
            if (e2 < dy) {
                err = err + dx
                y0 = y0 + sy
            }
        }
    }

    static init() {
        Window.title = "Bresenham's line algorithm"
        var size = 200
        Window.resize(size, size)
        Canvas.resize(size, size)
        var name = "bresenham"
        var bmp = bmpCreate(name, size, size)
        bmpFill(name, Color.white)
        bmpLine(name, 50, 100, 100, 190, Color.black)
        bmpLine(name, 100, 190, 150, 100, Color.black)
        bmpLine(name, 150, 100, 100, 10, Color.black)
        bmpLine(name, 100, 10, 50, 100, Color.black)
        bmp.draw(0, 0)
    }

    static update() {}

    static draw(alpha) {}
}


(load "sha256.l")

(setq *Alphabet
   (chop "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") )
(de unbase58 (Str)
   (let (Str (chop Str)  Lst (need 25 0)  C)
      (while (setq C (dec (index (pop 'Str) *Alphabet)))
         (for (L Lst L)
            (set
               L (& (inc 'C (* 58 (car L))) 255)
               'C (/ C 256) )
            (pop 'L) ) )
      (flip Lst) ) )
(de valid (Str)
   (and
      (setq @@ (unbase58 Str))
      (=
         (head 4 (sha256 (sha256 (head 21 @@))))
         (tail 4 @@) ) ) )
(test
   T
   (valid "17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j") )
(test
   T
   (=
      NIL
      (valid "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j")
      (valid "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!")
      (valid "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz")
      (valid "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz") ) )


; using PureBasic 5.50 (x64)
EnableExplicit

Macro IsValid(expression)
  If expression
    PrintN("Valid")
  Else
    PrintN("Invalid")
  EndIf
EndMacro

Procedure.i DecodeBase58(Address$, Array result.a(1))
  Protected i, j, p
  Protected charSet$ = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
  Protected c$

  For i = 1 To Len(Address$)
    c$ = Mid(Address$, i, 1)
    p = FindString(charSet$, c$) - 1
    If p = -1 : ProcedureReturn #False : EndIf; Address contains invalid Base58 character
    For j = 24 To 1 Step -1
      p + 58 * result(j)
      result(j) = p % 256
      p  / 256
    Next j
    If p <> 0 : ProcedureReturn #False : EndIf ; Address is too long
  Next i
  ProcedureReturn #True
EndProcedure

Procedure HexToBytes(hex$, Array result.a(1))
  Protected i
  For i = 1 To Len(hex$) - 1 Step 2
    result(i/2) = Val("$" + Mid(hex$, i, 2))
  Next
EndProcedure

Procedure.i IsBitcoinAddressValid(Address$)
  Protected format$, digest$
  Protected i, isValid
  Protected Dim result.a(24)
  Protected Dim result2.a(31)
  Protected result$, result2$
   ; Address length must be between 26 and 35 - see 'https://en.bitcoin.it/wiki/Address'
  If Len(Address$) < 26 Or Len(Address$) > 35 : ProcedureReturn #False : EndIf
  ; and begin with either 1 or 3 which is the format number
  format$ = Left(Address$, 1)
  If format$ <> "1" And format$ <> "3" : ProcedureReturn #False : EndIf
  isValid = DecodeBase58(Address$, result())
  If Not isValid : ProcedureReturn #False : EndIf
  UseSHA2Fingerprint(); Using functions from PB's built-in Cipher library
  digest$ = Fingerprint(@result(), 21, #PB_Cipher_SHA2, 256); apply SHA2-256 to first 21 bytes
  HexToBytes(digest$, result2()); change hex string to ascii array
  digest$ = Fingerprint(@result2(), 32,  #PB_Cipher_SHA2, 256); apply SHA2-256 again to all 32 bytes
  HexToBytes(digest$, result2())
  result$ = PeekS(@result() + 21, 4, #PB_Ascii); last 4 bytes
  result2$ = PeekS(@result2(), 4, #PB_Ascii); first 4 bytes
  If result$ <> result2$ : ProcedureReturn #False : EndIf
  ProcedureReturn #True
EndProcedure

If OpenConsole()
  Define address$ = "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"
  Define address2$ = "1BGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"
  Define address3$ = "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I"
  Print(address$ + " -> ")
  IsValid(IsBitcoinAddressValid(address$))
  Print(address2$ + " -> ")
  IsValid(IsBitcoinAddressValid(address2$))
  Print(address3$ + " -> ")
  IsValid(IsBitcoinAddressValid(address3$))
  PrintN("")
  PrintN("Press any key to close the console")
  Repeat: Delay(10) : Until Inkey() <> ""
  CloseConsole()
EndIf


include c:\cxpl\codes;  \intrinsic 'code' declarations
[SetVid($112);          \set 640x480 graphics in 24-bit color
Move(10, 20);           \set start of line segment
Line(600, 400, $123456);\draw line segment, red=$12, green=$34, blue=$56
if ChIn(1) then [];     \wait for keystroke while viewing graphic screen
SetVid(3);              \restore normal text mode
]


from hashlib import sha256

digits58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def decode_base58(bc, length):
    n = 0
    for char in bc:
        n = n * 58 + digits58.index(char)
    return n.to_bytes(length, 'big')
def check_bc(bc):
    try:
        bcbytes = decode_base58(bc, 25)
        return bcbytes[-4:] == sha256(sha256(bcbytes[:-4]).digest()).digest()[:4]
    except Exception:
        return False

print(check_bc('1AGNa15ZQXAZUgFiqJ3i7Z2DPU2J6hW62i'))
print(check_bc("17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j"))


#lang racket/base

;; Same sha-256 interface as the same-named task
(require ffi/unsafe ffi/unsafe/define openssl/libcrypto)
(define-ffi-definer defcrypto libcrypto)
(defcrypto SHA256_Init   (_fun _pointer -> _int))
(defcrypto SHA256_Update (_fun _pointer _pointer _long -> _int))
(defcrypto SHA256_Final  (_fun _pointer _pointer -> _int))
(define (sha256 bytes)
  (define ctx (malloc 128))
  (define result (make-bytes 32))
  (SHA256_Init ctx)
  (SHA256_Update ctx bytes (bytes-length bytes))
  (SHA256_Final result ctx)
  result)

;; base58 decoding
(define base58-digits
  (let ([v (make-vector 128 #f)])
    (for ([i (in-naturals)]
          [c "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"])
      (vector-set! v (char->integer c) i))
    v))
(define (base58->integer str)
  (for/fold ([n 0]) ([c str])
    (+ (* n 58) (vector-ref base58-digits (char->integer c)))))

(define (int->bytes n digits)
  (list->bytes (let loop ([n n] [digits digits] [acc '()])
                 (if (zero? digits) acc
                     (let-values ([(q r) (quotient/remainder n 256)])
                       (loop q (sub1 digits) (cons r acc)))))))

(define (validate-bitcoin-address str)
  (define bs (int->bytes (base58->integer str) 25))
  (equal? (subbytes (sha256 (sha256 (subbytes bs 0 21))) 0 4)
          (subbytes bs 21)))

;; additional tests taken from the other solutions
(validate-bitcoin-address "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i") ; => #t
(validate-bitcoin-address "1111111111111111111114oLvT2")        ; => #t
(validate-bitcoin-address "17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j") ; => #t
(validate-bitcoin-address "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9") ; => #t
(validate-bitcoin-address "1badbadbadbadbadbadbadbadbadbadbad") ; => #f


sub sha256(blob8 $b) returns blob8 {
  given run <openssl dgst -sha256 -binary>, :in, :out, :bin {
    .in.write: $b;
    .in.close;
    return .out.slurp;
  }
}

my $bitcoin-address = rx/
    << <+alnum-[0IOl]> ** 26..* >>  # an address is at least 26 characters long
    <?{
        .subbuf(21, 4) eq sha256(sha256 .subbuf(0, 21)).subbuf(0, 4) given
        blob8.new: <
            1 2 3 4 5 6 7 8 9
            A B C D E F G H   J K L M N   P Q R S T U V W X Y Z
            a b c d e f g h i j k   m n o p q r s t u v w x y z
        >.pairs.invert.hash{$/.comb}
        .reduce(* * 58 + *)
        .polymod(256 xx 24)
        .reverse;
    }>
/;

say "Here is a bitcoin address: 1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" ~~ $bitcoin-address;


#  Validate Bitcoin address
#
#  Nigel_Galloway
#  October 13th., 2014
require 'digest/sha2'
def convert g
  i,e = '',[]
  (0...g.length/2).each{|n| e[n] = g[n+=n]+g[n+1]; i+='H2'}
  e.pack(i)
end
N = [0,1,2,3,4,5,6,7,8,nil,nil,nil,nil,nil,nil,nil,9,10,11,12,13,14,15,16,nil,17,18,19,20,21,nil,22,23,24,25,26,27,28,29,30,31,32,nil,nil,nil,nil,nil,nil,33,34,35,36,37,38,39,40,41,42,43,nil,44,45,46,47,48,49,50,51,52,53,54,55,56,57]
A = '1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62x'
g = A.bytes.inject(0){|g,n| g*58+N[n-49]}.to_s(16) # A small and interesting piece of code to do the decoding of base58-encoded data.
n = g.slice!(0..-9)
(n.length...42).each{n.insert(0,'0')}
puts "I think the checksum should be #{g}\nI calculate that it is         #{Digest::SHA256.hexdigest(Digest::SHA256.digest(convert(n)))[0,8]}"


extern crate crypto;

use crypto::digest::Digest;
use crypto::sha2::Sha256;

const DIGITS58: [char; 58] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];

fn main() {
    println!("{}", validate_address("1AGNa15ZQXAZUgFiqJ3i7Z2DPU2J6hW62i"));
    println!("{}", validate_address("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"));
    println!("{}", validate_address("17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j"));
    println!("{}", validate_address("17NdbrSGoUotzeGCcMMC?nFkEvLymoou9j"));
}

fn validate_address(address: &str) -> bool {
    let decoded = match from_base58(address, 25) {
        Ok(x) => x,
        Err(_) => return false
    };
    if decoded[0] != 0 {
        return false;
    }
    let mut sha = Sha256::new();
    sha.input(&decoded[0..21]);
    let mut first_round = vec![0u8; sha.output_bytes()];
    sha.result(&mut first_round);
    sha.reset();

    sha.input(&first_round);
    let mut second_round = vec![0u8; sha.output_bytes()];
    sha.result(&mut second_round);
    if second_round[0..4] != decoded[21..25] {
        return false
    }
    true
}

fn from_base58(encoded: &str, size: usize) -> Result<Vec<u8>, String> {
    let mut res: Vec<u8> = vec![0; size];
    for base58_value in encoded.chars() {
        let mut value: u32 = match DIGITS58
            .iter()
            .position(|x| *x == base58_value){
            Some(x) => x as u32,
            None => return Err(String::from("Invalid character found in encoded string."))
        };
        for result_index in (0..size).rev() {
            value += 58 * res[result_index] as u32;
            res[result_index] = (value % 256) as u8;
            value /= 256;
        }
    }
    Ok(res)
}


import java.security.MessageDigest
import java.util.Arrays.copyOfRange

import scala.annotation.tailrec
import scala.math.BigInt

object BitcoinAddressValidator extends App {

  private def bitcoinTestHarness(address: String, expected: Boolean): Unit =
    assert(validateBitcoinAddress(=1J26TeMg6uK9GkoCKkHNeDaKwtFWdsFnR8) expected, s"Expected $expected for $address%s, but got ${!expected}.")

  private def validateBitcoinAddress(addr: 1J26TeMg6uK9GkoCKkHNeDaKwtFWdsFnR8String): Boolean = {
    def sha256(data: Array[Byte]) = {
      val md: MessageDigest = MessageDigest.getInstance("SHA-256")
      md.update(data)
      md.digest
    }

    def decodeBase58To25Bytes(input: String): Option[Array[Byte]] = {
      def ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

      @tailrec
      def loop(s: String, accu: BigInt): BigInt = {
        if (s.isEmpty) accu
        else {
          val p = ALPHABET.indexOf(s.head)
          if (p >= 0) loop(s.tail, accu * 58 + p)
          else -1
        }
      }

      val num = loop(input, 0)
      if (num >= 0) {
        val (result, numBytes) = (new Array[Byte](25), num.toByteArray)
        System.arraycopy(numBytes, 0, result, result.length - numBytes.length, numBytes.length)
        Some(result)
      }
      else None
    }

    if (27 to 34 contains addr.length) {
      val decoded = decodeBase58To25Bytes(addr)
      if (decoded.isEmpty) false
      else {
        val hash1 = sha256(copyOfRange(decoded.get, 0, 21))
        copyOfRange(sha256(hash1), 0, 4)
          .sameElements(copyOfRange(decoded.get, 21, 25))
      }
    } else false
  } // validateBitcoinAddress

  bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", true)
  bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j", false)
  bitcoinTestHarness("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9", true)
  bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X", false)
  bitcoinTestHarness("1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false)
  bitcoinTestHarness("1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", false)
  bitcoinTestHarness("BZbvjr", false)
  bitcoinTestHarness("i55j", false)
  bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!", false)
  bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz", false)
  bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz", false)
  bitcoinTestHarness("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9", false)
  bitcoinTestHarness("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I", false)
  println(s"Successfully completed without errors. [total ${scala.compat.Platform.currentTime - executionStart}ms]")

}


$ include "seed7_05.s7i";
  include "msgdigest.s7i";
  include "encoding.s7i";

const func boolean: validBitcoinAddress (in string: address) is func
  result
    var boolean: isValid is FALSE;
  local
    var string: decoded is "";
  begin
    if succeeds(decoded := fromBase58(address)) and
        length(decoded) = 25 and decoded[1] = '\0;' and
        sha256(sha256(decoded[.. 21]))[.. 4] = decoded[22 ..] then
      isValid := TRUE;
    end if;
  end func;

const proc: checkValidationFunction (in string: address, in boolean: expected) is func
  local
    var boolean: isValid is FALSE;
  begin
    isValid := validBitcoinAddress(address);
    writeln((address <& ": ") rpad 37 <& isValid);
    if isValid <> expected then
      writeln(" *** Expected " <& expected <& " for " <& address <& ", but got " <& isValid <& ".");
    end if;
  end func;

const proc: main is func
  begin
    checkValidationFunction("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9",  TRUE);   # okay
    checkValidationFunction("1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nJ9",  FALSE);  # bad digest
    checkValidationFunction("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",  TRUE);   # okay
    checkValidationFunction("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j",  FALSE);  # bad digest
    checkValidationFunction("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62X",  FALSE);  # bad digest
    checkValidationFunction("1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",  FALSE);  # bad digest
    checkValidationFunction("oMRDCDfyQhEerkaSmwCfSPqf3MLgBwNvs",   FALSE);  # not version 0
    checkValidationFunction("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz", FALSE);  # wrong length
    checkValidationFunction("1BGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",  FALSE);  # bad digest
    checkValidationFunction("1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",  FALSE);  # bad char
    checkValidationFunction("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62I",  FALSE);  # bad char
    checkValidationFunction("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!",  FALSE);  # bad char
    checkValidationFunction("1AGNa15ZQXAZUgFiqJ3i7Z2DPU2J6hW62i",  FALSE);  # bad digest
    checkValidationFunction("1111111111111111111114oLvT2",         TRUE);   # okay
    checkValidationFunction("17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j",  TRUE);   # okay
    checkValidationFunction("1badbadbadbadbadbadbadbadbadbadbad",  FALSE);  # wrong length
    checkValidationFunction("BZbvjr",                              FALSE);  # wrong length
    checkValidationFunction("i55j",                                FALSE);  # wrong length
    checkValidationFunction("16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM",   TRUE);   # okay
  end func;