importPackage(java.io)
importPackage(java.lang)
// Reverse a calculation procedure involving different kinds of price increase
// Increase by percent
function proz(p) {
return function(x) {
return x*(1+p/100)
}
}
// Increase by absolute value
function abs(q) {
var f = function(x) {
return x+q
}
f.isAbsolute = true
return f
}
// Increase by percent of the calculation base
function proz_base(p) {
return function(x,base) {
return x+base*p/100
}
}
function schema( ) {
var conditions = convertToArray( arguments );
return {
// "compute" applies the schema to a base price
compute:compute,
// "resolve" finds the base price yielding the specified result
resolve:function(result) {
return ( result - compute(0) ) / reducedSchema().compute(1)
}
}
function compute(base) {
return conditions.reduce( function(result,cond) {
return cond(result,base)
},
base )
}
function reducedSchema() {
return schema.apply( null, conditions.filter( isRelative ) )
}
function isRelative( cond ) {
return ! cond.isAbsolute
}
}
function convertToArray( arraylikeThing ) {
return Array.prototype.slice.apply( arraylikeThing )
}
// Test
var s = schema(
proz( 7 ),
abs(5),
proz_base(10),
abs(3),
proz(13)
)
System.out.println( s.compute( s.resolve( 20 ) ) )
aW1wb3J0UGFja2FnZShqYXZhLmlvKQppbXBvcnRQYWNrYWdlKGphdmEubGFuZykKCi8vIFJldmVyc2UgYSBjYWxjdWxhdGlvbiBwcm9jZWR1cmUgaW52b2x2aW5nIGRpZmZlcmVudCBraW5kcyBvZiBwcmljZSBpbmNyZWFzZQoKLy8gSW5jcmVhc2UgYnkgcGVyY2VudApmdW5jdGlvbiBwcm96KHApIHsgCiAgcmV0dXJuIGZ1bmN0aW9uKHgpIHsKICAgIHJldHVybiB4KigxK3AvMTAwKQogICAgfQogIH0gIAoKLy8gSW5jcmVhc2UgYnkgYWJzb2x1dGUgdmFsdWUgIApmdW5jdGlvbiBhYnMocSkgeyAKICB2YXIgZiA9IGZ1bmN0aW9uKHgpIHsKICAgIHJldHVybiB4K3EKICAgIH0KICBmLmlzQWJzb2x1dGUgPSB0cnVlCiAgcmV0dXJuIGYKICB9CgovLyBJbmNyZWFzZSBieSBwZXJjZW50IG9mIHRoZSBjYWxjdWxhdGlvbiBiYXNlICAKZnVuY3Rpb24gcHJvel9iYXNlKHApIHsKICByZXR1cm4gZnVuY3Rpb24oeCxiYXNlKSB7CiAgICByZXR1cm4geCtiYXNlKnAvMTAwCiAgICB9CiAgfSAgCgpmdW5jdGlvbiBzY2hlbWEoICkgewogIHZhciBjb25kaXRpb25zID0gY29udmVydFRvQXJyYXkoIGFyZ3VtZW50cyApOwogIHJldHVybiB7Ci8vICJjb21wdXRlIiBhcHBsaWVzIHRoZSBzY2hlbWEgdG8gYSBiYXNlIHByaWNlCiAgICAgIGNvbXB1dGU6Y29tcHV0ZSwKLy8gInJlc29sdmUiIGZpbmRzIHRoZSBiYXNlIHByaWNlIHlpZWxkaW5nIHRoZSBzcGVjaWZpZWQgcmVzdWx0ICAgICAgICAKICAgICAgcmVzb2x2ZTpmdW5jdGlvbihyZXN1bHQpIHsKICAgICAgICByZXR1cm4gKCByZXN1bHQgLSBjb21wdXRlKDApICkgLyByZWR1Y2VkU2NoZW1hKCkuY29tcHV0ZSgxKSAKICAgICAgICB9CiAgICAgIH0KICAgICAgCiAgZnVuY3Rpb24gY29tcHV0ZShiYXNlKSB7CiAgICByZXR1cm4gY29uZGl0aW9ucy5yZWR1Y2UoIGZ1bmN0aW9uKHJlc3VsdCxjb25kKSB7CiAgICAgIHJldHVybiBjb25kKHJlc3VsdCxiYXNlKQogICAgICB9LCAKICAgICAgYmFzZSApCiAgICB9CiAgICAKICBmdW5jdGlvbiByZWR1Y2VkU2NoZW1hKCkgewogIAlyZXR1cm4gc2NoZW1hLmFwcGx5KCBudWxsLCBjb25kaXRpb25zLmZpbHRlciggaXNSZWxhdGl2ZSApICkKICAgIH0gIAogICAgCiAgZnVuY3Rpb24gaXNSZWxhdGl2ZSggY29uZCApIHsKICAJcmV0dXJuICEgY29uZC5pc0Fic29sdXRlCiAgCX0KICAJCiAgfQoKZnVuY3Rpb24gY29udmVydFRvQXJyYXkoIGFycmF5bGlrZVRoaW5nICkgewogIHJldHVybiBBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkoIGFycmF5bGlrZVRoaW5nICkKICB9CgoKLy8gVGVzdCAKdmFyIHMgPSBzY2hlbWEoIAoJcHJveiggNyApLCAKCWFicyg1KSwgCglwcm96X2Jhc2UoMTApLCAKCWFicygzKSwgCglwcm96KDEzKSAKCSkKCQpTeXN0ZW0ub3V0LnByaW50bG4oIHMuY29tcHV0ZSggcy5yZXNvbHZlKCAyMCApICkgKQ==