Функция, которая возвращает медиану? (OCaml)

Как бы я написал в OCaml медианную функцию, которая принимает 5 аргументов и возвращает медиану. Например, med5 2 5 7 4 3 вернет 4.

Мне удалось написать функцию med3 (возвращает медиану 3 аргументов), используя операторы if и else, но это было бы смехотворно сложно, если бы я попытался использовать ту же технику для 5 аргументов :(

let med3 a b c =
  if ((b<=a && c>=a) || (c<=a && b>=a)) then a 
  else if ((a<=b && c>=b) || (c<=b && a>=b)) then b else c;;

Для функции med5 я хотел бы иметь возможность использовать функции min и max (встроенные в OCaml), чтобы отбрасывать самые высокие и самые низкие значения из набора из 5 аргументов. Затем я мог бы использовать функцию med3, которую я уже написал, чтобы вернуть медиану оставшихся 3 аргументов, но как мне отбросить минимальный и максимальный аргументы!?!?!?!?

Любая помощь приветствуется :)


person brnby    schedule 10.10.2012    source источник
comment
Если я не ошибаюсь, med5 2 5 7 4 3 это 4, а не 3   -  person Virgile    schedule 10.10.2012
comment
Ха-ха, вы абсолютно правы, спасибо, что указали на это :)   -  person brnby    schedule 10.10.2012


Ответы (3)


Если вы можете использовать Array, просто поместите свои 5 записей в массив, отсортируйте его и верните a[2]. Если это также запрещено в вашем задании, вы можете использовать пузырьковую сортировку бедняка, чтобы выбрать максимум, а затем минимум:

let med5 a b c d e =
  (* move the max towards 'e' *)
  let a,b = if a<=b then a,b else b,a in
  let b,c = if b<=c then b,c else c,b in
  ...
  (* then move the min towards 'd', don't forget to reverse the comparisons *)
  ...
  in med3 a b c
person Virgile    schedule 10.10.2012

Вы можете поместить эти 5 аргументов в список, тогда удалить элемент из списка будет легко.

person jrouquie    schedule 10.10.2012
comment
К сожалению, мой вопрос был частью задания, в котором указывалось, что мы не можем использовать списки, потому что мы еще не должны были узнать о них :( Не то чтобы я знал, как написать функцию, используя списки!!! :'( - person brnby; 10.10.2012
comment
Я также должен отметить, что крайний срок для этого задания уже прошел. - person brnby; 10.10.2012

Если списки и массивы запрещены, вы можете иметь три переменные, хранящие три самых больших элемента из пяти:

let med5 a b c d e =
    let first  = ref min_int in
    let second = ref min_int in
    let third  = ref min_int in

    if      a >= !first  then (third := !second; second := !first; first := a)
    else if a >= !second then (third := !second; second := a)
    else if a >= !third  then (third := a);

    if      b >= !first  then (third := !second; second := !first; first := b)
    else if b >= !second then (third := !second; second := b)
    else if b >= !third  then (third := b);

    (* you guess what to do for c, d, e ;-) *)

    (* return the third largest element: *)
    !third
person jrouquie    schedule 10.10.2012