2_2.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { deepClone, loadInput, numericAscSort, strToInt } from "../common.js";
  2. /** junk variable to hold junk */
  3. let _;
  4. // const input = loadInput("./2/test.input", parseInput, true);
  5. const input = loadInput(2, parseInput);
  6. solve(input);
  7. /**
  8. * @param {string} inputData
  9. * @returns {number[]}
  10. */
  11. function parseInput(inputData) {
  12. const reports = inputData.split(/\n/).map((report) => report.split(" ").map(strToInt));
  13. return reports;
  14. }
  15. /**
  16. * @param {number[][]} parsedInput
  17. */
  18. function solve(parsedInput) {
  19. let safeReports = 0;
  20. for(const report of parsedInput) {
  21. let [isSafe, unsafeIndex] = isReportSafe(report);
  22. // If the report isn't safe, try removing the first unsafe value, and check again
  23. if(!isSafe) {
  24. console.warn("Report wasn't safe. Checking other variations");
  25. // Clone the report so we don't affect the original array
  26. let reportClone = deepClone(report);
  27. // Remove the potentially unsafe index
  28. reportClone.splice(unsafeIndex, 1);
  29. console.warn("Trying modified report: ", reportClone);
  30. // Test its safety
  31. [isSafe, _] = isReportSafe(reportClone);
  32. // If that one is still unsafe, try removing the value to the right of the unsafe index, and try again
  33. if(!isSafe) {
  34. reportClone = deepClone(report);
  35. reportClone.splice(unsafeIndex + 1, 1);
  36. console.warn("Trying modified report: ", reportClone);
  37. [isSafe, _] = isReportSafe(reportClone);
  38. }
  39. console.log();
  40. }
  41. if(isSafe) { safeReports++; }
  42. }
  43. // Not: v420, v424, !435, ^500
  44. console.log("Safe Reports:", safeReports);
  45. }
  46. /**
  47. * Check if a given report is safe
  48. *
  49. * If the report is deemed unsafe, the first unsafe index will be returned along with
  50. * the safe boolean.
  51. *
  52. * @param {number[]} report The report to check
  53. *
  54. * @returns {array} A two-index array containing a boolean of whether the report is safe or not,
  55. * and the index of the unsafe value if
  56. */
  57. function isReportSafe(report) {
  58. let currDirection = 0;
  59. let lastDirection = 0;
  60. /**
  61. * Whether or not the report is safe
  62. *
  63. * Report is only safe when the data is sorted in one direction, and
  64. * each value is no less than 1 value away, and no more than 3 values
  65. * away from each other.
  66. *
  67. * e.g.
  68. * ```
  69. * 1,2,3,4,5 safe
  70. * 5,4,3,2,1 safe
  71. * 1,2,3,2,1 unsafe
  72. * 1,2,4,5,6 safe
  73. * 1,2,7,8,9 unsafe
  74. * ```
  75. */
  76. let safe = false;
  77. let unsafeLevel = null;
  78. // Safety check written this way to make troubleshooting easier
  79. for(let i = 0; i < report.length - 1; i++) {
  80. currDirection = numericAscSort(report[i], report[i + 1]);
  81. const difference = Math.abs(report[i] - report[i + 1]);
  82. // Check if the direction has changed, but skip the first round
  83. // Also catches if there were no differences between the two numbers
  84. if(i != 0 && lastDirection != currDirection) {
  85. unsafeLevel = i;
  86. safe = false;
  87. break;
  88. }
  89. // Make sure the difference wasn't too great
  90. else if(difference > 3) {
  91. unsafeLevel = i;
  92. safe = false;
  93. break;
  94. }
  95. else {
  96. safe = true;
  97. }
  98. lastDirection = currDirection;
  99. }
  100. return [safe, unsafeLevel];
  101. }