comparison 2017/day10/app.d @ 33:bc652fa0a645

Move all solutions to per-day subdirs
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Tue, 09 Jan 2018 21:50:37 -0500
parents 2017/day10.d@990a4fa2aebe
children
comparison
equal deleted inserted replaced
32:763c88851b91 33:bc652fa0a645
1 import std.stdio;
2 import std.range: iota, array, chunks;
3 import std.algorithm: invert=reverse, map, reduce;
4 import std.conv: to;
5 import std.format: format;
6 import std.string: join;
7
8 void reverse(int Size)(ref int[Size] twine, int a, int b) {
9 a = a % Size;
10 b = b % Size;
11 if (a <= b) {
12 invert(twine[a..b]);
13 }
14 else {
15 auto result = twine[a..$] ~ twine[0..b];
16 invert(result);
17 twine[a..$] = result[0..Size-a];
18 twine[0..b] = result[Size-a..$];
19 }
20 }
21
22 auto pos = 0, skip = 0;
23 auto knotUp(int Size)(int[] lengths, int[Size] twine) {
24 foreach(length; lengths) {
25 reverse(twine, pos, pos+length);
26 pos = (pos + length + skip) % Size;
27 skip = (skip + 1) % Size;
28 }
29 return twine;
30 }
31
32 auto calcHash(int Size=256, int Rounds=64, int ChunkSize=16)(string input)
33 if( Size % ChunkSize == 0)
34 {
35 int[] lengths = to!(int[])(cast(ubyte [])(input));
36 static salt = [17, 31, 73, 47, 23];
37 lengths ~= salt;
38 int[Size] twine = iota(0, Size).array;
39 for(int i = 0; i < Rounds; i++) {
40 twine = knotUp(lengths, twine);
41 }
42 pos=skip=0;
43 return twine.array.chunks(ChunkSize).map!(
44 x => reduce!((a,b) => a ^ b)(x[0], x[1..$])
45 ).array.to!(ubyte[Size/ChunkSize]);
46 }
47
48 auto getHash(int Size=256, int Rounds=64, int ChunkSize=16)(string input)
49 if( Size % ChunkSize == 0)
50 {
51 auto hash = calcHash!(Size, Rounds, ChunkSize)(input);
52 return hash.array.map!(x => format("%02x", x)).join;
53 }
54
55 version(standalone) {
56 void main(string[] args){
57 auto hash = getHash(args[1]);
58 writeln(hash);
59 }
60 }