all tasks

This commit is contained in:
Ingy döt Net 2013-04-11 01:07:29 -07:00
parent b83f433714
commit 68f8f3e56b
14735 changed files with 178959 additions and 0 deletions

7
Task/SHA-1/0DESCRIPTION Normal file
View file

@ -0,0 +1,7 @@
'''SHA-1''' or '''SHA1''' is a one-way hash function; it computes a 160-bit message digest. SHA-1 often appears in security protocols; for example, many HTTPS websites use RSA with SHA-1 to secure their connections. BitTorrent uses SHA-1 to verify downloads. Git and Mercurial use SHA-1 digests to identify commits.
A US government standard, [http://www.itl.nist.gov/fipspubs/fip180-1.htm FIPS 180-1], defines SHA-1.
Find the SHA-1 message digest for a string of [[octet]]s. You may either call a SHA-1 library, or implement SHA-1 in your language. Both approaches interest Rosetta Code.
{{alertbox|lightgray|'''Warning:''' SHA-1 has [https://en.wikinews.org/wiki/Chinese_researchers_crack_major_U.S._government_algorithm_used_in_digital_signatures known weaknesses]. Theoretical attacks may find a collision after [http://lwn.net/Articles/337745/ 2<sup>52</sup> operations], or perhaps fewer. This is much faster than a brute force attack of 2<sup>80</sup> operations. US government [http://csrc.nist.gov/groups/ST/hash/statement.html deprecated SHA-1]. For production-grade cryptography, users may consider a stronger alternative, such as SHA-256 (from the SHA-2 family) or the upcoming SHA-3.}}

3
Task/SHA-1/1META.yaml Normal file
View file

@ -0,0 +1,3 @@
---
category:
- Checksums

8
Task/SHA-1/Ada/sha-1.ada Normal file
View file

@ -0,0 +1,8 @@
with Ada.Text_IO;
with GNAT.SHA1;
procedure Main is
begin
Ada.Text_IO.Put_Line ("SHA1 (""Rosetta Code"") = " &
GNAT.SHA1.Digest ("Rosetta Code"));
end Main;

View file

@ -0,0 +1,21 @@
PRINT FNsha1("Rosetta Code")
END
DEF FNsha1(message$)
LOCAL buflen%, buffer%, hprov%, hhash%, hash$, i%
CALG_SHA1 = &8004
CRYPT_VERIFYCONTEXT = &F0000000
HP_HASHVAL = 2
PROV_RSA_FULL = 1
buflen% = 64
DIM buffer% LOCAL buflen%-1
SYS "CryptAcquireContext", ^hprov%, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT
SYS "CryptCreateHash", hprov%, CALG_SHA1, 0, 0, ^hhash%
SYS "CryptHashData", hhash%, message$, LEN(message$), 0
SYS "CryptGetHashParam", hhash%, HP_HASHVAL, buffer%, ^buflen%, 0
SYS "CryptDestroyHash", hhash%
SYS "CryptReleaseContext", hprov%
FOR i% = 0 TO buflen%-1
hash$ += RIGHT$("0" + STR$~buffer%?i%, 2)
NEXT
= hash$

View file

@ -0,0 +1,102 @@
*FLOAT64
PRINT FNsha1("Rosetta Code")
END
DEF FNsha1(message$)
LOCAL a%, b%, c%, d%, e%, f%, i%, j%, k%, l%, t%
LOCAL h0%, h1%, h2%, h3%, h4%, w%()
REM Initialize variables:
h0% = &67452301
h1% = &EFCDAB89
h2% = &98BADCFE
h3% = &10325476
h4% = &C3D2E1F0
l% = LEN(message$)*8
REM Pre-processing:
REM append the bit '1' to the message:
message$ += CHR$&80
REM append k bits '0', where k is the minimum number >= 0 such that
REM the resulting message length (in bits) is congruent to 448 (mod 512)
WHILE (LEN(message$) MOD 64) <> 56
message$ += CHR$0
ENDWHILE
REM append length of message (before pre-processing), in bits, as
REM 64-bit big-endian integer
FOR i% = 56 TO 0 STEP -8
message$ += CHR$(l% >>> i%)
NEXT
REM Process the message in successive 512-bit chunks:
REM break message into 512-bit chunks, for each chunk
REM break chunk into sixteen 32-bit big-endian words w[i], 0 <= i <= 15
DIM w%(79)
FOR j% = 0 TO LEN(message$) DIV 64 - 1
FOR i% = 0 TO 15
w%(i%) = !(!^message$ + 64*j% + 4*i%)
SWAP ?(^w%(i%)+0),?(^w%(i%)+3)
SWAP ?(^w%(i%)+1),?(^w%(i%)+2)
NEXT i%
REM Extend the sixteen 32-bit words into eighty 32-bit words:
FOR i% = 16 TO 79
w%(i%) = w%(i%-3) EOR w%(i%-8) EOR w%(i%-14) EOR w%(i%-16)
w%(i%) = (w%(i%) << 1) OR (w%(i%) >>> 31)
NEXT i%
REM Initialize hash value for this chunk:
a% = h0%
b% = h1%
c% = h2%
d% = h3%
e% = h4%
REM Main loop:
FOR i% = 0 TO 79
CASE TRUE OF
WHEN 0 <= i% AND i% <= 19
f% = (b% AND c%) OR ((NOT b%) AND d%)
k% = &5A827999
WHEN 20 <= i% AND i% <= 39
f% = b% EOR c% EOR d%
k% = &6ED9EBA1
WHEN 40 <= i% AND i% <= 59
f% = (b% AND c%) OR (b% AND d%) OR (c% AND d%)
k% = &8F1BBCDC
WHEN 60 <= i% AND i% <= 79
f% = b% EOR c% EOR d%
k% = &CA62C1D6
ENDCASE
t% = FN32(((a% << 5) OR (a% >>> 27)) + f% + e% + k% + w%(i%))
e% = d%
d% = c%
c% = (b% << 30) OR (b% >>> 2)
b% = a%
a% = t%
NEXT i%
REM Add this chunk's hash to result so far:
h0% = FN32(h0% + a%)
h1% = FN32(h1% + b%)
h2% = FN32(h2% + c%)
h3% = FN32(h3% + d%)
h4% = FN32(h4% + e%)
NEXT j%
= FNhex(h0%) + FNhex(h1%) + FNhex(h2%) + FNhex(h3%) + FNhex(h4%)
DEF FNhex(A%) = RIGHT$("0000000"+STR$~A%,8)
DEF FN32(n#)
WHILE n# > &7FFFFFFF : n# -= 2^32 : ENDWHILE
WHILE n# < &80000000 : n# += 2^32 : ENDWHILE
= n#

20
Task/SHA-1/C++/sha-1.cpp Normal file
View file

@ -0,0 +1,20 @@
#include <string>
#include <iostream>
#include "Poco/SHA1Engine.h"
#include "Poco/DigestStream.h"
using Poco::DigestEngine ;
using Poco::SHA1Engine ;
using Poco::DigestOutputStream ;
int main( ) {
std::string myphrase ( "Rosetta Code" ) ;
SHA1Engine sha1 ;
DigestOutputStream outstr( sha1 ) ;
outstr << myphrase ;
outstr.flush( ) ; //to pass everything to the digest engine
const DigestEngine::Digest& digest = sha1.digest( ) ;
std::cout << myphrase << " as a sha1 digest :" << DigestEngine::digestToHex( digest )
<< " !" << std::endl ;
return 0 ;
}

View file

@ -0,0 +1,21 @@
using System;
using System.Security.Cryptography;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace RosettaCode.SHA1
{
[TestClass]
public class SHA1CryptoServiceProviderTest
{
[TestMethod]
public void TestComputeHash()
{
var input = new UTF8Encoding().GetBytes("Rosetta Code");
var output = new SHA1CryptoServiceProvider().ComputeHash(input);
Assert.AreEqual(
"48-C9-8F-7E-5A-6E-73-6D-79-0A-B7-40-DF-C3-F5-1A-61-AB-E2-B5",
BitConverter.ToString(output));
}
}
}

18
Task/SHA-1/C/sha-1.c Normal file
View file

@ -0,0 +1,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
int main()
{
int i;
unsigned char result[SHA_DIGEST_LENGTH];
const char *string = "Rosetta Code";
SHA1(string, strlen(string), result);
for(i = 0; i < SHA_DIGEST_LENGTH; i++)
printf("%02x%c", result[i], i < (SHA_DIGEST_LENGTH-1) ? ' ' : '\n');
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,6 @@
;;; in addition to sha1, ironclad provides sha224, sha256, sha384, and sha512.
(defun sha1-hash (data)
(let ((sha1 (ironclad:make-digest 'ironclad:sha1))
(bin-data (ironclad:ascii-string-to-byte-array data)))
(ironclad:update-digest sha1 bin-data)
(ironclad:byte-array-to-hex-string (ironclad:produce-digest sha1))))

5
Task/SHA-1/D/sha-1.d Normal file
View file

@ -0,0 +1,5 @@
import std.stdio, std.digest.sha;
void main() {
writefln("%-(%02x%)", "Ars longa, vita brevis".sha1Of());
}

12
Task/SHA-1/Go/sha-1.go Normal file
View file

@ -0,0 +1,12 @@
package main
import (
"crypto/sha1"
"fmt"
)
func main() {
h := sha1.New()
h.Write([]byte("Rosetta Code"))
fmt.Printf("%x\n", h.Sum(nil))
}

View file

@ -0,0 +1,3 @@
IntegerString[Hash["Rosetta Code", "SHA1"], 16]
-> 48c98f7e5a6e736d790ab740dfc3f51a61abe2b5

View file

@ -0,0 +1,50 @@
/* NetRexx */
options replace format comments java crossref savelog symbols binary
import java.security.MessageDigest
SHA1('Rosetta Code', '48c98f7e5a6e736d790ab740dfc3f51a61abe2b5')
return
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method SHA1(messageText, verifyCheck) public static
algorithm = 'SHA-1'
digestSum = getDigest(messageText, algorithm)
say '<Message>'messageText'</Message>'
say Rexx('<'algorithm'>').right(12) || digestSum'</'algorithm'>'
say Rexx('<Verify>').right(12) || verifyCheck'</Verify>'
if digestSum == verifyCheck then say algorithm 'Confirmed'
else say algorithm 'Failed'
return
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method getDigest(messageText = Rexx, algorithm = Rexx 'MD5', encoding = Rexx 'UTF-8', lowercase = boolean 1) public static returns Rexx
algorithm = algorithm.upper
encoding = encoding.upper
message = String(messageText)
messageBytes = byte[]
digestBytes = byte[]
digestSum = Rexx ''
do
messageBytes = message.getBytes(encoding)
md = MessageDigest.getInstance(algorithm)
md.update(messageBytes)
digestBytes = md.digest
loop b_ = 0 to digestBytes.length - 1
bb = Rexx(digestBytes[b_]).d2x(2)
if lowercase then digestSum = digestSum || bb.lower
else digestSum = digestSum || bb.upper
end b_
catch ex = Exception
ex.printStackTrace
end
return digestSum

View file

@ -0,0 +1,5 @@
$ ocaml -I +sha sha1.cma
Objective Caml version 3.12.1
# Sha1.to_hex (Sha1.string "Rosetta Code") ;;
- : string = "48c98f7e5a6e736d790ab740dfc3f51a61abe2b5"

4
Task/SHA-1/PHP/sha-1.php Normal file
View file

@ -0,0 +1,4 @@
<?php
$string = 'Rosetta Code';
echo sha1( $string ), "\n";
?>

View file

@ -0,0 +1,44 @@
sub postfix:<mod2³²>(\x) { x % 2**32 }
sub infix:<>(\x,\y) { (x + y)mod2³² }
sub S(\n,\X) { (X +< n)mod2³² +| (X +> (32-n)) }
my \f = -> \B,\C,\D { (B +& C) +| ((+^B)mod2³² +& D) },
-> \B,\C,\D { B +^ C +^ D },
-> \B,\C,\D { (B +& C) +| (B +& D) +| (C +& D) },
-> \B,\C,\D { B +^ C +^ D };
my \K = 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6;
sub sha1-pad(Buf $msg)
{
my \bits = 8 * $msg.elems;
my @padded = $msg.list, 0x80, 0x00 xx (-(bits div 8 + 1 + 8) % 64);
@padded.map({ :256[$^a,$^b,$^c,$^d] }), (bits +> 32)mod2³², (bits)mod2³²;
}
sub sha1-block(@H is rw, @M)
{
my @W = @M;
@W.push: S(1, @W[$_-3] +^ @W[$_-8] +^ @W[$_-14] +^ @W[$_-16]) for 16..79;
my ($A,$B,$C,$D,$E) = @H;
for 0..79 -> \t {
my \TEMP = S(5,$A)f[t div 20]($B,$C,$D)$E@W[t]K[t div 20];
$E = $D; $D = $C; $C = S(30,$B); $B = $A; $A = TEMP;
}
@H «=» ($A,$B,$C,$D,$E);
}
sub sha1(Buf $msg)
{
my @M = sha1-pad($msg);
my @H = 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0;
sha1-block(@H,@M[$_..$_+15]) for 0,16...^+@M;
@H;
}
say sha1($_.encode('ascii'))».base(16), " $_"
for 'abc',
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
'Rosetta Code',
'Ars longa, vita brevis';

View file

@ -0,0 +1,3 @@
use Digest::SHA qw(sha1_hex);
print sha1_hex('Rosetta Code'), "\n";

View file

@ -0,0 +1,5 @@
use Digest::SHA;
my $sha1 = Digest::SHA->new(1);
$sha1->add('Rosetta Code');
print $sha1->hexdigest, "\n";

View file

@ -0,0 +1,4 @@
(let Str "Rosetta Code"
(pack
(mapcar '((B) (pad 2 (hex B)))
(native "libcrypto.so" "SHA1" '(B . 20) Str (length Str) '(NIL (20))) ) ) )

View file

@ -0,0 +1,5 @@
import hashlib
h = hashlib.sha1()
h.update(bytes("Ars longa, vita brevis", encoding="ASCII"))
h.hexdigest()
# "e640d285242886eb96ab80cbf858389b3df52f43"

View file

@ -0,0 +1,4 @@
#lang racket
(require file/sha1)
(sha1 (open-input-string "Rosetta Code"))

View file

@ -0,0 +1,4 @@
#lang racket
(require openssl/sha1)
(sha1 (open-input-string "Rosetta Code"))

View file

@ -0,0 +1,2 @@
require 'digest'
puts Digest::SHA1.hexdigest('Rosetta Code')

View file

@ -0,0 +1,2 @@
require 'openssl'
puts OpenSSL::Digest::SHA1.hexdigest('Rosetta Code')

View file

@ -0,0 +1,92 @@
require 'stringio'
# Calculates SHA-1 message digest of _string_. Returns binary digest.
# For hexadecimal digest, use +*sha1(string).unpack('H*')+.
#--
# This is a simple, pure-Ruby implementation of SHA-1, following
# the algorithm in FIPS 180-1.
#++
def sha1(string)
# functions and constants
mask = (1 << 32) - 1
s = proc{|n, x| ((x << n) & mask) | (x >> (32 - n))}
f = [
proc {|b, c, d| (b & c) | (b.^(mask) & d)},
proc {|b, c, d| b ^ c ^ d},
proc {|b, c, d| (b & c) | (b & d) | (c & d)},
proc {|b, c, d| b ^ c ^ d},
].freeze
k = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6].freeze
# initial hash
h = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]
io = StringIO.new(string)
block = ""
term = false # appended "\x80" in second-last block?
last = false # last block?
until last
# Read next block of 16 words (64 bytes, 512 bits).
io.read(64, block) or (
# Work around a bug in Rubinius 1.2.4. At eof,
# MRI and JRuby already replace block with "".
block.replace("")
)
# Unpack block into 32-bit words "N".
case len = block.length
when 64
# Unpack 16 words.
w = block.unpack("N16")
when 56..63
# Second-last block: append padding, unpack 16 words.
block.concat("\x80"); term = true
block.concat("\0" * (63 - len))
w = block.unpack("N16")
when 0..55
# Last block: append padding, unpack 14 words.
block.concat(term ? "\0" : "\x80")
block.concat("\0" * (55 - len))
w = block.unpack("N14")
# Append bit length, 2 words.
bit_len = string.length << 3
w.push(bit_len >> 32, bit_len & mask)
last = true
else
fail "impossible"
end
# Process block.
(16..79).each {|t|
w[t] = s[1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]]}
a, b, c, d, e = h[0..4]
t = 0
(0..3).each {|i|
20.times {
temp = (s[5, a] + f[i][b, c, d] + e + w[t] + k[i]) & mask
e = d; d = c; c = s[30, b]; b = a; a = temp
t += 1}}
h[0] = (h[0] + a) & mask
h[1] = (h[1] + b) & mask
h[2] = (h[2] + c) & mask
h[3] = (h[3] + d) & mask
h[4] = (h[4] + e) & mask
end
h.pack("N5")
end
if __FILE__ == $0
# Print some example SHA-1 digests.
# FIPS 180-1 has correct digests for 'abc' and 'abc...opq'.
[
'abc',
'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq',
'Rosetta Code',
].each {|s|
printf("%s:\n %s\n", s, *sha1(s).unpack('H*'))
}
end

View file

@ -0,0 +1,2 @@
PackageLoader fileInPackage: 'Digest'.
(SHA1 hexDigestOf: 'Rosetta Code') displayNl.

View file

@ -0,0 +1 @@
(SHA1Stream hashValueOf:'Rosetta Code')

2
Task/SHA-1/Tcl/sha-1.tcl Normal file
View file

@ -0,0 +1,2 @@
package require sha1
puts [sha1::sha1 "Rosetta Code"]

View file

@ -0,0 +1,2 @@
$ echo -n 'ASCII string' | sha1
9e9aeefe5563845ec5c42c5630842048c0fc261b

View file

@ -0,0 +1,2 @@
$ echo -n 'ASCII string' | openssl sha1 | sed 's/.*= //'
9e9aeefe5563845ec5c42c5630842048c0fc261b

View file

@ -0,0 +1,3 @@
'''SHA-256''' is the recommended stronger alternative to [[SHA-1]].
Either by using a dedicated library or implementing the algorithm in your language, show that the SHA-256 digest of the string "Rosetta code" is: 764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf

2
Task/SHA-256/1META.yaml Normal file
View file

@ -0,0 +1,2 @@
---
note: Checksums

View file

@ -0,0 +1,25 @@
PRINT FNsha256("Rosetta code")
END
DEF FNsha256(message$)
LOCAL buflen%, buffer%, hcont%, hprov%, hhash%, hash$, i%
CALG_SHA_256 = &800C
HP_HASHVAL = 2
CRYPT_NEWKEYSET = 8
PROV_RSA_AES = 24
buflen% = 128
DIM buffer% LOCAL buflen%-1
SYS "CryptAcquireContext", ^hcont%, 0, \
\ "Microsoft Enhanced RSA and AES Cryptographic Provider", \
\ PROV_RSA_AES, CRYPT_NEWKEYSET
SYS "CryptAcquireContext", ^hprov%, 0, 0, PROV_RSA_AES, 0
SYS "CryptCreateHash", hprov%, CALG_SHA_256, 0, 0, ^hhash%
SYS "CryptHashData", hhash%, message$, LEN(message$), 0
SYS "CryptGetHashParam", hhash%, HP_HASHVAL, buffer%, ^buflen%, 0
SYS "CryptDestroyHash", hhash%
SYS "CryptReleaseContext", hprov%
SYS "CryptReleaseContext", hcont%
FOR i% = 0 TO buflen%-1
hash$ += RIGHT$("0" + STR$~buffer%?i%, 2)
NEXT
= hash$

View file

@ -0,0 +1,124 @@
REM SHA-256 calculation by Richard Russell in BBC BASIC for Windows
REM Must run in FLOAT64 mode:
*FLOAT64
REM Test message for validation:
message$ = "Rosetta code"
REM Initialize variables:
h0% = &6A09E667
h1% = &BB67AE85
h2% = &3C6EF372
h3% = &A54FF53A
h4% = &510E527F
h5% = &9B05688C
h6% = &1F83D9AB
h7% = &5BE0CD19
REM Create table of constants:
DIM k%(63) : k%() = \
\ &428A2F98, &71374491, &B5C0FBCF, &E9B5DBA5, &3956C25B, &59F111F1, &923F82A4, &AB1C5ED5, \
\ &D807AA98, &12835B01, &243185BE, &550C7DC3, &72BE5D74, &80DEB1FE, &9BDC06A7, &C19BF174, \
\ &E49B69C1, &EFBE4786, &0FC19DC6, &240CA1CC, &2DE92C6F, &4A7484AA, &5CB0A9DC, &76F988DA, \
\ &983E5152, &A831C66D, &B00327C8, &BF597FC7, &C6E00BF3, &D5A79147, &06CA6351, &14292967, \
\ &27B70A85, &2E1B2138, &4D2C6DFC, &53380D13, &650A7354, &766A0ABB, &81C2C92E, &92722C85, \
\ &A2BFE8A1, &A81A664B, &C24B8B70, &C76C51A3, &D192E819, &D6990624, &F40E3585, &106AA070, \
\ &19A4C116, &1E376C08, &2748774C, &34B0BCB5, &391C0CB3, &4ED8AA4A, &5B9CCA4F, &682E6FF3, \
\ &748F82EE, &78A5636F, &84C87814, &8CC70208, &90BEFFFA, &A4506CEB, &BEF9A3F7, &C67178F2
Length% = LEN(message$)*8
REM Pre-processing:
REM append the bit '1' to the message:
message$ += CHR$&80
REM append k bits '0', where k is the minimum number >= 0 such that
REM the resulting message length (in bits) is congruent to 448 (mod 512)
WHILE (LEN(message$) MOD 64) <> 56
message$ += CHR$0
ENDWHILE
REM append length of message (before pre-processing), in bits, as
REM 64-bit big-endian integer:
FOR I% = 56 TO 0 STEP -8
message$ += CHR$(Length% >>> I%)
NEXT
REM Process the message in successive 512-bit chunks:
REM break message into 512-bit chunks, for each chunk
REM break chunk into sixteen 32-bit big-endian words w[i], 0 <= i <= 15
DIM w%(63)
FOR chunk% = 0 TO LEN(message$) DIV 64 - 1
FOR i% = 0 TO 15
w%(i%) = !(!^message$ + 64*chunk% + 4*i%)
SWAP ?(^w%(i%)+0),?(^w%(i%)+3)
SWAP ?(^w%(i%)+1),?(^w%(i%)+2)
NEXT i%
REM Extend the sixteen 32-bit words into sixty-four 32-bit words:
FOR i% = 16 TO 63
s0% = FNrr(w%(i%-15),7) EOR FNrr(w%(i%-15),18) EOR (w%(i%-15) >>> 3)
s1% = FNrr(w%(i%-2),17) EOR FNrr(w%(i%-2),19) EOR (w%(i%-2) >>> 10)
w%(i%) = FN32(w%(i%-16) + s0% + w%(i%-7) + s1%)
NEXT i%
REM Initialize hash value for this chunk:
a% = h0%
b% = h1%
c% = h2%
d% = h3%
e% = h4%
f% = h5%
g% = h6%
h% = h7%
REM Main loop:
FOR i% = 0 TO 63
s0% = FNrr(a%,2) EOR FNrr(a%,13) EOR FNrr(a%,22)
maj% = (a% AND b%) EOR (a% AND c%) EOR (b% AND c%)
t2% = FN32(s0% + maj%)
s1% = FNrr(e%,6) EOR FNrr(e%,11) EOR FNrr(e%,25)
ch% = (e% AND f%) EOR ((NOT e%) AND g%)
t1% = FN32(h% + s1% + ch% + k%(i%) + w%(i%))
h% = g%
g% = f%
f% = e%
e% = FN32(d% + t1%)
d% = c%
c% = b%
b% = a%
a% = FN32(t1% + t2%)
NEXT i%
REM Add this chunk's hash to result so far:
h0% = FN32(h0% + a%)
h1% = FN32(h1% + b%)
h2% = FN32(h2% + c%)
h3% = FN32(h3% + d%)
h4% = FN32(h4% + e%)
h5% = FN32(h5% + f%)
h6% = FN32(h6% + g%)
h7% = FN32(h7% + h%)
NEXT chunk%
REM Produce the final hash value (big-endian):
hash$ = FNhex(h0%) + " " + FNhex(h1%) + " " + FNhex(h2%) + " " + FNhex(h3%) + \
\ " " + FNhex(h4%) + " " + FNhex(h5%) + " " + FNhex(h6%) + " " + FNhex(h7%)
PRINT hash$
END
DEF FNrr(A%,I%) = (A% >>> I%) OR (A% << (32-I%))
DEF FNhex(A%) = RIGHT$("0000000"+STR$~A%,8)
DEF FN32(n#)
WHILE n# > &7FFFFFFF : n# -= 2^32 : ENDWHILE
WHILE n# < &80000000 : n# += 2^32 : ENDWHILE
= n#

View file

@ -0,0 +1,22 @@
using System;
using System.Security.Cryptography;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace RosettaCode.SHA256
{
[TestClass]
public class SHA256ManagedTest
{
[TestMethod]
public void TestComputeHash()
{
var buffer = Encoding.UTF8.GetBytes("Rosetta code");
var hashAlgorithm = new SHA256Managed();
var hash = hashAlgorithm.ComputeHash(buffer);
Assert.AreEqual(
"76-4F-AF-5C-61-AC-31-5F-14-97-F9-DF-A5-42-71-39-65-B7-85-E5-CC-2F-70-7D-64-68-D7-D1-12-4C-DF-CF",
BitConverter.ToString(hash));
}
}
}

15
Task/SHA-256/C/sha-256.c Normal file
View file

@ -0,0 +1,15 @@
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
int main (void) {
const char *s = "Rosetta code";
unsigned char *d = SHA256(s, strlen(s), 0);
int i;
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
printf("%02x", d[i]);
putchar('\n');
return 0;
}

View file

@ -0,0 +1,15 @@
package main
import (
"crypto/sha256"
"fmt"
"log"
)
func main() {
h := sha256.New()
if _, err := h.Write([]byte("Rosetta code")); err != nil {
log.Fatal(err)
}
fmt.Printf("%x\n", h.Sum(nil))
}

View file

@ -0,0 +1,4 @@
def sha256Hash = { text ->
java.security.MessageDigest.getInstance("SHA-256").digest(text.bytes)
.collect { String.format("%02x", it) }.join('')
}

View file

@ -0,0 +1 @@
assert sha256Hash('Rosetta code') == '764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf'

View file

@ -0,0 +1 @@
IntegerString[Hash["Rosetta code", "SHA256"], 16]

View file

@ -0,0 +1,50 @@
/* NetRexx */
options replace format comments java crossref savelog symbols binary
import java.security.MessageDigest
SHA256('Rosetta code', '764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf')
return
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method SHA256(messageText, verifyCheck) public static
algorithm = 'SHA-256'
digestSum = getDigest(messageText, algorithm)
say '<Message>'messageText'</Message>'
say Rexx('<'algorithm'>').right(12) || digestSum'</'algorithm'>'
say Rexx('<Verify>').right(12) || verifyCheck'</Verify>'
if digestSum == verifyCheck then say algorithm 'Confirmed'
else say algorithm 'Failed'
return
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method getDigest(messageText = Rexx, algorithm = Rexx 'MD5', encoding = Rexx 'UTF-8', lowercase = boolean 1) public static returns Rexx
algorithm = algorithm.upper
encoding = encoding.upper
message = String(messageText)
messageBytes = byte[]
digestBytes = byte[]
digestSum = Rexx ''
do
messageBytes = message.getBytes(encoding)
md = MessageDigest.getInstance(algorithm)
md.update(messageBytes)
digestBytes = md.digest
loop b_ = 0 to digestBytes.length - 1
bb = Rexx(digestBytes[b_]).d2x(2)
if lowercase then digestSum = digestSum || bb.lower
else digestSum = digestSum || bb.upper
end b_
catch ex = Exception
ex.printStackTrace
end
return digestSum

View file

@ -0,0 +1,4 @@
let () =
let s = "Rosetta code" in
let digest = Sha256.string s in
print_endline (Sha256.to_hex digest)

View file

@ -0,0 +1,8 @@
class ShaHash {
function : Main(args : String[]) ~ Nil {
hash:= Encryption.Hash->SHA256("Rosetta code"->ToByteArray());
str := hash->ToHexString()->ToLower();
str->PrintLine();
str->Equals("764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf")->PrintLine();
}
}

View file

@ -0,0 +1,2 @@
<?php
echo hash('sha256', 'Rosetta code');

View file

@ -0,0 +1,47 @@
say .list».fmt("%02x").join given sha256 "Rosetta code";
constant primes = grep &is-prime, 2 .. *;
sub init(&f) {
map { my $f = $^p.&f; (($f - $f.Int)*2**32).Int }, primes
}
sub infix:<m+> { ($^a + $^b) % 2**32 }
sub rotr($n, $b) { $n +> $b +| $n +< (32 - $b) }
proto sha256($) returns Buf {*}
multi sha256(Str $str where all($str.ords) < 128) {
sha256 $str.encode: 'ascii'
}
multi sha256(Buf $data) {
constant K = init(* **(1/3))[^64];
my $l = 8 * my @b = $data.list;
push @b, 0x80; push @b, 0 until (8*@b-448) %% 512;
push @b, reverse gather for ^8 { take $l%256; $l div=256 }
my @word = :256[@b.shift xx 4] xx @b/4;
my @H = init(&sqrt)[^8];
my @w;
loop (my $i = 0; $i < @word; $i += 16) {
my @h = @H;
for ^64 -> $j {
@w[$j] = $j < 16 ?? @word[$j + $i] // 0 !!
[m+]
rotr(@w[$j-15], 7) +^ rotr(@w[$j-15], 18) +^ @w[$j-15] +> 3,
@w[$j-7],
rotr(@w[$j-2], 17) +^ rotr(@w[$j-2], 19) +^ @w[$j-2] +> 10,
@w[$j-16];
my $ch = @h[4] +& @h[5] +^ +^@h[4] % 2**32 +& @h[6];
my $maj = @h[0] +& @h[2] +^ @h[0] +& @h[1] +^ @h[1] +& @h[2];
my $σ0 = [+^] map { rotr @h[0], $_ }, 2, 13, 22;
my $σ1 = [+^] map { rotr @h[4], $_ }, 6, 11, 25;
my $t1 = [m+] @h[7], $σ1, $ch, K[$j], @w[$j];
my $t2 = $σ0 m+ $maj;
@h = $t1 m+ $t2, @h[^3], @h[3] m+ $t1, @h[4..6];
}
@H = @H Z[m+] @h;
}
return Buf.new: map -> $word is rw {
reverse gather for ^4 { take $word % 256; $word div= 256 }
}, @H;
}

View file

@ -0,0 +1,7 @@
#!/usr/bin/perl
use strict ;
use warnings ;
use Digest::SHA qw( sha256_hex ) ;
my $digest = sha256_hex my $phrase = "Rosetta code" ;
print "SHA-256('$phrase'): $digest\n" ;

View file

@ -0,0 +1,4 @@
>>> import hashlib
>>> hashlib.sha256( "Rosetta code" ).hexdigest()
'764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf'
>>>

View file

@ -0,0 +1,2 @@
require 'digest/sha2'
puts Digest::SHA256.hexdigest('Rosetta code')

View file

@ -0,0 +1,3 @@
package require sha256
puts [sha2::sha256 -hex "Rosetta code"]

2
Task/SOAP/0DESCRIPTION Normal file
View file

@ -0,0 +1,2 @@
In this task, the goal is to create a SOAP client which accesses functions defined at '''http://example.com/soap/wsdl''', and calls the functions '''soapFunc( )''' and '''anotherSoapFunc( )'''.
{{Clarify_task}}

4
Task/SOAP/1META.yaml Normal file
View file

@ -0,0 +1,4 @@
---
category:
- Less Than 10 Examples
note: Networking and Web Interaction

View file

@ -0,0 +1,16 @@
import mx.rpc.soap.WebService;
import mx.rpc.events.ResultEvent;
var ws:WebService = new WebService();
ws.wsdl = 'http://example.com/soap/wsdl';
ws.soapFunc.addEventListener("result",soapFunc_Result);
ws.anotherSoapFunc.addEventListener("result",anotherSoapFunc_Result);
ws.loadWSDL();
ws.soapFunc();
ws.anotherSoapFunc();
// method invocation callback handlers
private function soapFunc_Result(event:ResultEvent):void {
// do something
}
private function anotherSoapFunc_Result(event:ResultEvent):void {
// do another something
}

View file

@ -0,0 +1,11 @@
WS_Initialize()
WS_Exec("Set client = CreateObject(""MSSOAP.SoapClient"")")
WS_Exec("client.MSSoapInit ""http://example.com/soap/wsdl""")
callhello = client.soapFunc("hello")
callanother = client.anotherSoapFunc(34234)
WS_Eval(result, callhello)
WS_Eval(result2, callanother)
Msgbox % result . "`n" . result2
WS_Uninitialize()
#Include ws4ahk.ahk ; http://www.autohotkey.net/~easycom/ws4ahk_public_api.html

View file

@ -0,0 +1,3 @@
<cfset client = createObject("webservice","http://example.com/soap/wsdl")>
<cfset result = client.soapFunc("hello")>
<cfset result = client.anotherSoapFunc(34234)>

View file

@ -0,0 +1,3 @@
InstallService["http://example.com/soap/wsdl"];
soapFunc["Hello"];
anotherSoapFunc[12345];

14
Task/SOAP/PHP/soap.php Normal file
View file

@ -0,0 +1,14 @@
<?php
//load the wsdl file
$client = new SoapClient("http://example.com/soap/definition.wsdl");
//functions are now available to be called
$result = $client->soapFunc("hello");
$result = $client->anotherSoapFunc(34234);
//SOAP Information
$client = new SoapClient("http://example.com/soap/definition.wsdl");
//list of SOAP types
print_r($client->__getTypes());
//list if SOAP Functions
print_r($client->__getFunctions());
?>

8
Task/SOAP/Perl/soap.pl Normal file
View file

@ -0,0 +1,8 @@
use SOAP::Lite;
print SOAP::Lite
-> service('http://example.com/soap/wsdl')
-> soapFunc("hello");
print SOAP::Lite
-> service('http://example.com/soap/wsdl')
-> anotherSoapFunc(34234);

View file

@ -0,0 +1,5 @@
XIncludeFile "COMatePLUS.pbi"
Define.COMateObject soapObject = COMate_CreateObject("MSSOAP.SoapClient")
soapObject\Invoke("MSSoapInit('http://example.com/soap/wsdl')")
result = soapObject\Invoke("soapFunc('hello')")
result2 = soapObject\Invoke("anotherSoapFunc(34234)")

4
Task/SOAP/Python/soap.py Normal file
View file

@ -0,0 +1,4 @@
from SOAPpy import WSDL
proxy = WSDL.Proxy("http://example.com/soap/wsdl")
result = proxy.soapFunc("hello")
result = proxy.anotherSoapFunc(34234)

10
Task/SOAP/Ruby/soap.rb Normal file
View file

@ -0,0 +1,10 @@
require 'soap/wsdlDriver'
wsdl = SOAP::WSDLDriverFactory.new("http://example.com/soap/wsdl")
soap = wsdl.create_rpc_driver
response1 = soap.soapFunc(:elementName => "value")
puts response1.soapFuncReturn
response2 = soap.anotherSoapFunc(:aNumber => 42)
puts response2.anotherSoapFuncReturn

9
Task/SOAP/Tcl/soap.tcl Normal file
View file

@ -0,0 +1,9 @@
package require WS::Client
# Grok the service, and generate stubs
::WS::Client::GetAndParseWsdl http://example.com/soap/wsdl
::WS::Client::CreateStubs ExampleService ;# Assume that's the service name...
# Do the calls
set result1 [ExampleService::soapFunc "hello"]
set result2 [ExampleService::anotherSoapFunc 34234]

View file

@ -0,0 +1,6 @@
Dim client
Dim result
Set client = CreateObject("MSSOAP.SoapClient")
client.MSSoapInit "http://example.com/soap/wsdl"
result = client.soapFunc("hello")
result = client.anotherSoapFunc(34234)

View file

@ -0,0 +1,10 @@
LOCAL oSoapClient AS OLEAUTOOBJECT
LOCAL cUrl AS STRING
LOCAL uResult AS USUAL
oSoapClient := OLEAutoObject{"MSSOAP.SoapClient30"}
cUrl := "http://example.com/soap/wsdl"
IF oSoapClient:fInit
oSoapClient:mssoapinit(cUrl,"", "", "" )
uResult := oSoapClient:soapFunc("hello")
uResult := oSoapClient:anotherSoapFunc(34234)
ENDIF

View file

@ -0,0 +1,15 @@
This task has three parts:
* Connect to a [[MySQL]] database (<tt>connect_db</tt>)
* Create user/password records in the following table (<tt>create_user</tt>)
* Authenticate login requests against the table (<tt>authenticate_user</tt>)
This is the table definition:
<lang sql>create table users (
userid int primary key auto_increment,
username varchar(32) unique key not null,
pass_salt tinyblob not null,
-- a string of 16 random bytes
pass_md5 tinyblob not null
-- binary MD5 hash of pass_salt concatenated with the password
);</lang>
(<tt>pass_salt</tt> and <tt>pass_md5</tt> would be <tt>binary(16)</tt> values, but MySQL versions before 5.0.15 strip trailing spaces when selecting them.)

View file

@ -0,0 +1,2 @@
---
note: Database operations

View file

@ -0,0 +1,174 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <mysql.h>
#include <openssl/md5.h>
void end_with_db(void);
MYSQL *mysql = NULL; // global...
bool connect_db(const char *host, const char *user, const char *pwd,
const char *db, unsigned int port)
{
if ( mysql == NULL )
{
if (mysql_library_init(0, NULL, NULL)) return false;
mysql = mysql_init(NULL); if ( mysql == NULL ) return false;
MYSQL *myp = mysql_real_connect(mysql, host, user, pwd, db, port, NULL, 0);
if (myp == NULL) {
fprintf(stderr, "connection error: %s\n", mysql_error(mysql));
end_with_db();
return false;
}
}
return true; // already connected... ?
}
#define USERNAMELIMIT 32
// no part of the spec, but it is reasonable!!
#define PASSWORDLIMIT 32
#define SALTBYTE 16
bool create_user(const char *username, const char *password)
{
int i;
char binarysalt[SALTBYTE];
char salt[SALTBYTE*2+1];
char md5hash[MD5_DIGEST_LENGTH];
char saltpass[SALTBYTE+PASSWORDLIMIT+1];
char pass_md5[MD5_DIGEST_LENGTH*2 + 1];
char user[USERNAMELIMIT*2 + 1];
char *q = NULL;
static const char query[] =
"INSERT INTO users "
"(username,pass_salt,pass_md5) "
"VALUES ('%s', X'%s', X'%s')";
static const size_t qlen = sizeof query;
for(i=0; username[i] != '\0' && i < USERNAMELIMIT; i++) ;
if ( username[i] != '\0' ) return false;
for(i=0; password[i] != '\0' && i < PASSWORDLIMIT; i++) ;
if ( password[i] != '\0' ) return false;
srand(time(NULL));
for(i=0; i < SALTBYTE; i++)
{
// this skews the distribution but it is lazyness-compliant;)
binarysalt[i] = rand()%256;
}
(void)mysql_hex_string(salt, binarysalt, SALTBYTE);
for(i=0; i < SALTBYTE; i++) saltpass[i] = binarysalt[i];
strcpy(saltpass+SALTBYTE, password);
(void)MD5(saltpass, SALTBYTE + strlen(password), md5hash);
(void)mysql_hex_string(pass_md5, md5hash, MD5_DIGEST_LENGTH);
(void)mysql_real_escape_string(mysql, user, username, strlen(username));
// salt, pass_md5, user are db-query-ready
q = malloc(qlen + USERNAMELIMIT*2 + MD5_DIGEST_LENGTH*2 + SALTBYTE*2 + 1);
if ( q == NULL ) return false;
sprintf(q, query, user, salt, pass_md5);
#if defined(DEBUG)
fprintf(stderr, "QUERY:\n%s\n\n", q);
#endif
int res = mysql_query(mysql, q);
free(q);
if ( res != 0 )
{
fprintf(stderr, "create_user query error: %s\n", mysql_error(mysql));
return false;
}
return true;
}
bool authenticate_user(const char *username, const char *password)
{
char user[USERNAMELIMIT*2 + 1];
char md5hash[MD5_DIGEST_LENGTH];
char saltpass[SALTBYTE+PASSWORDLIMIT+1];
bool authok = false;
char *q = NULL;
int i;
static const char query[] =
"SELECT * FROM users WHERE username='%s'";
static const size_t qlen = sizeof query;
// can't be authenticated with invalid username or password
for(i=0; username[i] != '\0' && i < USERNAMELIMIT; i++) ;
if ( username[i] != '\0' ) return false;
for(i=0; password[i] != '\0' && i < PASSWORDLIMIT; i++) ;
if ( password[i] != '\0' ) return false;
(void)mysql_real_escape_string(mysql, user, username, strlen(username));
q = malloc(qlen + strlen(user) + 1);
if (q == NULL) return false;
sprintf(q, query, username);
int res = mysql_query(mysql, q);
free(q);
if ( res != 0 )
{
fprintf(stderr, "authenticate_user query error: %s\n", mysql_error(mysql));
return false;
}
MYSQL_RES *qr = mysql_store_result(mysql);
if ( qr == NULL ) return false;
// should be only a result, or none
if ( mysql_num_rows(qr) != 1 ) {
mysql_free_result(qr);
return false;
}
MYSQL_ROW row = mysql_fetch_row(qr); // 1 row must exist
unsigned long *len = mysql_fetch_lengths(qr); // and should have 4 cols...
memcpy(saltpass, row[2], len[2]); // len[2] should be SALTBYTE
memcpy(saltpass + len[2], password, strlen(password));
(void)MD5(saltpass, SALTBYTE + strlen(password), md5hash);
authok = memcmp(md5hash, row[3], len[3]) == 0;
mysql_free_result(qr);
return authok;
}
void end_with_db(void)
{
mysql_close(mysql); mysql = NULL;
mysql_library_end();
}
int main(int argc, char **argv)
{
if ( argc < 4 ) return EXIT_FAILURE;
if ( connect_db("localhost", "devel", "", "test", 0 ) )
{
if ( strcmp(argv[1], "add") == 0 )
{
if (create_user(argv[2], argv[3]))
printf("created\n");
} else if ( strcmp(argv[1], "auth") == 0 ) {
if (authenticate_user(argv[2], argv[3]))
printf("authorized\n");
else
printf("access denied\n");
} else {
printf("unknown command\n");
}
end_with_db();
}
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,142 @@
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.math.BigInteger;
class UserManager {
private Connection dbConnection;
public UserManager() {
}
private String md5(String aString) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md;
String hex;
StringBuffer hexString;
byte[] bytesOfMessage;
byte[] theDigest;
hexString = new StringBuffer();
bytesOfMessage = aString.getBytes("UTF-8");
md = MessageDigest.getInstance("MD5");
theDigest = md.digest(bytesOfMessage);
for (int i = 0; i < theDigest.length; i++) {
hex = Integer.toHexString(0xff & theDigest[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
public void connectDB(String host, int port, String db, String user, String password)
throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
this.dbConnection = DriverManager.getConnection("jdbc:mysql://"
+ host
+ ":"
+ port
+ "/"
+ db, user, password);
}
public boolean createUser(String user, String password) {
SecureRandom random;
String insert;
String salt;
random = new SecureRandom();
salt = new BigInteger(130, random).toString(16);
insert = "INSERT INTO users "
+ "(username, pass_salt, pass_md5) "
+ "VALUES (?, ?, ?)";
try (PreparedStatement pstmt = this.dbConnection.prepareStatement(insert)) {
pstmt.setString(1, user);
pstmt.setString(2, salt);
pstmt.setString(3, this.md5(salt + password));
pstmt.executeUpdate();
return true;
} catch(NoSuchAlgorithmException | SQLException | UnsupportedEncodingException ex) {
return false;
}
}
public boolean authenticateUser(String user, String password) {
String pass_md5;
String pass_salt;
String select;
ResultSet res;
select = "SELECT pass_salt, pass_md5 FROM users WHERE username = ?";
res = null;
try(PreparedStatement pstmt = this.dbConnection.prepareStatement(select)) {
pstmt.setString(1, user);
res = pstmt.executeQuery();
res.next(); // We assume that username is unique
pass_salt = res.getString(1);
pass_md5 = res.getString(2);
if (pass_md5.equals(this.md5(pass_salt + password))) {
return true;
} else {
return false;
}
} catch(NoSuchAlgorithmException | SQLException | UnsupportedEncodingException ex) {
return false;
} finally {
try {
if (res instanceof ResultSet && !res.isClosed()) {
res.close();
}
} catch(SQLException ex) {
}
}
}
public void closeConnection() {
try {
this.dbConnection.close();
} catch(NullPointerException | SQLException ex) {
}
}
public static void main(String[] args) {
UserManager um;
um = new UserManager();
try {
um.connectDB("localhost", 3306, "test", "root", "admin");
if (um.createUser("johndoe", "test")) {
System.out.println("User created");
}
if (um.authenticateUser("johndoe", "test")) {
System.out.println("User authenticated");
}
} catch(ClassNotFoundException | SQLException ex) {
ex.printStackTrace();
} finally {
um.closeConnection();
}
}
}

View file

@ -0,0 +1,69 @@
function connect_db($database, $db_user, $db_password, $host = 'localhost', $port = NULL, $die = false) {
// Returns a MySQL link identifier (handle) on success
// Returns false or dies() on error depending on the setting of parameter $die
// Parameter $die configures error handling, setting it any non-false value will die() on error
// Parameters $host, $port and $die have sensible defaults and are not usually required
if(!$db_handle = @mysql_connect($host.($port ? ':'.$port : ''), $db_user, $db_password)) {
if($die)
die("Can't connect to MySQL server:\r\n".mysql_error());
else
return false;
}
if(!@mysql_select_db($database, $db_handle)) {
if($die)
die("Can't select database '$database':\r\n".mysql_error());
else
return false;
}
return $db_handle;
}
function create_user($username, $password, $db_handle) {
// Returns the record ID on success or false on failure
// Username limit is 32 characters (part of spec)
if(strlen($username) > 32)
return false;
// Salt limited to ASCII 32 thru 254 (not part of spec)
$salt = '';
do {
$salt .= chr(mt_rand(32, 254));
} while(strlen($salt) < 16);
// Create pass_md5
$pass_md5 = md5($salt.$password);
// Make it all binary safe
$username = mysql_real_escape_string($username);
$salt = mysql_real_escape_string($salt);
// Try to insert it into the table - Return false on failure
if(!@mysql_query("INSERT INTO users (username,pass_salt,pass_md5) VALUES('$username','$salt','$pass_md5')", $db_handle))
return false;
// Return the record ID
return mysql_insert_id($db_handle);
}
function authenticate_user($username, $password, $db_handle) {
// Checks a username/password combination against the database
// Returns false on failure or the record ID on success
// Make the username parmeter binary-safe
$safe_username = mysql_real_escape_string($username);
// Grab the record (if it exists) - Return false on failure
if(!$result = @mysql_query("SELECT * FROM users WHERE username='$safe_username'", $db_handle))
return false;
// Grab the row
$row = @mysql_fetch_assoc($result);
// Check the password and return false if incorrect
if(md5($row['pass_salt'].$password) != $row['pass_md5'])
return false;
// Return the record ID
return $row['userid'];
}

View file

@ -0,0 +1,30 @@
use DBI;
# returns a database handle configured to throw an exception on query errors
sub connect_db {
my ($dbname, $host, $user, $pass) = @_;
my $db = DBI->connect("dbi:mysql:$dbname:$host", $user, $pass)
or die $DBI::errstr;
$db->{RaiseError} = 1;
$db
}
# if the user was successfully created, returns its user id.
# if the name was already in use, returns undef.
sub create_user {
my ($db, $user, $pass) = @_;
my $salt = pack "C*", map {int rand 256} 1..16;
$db->do("INSERT IGNORE INTO users (username, pass_salt, pass_md5)
VALUES (?, ?, unhex(md5(concat(pass_salt, ?))))",
undef, $user, $salt, $pass)
and $db->{mysql_insertid} or undef
}
# if the user is authentic, returns its user id. otherwise returns undef.
sub authenticate_user {
my ($db, $user, $pass) = @_;
my $userid = $db->selectrow_array("SELECT userid FROM users WHERE
username=? AND pass_md5=unhex(md5(concat(pass_salt, ?)))",
undef, $user, $pass);
$userid
}

View file

@ -0,0 +1,82 @@
import mysql.connector
import hashlib
import sys
import random
DB_HOST = "localhost"
DB_USER = "devel"
DB_PASS = "devel"
DB_NAME = "test"
def connect_db():
''' Try to connect DB and return DB instance, if not, return False '''
try:
return mysql.connector.connect(host=DB_HOST, user=DB_USER, passwd=DB_PASS, db=DB_NAME)
except:
return False
def create_user(username, passwd):
''' if user was successfully created, returns its ID; returns None on error '''
db = connect_db()
if not db:
print "Can't connect MySQL!"
return None
cursor = db.cursor()
salt = randomValue(16)
passwd_md5 = hashlib.md5(salt+passwd).hexdigest()
# If username already taken, inform it
try:
cursor.execute("INSERT INTO users (`username`, `pass_salt`, `pass_md5`) VALUES (%s, %s, %s)", (username, salt, passwd_md5))
cursor.execute("SELECT userid FROM users WHERE username=%s", (username,) )
id = cursor.fetchone()
db.commit()
cursor.close()
db.close()
return id[0]
except:
print 'Username was already taken. Please select another'
return None
def authenticate_user(username, passwd):
db = connect_db()
if not db:
print "Can't connect MySQL!"
return False
cursor = db.cursor()
cursor.execute("SELECT pass_salt, pass_md5 FROM users WHERE username=%s", (username,))
row = cursor.fetchone()
cursor.close()
db.close()
if row is None: # username not found
return False
salt = row[0]
correct_md5 = row[1]
tried_md5 = hashlib.md5(salt+passwd).hexdigest()
return correct_md5 == tried_md5
def randomValue(length):
''' Creates random value with given length'''
salt_chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
return ''.join(random.choice(salt_chars) for x in range(length))
if __name__ == '__main__':
user = randomValue(10)
passwd = randomValue(16)
new_user_id = create_user(user, passwd)
if new_user_id is None:
print 'Failed to create user %s' % user
sys.exit(1)
auth = authenticate_user(user, passwd)
if auth:
print 'User %s authenticated successfully' % user
else:
print 'User %s failed' % user

View file

@ -0,0 +1,31 @@
'mysql://root@localhost/test' open as mysql
'abcdefghijklmnopqrstuvwxyz0123456789' as $salt_chars
# return userid for success and FALSE for failure.
define create_user use $user, $pass
group 16 each as i
$salt_chars choose chr
join as $pass_salt
"%($pass_salt)s%($pass)s" md5 as $pass_md5
$user copy mysql escape as $user_name
group 'INSERT IGNORE into users (username, pass_md5, pass_salt)'
" VALUES ('%($user_name)s', unhex('%($pass_md5)s'), '%($pass_salt)s')"
join mysql query inserted
# return userid for success and FALSE for failure.
define authenticate_user use $user, $pass
FALSE as $userid
$user copy mysql escape as $user_name
group 'SELECT userid, pass_salt, hex(pass_md5)'
" FROM users WHERE username = '%($user_name)s'"
join mysql query as rs
rs selected
if rs fetch values into $possible_userid, $pass_salt, $pass_md5
"%($pass_salt)s%($pass)s" md5 $pass_md5 lower =
if $possible_userid as $userid
$userid
'foo' 'bar' create_user !if "could not create user\n" print bye
'foo' 'bar' authenticate_user !if "could not authenticate user\n" print bye
"user successfully created and authenticated!\n" print

View file

@ -0,0 +1,36 @@
package require tdbc
proc connect_db {handleName dbname host user pass} {
package require tdbc::mysql
tdbc::mysql::connection create $handleName -user $user -passwd $pass \
-host $host -database $dbname
return $handleName
}
# A simple helper to keep code shorter
proc r64k {} {
expr int(65536*rand())
}
proc create_user {handle user pass} {
set salt [binary format ssssssss \
[r64k] [r64k] [r64k] [r64k] [r64k] [r64k] [r64k] [r64k]]
# Note that we are using named parameters below, :user :salt :pass
# They are bound automatically to local variables with the same name
$handle allrows {
INSERT IGNORE INTO users (username, pass_salt, pass_md5)
VALUES (:user, :salt, unhex(md5(concat(:salt, :pass))))
}
return ;# Ignore the result of the allrows method
}
proc authenticate_user {handle user pass} {
$handle foreach row {
SELECT userid FROM users WHERE
username=:user AND pass_md5=unhex(md5(concat(pass_salt, :pass)))
} {
return [dict get $row userid]
}
# Only get here if no rows selected
error "authentication failed for user \"$user\""
}

View file

@ -0,0 +1,62 @@
Set Puzzles are created with a deck of cards from the [[wp:Set (game)|Set Game™]]. The object of the puzzle is to find sets of 3 cards in a rectangle of cards that have been dealt face up. There are 81 cards in a deck. Each card contains a unique variation of the following four features: ''color, symbol, number and shading''.
; there are three colors: '''red''', '''green''', or '''purple'''
; there are three symbols: '''oval''', '''squiggle''', or '''diamond'''
; there is a number of symbols on the card: '''one''', '''two''', or '''three'''
; there are three shadings: '''solid''', '''open''', or '''striped'''
Three cards form a ''set'' if each feature is either the same on each card, or is different on each card. For instance: all 3 cards are red, all 3 cards have a different symbol, all 3 cards have a different number of symbols, all 3 cards are striped.
There are two degrees of difficulty: [http://www.setgame.com/set/rules_basic.htm ''basic''] and [http://www.setgame.com/set/rules_advanced.htm ''advanced'']. The basic mode deals 9 cards, that contain exactly 4 sets; the advanced mode deals 12 cards that contain exactly 6 sets. When creating sets you may use the same card more than once. The task is to write code that deals the cards (9 or 12, depending on selected mode) from a shuffled deck in which the total number of sets that could be found is 4 (or 6, respectively); and print the contents of the cards and the sets. For instance:
'''DEALT 9 CARDS:'''
:green, one, oval, striped
:green, one, diamond, open
:green, one, diamond, striped
:green, one, diamond, solid
:purple, one, diamond, open
:purple, two, squiggle, open
:purple, three, oval, open
:red, three, oval, open
:red, three, diamond, solid
'''CONTAINING 4 SETS:'''
:green, one, oval, striped
:purple, two, squiggle, open
:red, three, diamond, solid
:green, one, diamond, open
:green, one, diamond, striped
:green, one, diamond, solid
:green, one, diamond, open
:purple, two, squiggle, open
:red, three, oval, open
:purple, one, diamond, open
:purple, two, squiggle, open
:purple, three, oval, open

View file

@ -0,0 +1,95 @@
#include <stdio.h>
#include <stdlib.h>
char *names[4][3] = {
{ "red", "green", "purple" },
{ "oval", "squiggle", "diamond" },
{ "one", "two", "three" },
{ "solid", "open", "striped" }
};
int set[81][81];
void init_sets(void)
{
int i, j, t, a, b;
for (i = 0; i < 81; i++) {
for (j = 0; j < 81; j++) {
for (t = 27; t; t /= 3) {
a = (i / t) % 3;
b = (j / t) % 3;
set[i][j] += t * (a == b ? a : 3 - a - b);
}
}
}
}
void deal(int *out, int n)
{
int i, j, t, c[81];
for (i = 0; i < 81; i++) c[i] = i;
for (i = 0; i < n; i++) {
j = i + (rand() % (81 - i));
t = c[i], c[i] = out[i] = c[j], c[j] = t;
}
}
int get_sets(int *cards, int n, int sets[][3])
{
int i, j, k, s = 0;
for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
for (k = j + 1; k < n; k++) {
if (set[cards[i]][cards[j]] == cards[k])
sets[s][0] = i,
sets[s][1] = j,
sets[s][2] = k,
s++;
}
}
}
return s;
}
void show_card(int c)
{
int i, t;
for (i = 0, t = 27; t; i++, t /= 3)
printf("%9s", names[i][(c/t)%3]);
putchar('\n');
}
void deal_sets(int ncard, int nset)
{
int c[81];
int csets[81][3]; // might not be enough for large ncard
int i, j, s;
do deal(c, ncard); while ((s = get_sets(c, ncard, csets)) != nset);
printf("dealt %d cards\n", ncard);
for (i = 0; i < ncard; i++) {
printf("%2d:", i);
show_card(c[i]);
}
printf("\nsets:\n");
for (i = 0; i < s; i++) {
for (j = 0; j < 3; j++) {
printf("%2d:", csets[i][j]);
show_card(c[csets[i][j]]);
}
putchar('\n');
}
}
int main(void)
{
init_sets();
deal_sets(9, 4);
while (1) deal_sets(12, 6);
return 0;
}

View file

@ -0,0 +1,108 @@
import std.stdio, std.random, std.array, std.conv, std.traits,
std.exception;
const class SetDealer {
protected {
enum Color : ubyte {green, purple, red}
enum Number : ubyte {one, two, three}
enum Symbol : ubyte {oval, diamond, squiggle}
enum Fill : ubyte {open, striped, solid}
static struct Card {
Color c;
Number n;
Symbol s;
Fill f;
}
immutable Card[81] deck;
}
this() pure nothrow {
Card[] tmpdeck;
immutable colors = [EnumMembers!Color];
immutable numbers = [EnumMembers!Number];
immutable symbols = [EnumMembers!Symbol];
immutable fill = [EnumMembers!Fill];
foreach (immutable i; 0 .. deck.length)
tmpdeck ~= Card(colors[i / 27],
numbers[(i / 9) % 3],
symbols[(i / 3) % 3],
fill[i % 3]);
// randomShuffle(tmpdeck); /* not pure nothrow */
deck = assumeUnique(tmpdeck);
}
// randomSample produces a sorted output that's convenient in our
// case because we're printing to stout. Normally you would want
// to shuffle.
immutable(Card)[] deal(in uint numCards) const {
enforce(numCards < deck.length, "number of cards too large");
return deck[].randomSample(numCards).array();
}
// The summed enums of valid sets are always zero or a multiple
// of 3.
bool validSet(in ref Card c1, in ref Card c2, in ref Card c3)
const pure nothrow {
return !((c1.c + c2.c + c3.c) % 3 ||
(c1.n + c2.n + c3.n) % 3 ||
(c1.s + c2.s + c3.s) % 3 ||
(c1.f + c2.f + c3.f) % 3);
}
immutable(Card)[3][] findSets(in Card[] cards, in uint target = 0)
const pure nothrow {
immutable len = cards.length;
if (len < 3)
return null;
typeof(return) sets;
foreach (immutable i; 0 .. len - 2)
foreach (immutable j; i + 1 .. len - 1)
foreach (immutable k; j + 1 .. len)
if (validSet(cards[i], cards[j], cards[k])) {
sets ~= [cards[i], cards[j], cards[k]];
if (target != 0 && sets.length > target)
return null;
}
return sets;
}
}
const final class SetPuzzleDealer : SetDealer {
enum {basic = 9, advanced = 12}
override immutable(Card)[] deal(in uint numCards = basic) const {
immutable numSets = numCards / 2;
typeof(return) cards;
do {
cards = super.deal(numCards);
} while (findSets(cards, numSets).length != numSets);
return cards;
}
}
void main() {
const dealer = new SetPuzzleDealer();
const cards = dealer.deal();
writefln("\nDEALT %d CARDS:\n", cards.length);
foreach (c; cards)
writeln(cast()c);
immutable sets = dealer.findSets(cards);
immutable len = sets.length;
writefln("\nFOUND %d %s:\n", len, len == 1 ? "SET" : "SETS");
foreach (set; sets) {
foreach (c; set)
writeln(cast()c);
writeln();
}
}

View file

@ -0,0 +1,24 @@
require 'stats/base'
Number=: ;:'one two three'
Colour=: ;:'red green purple'
Fill=: ;:'solid open striped'
Symbol=: ;:'oval squiggle diamond'
Features=: Number ; Colour ; Fill ;< Symbol
Deck=: > ; <"1 { i.@#&.> Features
sayCards=: (', ' joinstring Features {&>~ ])"1
drawRandom=: ] {~ (? #)
isSet=: *./@:(1 3 e.~ [: #@~."1 |:)"2
getSets=: ([: (] #~ isSet) ] {~ 3 comb #)
countSets=: #@:getSets
set_puzzle=: verb define
target=. <. -: y
whilst. target ~: countSets Hand do.
Hand=. y drawRandom Deck
end.
echo 'Dealt ',(": y),' Cards:'
echo sayCards Hand
echo 'Found ',(":target),' Sets:'
echo sayCards getSets Hand
)

View file

@ -0,0 +1,27 @@
set_puzzle 9
Dealt 9 Cards:
three, purple, open, oval
three, green, open, diamond
three, red, solid, squiggle
three, green, solid, oval
three, purple, striped, oval
three, red, open, oval
one, red, solid, oval
one, green, open, squiggle
two, purple, striped, squiggle
Found 4 Sets:
three, green, open, diamond
three, red, solid, squiggle
three, purple, striped, oval
three, green, open, diamond
one, red, solid, oval
two, purple, striped, squiggle
three, red, solid, squiggle
one, green, open, squiggle
two, purple, striped, squiggle
three, green, solid, oval
three, purple, striped, oval
three, red, open, oval

View file

@ -0,0 +1,126 @@
import java.util.*;
import org.apache.commons.lang3.ArrayUtils;
public class SetPuzzle {
enum Color {
GREEN(0), PURPLE(1), RED(2);
private Color(int v) {
val = v;
}
public final int val;
}
enum Number {
ONE(0), TWO(1), THREE(2);
private Number(int v) {
val = v;
}
public final int val;
}
enum Symbol {
OVAL(0), DIAMOND(1), SQUIGGLE(2);
private Symbol(int v) {
val = v;
}
public final int val;
}
enum Fill {
OPEN(0), STRIPED(1), SOLID(2);
private Fill(int v) {
val = v;
}
public final int val;
}
private static class Card implements Comparable<Card> {
Color c;
Number n;
Symbol s;
Fill f;
public String toString() {
return String.format("[Card: %s, %s, %s, %s]", c, n, s, f);
}
public int compareTo(Card o) {
return (c.val - o.c.val) * 10 + (n.val - o.n.val);
}
}
private static Card[] deck;
public static void main(String[] args) {
deck = new Card[81];
Color[] colors = Color.values();
Number[] numbers = Number.values();
Symbol[] symbols = Symbol.values();
Fill[] fillmodes = Fill.values();
for (int i = 0; i < deck.length; i++) {
deck[i] = new Card();
deck[i].c = colors[i / 27];
deck[i].n = numbers[(i / 9) % 3];
deck[i].s = symbols[(i / 3) % 3];
deck[i].f = fillmodes[i % 3];
}
findSets(12);
}
private static void findSets(int numCards) {
int target = numCards / 2;
Card[] cards;
Card[][] sets = new Card[target][3];
int cnt;
do {
Collections.shuffle(Arrays.asList(deck));
cards = ArrayUtils.subarray(deck, 0, numCards);
cnt = 0;
outer:
for (int i = 0; i < cards.length - 2; i++) {
for (int j = i + 1; j < cards.length - 1; j++) {
for (int k = j + 1; k < cards.length; k++) {
if (validSet(cards[i], cards[j], cards[k])) {
if (cnt < target)
sets[cnt] = new Card[]{cards[i], cards[j], cards[k]};
if (++cnt > target) {
break outer;
}
}
}
}
}
} while (cnt != target);
Arrays.sort(cards);
System.out.printf("GIVEN %d CARDS:\n\n", numCards);
for (Card c : cards) {
System.out.println(c);
}
System.out.println();
System.out.println("FOUND " + target + " SETS:\n");
for (Card[] set : sets) {
for (Card c : set) {
System.out.println(c);
}
System.out.println();
}
}
private static boolean validSet(Card c1, Card c2, Card c3) {
int tot = 0;
tot += (c1.c.val + c2.c.val + c3.c.val) % 3;
tot += (c1.n.val + c2.n.val + c3.n.val) % 3;
tot += (c1.s.val + c2.s.val + c3.s.val) % 3;
tot += (c1.f.val + c2.f.val + c3.f.val) % 3;
return tot == 0;
}
}

View file

@ -0,0 +1,26 @@
enum Color (red => 0o1000, green => 0o2000, purple => 0o4000);
enum Count (one => 0o100, two => 0o200, three => 0o400);
enum Shape (oval => 0o10, squiggle => 0o20, diamond => 0o40);
enum Style (solid => 0o1, open => 0o2, striped => 0o4);
my @deck := (Color.enums X Count.enums X Shape.enums X Style.enums).tree;
sub MAIN($DRAW = 9, $GOAL = $DRAW div 2) {
my @combinations = combine(3, [^$DRAW]);
my @draw;
repeat until (my @sets) == $GOAL {
@draw = @deck.pick($DRAW);
my @bits = @draw.map: { [+] @^enums».value }
@sets = gather for @combinations -> @c {
take @draw[@c].item when /^ <[1247]>+ $/ given ( [+|] @bits[@c] ).base(8);
}
}
say "Drew $DRAW cards:";
show-cards @draw;
for @sets.kv -> $i, @cards {
say "\nSet {$i+1}:";
show-cards @cards;
}
}
sub show-cards(@c) { for @c -> $c { printf " %-6s %-5s %-8s %s\n", $c».key } }

View file

@ -0,0 +1,46 @@
#!/usr/bin/python
from itertools import product, combinations
from random import sample
## Major constants
features = [ 'green purple red'.split(),
'one two three'.split(),
'oval diamond squiggle'.split(),
'open striped solid'.split() ]
deck = list(product(list(range(3)), repeat=4))
dealt = 9
## Functions
def printcard(card):
print(' '.join('%8s' % f[i] for f,i in zip(features, card)))
def getdeal(dealt=dealt):
deal = sample(deck, dealt)
return deal
def getsets(deal):
good_feature_count = set([1, 3])
sets = [ comb for comb in combinations(deal, 3)
if all( [(len(set(feature)) in good_feature_count)
for feature in zip(*comb)]
) ]
return sets
def printit(deal, sets):
print('Dealt %i cards:' % len(deal))
for card in deal: printcard(card)
print('\nFound %i sets:' % len(sets))
for s in sets:
for card in s: printcard(card)
print('')
if __name__ == '__main__':
while True:
deal = getdeal()
sets = getsets(deal)
if len(sets) == dealt / 2:
break
printit(deal, sets)

View file

@ -0,0 +1,82 @@
# Generate random integer uniformly on range [0..$n-1]
proc random n {expr {int(rand() * $n)}}
# Generate a shuffled deck of all cards; the card encoding was stolen from the
# Perl6 solution. This is done once and then used as a constant. Note that the
# rest of the code assumes that all cards in the deck are unique.
set ::AllCards [apply {{} {
set cards {}
foreach color {1 2 4} {
foreach symbol {1 2 4} {
foreach number {1 2 4} {
foreach shading {1 2 4} {
lappend cards [list $color $symbol $number $shading]
}
}
}
}
# Knuth-Morris-Pratt shuffle (not that it matters)
for {set i [llength $cards]} {$i > 0} {} {
set j [random $i]
set tmp [lindex $cards [incr i -1]]
lset cards $i [lindex $cards $j]
lset cards $j $tmp
}
return $cards
}}]
# Randomly pick a hand of cards from the deck (itself in a global for
# convenience).
proc drawCards n {
set cards $::AllCards; # Copies...
for {set i 0} {$i < $n} {incr i} {
set idx [random [llength $cards]]
lappend hand [lindex $cards $idx]
set cards [lreplace $cards $idx $idx]
}
return $hand
}
# Test if a particular group of three cards is a valid set
proc isValidSet {a b c} {
expr {
([lindex $a 0]|[lindex $b 0]|[lindex $c 0]) in {1 2 4 7} &&
([lindex $a 1]|[lindex $b 1]|[lindex $c 1]) in {1 2 4 7} &&
([lindex $a 2]|[lindex $b 2]|[lindex $c 2]) in {1 2 4 7} &&
([lindex $a 3]|[lindex $b 3]|[lindex $c 3]) in {1 2 4 7}
}
}
# Get all unique valid sets of three cards in a hand.
proc allValidSets {hand} {
set sets {}
for {set i 0} {$i < [llength $hand]} {incr i} {
set a [lindex $hand $i]
set hand [set cards2 [lreplace $hand $i $i]]
for {set j 0} {$j < [llength $cards2]} {incr j} {
set b [lindex $cards2 $j]
set cards2 [set cards3 [lreplace $cards2 $j $j]]
foreach c $cards3 {
if {[isValidSet $a $b $c]} {
lappend sets [list $a $b $c]
}
}
}
}
return $sets
}
# Solve a particular version of the set puzzle, by picking random hands until
# one is found that satisfies the constraints. This is usually much faster
# than a systematic search. On success, returns the hand found and the card
# sets within that hand.
proc SetPuzzle {numCards numSets} {
while 1 {
set hand [drawCards $numCards]
set sets [allValidSets $hand]
if {[llength $sets] == $numSets} {
break
}
}
return [list $hand $sets]
}

View file

@ -0,0 +1,29 @@
# Render a hand (or any list) of cards (the "."s are just placeholders).
proc PrettyHand {hand {separator \n}} {
set Co {. red green . purple}
set Sy {. oval squiggle . diamond}
set Nu {. one two . three}
set Sh {. solid open . striped}
foreach card $hand {
lassign $card co s n sh
lappend result [format "(%s,%s,%s,%s)" \
[lindex $Co $co] [lindex $Sy $s] [lindex $Nu $n] [lindex $Sh $sh]]
}
return $separator[join $result $separator]
}
# Render the output of the Set Puzzle solver.
proc PrettyOutput {setResult} {
lassign $setResult hand sets
set sep "\n "
puts "Hand (with [llength $hand] cards) was:[PrettyHand $hand $sep]"
foreach s $sets {
puts "Found set [incr n]:[PrettyHand $s $sep]"
}
}
# Demonstrate on the two cases
puts "=== BASIC PUZZLE ========="
PrettyOutput [SetPuzzle 9 4]
puts "=== ADVANCED PUZZLE ======"
PrettyOutput [SetPuzzle 12 6]

View file

@ -0,0 +1,11 @@
Given an equal-probability generator of one of the integers 1 to 5
as <code>dice5</code>; create <code>dice7</code> that generates a pseudo-random integer from
1 to 7 in equal probability using only <code>dice5</code> as a source of random
numbers, and check the distribution for at least 1000000 calls using the function created in [[Simple Random Distribution Checker]].
'''Implementation suggestion:'''
<code>dice7</code> might call <code>dice5</code> twice, re-call if four of the 25
combinations are given, otherwise split the other 21 combinations
into 7 groups of three, and return the group index from the rolls.
<small>(Task adapted from an answer [http://stackoverflow.com/questions/90715/what-are-the-best-programming-puzzles-you-came-across here])</small>

View file

@ -0,0 +1,2 @@
---
note: Probability and statistics

View file

@ -0,0 +1,35 @@
PROC dice5 = INT:
1 + ENTIER (5*random);
PROC mulby5 = (INT n)INT:
ABS (BIN n SHL 2) + n;
PROC dice7 = INT: (
INT d55 := 0;
INT m := 1;
WHILE
m := ABS ((2r1 AND BIN m) SHL 2) + ABS (BIN m SHR 1); # repeats 4 - 2 - 1 #
d55 := mulby5(mulby5(d55)) + mulby5(dice5) + dice5 - 6;
# WHILE # d55 < m DO SKIP OD;
m := 1;
WHILE d55>0 DO
d55 +:= m;
m := ABS (BIN d55 AND 2r111); # modulas by 8 #
d55 := ABS (BIN d55 SHR 3) # divide by 8 #
OD;
m
);
PROC distcheck = (PROC INT dice, INT count, upb)VOID: (
[upb]INT sum; FOR i TO UPB sum DO sum[i] := 0 OD;
FOR i TO count DO sum[dice]+:=1 OD;
FOR i TO UPB sum WHILE print(whole(sum[i],0)); i /= UPB sum DO print(", ") OD;
print(new line)
);
main:
(
distcheck(dice5, 1000000, 5);
distcheck(dice7, 1000000, 7)
)

View file

@ -0,0 +1,10 @@
package Random_57 is
type Mod_7 is mod 7;
function Random7 return Mod_7;
-- a "fast" implementation, minimazing the calls to the Random5 generator
function Simple_Random7 return Mod_7;
-- a simple implementation
end Random_57;

View file

@ -0,0 +1,57 @@
with Ada.Numerics.Discrete_Random;
package body Random_57 is
type M5 is mod 5;
package Rand_5 is new Ada.Numerics.Discrete_Random(M5);
Gen: Rand_5.Generator;
function Random7 return Mod_7 is
N: Natural;
begin
loop
N := Integer(Rand_5.Random(Gen))* 5 + Integer(Rand_5.Random(Gen));
-- N is uniformly distributed in 0 .. 24
if N < 21 then
return Mod_7(N/3);
else -- (N-21) is in 0 .. 3
N := (N-21) * 5 + Integer(Rand_5.Random(Gen)); -- N is in 0 .. 19
if N < 14 then
return Mod_7(N / 2);
else -- (N-14) is in 0 .. 5
N := (N-14) * 5 + Integer(Rand_5.Random(Gen)); -- N is in 0 .. 29
if N < 28 then
return Mod_7(N/4);
else -- (N-28) is in 0 .. 1
N := (N-28) * 5 + Integer(Rand_5.Random(Gen)); -- 0 .. 9
if N < 7 then
return Mod_7(N);
else -- (N-7) is in 0, 1, 2
N := (N-7)* 5 + Integer(Rand_5.Random(Gen)); -- 0 .. 14
if N < 14 then
return Mod_7(N/2);
else -- (N-14) is 0. This is not useful for us!
null;
end if;
end if;
end if;
end if;
end if;
end loop;
end Random7;
function Simple_Random7 return Mod_7 is
N: Natural :=
Integer(Rand_5.Random(Gen))* 5 + Integer(Rand_5.Random(Gen));
-- N is uniformly distributed in 0 .. 24
begin
while N > 20 loop
N := Integer(Rand_5.Random(Gen))* 5 + Integer(Rand_5.Random(Gen));
end loop; -- Now I <= 20
return Mod_7(N / 3);
end Simple_Random7;
begin
Rand_5.Reset(Gen);
end Random_57;

View file

@ -0,0 +1,51 @@
with Ada.Text_IO, Random_57;
procedure R57 is
use Random_57;
type Fun is access function return Mod_7;
function Rand return Mod_7 renames Random_57.Random7;
-- change this to "... renames Random_57.Simple_Random;" if you like
procedure Test(Sample_Size: Positive; Rand: Fun; Precision: Float := 0.3) is
Counter: array(Mod_7) of Natural := (others => 0);
Expected: Natural := Sample_Size/7;
Small: Mod_7 := Mod_7'First;
Large: Mod_7 := Mod_7'First;
Result: Mod_7;
begin
Ada.Text_IO.New_Line;
Ada.Text_IO.Put_Line("Sample Size: " & Integer'Image(Sample_Size));
Ada.Text_IO.Put( " Bins:");
for I in 1 .. Sample_Size loop
Result := Rand.all;
Counter(Result) := Counter(Result) + 1;
end loop;
for J in Mod_7 loop
Ada.Text_IO.Put(Integer'Image(Counter(J)));
if Counter(J) < Counter(Small) then Small := J; end if;
if Counter(J) > Counter(Large) then Large := J; end if;
end loop;
Ada.Text_IO.New_Line;
Ada.Text_IO.Put_Line(" Small Bin:" & Integer'Image(Counter(Small)));
Ada.Text_IO.Put_Line(" Large Bin: " & Integer'Image(Counter(Large)));
if Float(Counter(Small)*7) * (1.0+Precision) < Float(Sample_Size) then
Ada.Text_IO.Put_Line("Failed! Small too small!");
elsif Float(Counter(Large)*7) * (1.0-Precision) > Float(Sample_Size) then
Ada.Text_IO.Put_Line("Failed! Large too large!");
else
Ada.Text_IO.Put_Line("Passed");
end if;
end Test;
begin
Test( 10_000, Rand'Access, 0.08);
Test( 100_000, Rand'Access, 0.04);
Test( 1_000_000, Rand'Access, 0.02);
Test(10_000_000, Rand'Access, 0.01);
end R57;

View file

@ -0,0 +1,11 @@
dice5()
{ Random, v, 1, 5
Return, v
}
dice7()
{ Loop
{ v := 5 * dice5() + dice5() - 6
IfLess v, 21, Return, (v // 3) + 1
}
}

View file

@ -0,0 +1,31 @@
MAXRND = 7
FOR r% = 2 TO 5
check% = FNdistcheck(FNdice7, 10^r%, 0.1)
PRINT "Over "; 10^r% " runs dice7 ";
IF check% THEN
PRINT "failed distribution check with "; check% " bin(s) out of range"
ELSE
PRINT "passed distribution check"
ENDIF
NEXT
END
DEF FNdice7
LOCAL x% : x% = FNdice5 + 5*FNdice5
IF x%>26 THEN = FNdice7 ELSE = (x%+1) MOD 7 + 1
DEF FNdice5 = RND(5)
DEF FNdistcheck(RETURN func%, repet%, delta)
LOCAL i%, m%, r%, s%, bins%()
DIM bins%(MAXRND)
FOR i% = 1 TO repet%
r% = FN(^func%)
bins%(r%) += 1
IF r%>m% m% = r%
NEXT
FOR i% = 1 TO m%
IF bins%(i%)/(repet%/m%) > 1+delta s% += 1
IF bins%(i%)/(repet%/m%) < 1-delta s% += 1
NEXT
= s%

View file

@ -0,0 +1,49 @@
template<typename F> class fivetoseven
{
public:
fivetoseven(F f): d5(f), rem(0), max(1) {}
int operator()();
private:
F d5;
int rem, max;
};
template<typename F>
int fivetoseven<F>::operator()()
{
while (rem/7 == max/7)
{
while (max < 7)
{
int rand5 = d5()-1;
max *= 5;
rem = 5*rem + rand5;
}
int groups = max / 7;
if (rem >= 7*groups)
{
rem -= 7*groups;
max -= 7*groups;
}
}
int result = rem % 7;
rem /= 7;
max /= 7;
return result+1;
}
int d5()
{
return 5.0*std::rand()/(RAND_MAX + 1.0) + 1;
}
fivetoseven<int(*)()> d7(d5);
int main()
{
srand(time(0));
test_distribution(d5, 1000000, 0.001);
test_distribution(d7, 1000000, 0.001);
}

View file

@ -0,0 +1,20 @@
int rand5()
{
int r, rand_max = RAND_MAX - (RAND_MAX % 5);
while ((r = rand()) >= rand_max);
return r / (rand_max / 5) + 1;
}
int rand5_7()
{
int r;
while ((r = rand5() * 5 + rand5()) >= 27);
return r / 3 - 1;
}
int main()
{
printf(check(rand5, 5, 1000000, .05) ? "flat\n" : "not flat\n");
printf(check(rand7, 7, 1000000, .05) ? "flat\n" : "not flat\n");
return 0;
}

View file

@ -0,0 +1,15 @@
(def dice5 #(rand-int 5))
(defn dice7 []
(quot (->> dice5 ; do the following to dice5
(repeatedly 2) ; call it twice
(apply #(+ %1 (* 5 %2))) ; d1 + 5*d2 => 0..24
#() ; wrap that up in a function
repeatedly ; make infinite sequence of the above
(drop-while #(> % 20)) ; throw away anything > 20
first) ; grab first acceptable element
3)) ; divide by three rounding down
(doseq [n [100 1000 10000] [num count okay?] (verify dice7 n)]
(println "Saw" num count "times:"
(if okay? "that's" " not") "acceptable"))

View file

@ -0,0 +1,7 @@
(defun d5 ()
(1+ (random 5)))
(defun d7 ()
(loop for d55 = (+ (* 5 (d5)) (d5) -6)
until (< d55 21)
finally (return (1+ (mod d55 7)))))

View file

@ -0,0 +1,47 @@
import std.random;
import verify_distribution_uniformity_naive: distCheck;
/// Generates a random number in [1, 5].
int dice5() /*pure nothrow*/ {
return uniform(1, 6);
}
/// Naive, generates a random number in [1, 7] using dice5.
int fiveToSevenNaive() /*pure nothrow*/ {
immutable int r = dice5() + dice5() * 5 - 6;
return (r < 21) ? (r % 7) + 1 : fiveToSevenNaive();
}
/**
Generates a random number in [1, 7] using dice5,
minimizing calls to dice5.
*/
int fiveToSevenSmart() {
static int rem = 0, max = 1;
while (rem / 7 == max / 7) {
while (max < 7) {
immutable int rand5 = dice5() - 1;
max *= 5;
rem = 5 * rem + rand5;
}
immutable int groups = max / 7;
if (rem >= 7 * groups) {
rem -= 7 * groups;
max -= 7 * groups;
}
}
immutable int result = rem % 7;
rem /= 7;
max /= 7;
return result + 1;
}
void main() {
enum int N = 400_000;
distCheck(&dice5, N, 1);
distCheck(&fiveToSevenNaive, N, 1);
distCheck(&fiveToSevenSmart, N, 1);
}

View file

@ -0,0 +1,9 @@
def dice5() {
return entropy.nextInt(5) + 1
}
def dice7() {
var d55 := null
while ((d55 := 5 * dice5() + dice5() - 6) >= 21) {}
return d55 %% 7 + 1
}

View file

@ -0,0 +1,5 @@
def bins := ([0] * 7).diverge()
for x in 1..1000 {
bins[dice7() - 1] += 1
}
println(bins.snapshot())

View file

@ -0,0 +1,37 @@
module rand_mod
implicit none
contains
function rand5()
integer :: rand5
real :: r
call random_number(r)
rand5 = 5*r + 1
end function
function rand7()
integer :: rand7
do
rand7 = 5*rand5() + rand5() - 6
if (rand7 < 21) then
rand7 = rand7 / 3 + 1
return
end if
end do
end function
end module
program Randtest
use rand_mod
implicit none
integer, parameter :: samples = 1000000
call distcheck(rand7, samples, 0.005)
write(*,*)
call distcheck(rand7, samples, 0.001)
end program

View file

@ -0,0 +1,56 @@
package main
import (
"fmt"
"math"
"math/rand"
"time"
)
// "given"
func dice5() int {
return rand.Intn(5) + 1
}
// function specified by task "Seven-sided dice from five-sided dice"
func dice7() (i int) {
for {
i = 5*dice5() + dice5()
if i < 27 {
break
}
}
return (i / 3) - 1
}
// function specified by task "Verify distribution uniformity/Naive"
//
// Parameter "f" is expected to return a random integer in the range 1..n.
// (Values out of range will cause an unceremonious crash.)
// "Max" is returned as an "indication of distribution achieved."
// It is the maximum delta observed from the count representing a perfectly
// uniform distribution.
// Also returned is a boolean, true if "max" is less than threshold
// parameter "delta."
func distCheck(f func() int, n int,
repeats int, delta float64) (max float64, flatEnough bool) {
count := make([]int, n)
for i := 0; i < repeats; i++ {
count[f()-1]++
}
expected := float64(repeats) / float64(n)
for _, c := range count {
max = math.Max(max, math.Abs(float64(c)-expected))
}
return max, max < delta
}
// Driver, produces output satisfying both tasks.
func main() {
rand.Seed(time.Now().UnixNano())
const calls = 1000000
max, flatEnough := distCheck(dice7, 7, calls, 500)
fmt.Println("Max delta:", max, "Flat enough:", flatEnough)
max, flatEnough = distCheck(dice7, 7, calls, 500)
fmt.Println("Max delta:", max, "Flat enough:", flatEnough)
}

View file

@ -0,0 +1,13 @@
random = new Random()
int rand5() {
random.nextInt(5) + 1
}
int rand7From5() {
def raw = 25
while (raw > 21) {
raw = 5*(rand5() - 1) + rand5()
}
(raw % 7) + 1
}

Some files were not shown because too many files have changed in this diff Show more