Created
December 5, 2019 13:38
-
-
Save pvik/59fe23f2000e693a6af2362c3573d95b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let wire1 = ["R98" ; "U47" ; "R26" ; "D63" ; "R33" ; "U87" ; "L62" ; "D20" ; "R33" ; "U53" ; "R51"] | |
let wire2 = ["U98" ; "R91" ; "D20" ; "R16" ; "D67" ; "R40" ; "U7" ; "R15" ; "U6" ; "R7"] | |
type point = { | |
x : float ; | |
y : float | |
} | |
type line = { | |
p1 : point ; | |
p2 : point | |
} | |
type line_eq = { | |
(* ax + by = c *) | |
a : float ; | |
b : float ; | |
c : float | |
} | |
let as_line_eq (l1 : line) = | |
let a1 = l1.p2.y -. l1.p1.y and | |
b1 = l1.p1.x -. l1.p2.x in | |
let c1 = (a1 *. l1.p1.x) +. (b1 *. l1.p1.y) in | |
{a = a1 ; b = b1 ; c = c1} | |
let on_segment (l : line) (p : point) = | |
if p.x >= (min l.p1.x l.p2.x) | |
&& p.x <= (max l.p1.x l.p2.x) | |
&& p.y >= (min l.p1.y l.p2.y) | |
&& p.y <= (max l.p1.y l.p2.y) | |
then | |
true | |
else | |
false | |
let intersection_point (ll1 : line) (ll2 : line) = | |
let l1 = as_line_eq ll1 and | |
l2 = as_line_eq ll2 in | |
let determinant = (l1.a *. l2.b) -. (l2.a *. l1.b) in | |
if determinant = 0.0 then | |
{x = 0.0 ; y = 0.0} | |
else | |
let x = (l2.b *. l1.c -. l1.b *. l2.c) /. determinant and | |
y = (l1.a *. l2.c -. l2.a *. l1.c) /. determinant in | |
{x = x ; y = y} | |
let is_intersect (l1 : line) (l2 : line) = | |
let intr_pt = (intersection_point l1 l2) in | |
if intr_pt.x = 0.0 && intr_pt.y = 0. then | |
false | |
else | |
if on_segment l1 intr_pt && on_segment l2 intr_pt then | |
true | |
else | |
false | |
let magnitude {x ; y} = | |
Float.sqrt (x ** 2.0 +. y ** 2.0) | |
let length (ln : line) = | |
Float.sqrt (((ln.p2.x -. ln.p1.x) ** 2.0) +. ((ln.p2.y -. ln.p1.y) ** 2.0)) | |
let manhattan_distance {x ; y} = | |
(Float.abs x) +. (Float.abs y) | |
let steps lns_lst pt = | |
List.fold_left | |
(fun (steps , reached) ln -> | |
if reached then | |
(steps, reached) | |
else | |
if on_segment ln pt then | |
let new_ln = {p1 = ln.p1 ; p2 = pt} in | |
(steps +. (length new_ln) , true) | |
else | |
(steps +. (length ln) , reached) | |
) | |
(0.0 , false) | |
lns_lst | |
let path_to_line (start_pt : point) (path : string) = | |
let path_lst = List.init (String.length path) (String.get path) and | |
len_str = String.sub path 1 ((String.length path) - 1) in | |
let path_len = float_of_string len_str in | |
match path_lst with | |
| 'R' :: _ -> { p1 = start_pt ; p2 = { x = start_pt.x +. path_len ; y = start_pt.y }} | |
| 'L' :: _ -> { p1 = start_pt ; p2 = { x = start_pt.x -. path_len ; y = start_pt.y }} | |
| 'U' :: _ -> { p1 = start_pt ; p2 = { x = start_pt.x ; y = start_pt.y +. path_len }} | |
| 'D' :: _ -> { p1 = start_pt ; p2 = { x = start_pt.x ; y = start_pt.y -. path_len }} | |
| _ -> {p1 = start_pt ; p2 = start_pt} | |
let paths_to_lines paths_lst = | |
List.tl ( | |
List.rev ( | |
List.fold_left | |
(fun acc (path : string) -> | |
let last_ln = List.hd acc in | |
let next_ln = path_to_line last_ln.p2 path in | |
next_ln :: acc) | |
[{p1 = {x = 0. ; y = 0.} ; p2 = {x = 0. ; y = 0.}}] | |
paths_lst) | |
) | |
let third_b w1 w2 = | |
let lw1 = paths_to_lines w1 and | |
lw2 = paths_to_lines w2 in | |
List.fold_left | |
(fun acc (ln : line) -> | |
let acc_inner = | |
(List.fold_left | |
(fun acc1 (ln2 : line) -> | |
if is_intersect ln ln2 then | |
let intr_pt = intersection_point ln ln2 in | |
let (steps1 , reached1) = steps lw1 intr_pt and | |
(steps2 , reached2) = steps lw2 intr_pt in | |
if reached1 && reached2 then | |
steps1 +. steps2 | |
else | |
acc1 | |
else acc1) | |
acc | |
lw2) in | |
if acc_inner < acc then | |
acc_inner | |
else acc) | |
max_float | |
lw1 | |
let third_a w1 w2 = | |
let lw1 = paths_to_lines w1 and | |
lw2 = paths_to_lines w2 in | |
List.fold_left | |
(fun acc (ln : line) -> | |
let acc_inner = | |
(List.fold_left | |
(fun acc1 (ln2 : line) -> | |
(* Printf.printf "inner min mag is %f ; outter min mag is %f \n" acc1 acc ; | |
* Printf.printf " checking line [(%f,%f) - (%f,%f)] against line [(%f,%f) - (%f,%f)] \n" | |
* ln.p1.x ln.p1.y ln.p2.x ln.p2.y ln2.p1.x ln2.p1.y ln2.p2.x ln2.p2.y ; *) | |
if is_intersect ln ln2 then | |
let intr_pt = intersection_point ln ln2 in | |
let intr_mag = manhattan_distance intr_pt in | |
(* Printf.printf " - lines intersect at (%f,%f) ; manhattan_distance is %f\n" | |
* intr_pt.x intr_pt.y intr_mag; *) | |
if intr_mag < acc1 then | |
intr_mag | |
else acc1 | |
else acc1) | |
acc | |
lw2) in | |
if acc_inner < acc then | |
acc_inner | |
else acc) | |
max_float | |
lw1 | |
let () = | |
Printf.printf "Res: %f\n" (third_b wire1 wire2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment