17
\$\begingroup\$

In the Bitcoin protocol, 2016 is a very special number. The "difficulty" of finding a hash to create a new block is adjusted every 2,016 blocks to approximate changing once every two weeks.

This number was chosen is because the difficulty adjusts itself so that every block takes about 10 minutes to be found, and in two weeks, there are 2 × 7 × 24 × 6 = 2,016 ten-minute periods.


To commemorate this numerical coincidence, this year's New Year's problem is about Bitcoin — specifically, the hashing algorithm it uses to sign blocks, SHA-256.

Your task is to create a program that will take byte input (in at least ASCII) and output a nonce in bytes (in the format of your choice) that will produce a SHA-256 hash containing 2016 in its base64 representation when appended to the original byte input.

Here are some examples of valid solutions, courtesy of the engines people have already generated, as well as the hashes they produced:

> foo
Nonce: 196870
SHA256 hash: OCUdDDtQ42wUlKz2016x+NROo8P2lbJf8F4yCKedTLE=

> bar
Nonce: 48230
SHA256 hash: CNcaOCQgT7bnlQzQPXNwuBu8/LYEdk2016khRaROyZk=

> happynewyear
Nonce: 1740131
SHA256 hash: XsKke6z2016BzB+wRNCm53LKJ6TW6ir66GwuC8oz1nQ=

> 2016
Nonce: 494069
SHA256 hash: rWAHW2YFhHCr22016zw+Sog6aW76eImgO5Lh72u6o5s=

(note: the nonces don't actually have to be ASCII numbers; you can do
 any byte input you find convenient.)

The only pre-built library (other than standard input and output functions) your program may use is a SHA256(bytes) function that takes byte input and returns a SHA256 hash, in any format including base64.

The program to do this in the fewest bytes of source code wins.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Call me crazy, but isn't this bitcoin mining by another name? \$\endgroup\$
    – Codefun64
    Jan 1 '16 at 6:10
  • 1
    \$\begingroup\$ Also, define a "pre-built library". My language's SHA-256 function produces the hash, but not the Base64 hash. Therefore, I would also need to use conversion to bytes, then conversion into characters, then conversion into Base64. \$\endgroup\$ Jan 1 '16 at 11:41
  • \$\begingroup\$ @LegionMammal978 A "pre-built library" would be any function defined outside the code that counts for this challenge. So you can create a base64 wrapper function for your SHA-256 function, in order to use it in this problem. \$\endgroup\$
    – Joe Z.
    Jan 1 '16 at 16:28
  • \$\begingroup\$ @Codefun64 This is a code problem that simulates the procedure used in Bitcoin mining, but does not itself mine for bitcoins. \$\endgroup\$
    – Joe Z.
    Jan 3 '16 at 2:43
8
\$\begingroup\$

Mathematica, 94

(For[i=0,IntegerDigits[4Hash[#<>ToString@++i,"SHA256"],64]~SequenceCount~{54,52,53,58}<1,];i)&

This function will try positive integers as candidates. It takes over 4 minutes on my laptop to get the correct answer.

%["foo"]
(* 196870 *)

Longer however faster (~5x) implementation makes use of parallelization:

f[k_]:=
    Do[If[Length@#>0,Return[i+#[[1,1]]]]&@
        Position[ParallelMap[IntegerDigits[4Hash[k<>ToString@#,"SHA256"],64]
            ~SequenceCount~{54,52,53,58}&,i+Range@1*^4],1]
        ,{i,0,∞,1*^4}]
\$\endgroup\$
4
  • 2
    \$\begingroup\$ We should create a golfing version of Wolfram Language, with every command replaced by one or two characters. Actually, given the number of commands, we might need to use three characters for some of the less common ones. \$\endgroup\$ Jan 20 '16 at 19:09
  • \$\begingroup\$ @MichaelStern I cannot agree more. \$\endgroup\$ Jan 21 '16 at 0:11
  • \$\begingroup\$ @MichaelStern Did that. \$\endgroup\$ Mar 17 '16 at 21:29
  • \$\begingroup\$ @LegionMammal978 Fantastic! Btw, why not consider a better name like "WOLF"? \$\endgroup\$ Mar 18 '16 at 0:17
7
\$\begingroup\$

Perl 5.10+, 39 + 18 = 57 bytes

sha256_base64($_.++$i)!~2016?redo:say$i

This needs to be run with the -nMDigest::SHA=/./ command line switch, which is included in the byte count. It also uses the Perl 5.10+ say feature, and so needs to be run with the -M5.010 (or -E) command line switch, which is considered free. The input should be provided on stdin, without a trailing newline (unless you want the newline to be considered part of the input).

Examples:

$ echo -n foo | perl -nMDigest::SHA=/./ -E 'sha256_base64($_.++$i)!~2016?redo:say$i'
196870
$ echo -n bar | perl -nMDigest::SHA=/./ -E 'sha256_base64($_.++$i)!~2016?redo:say$i'
48230
$ echo -n happynewyear | perl -nMDigest::SHA=/./ -E 'sha256_base64($_.++$i)!~2016?redo:say$i'
1740131
$ echo -n 2016 | perl -nMDigest::SHA=/./ -E 'sha256_base64($_.++$i)!~2016?redo:say$i'
494069
\$\endgroup\$
5
\$\begingroup\$

Ruby, 87 86 bytes

I'm not sure if I understood the challenge correctly, but it finds 196870 in a few seconds if you input foo.

require"digest"
gets.chop!
$.+=1until/2016/=~Digest::SHA256.base64digest("#$_#$.")
p$.
\$\endgroup\$
5
\$\begingroup\$

PowerShell, 150 152 153 bytes

while([Convert]::ToBase64String([Security.Cryptography.SHA256]::Create().ComputeHash([Text.Encoding]::UTF8.GetBytes("$args$i")))-notmatch2016){$i++}$i

Example

PS > .\BitCoin.ps1 foo
196870

PS > .\BitCoin.ps1 bar
48230

PS > .\BitCoin.ps1 happynewyear
1740131

PS > .\BitCoin.ps1 2016
494069
\$\endgroup\$
2
\$\begingroup\$

C#, 179 bytes

s=>{int i=0;while(!System.Convert.ToBase64String(System.Security.Cryptography.SHA256.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(s+i))).Contains("2016"))i++;return i;}

Similar to the PowerShell solution, just longer.

\$\endgroup\$
2
  • \$\begingroup\$ That's a lot of keywords. \$\endgroup\$
    – Joe Z.
    Jan 11 '16 at 22:27
  • 1
    \$\begingroup\$ @JoeZ. That's C# for you. \$\endgroup\$ Jan 11 '16 at 22:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.