solve_1.ml 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. open Stdio
  2. open Str
  3. let next_char = function
  4. | 'X' -> 'M'
  5. | 'M' -> 'A'
  6. | 'A' -> 'S'
  7. | _ -> 'Z'
  8. ;;
  9. let input_info =
  10. let rec one_string inp nb_rows nb_columns =
  11. let line = In_channel.input_line In_channel.stdin in
  12. match line with
  13. | None -> (inp, (nb_rows, nb_columns))
  14. | Some x -> one_string (inp ^ x) (nb_rows + 1) (String.length x)
  15. in one_string "" 0 0
  16. ;;
  17. let input = fst input_info;;
  18. let nb_rows = (fst (snd input_info));;
  19. let nb_columns = (snd (snd input_info));;
  20. let get_valid_indexes letter pos =
  21. let filter i =
  22. ( let right = (if ((pos mod nb_columns) < (nb_columns - i)) then (pos + 1) else -99) in
  23. let left = (if ((pos mod nb_columns) > (i-1) ) then (pos -1) else -99) in
  24. let up = (if ((pos - i*nb_columns) >= 0) then (pos - nb_columns) else -99) in
  25. let down = (if ((pos + i*nb_columns) < nb_columns*nb_rows) then (pos + nb_columns) else -99) in
  26. let upright = (let is_valid_upright = ((((pos - i*(nb_columns - 1)) mod nb_columns) - (pos mod nb_columns)) == i) in
  27. if is_valid_upright then (up + 1) else -99) in
  28. let upleft = (let is_valid_upleft = (((pos mod nb_columns) - ((pos - i*(nb_columns + 1)) mod nb_columns)) == i) in
  29. if is_valid_upleft then (up - 1) else -99) in
  30. let downright = (let is_valid_downright = ((((pos + i*(nb_columns + 1)) mod nb_columns) - (pos mod nb_columns)) == i) in
  31. if is_valid_downright then (down + 1) else -99) in
  32. let downleft = (let is_valid_downleft = (((pos mod nb_columns) - ((pos + i*(nb_columns - 1)) mod nb_columns)) == i) in
  33. if is_valid_downleft then (down - 1) else -99) in
  34. List.filter (fun x -> (snd x) >= 0) [('r',right);('l',left);('u',up);
  35. ('d',down);('R',upright);('L',upleft);
  36. ('\\',downright);('/',downleft)]) in
  37. (match letter with
  38. | 'X' -> filter 3
  39. | 'M' -> filter 2
  40. | 'A' -> filter 1
  41. | 'S' | _ -> [])
  42. ;;
  43. let rec count_xmas letter pos direction accum=
  44. if letter == 'S' then (accum + 1) else
  45. let list_indexes = get_valid_indexes letter pos in
  46. let direction_filter = if direction != 'a' then List.filter (fun x -> (fst x) == direction) list_indexes else list_indexes in
  47. let adjacent_wanted = List.filter (fun l -> input.[snd l] == (next_char letter)) direction_filter in
  48. let rec aux = (function
  49. | (d, i):: tl -> count_xmas input.[i] i d accum + aux tl
  50. | [] -> accum)
  51. in aux adjacent_wanted
  52. ;;
  53. let solve =
  54. let rec aux pos accum=
  55. try
  56. let pos_x = search_forward (regexp "X") input pos in
  57. aux (pos_x + 1) (accum + count_xmas 'X' pos_x 'a' 0 )
  58. with Not_found -> accum
  59. in
  60. aux 0 0
  61. ;;
  62. let () = printf "Total : %d\n" solve