Guest User

Untitled

a guest
Dec 18th, 2018
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.18 KB | None | 0 0
  1. <?php
  2.  
  3. function generate_character($x, $y, $type, $att)
  4. {
  5. $char = new StdClass();
  6. $char->x = $x;
  7. $char->y = $y;
  8. $char->health = 200;
  9. $char->attack = $type==='E'?$att:3;
  10. $char->type = $type;
  11. $char->char_key = 0;
  12. $char->pos_value = 0;
  13.  
  14. return $char;
  15. }
  16.  
  17. function find_path($sx, $sy, $ex, $ey)
  18. {
  19. global $dist, $characters, $ymax;
  20.  
  21. $start = $sy * $ymax + $sx;
  22. $end = $ey * $ymax + $ex;
  23.  
  24. $search = array();
  25. $question = array();
  26. foreach (array_keys($dist) as $val)
  27. {
  28. $question[$val] = PHP_INT_MAX;
  29. }
  30. $question[$start] = 0;
  31.  
  32.  
  33. while (!empty($question)) {
  34. $min = array_search(min($question), $question);
  35. if ($min == $end) break;
  36.  
  37. $x = $min % $ymax;
  38. $y = (int)($min / $ymax);
  39.  
  40. $ignore = false;
  41. foreach ($characters as $character) {
  42. if (!($character->x == $sx && $character->y == $sy) && !($character->x == $ex && $character->y == $ey) && $character->x == $x && $character->y == $y) {
  43. $ignore = true;
  44. break;
  45. }
  46. }
  47.  
  48. if (!$ignore) {
  49. foreach ($dist[$min] as $key => $val) {
  50.  
  51. if (!empty($question[$key]) && $question[$min] + $val < $question[$key]) {
  52. $question[$key] = $question[$min] + $val;
  53. $search[$key] = array($min, $question[$key]);
  54. }
  55. }
  56. }
  57. unset($question[$min]);
  58. }
  59.  
  60. $path = array();
  61.  
  62.  
  63. if (!array_key_exists($end, $search)) {
  64. return false;
  65. }
  66. while ($end != $start) {
  67. $path[] = $end;
  68. $end = $search[$end][0];
  69. }
  70. $path[] = $start;
  71. $path = array_reverse($path);
  72.  
  73. return $path;
  74. }
  75.  
  76. function sort_on_position($a, $b)
  77. {
  78. global $ymax;
  79.  
  80. $ax = $a->x;
  81. $ay = $a->y;
  82. $apos = $ay * $ymax + $ax;
  83.  
  84. $bx = $b->x;
  85. $by = $b->y;
  86. $bpos = $by * $ymax + $bx;
  87.  
  88. if ($apos === $bpos) return 0;
  89.  
  90. return $apos > $bpos ? 1 : -1;
  91.  
  92. }
  93.  
  94. function print_grid($grid, $characters)
  95. {
  96. for ($y = 0; $y < count($grid); $y++) {
  97. for ($x = 0; $x < count($grid[$y]); $x++) {
  98. $symbol = $grid[$y][$x];
  99. foreach ($characters as $character) {
  100. if ($character->x === $x && $character->y === $y) {
  101. $symbol = $character->type;
  102. }
  103. }
  104. echo $symbol;
  105. }
  106. echo PHP_EOL;
  107. }
  108. }
  109.  
  110. function get_other_characters($characters, $type)
  111. {
  112. $search_type = $type === 'E' ? 'G' : 'E';
  113. $result = array();
  114. foreach ($characters as $char_key => $character) {
  115. if ($character->type === $search_type) {
  116. $character->char_key = $char_key;
  117. $result[] = $character;
  118. }
  119. }
  120.  
  121. return $result;
  122. }
  123.  
  124. function stop_battle($characters)
  125. {
  126. $types = array();
  127. foreach ($characters as $character) {
  128. $types[] = $character->type;
  129. }
  130. $types = array_unique($types);
  131.  
  132. return count($types) === 1;
  133. }
  134.  
  135. function get_sum($characters)
  136. {
  137. $sum = 0;
  138. foreach ($characters as $character) {
  139. $sum += $character->health;
  140. }
  141.  
  142. return $sum;
  143. }
  144.  
  145. function get_closest($characters, $character)
  146. {
  147. global $ymax;
  148. $type = $character->type;
  149. $others = get_other_characters($characters, $type);
  150. $closest = array();
  151.  
  152. foreach ($others as $other) {
  153. $path = find_path($character->x, $character->y, $other->x, $other->y);
  154.  
  155. if ($path) {
  156. $count = count($closest);
  157. if ($count === 0) {
  158. $closest[0] = $other;
  159. $closest[0]->path = $path;
  160. $closest[0]->pos_value = $closest[0]->y * $ymax + $closest[0]->x;
  161. } else {
  162. $cd = count($path);
  163. $cc = count($closest[0]->path);
  164. if ($cc > $cd) {
  165. $closest = array();
  166. $closest[0] = $other;
  167. $closest[0]->path = $path;
  168. $closest[0]->pos_value = $closest[0]->y * $ymax + $closest[0]->x;
  169. } elseif ($cc === $cd) {
  170. $closest[$count] = $other;
  171. $closest[$count]->path = $path;
  172. $closest[$count]->pos_value = $closest[$count]->y * $ymax + $closest[$count]->x;
  173. }
  174. }
  175. }
  176. }
  177. return $closest;
  178. }
  179.  
  180. function move_character(&$characters, &$character)
  181. {
  182. global $ymax;
  183.  
  184. $closest = get_closest($characters, $character);
  185. $closest_count = count($closest);
  186.  
  187. if ($closest_count > 0) {
  188. $current_pos_value = $character->y * $ymax + $character->x;
  189. $found_closest = $closest[0];
  190.  
  191. if (count($closest[0]->path) > 2) {
  192. for ($i = 0; $i < $closest_count; $i++) {
  193. if ($closest[$i]->pos_value > $current_pos_value && abs($closest[$i]->pos_value - $current_pos_value) < abs($found_closest->pos_value - $current_pos_value)) {
  194. $found_closest = $closest[$i];
  195. }
  196. }
  197.  
  198. $move_to = $found_closest->path[1];
  199. $mx = $move_to % $ymax;
  200. $my = (int)($move_to / $ymax);
  201.  
  202. $character->x = $mx;
  203. $character->y = $my;
  204. }
  205. }
  206. }
  207.  
  208. function attack_character(&$characters, &$character)
  209. {
  210. global $ymax, $battle;
  211.  
  212. $closest = get_closest($characters, $character);
  213. $closest_count = count($closest);
  214.  
  215. if ($closest_count > 0) {
  216. $current_pos_value = $character->y * $ymax + $character->x;
  217. $found_closest = $closest[0];
  218.  
  219. if (count($closest[0]->path) == 2) {
  220. for ($i = 0; $i < $closest_count; $i++) {
  221. if ($closest[$i]->health < $found_closest->health || ($closest[$i]->health === $found_closest->health && $closest[$i]->pos_value > $current_pos_value && abs($closest[$i]->pos_value - $current_pos_value) < abs($found_closest->pos_value - $current_pos_value))) {
  222. $found_closest = $closest[$i];
  223. }
  224. }
  225.  
  226. $characters[$found_closest->char_key]->health -= $character->attack;
  227.  
  228. if ($characters[$found_closest->char_key]->health <= 0) {
  229. unset($characters[$found_closest->char_key]);
  230. }
  231. }
  232. }
  233. }
  234.  
  235. for($att = 20; $att < 100 ; $att++) {
  236.  
  237. $start_elves = 0;
  238.  
  239. $input = file('input.txt');
  240.  
  241. $grid = array();
  242.  
  243. foreach ($input as $line) {
  244. $grid[] = str_split(trim($line));
  245. }
  246.  
  247. $characters = array();
  248.  
  249. $distance = array();
  250.  
  251. $ymax = count($grid);
  252. $xmax = count($grid[0]);
  253.  
  254. for ($y = 0; $y < $ymax; $y++) {
  255. $distance[$y] = array();
  256. for ($x = 0; $x < $xmax; $x++) {
  257. if ($grid[$y][$x] === 'E') {
  258. $characters[] = generate_character($x, $y, 'E', $att);
  259. $grid[$y][$x] = '.';
  260. $start_elves++;
  261. }
  262. if ($grid[$y][$x] === 'G') {
  263. $characters[] = generate_character($x, $y, 'G', $att);
  264. $grid[$y][$x] = '.';
  265. }
  266. if ($grid[$y][$x] === '.') {
  267. $distance[$y][$x] = 1;
  268. }
  269. }
  270. }
  271.  
  272. $dist = array();
  273.  
  274. for ($y = 0; $y < $ymax; $y++) {
  275. for ($x = 0; $x < $xmax; $x++) {
  276. if (isset($distance[$y][$x])) {
  277. $dpos = $y * $xmax + $x;
  278. $dist[$dpos] = array();
  279. if (isset($distance[$y][$x - 1])) {
  280. $npos = $y * $xmax + $x - 1;
  281. $dist[$dpos][$npos] = 1;
  282. }
  283. if (isset($distance[$y][$x + 1])) {
  284. $npos = $y * $xmax + $x + 1;
  285. $dist[$dpos][$npos] = 1;
  286. }
  287. if (isset($distance[$y - 1][$x])) {
  288. $npos = ($y - 1) * $xmax + $x;
  289. $dist[$dpos][$npos] = 1;
  290. }
  291. if (isset($distance[$y + 1][$x])) {
  292. $npos = ($y + 1) * $xmax + $x;
  293. $dist[$dpos][$npos] = 1;
  294. }
  295. }
  296. }
  297. }
  298.  
  299. $battle = true;
  300. $rounds = 0;
  301.  
  302. while ($battle) {
  303. usort($characters, 'sort_on_position');
  304. $round_inc = false;
  305. foreach ($characters as &$character) {
  306. if ($battle) {
  307. move_character($characters, $character);
  308. attack_character($characters, $character);
  309. if (stop_battle($characters)) {
  310. $battle = false;
  311. break;
  312.  
  313. }
  314. }
  315. }
  316. if ($battle) {
  317. $rounds++;
  318. }
  319. }
  320.  
  321. if($characters[0]->type === 'E' && $start_elves === count($characters)) {
  322.  
  323. print_grid($grid, $characters);
  324. echo PHP_EOL;
  325.  
  326. $sum = get_sum($characters);
  327. printf('Sum: %d', $sum);
  328. echo PHP_EOL;
  329. printf('Rounds: %d', $rounds);
  330. echo PHP_EOL;
  331.  
  332. printf('Part 1: %d', $rounds * $sum);
  333. echo PHP_EOL;
  334. exit();
  335. } else {
  336. printf('Not found for %d', $att);
  337. echo PHP_EOL;
  338. }
  339. }
Advertisement
Add Comment
Please, Sign In to add comment