Mine for 2016 in Bitcoins! PCG.SE New Year's Puzzle 2016

17

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.

Joe Z.

Posted 2016-01-01T01:42:24.693

Reputation: 30 589

1Call me crazy, but isn't this bitcoin mining by another name? – Codefun64 – 2016-01-01T06:10:37.680

1Also, 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. – LegionMammal978 – 2016-01-01T11:41:55.327

@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. – Joe Z. – 2016-01-01T16:28:28.817

@Codefun64 This is a code problem that simulates the procedure used in Bitcoin mining, but does not itself mine for bitcoins. – Joe Z. – 2016-01-03T02:43:32.930

Answers

7

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

Ilmari Karonen

Posted 2016-01-01T01:42:24.693

Reputation: 19 513

8

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}]

njpipeorgan

Posted 2016-01-01T01:42:24.693

Reputation: 2 992

2We 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. – Michael Stern – 2016-01-20T19:09:04.257

@MichaelStern I cannot agree more. – njpipeorgan – 2016-01-21T00:11:32.393

@MichaelStern Did that.

– LegionMammal978 – 2016-03-17T21:29:50.503

@LegionMammal978 Fantastic! Btw, why not consider a better name like "WOLF"? – njpipeorgan – 2016-03-18T00:17:08.670

5

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$.

daniero

Posted 2016-01-01T01:42:24.693

Reputation: 17 193

5

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

beatcracker

Posted 2016-01-01T01:42:24.693

Reputation: 379

2

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.

LegionMammal978

Posted 2016-01-01T01:42:24.693

Reputation: 15 731

That's a lot of keywords. – Joe Z. – 2016-01-11T22:27:44.217

1@JoeZ. That's C# for you. – LegionMammal978 – 2016-01-11T22:29:09.517