-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlist-monad.js
114 lines (95 loc) · 2.68 KB
/
list-monad.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* https://www.codewars.com/kata/53db4acb1f1a7dd68700040a
*/
let tests = require('./lib/framework.js');
let Test = tests.Test, describe = tests.describe, it = tests.it, before = tests.before, after = tests.after;
/*
* from: actual position of the knight
* returns: an array of valid position in one movement
* ex: moveKnight([6, 2]) -> [ [ 8, 1 ], [ 8, 3 ], [ 4, 1 ], [ 4, 3 ], [ 7, 4 ], [ 5, 4 ] ]
*
* moveKnight :: Square -> [Square]
*/
function moveKnight(from) {
var retval = [];
var p = [2, -2, 1, -1];
for (var i = 0; i < p.length; i++) {
for (var j = 0; j < p.length; j++) {
if (Math.abs(p[i]) === Math.abs(p[j])) continue;
var x = from[0] + p[i];
var y = from[1] + p[j];
if (x > 0 && y > 0 && x < 9 && y < 9) {
retval.push([x, y]);
}
}
}
return retval;
}
function moveKnightRandom(from) {
var possibilities = moveKnight(from);
return possibilities[Math.floor(Math.random() * possibilities.length)];
}
function compose() {
var fns = [].slice.call(arguments);
return function (x) {
return fns.reduceRight(function (carry, fn) {
return fn(carry);
}, x);
}
}
/**
* bind :: (a -> [b]) -> ([a] -> [b])
*
* f is a function that receives a single value of a type (like Square, Number, String, ...) and returns an array of simple type b (a and bcould be the same type).
* The returned function, g, receives an array of a type and returns an array of b type. The returned array contains the values processed by the f function.
* @param f
* @returns {Function}
*/
function bind(f) {
return function (args) {
return args.reduce(function (carry, x) {
return carry.concat(f(x));
}, []);
}
}
/**
* unit :: a -> [a]
*
* @param x
* @returns {*[]}
*/
function unit(x) {
return [x];
}
/*
* wrap :: a -> [a]
*/
function wrap(x) {
return [x];
}
function moveKnightFromArray(fromPositions) {
return fromPositions.reduce(function(ac, from) {
var to = moveKnight(from);
return ac.concat(to);
}, []);
}
/* from: starting square
* movements: quantity of movements to do
* returns: array with all possible valid squares
*
* knightEngine -> Square -> Int -> [Square]
*/
function knightEngine(from, movements) {
var f = function (x) { return x };
for (var i = 0; i < movements; i++) {
f = compose(f, bind(moveKnight));
}
f = compose(f, unit);
return f(from);
}
function canReach(from, to, movements) {
var res = knightEngine(from, movements).filter(function (x) {
return x[0] === to[0] && x[1] === to[1];
});
return Boolean(res.length);
}