/* Base58Check Encoding (Rosetta code) in Picat. http://rosettacode.org/wiki/Base58Check_encoding """ The popular encoding of small and medium-sized checksums is base16, that is more compact than usual base10 and is human readable... For checksums resulting in hash digests bigger than ~100 bits, the base16 is too long: base58 is shorter and (when using good alphabet) preserves secure human readability. The most popular alphabet of base58 is the variant used in bitcoin address (see Bitcoin/address validation), so it is the "default base58 alphabet". Write a program that takes a checksum (resultant hash digest) integer binary representation as argument, and converts (encode it) into base58 with the standard Bitcoin alphabet — which uses an alphabet of the characters 0 .. 9, A ..Z, a .. z, but without the four characters: O the uppercase letter "oh", I the uppercase letter "eye", l the lowercase letter "ell", and 0 the digit zero. The reference algorithm is at the Bitcoin's Base58Check page https://en.bitcoin.it/wiki/Base58Check_encoding#Base58_symbol_chart """ This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ main => go. go => Tests = [[25420294593250030202636073700053352635053786165627414518,"6UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"], ["0x61","2g"], ["0x626262", "a3gV"], ["0x636363", "aPEr"], ["0x73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"], ["0x516b6fcd0f", "ABnLTmg"], ["0xbf4f89001e670274dd", "3SEo3LWLoPntC"], ["0x572e4794", "3EFU7m"], ["0xecac89cad93923c02321", "EJDM8drfXA6uyA"], ["0x10c8511e", "Rt5zm"]], foreach([Test,Check] in Tests) Res = base58Check(Test), printf("%-56w -> %w (%s)\n", Test, Res, cond(Res==Check,"ok", "not ok")) end, nl. go => true. base58Check(Hash) = OutputString.reverse => CodeString = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", % Convert to number if needed (string(Hash) -> X = Hash.to_int ; X = Hash), OutputString = "", while (X > 0) Remainder = X mod 58, X := X // 58, OutputString := OutputString ++ [CodeString[Remainder+1]] end.