main.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. function read(done) {
  2. require("fs").readFile('./input', 'utf8', (err, data) => {
  3. var map = new Map(),
  4. line = 0;
  5. data.split("\n").forEach((l) => {
  6. if (l && l.length) {
  7. while (true) {
  8. var reg = /[\^><v]/.exec(l);
  9. if (!reg)
  10. break;
  11. if (reg[0] == ">" || reg[0] == "<")
  12. l = l.replace(reg[0], "-");
  13. else
  14. l = l.replace(reg[0], "|");
  15. map.carts.push(new Cart(reg.index, line, reg[0]));
  16. }
  17. map.push(l);
  18. ++line;
  19. }
  20. });
  21. done(map);
  22. });
  23. }
  24. function Map() {
  25. this.world = [];
  26. this.carts = [];
  27. }
  28. Map.prototype.show = function() {
  29. var data = [];
  30. this.world.forEach(row => {
  31. var str = "";
  32. row.forEach(c => str += (c == '|' || c == '-' ? ' ' : c));
  33. data.push(str);
  34. });
  35. this.carts.forEach(c => {
  36. if (!data[c.py] || c.px >= data[c.py].length) return;
  37. data[c.py] = data[c.py].substring(0, c.px) +'x' +data[c.py].substring(c.px +1);
  38. });
  39. data.forEach(row => {
  40. console.log(row);
  41. });
  42. for (var i =data[0].length; i > 0; --i)
  43. process.stdout.write('-');
  44. process.stdout.write("\n");
  45. }
  46. Map.prototype.tick = function() {
  47. this.carts.sort((a, b) => {
  48. if (a.py == b.py)
  49. return a.px -b.px;
  50. return a.py -b.py;
  51. });
  52. this.carts.some(c => {
  53. if (c.colided)
  54. return;
  55. c.move(this);
  56. var colide = this.colision(c.px, c.py);
  57. if (colide) {
  58. colide.forEach(c => c.colided = true);
  59. }
  60. });
  61. }
  62. Map.prototype.nbCartAlive = function() {
  63. var live = 0;
  64. this.carts.forEach(c => c.colided ? live : ++live);
  65. return live;
  66. }
  67. Map.prototype.colision = function(px, py) {
  68. var colided = [];
  69. this.carts.forEach(c => {
  70. if (c.px == px && c.py == py && !c.colided)
  71. colided.push(c);
  72. });
  73. return colided.length > 1 ? colided : null;
  74. }
  75. Map.prototype.isCross = function(px, py) {
  76. var c = this.world[py][px];
  77. return c == '/' || c == '\\' || c == '+' ? c : null;
  78. }
  79. Map.prototype.push = function(line) {
  80. var l = [];
  81. for (var i =0, len = line.length; i < len; ++i)
  82. l[i] = line.charAt(i);
  83. this.world.push(l);
  84. }
  85. function Cart(px, py, direction) {
  86. this.px = px;
  87. this.py = py;
  88. this.colided = false;
  89. this.nextTurn = 0;
  90. this.id = px +"x" +py;
  91. switch (direction) {
  92. case '>':
  93. this.direction = [1, 0];
  94. break;
  95. case '<':
  96. this.direction = [-1, 0];
  97. break;
  98. case '^':
  99. this.direction = [0, -1];
  100. break;
  101. case 'v':
  102. this.direction = [0, 1];
  103. break;
  104. }
  105. }
  106. Cart.prototype.move = function(map) {
  107. this.px += this.direction[0];
  108. this.py += this.direction[1];
  109. var cross = map.isCross(this.px, this.py);
  110. if (!cross)
  111. return;
  112. if (cross == '+') {
  113. if (this.nextTurn == 0)
  114. this.direction = [ this.direction[1], -this.direction[0] ];
  115. else if (this.nextTurn == 2)
  116. this.direction = [ -this.direction[1], this.direction[0] ];
  117. this.nextTurn = (this.nextTurn +1) %3;
  118. } else {
  119. var factor = cross == '/' ? -1 : 1;
  120. this.direction = [ this.direction[1] *factor, this.direction[0] *factor ];
  121. }
  122. }
  123. function ex1() {
  124. read(map => {
  125. while (map.nbCartAlive() == map.carts.length)
  126. map.tick();
  127. map.carts.some(c => c.colided ? (console.log(c) || true) : null);
  128. });
  129. }
  130. function ex2() {
  131. read(map => {
  132. while (map.nbCartAlive() > 1)
  133. map.tick();
  134. map.carts.some(c => c.colided ? null : (console.log(c) || true));
  135. });
  136. }
  137. ex1();
  138. ex2();