Find It

Mercator Upcoming Events

Home icon Home»Events»CID»Romanian Country Information Day 2010
Romanian Country Information Day 2010

Romanian_CID_mail03Due to the numerous midterms and the vast amount of the homework in that period the Romanian CID (Country Information Day) was not held on its original date, 4th of November 2010.

But no fear ! After that shaky start, the Romanians are back to show everyone what they're made of. Wisely reprogramming the event before the finals period and right after the Mercator Christmas Decoration, they regrouped and are now plotting to make a CID that will baffle everyone, that will take place on the 9th of December. If you happen to pass late in the evening through our common room, you will have a good change to take a peek of what will be happening that day, as they are often there either dancing their dances, plotting their planes or just simply brainstorming.

Meanwhile, you can check their previous 2 CID's, one better than the other :

The 2006 one

The 2004 one

 

Romanian_CID_mail06

(** Stefan Mirea **)

(**

zxdszNOTE: this is a general equation parser function without paranthesis, not only a 2nd degree polinomial one. **)

exception Bonk;
exception BonkInvalidInput;
exception BonkEmptyString;
exception BonkNotReal;
exception BonkEmptyList;
exception BonkNeedGreaterThanZero;
exception BonkParanthesisMissmatch;

(** The maximum element in a list **)
fun max ([]) = raise BonkEmptyList
| max (a::[]) = a
| max (a::b::t) = if a > b
then max (a::t)
else max (b::t);

(** The minimum element in a list **)
fun min ([]) = raise BonkEmptyList
| min (a::[]) = a
| min (a::b::t) = if a < b
then min (a::t)
else min (b::t);

(** repl(list, index, length, replaceWith)
-replaces "length" characters from "list" starting after the element at position "index" with "replaceWith"

**)
fun repl ([], _, _,_ ) = []
| repl(h::t, 0, 0, l) = (h :: l) @ t
| repl(a::b::t, 0, n, l) = repl (a::t, 0, n-1, l)
| repl(h::t, p, n, l) = [h] @ repl (t, p-1, n, l);

(** Same as above, only works with strings **)
fun replStr (l1, p, n, l2) = implode ( repl(explode l1, p, n, explode l2) );

(** Returns a list sliced in 2 at position n as a pair (a, b) **)
fun sliceAt (a, b, 0) = (b, a)
| sliceAt (h::t, b, n) = sliceAt (t, b @ [h], n-1)
| sliceAt (_, _, _) = ([], []);

(** Returns a string sliced in 2 at position n as a pair (a, b) **)
fun sliceStrAt (str, n) = let    val (a, b) = sliceAt ( explode str, [], n );
in (implode a, implode b)
end;

(** Pos of an element in a list **)
fun indexOf ([], x, p) = ~1
| indexOf (h::t, x, p) = if h = x then p else indexOf (t, x, p+1);

(** Pos of an element in a string **)
fun indexOfStr (str, x) = indexOf(explode str, x, 0);

(** Pos of an element in a string starting from offset "off" **)
fun indexOfStrOffset (str, x, off) = let val (a, b) = sliceStrAt(str, off)
val p = indexOfStr(b, x)
in if p < 0 then ~1
else size a + p
end;

(** Pos of the last of that kind of elements in a list **)
fun lastIndexOf([], x, p, l) = l
| lastIndexOf(h::t, x, p, l) = if h = x then lastIndexOf(t, x, p+1, p) else lastIndexOf(t, x, p+1, l);

(** Pos of the last of that kind of elements in the string **)
fun lastIndexOfStr (str, x) = lastIndexOf(explode str, x, 0, ~1);


(** Replace all occurences of "x" with "y" in a string **)
fun replaceAll (str, x, y) = let val p = indexOfStr(str, x)
in if p > ~1
then let val s = replStr(" " ^ str, p, 1, y)
in replaceAll( substring(s, 1, (size s)-1 ), x, y)
end
else str
end;


(** Used map the function bellow so negative values won't be considered **)
fun greaterThanZero x = if x <= 0 then 69696969 else x;
(** Gets the first token in a string **)
fun getFirst str = let val p = min( map greaterThanZero [indexOfStr(str, #"+"), indexOfStr(str, #"-"), indexOfStr(str, #"*"), indexOfStr(str, #"/")] )
in if p > ~1 andalso p <> 69696969
then sliceStrAt(str, p)
else (str, "")
end;

(** Gets the last token in a string **)
fun getLast str = let val p = max( [lastIndexOfStr(str, #"+"), lastIndexOfStr(str, #"-"), lastIndexOfStr(str, #"*"), lastIndexOfStr(str, #"/")] )
in if p > ~1
then sliceStrAt(str, p+1)
else ("", str)
end;

(** Takes a string, returns a real or bonks an exception **)
fun toReal x = let
fun isReal NONE = false
| isReal (SOME x) = true;
in
if isReal(Real.fromString(x))
then
let val SOME y = Real.fromString(x)
in y
end
else raise BonkNotReal
end;

(**
Simple operations evaluator;
It evaluates only 1 operation at a time
Example algorithm: input: ( 2+3*5+4*2+1, op* ) (this will get tokenized in the main function)
-> ["2+3", "5+4", "2+1"]
It iterates the list once, taking the first 2 elements. The last token from each element and the first token from the second element
are added as arguments to the operation function and the result is concatenated. Output: "2+15.0+8.0+1"
**)
fun ev (e1::[], _) = e1
| ev (e1::e2::e3, f) = let val (h, a) = getLast e1
val (b, t) = getFirst e2
val str = h ^ ev( (Real.toString( f( toReal a, toReal b ) ) ^ t ):: e3, f )
in  str
end
| ev(_, _) = "";

(** Functions used for tokenizing by operators **)
fun getSum #"+" = true | getSum _ = false;
fun getDifference #"-" = true | getDifference _ = false;
fun getMultiplication #"*" = true | getMultiplication _ = false;
fun getDivision #"/" = true | getDivision _ = false;

(** THE Function for evaluating polinomial equations
It takes each of the 4 operations and applies the ev() function with each of them,
prioritizing by the order: / * - + and outputs the result as a Real
**)
fun evPoli(str, x:real) = let
val s = replaceAll(str, #"x", Real.toString x)
val step1 = ev(String.tokens getDivision s, op/)
val step2 = ev(String.tokens getMultiplication step1, op* )
val step3 = ev(String.tokens getDifference step2, op-)
val step4 = ev(String.tokens getSum step3, op+)
in toReal step4
end;

(** Math functions with embeded exceptions **)
fun sin x = Math.sin x;
fun cos x = Math.cos x;
fun log x = if x <= 0.0 then raise BonkNeedGreaterThanZero else Math.ln x;
fun exp x = Math.exp x;

(** In order to get this done quickly and not have to implement an indexOf String*String->int,
i will simply rename all the functions with their first character. i.e.: "sin(x)"->"S(x)"
**)
(** We a list made from our functions and their notations **)
val functions = [ (#"S", sin), (#"C", cos), (#"L", log), (#"E", exp) ];

(**
The main function string parser. It gets the arguments of every function and applies the custom math functions above
It is also modular, meaning that by simply adding a abreviation and a function, as a pair, to the "functions" list above
you can register a new function to the parser
**)
fun evFn(str, [], x:real) = evPoli(str, x)
| evFn(str, h::t, x:real) = let
val (s, f) = h
val p = indexOfStr(str, s)
in if p > ~1
then let
val pos = indexOfStrOffset(str, #")", p + 1 + 1) (** normally it should be: "p + (size s) + 1" **)
in
if pos > ~1
then let
val argStr = replaceAll( substring(str, p + 1 + 1, pos - p - 2), #"x", Real.toString x)
val newStr = substring(str, 0, p)
^ Real.toString( f( evFn( argStr, h::t, x) ) )
^ substring(str, pos+1, (size str) - pos-1)
in
evFn(newStr, h::t, x)
end
else raise BonkParanthesisMissmatch
end
else evFn(str, t, x)
end;

(** Checks if the first list is made only with the elements of the second string **)
fun hasOnly([], str) = true
| hasOnly(_, "") = false
| hasOnly(a::A, str) = (Char.contains str a)  andalso hasOnly(A, str);

(** Checks if the first string is made only with the elements of the second string **)
fun hasOnlyStr(str, l) = hasOnly(explode str, l);

(** THE function. Checks if the string is valid and if it is, evaluates it **)
fun evaluateexp ("", _) = raise BonkEmptyString
| evaluateexp (str, x:real) = if hasOnlyStr(str, "0123456789xSCEL.+-*/()")
then evFn( replaceAll(str, #"x", Real.toString x), functions, x)
else raise BonkInvalidInput;