Skip to content

Instantly share code, notes, and snippets.

@valtih1978
Last active November 14, 2016 19:06
Show Gist options
  • Save valtih1978/dc20ff861cc3981772a1aa8f02ce9fe9 to your computer and use it in GitHub Desktop.
Save valtih1978/dc20ff861cc3981772a1aa8f02ce9fe9 to your computer and use it in GitHub Desktop.
javascript unils
const log = console.log ; const assert = console.assert
//Object.prototype.trace = function(format) {format = format || (data => data); log(format(this)); return this} // prints something wrong
const trace = (data, format) => {format = format || (data => data); log(format(data)); return data}
const tracejs = (ms, data) => trace(data, data => [ms, data.json()])
function range (len, begin) {begin = begin || 0
return Array.apply(null, Array(len)).map((_, i) => {return begin+i;})}
//Array.prototype.fill = function(filler) {return this.map(_ => filler)} // startard func
Array.prototype.equals = function(that) {return this.every((my, i) => my == that[i] )} ; [1,2].equals([1,2])
Array.prototype.sum = function() {return this.reduce((acc, el) => acc + el,0)}
Array.prototype.product = function() {return this.reduce((acc, el) => acc * el,1)}
Object.prototype.json = function() {return JSON.stringify(this)}
Array.prototype.last = function() {return this[this.length-1]}
Array.prototype.mapField = function(key, f){ return this.map( o=>Object.assign({},o,{[key]:f(o.key)}) ) }
Array.prototype.sliceIndex = function(i) {return this.map(e => e[i])}
Array.prototype.mapIndex = function(i, f){ return this.map( child =>Object.assign([], child, {[i]:f(child[i])} ) )}
Array.prototype.equals = function(that) {return this.length == that.length && this.every((v,i)=> v === that[i])}
Array.prototype.zip = function(...those) {return this.map((my, i) => those.reduce((acc, that) => [...acc, that[i]],[my])) } //; [11,22,33].zip([1,2,3]).json()
String.prototype.toArray = function() {return range(this.length).map(i => this.charAt(i))}
Array.prototype.unzip = function() {return this[0].map((_, i) => this.map(sub => sub[i]))}
Array.prototype.partition = function(filter) {return this.reduce(([passed, failed], el) => {(filter(el) ? passed : failed).push(el); return [passed, failed]}, [[],[]])} ; [1,2,3,4].partition(el => el > 3).json()
//http://stackoverflow.com/a/40573648/6267925
Map.prototype.getOrElse = function(key, value) { return this.has(key) ? this.get(key) : value}
Map.prototype.withDefaultValue = function(defaultValue) {
const result = new Map([...this.entries()]);
const getWas = result.get; result.get = (key) =>
result.has(key) ? getWas.call(this, key) : defaultValue;
return result
}
merge = (f, ...trees) => {
const [head, ...tail] = trees
return (typeof head == "object") ?
head.zip(...tail).map(trees => merge(f, ...trees)) : f(...trees)
} ; merge((a,b) => a+b , [1,2,3], [11,22,33])
Math.fact = (k) => k == 0 ? 1 : k * Math.fact(k-1)
Math.choose = (n, k) => Math.fact(n) / Math.fact(n-k) / Math.fact(k)
RegExp.prototype.execAllGen = function*(input) {
for (let match; (match = this.exec(input)) !== null;)
yield [match, this.lastIndex];
} ; RegExp.prototype.execAll = function(input) {
return [...this.execAllGen(input)]};
/^\s*(\w+)\s*=.*/gm.execAll(" a=b\n d = ef ").map(([match, index]) => [match[1], index])
Array.prototype.flatten = function() {return this.reduce((acc, e) => [...acc, ...e],[])}
Array.prototype.flatMap = function(f) {return this.map(e => f(e)).flatten()};
//my sucks http://cs.stackexchange.com/questions/65962/anatomy-of-representing-of-cartesian-product-in-sw
// http://eddmann.com/posts/cartesian-product-in-javascript/
const cartesian = (...sets) => sets.reduce((acc, set) =>
acc.flatMap(x => set.map(y => [ ...x, y ])), [[]]);
const applyNtimes = (seed, increment, times) => range(times).reduce((acc, _) => increment(acc), seed)
Array.prototype.pow = function(n) {return applyNtimes([[]], acc => cartesian(acc, this)
.reduce((acc, [path, lastStep]) => [...acc, [...path, lastStep]], []), n); }
cartesian(
['small', 'medium', 'large'],
['red', 'green', 'blue'],
['shirt', 'jeans', 'shoes']);
// [["small", "red", "shirt"], ["small", "red", "jeans"] ...
const percent = p => Math.round(p * 100)
Distributions = {Binomial: (n,p) => range(n+1).map(i => Math.choose(n, i) * Math.pow(p, i) * Math.pow(1-p, n-i) )}
Distributions = function(family, ...params) {const result = {binomial: (n,p) => range(n+1).map(i => Math.choose(n, i) * Math.pow(p, i) * Math.pow(1-p, n-i) )}[family](...params); result.cum = (filter) => result.reduce((acc, p,v) => filter(v) ? Object.assign(acc, {[v]:p}) : acc, []).sum(); return result}
bin = Distributions("binomial", 2, 1/2); log(bin, bin.cum(n => n > 0))
const cartStr = (str, n) => {
return range(n).reduce((lowerdim, _) =>
range(str.length).map(li => lowerdim.map(ld =>
ld + str.charAt(li))).flatten(), [""])
}
Array.prototype.isAscending = function(strict) {const greater = (a,b) => strict ? a > b : a >= b; return this.length == 0 ? true : this.reduce(([result, max], a) => [result && greater(a, max), a], [true, this[0]-1])[0]} ; [false, true].forEach(strict => log([1,2,3,3].isAscending(strict), [1,2,3].isAscending(strict), [1,3, 2].isAscending(strict)))
const inclExcl = (...probs) => range(probs.length, 1).map(len => range(probs.length).pow(len).filter(a => a.isAscending(true)).map(a => a.map(i => probs[i]).product()).sum()).map((nsum, i) => nsum * Math.pow(-1, i)).sum() ;
[1,2,3,5].map(n => inclExcl(...range(n).map(_ => 1/n)))
var Some = function(value) { this.value = value;};
Some.prototype.get = function() {return this.value}
Some.prototype.map = function(f) {return new Some(f(this.value))}
Some.prototype.isEmpty = function() {return false}
var None = function() { };
None.prototype.get = function() {throw "attempt to get value from None"}
None.prototype.map = function(f) {return this}
None.prototype.isEmpty = function() {return true}
success = (value) => new Success(value);
var Success = function(value) { this.success = value;};
Success.prototype = {
isFailure: () => false, isSuccess: () => true,
map: function(f) {return success(f(this.success));},
flatMap: function(f) {return f(this.success);},
getOrElse: function(value) {return this.success;},
get: function() {return this.success;},
recover: function(f) {return this}
}
fail = (error) => new Failure(error);
var Failure = function(error) { this.error = error}
Failure.prototype = {
isSuccess: () => false, isFailure: () => true,
map: function(f) {return this},
flatMap: function(f) {return this},
getOrElse: function(value) {return value},
getError: function() {return this.error},
get: function() {throw this.error},
recover: function(f) {return f(this.error)}
}
// Integration
integrateLeft = (f, a,b, intervals) => {const dx = (b-a)/intervals ; return range(intervals).map(i => f(a + dx * i) ).sum()} ;
[10, 100, 1000].map(intervals => integrateLeft ((x) => x * Math.exp(-x), 0,1000, intervals))
// we see that result is poor is even with 1000 intervals
//[3.7200759760208363e-42, 0.00045404052350475404, 0.9206735942077925]
sampleMid = (a,b, intervals) => {const dx = (b-a)/(intervals+1) ; return range(intervals,1).map(i => a + i*dx)} ;
[1,2,3].map(intervals => sampleMid(0,1, intervals)).json() // gives "[[0.5],[0.3333333333333333,0.6666666666666666],[0.25,0.5,0.75]]"
integrateLeft = (f, a,b, intervals) => integrate (f, a,b,intervals, sampleLeft)
integrate = (f, a,b, intervals, sampleProc) => {const lefts = sampleProc(a,b,intervals); const all = [...lefts, b]; return lefts.map((x1, i) => {const x2 = all[i+1]; return f((x2+x1)/2) * (x2-x1)} ).sum()}
sampleLeft = (a,b,intervals) => range(intervals).map(i => a + i*(b-a)/intervals)
integrateLeft = (f, a,b, intervals) => integrate (f, a,b,intervals, sampleLeft)
// The following displays that sampleMid improvement is marginsl
//[sampleMid, sampleLeft].forEach(sampleProc => console.log(sampleProc.name, ":", [10, 100, 1000].map(intervals =>
// integrate ((x) => x * Math.exp(-x), 0,1000, intervals, sampleProc)).json()))
// sampleLeft : [3.7200759760208365e-40, 0.00454040523504754, 0.9206735942077925]
// sampleMid : [3.001171255175747e-36, 0.004963371698308279, 0.9217451547681337]
SigmaDelta = (deltas, initialSigma) => deltas.reduce(([sigma, intsAt], delta, i) => {const nextSigma = sigma+delta; range(Math.floor(nextSigma)-intsAt.length).forEach(_ => intsAt.push([i, intsAt.length+1-sigma])); return [nextSigma, intsAt]}, [initialSigma, []])
a = [2, .9, .3+.8]; log(SigmaDelta(a, 0).json(), a.sum()) // response [4,[[0,1],[0,2],[2,0.10000000000000009],[2,1.1]]] 4 says that total len is 4
// and we have two integer marks in the first interval, at offests 1 and 2 within it. We also have two intger marks in the last interval .3+.8,
// at offests .1 and 1.1 within it. The offsets are caused by previous, .9, interval that lacks .1 to complete the integer.
resample = (f, convergence, iterations) => (a,b,intervals) => {const iteration = (xes) => {const sl = [...xes, b] ; const diffs = sl.slice(0,-1).map((x,i) => Math.abs(f(sl[i+1]) - f(x))); const totalDiff = diffs.sum(); const spi = diffs.map(df => convergence * df/totalDiff* intervals + (1-convergence)); log("spi", spi.map(spi=>spi.toFixed(3))); const sd = SigmaDelta(spi, 1)[1]; if (sd.length > intervals) sd.pop() ; const sd2 = sd.map(([i, offset]) => {return sl[i]+(sl[i+1]-sl[i]) * offset/intervals}); return sd2} ; return range(iterations).reduce((was, _) => {log("resampling", was); return iteration(was)}, sampleLeft(a,b,intervals)) }
a = resample(x => 1/x, 0.00001, 1, 5, 10, .05)
integrateRes = (f, a,b, intervals, conv, iterations) => integrate (f, a,b,intervals, resample(f, conv, iterations))
// The following demo suggests that resample-based integral performs good with as much as 5 sample points whereas dumb uniform sampling needs 500
;[5, 50, 500].map(sp => [sp, "bars:", [integrateLeft, integrateRes].map(integrator => [integrator.name, ":", integrator(x => x*Math.exp(-x), .0000, 1000, sp, .1, 10)])]) .forEach(res => log(res.json()))
// Results
//[5,"bars:",[["integrateLeft",":",7.440151952041673e-40],["integrateRes",":",1.0636014628796828]]]
//[50,"bars:",[["integrateLeft",":",0.009079986008642706],["integrateRes",":",0.9667958117606238]]]
//[500,"bars:",[["integrateLeft",":",1.1172855274492746],["integrateRes",":",1.03947913790368]]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment