OCaml

練習問題 6.2 ヴァリアントを使う

練習問題 6.2

位置情報が付加された2つの図形が重なりを持つか判定する。
figure with_location -> figure with_location -> bool
型の関数 overlap を定義しなさい。ただし、位置は図形の中心を示し、正方形、長方形は、各辺がx軸・y軸に平行で、長方形に関しては、Rectangle(x, y) の x の表す辺がx軸に平行、と仮定します。

2つの図形というのをどう考えるかが難しかった。

長方形と長方形、正方形と正方形、円と円だと考えやすいので、それでやったが、

長方形と円、正方形と円などと、さまざまな図形の組み合わせを考えるのができなかった。

(* 図形をあらわすヴァリアント *)
type figure =
    Circle of int
    | Rectangle of int * int
    | Square of int;;

(* 位置情報を付加する *)
type 'a with_location = { loc_x: float; loc_y: float; body: 'a};;

(* 原点 *)
{ loc_x = 0.0; loc_y = 0.0; body = Point };;

(* ある長方形 *)
let rec1 = { loc_x = 4.; loc_y = 2.; body = Rectangle (4, 2) };;
let rec2 = { loc_x = 6.; loc_y = 3.; body = Rectangle (5, 3) };;

(* 自乗 *)
let joh (x: float) = x *. x;;
let test1 = joh 2. = 4.;;
let test2 = joh 3. = 9.;;

let abs (x: float) =
    if x < 0. then -1. *. x else x;;

let overlap a b =
  match (a.body, b.body) with
    Circle c1, Circle c2 ->
    let d1 = float_of_int c1 in
    let d2 = float_of_int c2 in
    if (joh(a.loc_x -. b.loc_x) +. joh(a.loc_y -. b.loc_y))
       < joh(d1 +. d2)
    then true
    else false
  | Rectangle (l1, l2), Rectangle (l3, l4) ->
     let d1 = float_of_int l1 in
     let d2 = float_of_int l2 in
     let d3 = float_of_int l3 in
     let d4 = float_of_int l4 in
     if (abs(a.loc_x -. b.loc_x) < (d1 +. d3) /. 2.) &&
          (abs(a.loc_y -. b.loc_y) < (d2 +. d4) /. 2.) 
     then true
     else false
  | Square l1, Square l2 ->
     let d1 = float_of_int l1 in
     let d2 = float_of_int l2 in
     if (abs(a.loc_x -. b.loc_x) < (d1 +. d2) /. 2.) &&
          (abs(a.loc_y -. b.loc_y) < (d1 +. d2) /. 2.)
     then true
     else false;;

(* すべての組み合わせを網羅するような関数を作りたかったが、よくわからなかった。
let overlap a b =
  match (a.body, b.body) with
    ((Square k1, (Circle k3 | Square k3 | Rectangle (l3, l4)))|
     (Circle k1, (Circle k3 | Square k3 | Rectangle (l3, l4)))|
     (Rectangle (l1, l2) (Circle k3 | Square k3 | Rectangle (l3, l4)))) ->
 *)    

let cir1 = { loc_x = 3.; loc_y = 3.; body = Circle 2 };;
let cir2 = { loc_x = 1.; loc_y = 1.; body = Circle 3 };;

let test3 = overlap cir1 cir2 = true;;

let cir3 = {loc_x = 5.; loc_y = 5.; body = Circle 1};;
let cir4 = {loc_x = 1.; loc_y = 1.; body = Circle 2};;

let test4 = overlap cir3 cir4 = false;;