Translate Excel formula into structured english - excel

I have this formula, with the variables, m,s and e.
IFERROR(IF(m - IF(s*(1/ABS(e))>m;m;s*(1/ABS(e)))>m;m;m-IF(s*(1/ABS(e))>m;m;s*(1/ABS(e))))/100;0)
I want to translate it to structured english, this is what I have, but I doubt its correct:
IF e != 0
IF m > m
return m
ELSE IF s / |e| > m
return m
ELSE IF s / e > m
return m - s / e
ELSE
return s / e
ELSE
return 0
?? forgot this one upss.. s / e / 100;

After analyzing the function, I think this simplified version has the same result:
=IFERROR(IF(MIN(m;s/ABS(e))<0;m;m-MIN(m;s/ABS(e)))/100;0)
And its logic can be explained like this:
if e = 0
0
else if m - (min between s/|e| and m) > m
m
else
m - (min between s/|e| and m)
Even still, I don't understand what that is for. :P
Edit: I added a simplified Javascript version of Sir Ben's code:
function whacko (m,s,e) {
if (e === 0)
return 0;
var value = m - Math.min(s / Math.abs(e), m);
if (value > m)
return m;
return value;
};

Thanks to Andrew's great reply, this is the working code in JS:
var m = 33
, s = 43
, e = 12.75; // Excel: 29,6%
function whacko (m,s,e) {
if (e === 0) {
return 0;
} else if (m - (Math.min(s/Math.abs(e), m)) > m) {
return m;
} else {
return m - (Math.min(s/Math.abs(e), m));
}
};
console.log(whacko(m,s,e)); // 29.627450980392158

Related

Dafny. Prove that all values from an interval appear in seq

I try to prove the following lemma. It seems really trivial, but I can't manage to prove it. Thank you in advance!
lemma test(x : seq<int>)
// if the values from x are margined by an interval
// the values are different
// and the number of values equals the size of the interval
// then all values from the interval appear in x
requires forall i :: 0 <= i < |x| ==>
0 <= x[i] < |x|;
requires forall i :: 0 <= i < |x| ==>
forall i' :: 0 <= i' < |x| && i != i' ==>
x[i] != x[i'];
ensures forall v :: 0 <= v < |x| ==>
exists i :: 0 <= i < |x| && x[i] == v;
{
}
https://rise4fun.com/Dafny/d8VK
Here's one way to do it, using some facts about set cardinalities.
lemma test(x : seq<int>)
// if the values from x are margined by an interval
// the values are different
// and the number of values equals the size of the interval
// then all values from the interval appear in x
requires forall i :: 0 <= i < |x| ==>
0 <= x[i] < |x|;
requires forall i :: 0 <= i < |x| ==>
forall i' :: 0 <= i' < |x| && i != i' ==>
x[i] != x[i'];
ensures forall v :: 0 <= v < |x| ==> v in x
{
var L: set<int>, R: set<int> := {}, RangeSet(0, |x|);
var i := 0;
CardinalityRangeSet(0, |x|);
while i < |x|
invariant 0 <= i <= |x|
invariant L == set j | 0 <= j < i :: x[j]
invariant forall v | v in L :: v in x
invariant forall v | 0 <= v < |x| :: v in L || v in R
invariant |R| == |x| - i
{
L, R := L + {x[i]}, R - {x[i]};
i := i + 1;
}
}
predicate InRange(lo: int, hi: int, i: int)
{
lo <= i < hi
}
function RangeSet(lo: int, hi: int): set<int>
{
set i | lo <= i < hi && InRange(lo, hi, i)
}
lemma CardinalityRangeSet(lo: int, hi: int)
decreases hi - lo
ensures |RangeSet(lo, hi)| == if lo >= hi then 0 else hi - lo
{
if lo < hi {
assert RangeSet(lo, hi) == {lo} + RangeSet(lo + 1, hi);
CardinalityRangeSet(lo + 1, hi);
}
}
I changed your specification slightly to use the Dafny syntax v in x, which is equivalent to what you wrote, and a little easier for Dafny to reason about.
The basic idea of the proof is to start with the range R of elements 0..|x|, and then iteratively remove elements x[i] from R and add them to L. This maintains the invariant that every number in the range 0..|x| is either in L or R, while the cardinality of R decreases on every iteration. Thus, at the end of the loop R is empty, so every number in the range must be in L, and therefore in x.
I also used one helper lemma proved by induction to show that RangeSet has the expected size.
(Edited to get rid of "No terms found to trigger on" warning in RangeSet. Introducing the predicate InRange gives it something to trigger on, but you still need to include the explicit range in RangeSet because otherwise it can't figure that the set is finite.)

What's the syntax to create nested if else statements with do's

So I am just getting the hang of Haskell and got stuck with the syntax for creating nested if-else statements with Do.
I am not sure, if I am supposed to use multiple Do's or if I can accomplish it all with just one.
I am also not sure if I should use the return statement and if all the semicolons are necessary.
I tried adding and removing braces, return statements, semicolons, different indenting and do not know what else to try.
I get errors like " • Couldn't match expected type ‘m0 (m0 b0)’ with actual type ‘Int’
• In a stmt of a 'do' block: a <- getVal
"
This is the kind of structure I am trying to build but it gives me errors. You can imagine the getVal functions as arbitrary functions, that return an integer :
func :: Int -> Int
func val = do {
if val < 10
then do {
a <- getVal0;
b <- getVal1;
if (val+a+b) < 0
then return 1
else return 2}
else if val > 10
then do {
a <- getVal2;
b <- getVal3;
if (val + a +b) < 0
then return 0
else return 1}
else return 99; }
An example of get val would be:
getVal :: Int
getVal = 5
So this is what I want to happen :
If val is < 10, then get the value a with 2 parameters from getVal0 and get b from getVal1 . Then add val+a+b and if that is smaller than 0, return 1, else 2
If val is > 10, then get a from getVal2 and get b from getVal3. If val+a+b <0 then return 0, otherwise 1 .
If val is neither <10 or >10 ( val = 10) then return 99
Thanks for feedback and help!
As already mentioned in the comments, you don't need do, <-, or return here. Those are for monadic code, but here you are defining a regular function -- there are no monads around.
So, we can instead use let .. in ... Here's a possible way, performing minor changes to the original code.
func :: Int -> Int
func val =
if val < 10 then let
a = getVal0
b = getVal1
in if val + a + b < 0
then 1
else 2
else if val > 10 then let
a = getVal2
b = getVal3
in if val + a + b < 0
then 0
else 1
else 99
Many Haskellers would consider to turn the outermost ifs into guards:
func :: Int -> Int
func val
| val < 10 = let
a = getVal0
b = getVal1
in if val + a + b < 0
then 1
else 2
| val > 10 = let
a = getVal2
b = getVal3
in if val + a + b < 0
then 0
else 1
| otherwise = 99

Printing intermediate value in recursive function in Haskell

I am new to Haskel and want to learn it. I want to print intermediate value in recursive function in haskell but i am stuck in parse error on input "=" on line b= b+50.
`main' t s a b c
| t > s = 0
| otherwise = do
print a
print b
print c
b = b + 50
c = b + 2 * a
main' (t+1) s (a+1) b c `
the C equivalent for this code is
int calculate(t,s,a,b,c)
{
printf( "%d,%d,%d",a,b,c);
if(t > s)
return 0;
else
{
b = b + 50;
c = b + 2 * a;
return calculate (t+1,s,a,b,c);
}
}
int main()
{
calculate(0,10,2,6,7);
return 0;
}`
Please help me to resolve this problem. It is not so difficult to do in C but I could not figure out how to do it in Haskel.
As PyRulez says in his comment, you need to use let syntax in do blocks. However, you are also going to run into issues because your function parameters, like all values in Haskell, are immutable. You will need to do something like:
let b' = b + 5
let c' = b' + 2 * a
If you only want to print some intermediate value, you don't need to have your function in the IO world:
you can use the Debug.Trace module:
import Debug.Trace
func :: Int -> Int -> Int -> Int -> Int
func 0 _ _ _ = 0
func t a b c = trace ("a="++(show a)++" b="++(show b)++" c="++(show c)) $ recurs
where recurs = func (t-1) (a+1) (b+50) (b+2*a)
it gives me:
> func 5 1 1 1
a=1 b=1 c=1
a=2 b=51 c=3
a=3 b=101 c=55
a=4 b=151 c=107
a=5 b=201 c=159

Scala parallel frequency calculation using aggregate doesn't work

I'm learning Scala by working the exercises from the book "Scala for the Impatient". Please see the following question and my answer and code. I'd like to know if my answer is correct. Also the code doesn't work (all frequencies are 1). Where's the bug?
Q10: Harry Hacker reads a file into a string and wants to use a
parallel collection to update the letter frequencies concurrently on
portions of the string. He uses the following code:
val frequencies = new scala.collection.mutable.HashMap[Char, Int]
for (c <- str.par) frequencies(c) = frequencies.getOrElse(c, 0) + 1
Why is this a terrible idea? How can he really parallelize the
computation?
My answer:
It is not a good idea because if 2 threads are concurrently updating the same frequency, the result is undefined.
My code:
def parFrequency(str: String) = {
str.par.aggregate(Map[Char, Int]())((m, c) => { m + (c -> (m.getOrElse(c, 0) + 1)) }, _ ++ _)
}
Unit test:
"Method parFrequency" should "return the frequency of each character in a string" in {
val freq = parFrequency("harry hacker")
freq should have size 8
freq('h') should be(2) // fails
freq('a') should be(2)
freq('r') should be(3)
freq('y') should be(1)
freq(' ') should be(1)
freq('c') should be(1)
freq('k') should be(1)
freq('e') should be(1)
}
Edit:
After reading this thread, I updated the code. Now the test works if ran alone, but fails if ran as a suite.
def parFrequency(str: String) = {
val freq = ImmutableHashMap[Char, Int]()
str.par.aggregate(freq)((_, c) => ImmutableHashMap(c -> 1), (m1, m2) => m1.merged(m2)({
case ((k, v1), (_, v2)) => (k, v1 + v2)
}))
}
Edit 2:
See my solution below.
++ does not combine the values of identical keys. So when you merge the maps, you get (for shared keys) one of the values (which in this case is always 1), not the sum of the values.
This works:
def parFrequency(str: String) = {
str.par.aggregate(Map[Char, Int]())((m, c) => { m + (c -> (m.getOrElse(c, 0) + 1)) },
(a,b) => b.foldLeft(a){case (acc, (k,v))=> acc updated (k, acc.getOrElse(k,0) + v) })
}
val freq = parFrequency("harry hacker")
//> Map(e -> 1, y -> 1, a -> 2, -> 1, c -> 1, h -> 2, r -> 3, k -> 1)
The foldLeft iterates over one of the maps, updating the other map with the key/values found.
You trouble in first case as you detected by yourself was in ++ operator which just concatenating, dropping second occurence of same key.
Now in the second case you have the (_, c) => ImmutableHashMap(c -> 1) which just drops all of chars found my the map in seqop stage.
My suggestion is to extend the Map type with special compination operation, working like merged in HashMap and preserve collecting from first example at seqop stage:
implicit class MapUnionOps[K, V](m1: Map[K, V]) {
def unionWith[V1 >: V](m2: Map[K, V1])(f: (V1, V1) => V1): Map[K, V1] = {
val kv1 = m1.filterKeys(!m2.contains(_))
val kv2 = m2.filterKeys(!m1.contains(_))
val common = (m1.keySet & m2.keySet).toSeq map (k => (k, f(m1(k), m2(k))))
(common ++ kv1 ++ kv2).toMap
}
}
def parFrequency(str: String) = {
str.par.aggregate(Map[Char, Int]())((m, c) => {m + (c -> (m.getOrElse(c, 0) + 1))}, (m1, m2) => (m1 unionWith m2)(_ + _))
}
Or you can use fold solution from Paul's answer, but for better performance for each merge choose lesser map to traverse:
implicit class MapUnionOps[K, V](m1: Map[K, V]) {
def unionWith(m2: Map[K, V])(f: (V, V) => V): Map[K, V] =
if (m2.size > m1.size) m2.unionWith(m1)(f)
else m2.foldLeft(m1) {
case (acc, (k, v)) => acc + (k -> acc.get(k).fold(v)(f(v, _)))
}
}
This seems to work. I like it better than the other solutions proposed here because:
It's lot less code than an implicit class and slightly less code than using getOrElse with foldLeft.
It uses the merged function from the API which's intended to do what I want.
It's my own solution :)
def parFrequency(str: String) = {
val freq = ImmutableHashMap[Char, Int]()
str.par.aggregate(freq)((_, c) => ImmutableHashMap(c -> 1), _.merged(_) {
case ((k, v1), (_, v2)) => (k, v1 + v2)
})
}
Thanks for taking the time to help me out.

How do I simplify the below expressions using primitive recursion? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Symbolic simplification in Haskell (using recursion?)
The simplifications I have in mind are
0*e = e*0 = 0
1*e = e*1 = 0+e = e+0 = e-0 = e
and simplifying constant subexpressions, e.g. Plus (Const 1) (Const 2) would become Const 3. I would not expect variables (or variables and constants) to be concatenated: Var "st" is a distinct variable from Var "s".
For example simplify(Plus (Var "x") (Const 0))= Var "x"
Well, can't you apply pattern matching to the individual cases?
simplify (Plus (Const 0) (Expr x)) = simplify (Expr x)
simplify (Plus (Expr x) (Const 0)) = simplify (Expr x)
simplify (Mult (Const 0) _) = Const 0
simplify (Mult _ (Const 0)) = Const 0
– … and so on
EDIT: Yes, of course … recursion added.
I don't know much about haskell, but essentially your are going to want to do an expression tree traversal.
the tree is
EXP: (operator) (EXP) (EXP)
EXP: (const)
EXP: (var)
then your simplify becomes
heres the psuedo code
simplify(Exp e)
if (e is const) return e
else if (e is var) return e
else
{//encode simplification rules
Exp left = simplify(e.left)
Exp right = simplify(e.right)
if(operator is PLUS)
{
if(left == 0) return right;
if(right == 0) return left;
}
else if(operator is MULT)
{
if(left == 1) return right;
if(right == 1) return left;
if(left == 0) return 0;
if(right == 0) return 0;
}
//and so on for other operators
}
this is sort of java esque but i think the idea is there, essentially youre going to have to do a tree traversal.

Resources