01.sml 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. (* open IntInf; *)
  2. fun read file =
  3. let
  4. val inStream = TextIO.openIn file
  5. in
  6. (* TextIO.inputAll returns a TextIO.vector, which is a string. *)
  7. TextIO.inputAll inStream
  8. end;
  9. val newline_tokenizer = String.tokens (fn c => c = #"\n");
  10. fun sum_lists (nil, nil) = []
  11. | sum_lists (nil, l2) = []
  12. | sum_lists (l1, nil) = []
  13. | sum_lists (alst as (a::arest), blst as (b::brest)) =
  14. (a + b)::sum_lists(arest, brest);
  15. fun string_to_ints str =
  16. map (fn c =>
  17. case c of
  18. #"1" => 1
  19. | #"0" => 0
  20. | _ => raise Fail "unrecognized bit value")
  21. (String.explode str);
  22. fun invert 0 = 1
  23. | invert 1 = 0
  24. | invert _ = raise Fail "unrecognized bit value";
  25. fun invert_list lst = map invert lst;
  26. fun make_list (0, _) = []
  27. | make_list (len, fill) =
  28. fill :: make_list (len - 1, fill);
  29. fun calc_rates lines =
  30. let
  31. fun iter (nil, sum, count) = (sum, count)
  32. | iter (remaining_lines as (line::rest_lines), sum, count) =
  33. let
  34. val ints = string_to_ints line;
  35. val acc = sum_lists (sum, ints);
  36. in
  37. iter (rest_lines, acc, count + 1)
  38. end;
  39. in
  40. let
  41. val zero = make_list (length (String.explode (hd lines)), 0);
  42. val (sums, len) = iter (lines, zero, 0);
  43. val gamma_rate_bits =
  44. map (fn sum => if sum > (len div 2)
  45. then 1
  46. else 0)
  47. sums;
  48. val epsilon_bits = invert_list gamma_rate_bits;
  49. in
  50. (gamma_rate_bits, epsilon_bits)
  51. end
  52. end;
  53. fun int_expt (0, _) = 0
  54. | int_expt (1, _) = 1
  55. | int_expt (base, 0) = 1
  56. | int_expt (base, 1) = base
  57. | int_expt (base, exponent) =
  58. base * int_expt (base, exponent - 1);
  59. fun bit_to_decimal (bit, ind) =
  60. bit * int_expt (2, ind);
  61. fun bits_to_decimal bits =
  62. List.foldli (fn (ind, bit, acc) =>
  63. acc + bit_to_decimal (bit, ind))
  64. 0
  65. (rev bits);
  66. val str = read "input";
  67. val lines = newline_tokenizer str;
  68. val (gamma_rate, epsilon_rate) = calc_rates lines;
  69. val solution = (bits_to_decimal gamma_rate) * (bits_to_decimal epsilon_rate);
  70. solution;