|
|
@@ -0,0 +1,81 @@
|
|
|
+open Stdio
|
|
|
+open Str
|
|
|
+
|
|
|
+
|
|
|
+let input =
|
|
|
+ let rec one_string inp=
|
|
|
+ let line = In_channel.input_line In_channel.stdin in
|
|
|
+ match line with
|
|
|
+ | None -> inp
|
|
|
+ | Some x -> one_string (inp ^ x)
|
|
|
+ in one_string ""
|
|
|
+;;
|
|
|
+
|
|
|
+let repeat_string str n =
|
|
|
+ String.concat "" (List.init n (fun _ -> str))
|
|
|
+;;
|
|
|
+
|
|
|
+let expand dm =
|
|
|
+ let rec aux i acc=
|
|
|
+ if (i >= String.length dm) then
|
|
|
+ acc
|
|
|
+ else (if (i == String.length dm -1)
|
|
|
+ then
|
|
|
+ let id = string_of_int (i/2) in
|
|
|
+ let file_size = (int_of_char dm.[i] - int_of_char '0') in
|
|
|
+ let new_encoding = (repeat_string id file_size) in
|
|
|
+ (acc ^ new_encoding)
|
|
|
+ else
|
|
|
+ let id = string_of_int (i/2) in
|
|
|
+ let file_size = (int_of_char dm.[i] - int_of_char '0') in
|
|
|
+ let empty_space = (int_of_char dm.[i+1] - int_of_char '0') in
|
|
|
+ let new_encoding = (repeat_string id file_size) ^ (String.make empty_space '.') in
|
|
|
+ aux (i+2) (acc ^ new_encoding))
|
|
|
+ in
|
|
|
+ aux 0 String.empty
|
|
|
+;;
|
|
|
+
|
|
|
+let reverse_compact dm=
|
|
|
+ let rec aux left_most_pos accum =
|
|
|
+ try
|
|
|
+ if (left_most_pos < 0) then accum
|
|
|
+ else
|
|
|
+ (let nleft_most_pos = search_backward (regexp "[0-9]") dm left_most_pos in
|
|
|
+ aux (nleft_most_pos-1) (accum^(String.make 1 dm.[nleft_most_pos])))
|
|
|
+ with Not_found -> accum
|
|
|
+ in
|
|
|
+ aux (String.length dm) (String.empty)
|
|
|
+;;
|
|
|
+
|
|
|
+let compact dm rcomp=
|
|
|
+ let dm_len = (String.length rcomp) in
|
|
|
+ let rec aux i pos accum =
|
|
|
+ try
|
|
|
+ let npos = search_forward (regexp {|\.|}) dm pos in
|
|
|
+ aux (i+1) (npos+1) (accum ^ (String.sub dm pos (npos - pos)) ^ (String.make 1 rcomp.[i]))
|
|
|
+ with Not_found -> (String.sub accum 0 dm_len) ^ (String.make 1 '.')
|
|
|
+ in
|
|
|
+ aux 0 0 String.empty
|
|
|
+;;
|
|
|
+
|
|
|
+let calculate_checksum dm=
|
|
|
+ let rec aux id accum =
|
|
|
+ if (dm.[id] == '.') then accum
|
|
|
+ else
|
|
|
+ let block = (int_of_char dm.[id] - int_of_char '0') in
|
|
|
+ (aux (id+1) ((id * block) + accum))
|
|
|
+ in
|
|
|
+ aux 0 0;;
|
|
|
+
|
|
|
+let solve =
|
|
|
+ let expanded = expand input in
|
|
|
+ calculate_checksum
|
|
|
+ (compact expanded (reverse_compact expanded));
|
|
|
+;;
|
|
|
+
|
|
|
+let () =
|
|
|
+ printf "%s\n" (expand input);
|
|
|
+ (* printf "%s\n" (reverse_compact (expand input)); *)
|
|
|
+ (* printf "%s\n" (compact (expand input) (reverse_compact (expand input))); *)
|
|
|
+ (* printf "Total: %d\n" solve;; *)
|
|
|
+
|