all tasks
This commit is contained in:
parent
b83f433714
commit
68f8f3e56b
14735 changed files with 178959 additions and 0 deletions
7
Task/SHA-1/0DESCRIPTION
Normal file
7
Task/SHA-1/0DESCRIPTION
Normal 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
3
Task/SHA-1/1META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
category:
|
||||
- Checksums
|
||||
8
Task/SHA-1/Ada/sha-1.ada
Normal file
8
Task/SHA-1/Ada/sha-1.ada
Normal 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;
|
||||
21
Task/SHA-1/BBC-BASIC/sha-1-1.bbc
Normal file
21
Task/SHA-1/BBC-BASIC/sha-1-1.bbc
Normal 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$
|
||||
102
Task/SHA-1/BBC-BASIC/sha-1-2.bbc
Normal file
102
Task/SHA-1/BBC-BASIC/sha-1-2.bbc
Normal 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
20
Task/SHA-1/C++/sha-1.cpp
Normal 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 ;
|
||||
}
|
||||
21
Task/SHA-1/C-sharp/sha-1.cs
Normal file
21
Task/SHA-1/C-sharp/sha-1.cs
Normal 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
18
Task/SHA-1/C/sha-1.c
Normal 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;
|
||||
}
|
||||
6
Task/SHA-1/Common-Lisp/sha-1.lisp
Normal file
6
Task/SHA-1/Common-Lisp/sha-1.lisp
Normal 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
5
Task/SHA-1/D/sha-1.d
Normal 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
12
Task/SHA-1/Go/sha-1.go
Normal 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))
|
||||
}
|
||||
3
Task/SHA-1/Mathematica/sha-1.math
Normal file
3
Task/SHA-1/Mathematica/sha-1.math
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
IntegerString[Hash["Rosetta Code", "SHA1"], 16]
|
||||
|
||||
-> 48c98f7e5a6e736d790ab740dfc3f51a61abe2b5
|
||||
50
Task/SHA-1/NetRexx/sha-1.netrexx
Normal file
50
Task/SHA-1/NetRexx/sha-1.netrexx
Normal 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
|
||||
5
Task/SHA-1/OCaml/sha-1.ocaml
Normal file
5
Task/SHA-1/OCaml/sha-1.ocaml
Normal 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
4
Task/SHA-1/PHP/sha-1.php
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
$string = 'Rosetta Code';
|
||||
echo sha1( $string ), "\n";
|
||||
?>
|
||||
44
Task/SHA-1/Perl-6/sha-1.pl6
Normal file
44
Task/SHA-1/Perl-6/sha-1.pl6
Normal 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';
|
||||
3
Task/SHA-1/Perl/sha-1-1.pl
Normal file
3
Task/SHA-1/Perl/sha-1-1.pl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
use Digest::SHA qw(sha1_hex);
|
||||
|
||||
print sha1_hex('Rosetta Code'), "\n";
|
||||
5
Task/SHA-1/Perl/sha-1-2.pl
Normal file
5
Task/SHA-1/Perl/sha-1-2.pl
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
use Digest::SHA;
|
||||
|
||||
my $sha1 = Digest::SHA->new(1);
|
||||
$sha1->add('Rosetta Code');
|
||||
print $sha1->hexdigest, "\n";
|
||||
4
Task/SHA-1/PicoLisp/sha-1.l
Normal file
4
Task/SHA-1/PicoLisp/sha-1.l
Normal 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))) ) ) )
|
||||
5
Task/SHA-1/Python/sha-1.py
Normal file
5
Task/SHA-1/Python/sha-1.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import hashlib
|
||||
h = hashlib.sha1()
|
||||
h.update(bytes("Ars longa, vita brevis", encoding="ASCII"))
|
||||
h.hexdigest()
|
||||
# "e640d285242886eb96ab80cbf858389b3df52f43"
|
||||
4
Task/SHA-1/Racket/sha-1-1.rkt
Normal file
4
Task/SHA-1/Racket/sha-1-1.rkt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#lang racket
|
||||
(require file/sha1)
|
||||
|
||||
(sha1 (open-input-string "Rosetta Code"))
|
||||
4
Task/SHA-1/Racket/sha-1-2.rkt
Normal file
4
Task/SHA-1/Racket/sha-1-2.rkt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#lang racket
|
||||
(require openssl/sha1)
|
||||
|
||||
(sha1 (open-input-string "Rosetta Code"))
|
||||
2
Task/SHA-1/Ruby/sha-1-1.rb
Normal file
2
Task/SHA-1/Ruby/sha-1-1.rb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
require 'digest'
|
||||
puts Digest::SHA1.hexdigest('Rosetta Code')
|
||||
2
Task/SHA-1/Ruby/sha-1-2.rb
Normal file
2
Task/SHA-1/Ruby/sha-1-2.rb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
require 'openssl'
|
||||
puts OpenSSL::Digest::SHA1.hexdigest('Rosetta Code')
|
||||
92
Task/SHA-1/Ruby/sha-1-3.rb
Normal file
92
Task/SHA-1/Ruby/sha-1-3.rb
Normal 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
|
||||
2
Task/SHA-1/Smalltalk/sha-1-1.st
Normal file
2
Task/SHA-1/Smalltalk/sha-1-1.st
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
PackageLoader fileInPackage: 'Digest'.
|
||||
(SHA1 hexDigestOf: 'Rosetta Code') displayNl.
|
||||
1
Task/SHA-1/Smalltalk/sha-1-2.st
Normal file
1
Task/SHA-1/Smalltalk/sha-1-2.st
Normal file
|
|
@ -0,0 +1 @@
|
|||
(SHA1Stream hashValueOf:'Rosetta Code')
|
||||
2
Task/SHA-1/Tcl/sha-1.tcl
Normal file
2
Task/SHA-1/Tcl/sha-1.tcl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
package require sha1
|
||||
puts [sha1::sha1 "Rosetta Code"]
|
||||
2
Task/SHA-1/UNIX-Shell/sha-1-1.sh
Normal file
2
Task/SHA-1/UNIX-Shell/sha-1-1.sh
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
$ echo -n 'ASCII string' | sha1
|
||||
9e9aeefe5563845ec5c42c5630842048c0fc261b
|
||||
2
Task/SHA-1/UNIX-Shell/sha-1-2.sh
Normal file
2
Task/SHA-1/UNIX-Shell/sha-1-2.sh
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
$ echo -n 'ASCII string' | openssl sha1 | sed 's/.*= //'
|
||||
9e9aeefe5563845ec5c42c5630842048c0fc261b
|
||||
3
Task/SHA-256/0DESCRIPTION
Normal file
3
Task/SHA-256/0DESCRIPTION
Normal 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
2
Task/SHA-256/1META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Checksums
|
||||
25
Task/SHA-256/BBC-BASIC/sha-256-1.bbc
Normal file
25
Task/SHA-256/BBC-BASIC/sha-256-1.bbc
Normal 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$
|
||||
124
Task/SHA-256/BBC-BASIC/sha-256-2.bbc
Normal file
124
Task/SHA-256/BBC-BASIC/sha-256-2.bbc
Normal 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#
|
||||
22
Task/SHA-256/C-sharp/sha-256.cs
Normal file
22
Task/SHA-256/C-sharp/sha-256.cs
Normal 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
15
Task/SHA-256/C/sha-256.c
Normal 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;
|
||||
}
|
||||
15
Task/SHA-256/Go/sha-256.go
Normal file
15
Task/SHA-256/Go/sha-256.go
Normal 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))
|
||||
}
|
||||
4
Task/SHA-256/Groovy/sha-256-1.groovy
Normal file
4
Task/SHA-256/Groovy/sha-256-1.groovy
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
def sha256Hash = { text ->
|
||||
java.security.MessageDigest.getInstance("SHA-256").digest(text.bytes)
|
||||
.collect { String.format("%02x", it) }.join('')
|
||||
}
|
||||
1
Task/SHA-256/Groovy/sha-256-2.groovy
Normal file
1
Task/SHA-256/Groovy/sha-256-2.groovy
Normal file
|
|
@ -0,0 +1 @@
|
|||
assert sha256Hash('Rosetta code') == '764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf'
|
||||
1
Task/SHA-256/Mathematica/sha-256.math
Normal file
1
Task/SHA-256/Mathematica/sha-256.math
Normal file
|
|
@ -0,0 +1 @@
|
|||
IntegerString[Hash["Rosetta code", "SHA256"], 16]
|
||||
50
Task/SHA-256/NetRexx/sha-256.netrexx
Normal file
50
Task/SHA-256/NetRexx/sha-256.netrexx
Normal 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
|
||||
4
Task/SHA-256/OCaml/sha-256.ocaml
Normal file
4
Task/SHA-256/OCaml/sha-256.ocaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
let () =
|
||||
let s = "Rosetta code" in
|
||||
let digest = Sha256.string s in
|
||||
print_endline (Sha256.to_hex digest)
|
||||
8
Task/SHA-256/Objeck/sha-256.objeck
Normal file
8
Task/SHA-256/Objeck/sha-256.objeck
Normal 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();
|
||||
}
|
||||
}
|
||||
2
Task/SHA-256/PHP/sha-256.php
Normal file
2
Task/SHA-256/PHP/sha-256.php
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?php
|
||||
echo hash('sha256', 'Rosetta code');
|
||||
47
Task/SHA-256/Perl-6/sha-256.pl6
Normal file
47
Task/SHA-256/Perl-6/sha-256.pl6
Normal 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;
|
||||
}
|
||||
7
Task/SHA-256/Perl/sha-256.pl
Normal file
7
Task/SHA-256/Perl/sha-256.pl
Normal 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" ;
|
||||
4
Task/SHA-256/Python/sha-256.py
Normal file
4
Task/SHA-256/Python/sha-256.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
>>> import hashlib
|
||||
>>> hashlib.sha256( "Rosetta code" ).hexdigest()
|
||||
'764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf'
|
||||
>>>
|
||||
2
Task/SHA-256/Ruby/sha-256.rb
Normal file
2
Task/SHA-256/Ruby/sha-256.rb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
require 'digest/sha2'
|
||||
puts Digest::SHA256.hexdigest('Rosetta code')
|
||||
3
Task/SHA-256/Tcl/sha-256.tcl
Normal file
3
Task/SHA-256/Tcl/sha-256.tcl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
package require sha256
|
||||
|
||||
puts [sha2::sha256 -hex "Rosetta code"]
|
||||
2
Task/SOAP/0DESCRIPTION
Normal file
2
Task/SOAP/0DESCRIPTION
Normal 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
4
Task/SOAP/1META.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category:
|
||||
- Less Than 10 Examples
|
||||
note: Networking and Web Interaction
|
||||
16
Task/SOAP/ActionScript/soap.as
Normal file
16
Task/SOAP/ActionScript/soap.as
Normal 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
|
||||
}
|
||||
11
Task/SOAP/AutoHotkey/soap.ahk
Normal file
11
Task/SOAP/AutoHotkey/soap.ahk
Normal 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
|
||||
3
Task/SOAP/ColdFusion/soap.cfm
Normal file
3
Task/SOAP/ColdFusion/soap.cfm
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<cfset client = createObject("webservice","http://example.com/soap/wsdl")>
|
||||
<cfset result = client.soapFunc("hello")>
|
||||
<cfset result = client.anotherSoapFunc(34234)>
|
||||
3
Task/SOAP/Mathematica/soap.math
Normal file
3
Task/SOAP/Mathematica/soap.math
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
InstallService["http://example.com/soap/wsdl"];
|
||||
soapFunc["Hello"];
|
||||
anotherSoapFunc[12345];
|
||||
14
Task/SOAP/PHP/soap.php
Normal file
14
Task/SOAP/PHP/soap.php
Normal 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
8
Task/SOAP/Perl/soap.pl
Normal 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);
|
||||
5
Task/SOAP/PureBasic/soap.purebasic
Normal file
5
Task/SOAP/PureBasic/soap.purebasic
Normal 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
4
Task/SOAP/Python/soap.py
Normal 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
10
Task/SOAP/Ruby/soap.rb
Normal 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
9
Task/SOAP/Tcl/soap.tcl
Normal 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]
|
||||
6
Task/SOAP/VBScript/soap.vbscript
Normal file
6
Task/SOAP/VBScript/soap.vbscript
Normal 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)
|
||||
10
Task/SOAP/Visual-Objects/soap.vobj
Normal file
10
Task/SOAP/Visual-Objects/soap.vobj
Normal 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
|
||||
15
Task/SQL-based-authentication/0DESCRIPTION
Normal file
15
Task/SQL-based-authentication/0DESCRIPTION
Normal 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.)
|
||||
2
Task/SQL-based-authentication/1META.yaml
Normal file
2
Task/SQL-based-authentication/1META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Database operations
|
||||
174
Task/SQL-based-authentication/C/sql-based-authentication.c
Normal file
174
Task/SQL-based-authentication/C/sql-based-authentication.c
Normal 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;
|
||||
}
|
||||
142
Task/SQL-based-authentication/Java/sql-based-authentication.java
Normal file
142
Task/SQL-based-authentication/Java/sql-based-authentication.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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'];
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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\""
|
||||
}
|
||||
62
Task/Set-puzzle/0DESCRIPTION
Normal file
62
Task/Set-puzzle/0DESCRIPTION
Normal 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
|
||||
95
Task/Set-puzzle/C/set-puzzle.c
Normal file
95
Task/Set-puzzle/C/set-puzzle.c
Normal 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;
|
||||
}
|
||||
108
Task/Set-puzzle/D/set-puzzle.d
Normal file
108
Task/Set-puzzle/D/set-puzzle.d
Normal 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();
|
||||
}
|
||||
}
|
||||
24
Task/Set-puzzle/J/set-puzzle-1.j
Normal file
24
Task/Set-puzzle/J/set-puzzle-1.j
Normal 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
|
||||
)
|
||||
27
Task/Set-puzzle/J/set-puzzle-2.j
Normal file
27
Task/Set-puzzle/J/set-puzzle-2.j
Normal 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
|
||||
126
Task/Set-puzzle/Java/set-puzzle.java
Normal file
126
Task/Set-puzzle/Java/set-puzzle.java
Normal 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;
|
||||
}
|
||||
}
|
||||
26
Task/Set-puzzle/Perl-6/set-puzzle.pl6
Normal file
26
Task/Set-puzzle/Perl-6/set-puzzle.pl6
Normal 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 } }
|
||||
46
Task/Set-puzzle/Python/set-puzzle.py
Normal file
46
Task/Set-puzzle/Python/set-puzzle.py
Normal 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)
|
||||
82
Task/Set-puzzle/Tcl/set-puzzle-1.tcl
Normal file
82
Task/Set-puzzle/Tcl/set-puzzle-1.tcl
Normal 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]
|
||||
}
|
||||
29
Task/Set-puzzle/Tcl/set-puzzle-2.tcl
Normal file
29
Task/Set-puzzle/Tcl/set-puzzle-2.tcl
Normal 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]
|
||||
11
Task/Seven-sided-dice-from-five-sided-dice/0DESCRIPTION
Normal file
11
Task/Seven-sided-dice-from-five-sided-dice/0DESCRIPTION
Normal 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>
|
||||
2
Task/Seven-sided-dice-from-five-sided-dice/1META.yaml
Normal file
2
Task/Seven-sided-dice-from-five-sided-dice/1META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Probability and statistics
|
||||
|
|
@ -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)
|
||||
)
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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%
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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"))
|
||||
|
|
@ -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)))))
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
def bins := ([0] * 7).diverge()
|
||||
for x in 1..1000 {
|
||||
bins[dice7() - 1] += 1
|
||||
}
|
||||
println(bins.snapshot())
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue