day 15 solution
parent
8fedd15dc8
commit
adc8c70575
|
@ -0,0 +1,278 @@
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.6.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "day15"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"pretty_env_logger 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.5.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.39"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pretty_env_logger"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-error"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_termios"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termion"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.1.41"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ucd-util"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8-ranges"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wincolor"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
|
||||||
|
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
|
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
||||||
|
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
|
||||||
|
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
|
||||||
|
"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
|
||||||
|
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
|
||||||
|
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
|
||||||
|
"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
|
||||||
|
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
|
||||||
|
"checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9"
|
||||||
|
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
||||||
|
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||||
|
"checksum pretty_env_logger 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8d1e63042e889b85228620629b51c011d380eed2c7e0015f8a644def280c28"
|
||||||
|
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||||
|
"checksum redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a84bcd297b87a545980a2d25a0beb72a1f490c31f0a9fde52fca35bfbb1ceb70"
|
||||||
|
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||||
|
"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
|
||||||
|
"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
|
||||||
|
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
||||||
|
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||||
|
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||||
|
"checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c"
|
||||||
|
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
|
||||||
|
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
|
||||||
|
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||||
|
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
|
||||||
|
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
|
||||||
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
|
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "day15"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Andrew Coleman <penguincoder@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = "0.4"
|
||||||
|
pretty_env_logger = "0.2"
|
|
@ -0,0 +1,32 @@
|
||||||
|
################################
|
||||||
|
##########################.#####
|
||||||
|
##########################.#####
|
||||||
|
##########################.#.###
|
||||||
|
#######################......###
|
||||||
|
#################....#........##
|
||||||
|
##############.##....G......G.##
|
||||||
|
#############..#G...##.........#
|
||||||
|
#############.GG..G..##.......##
|
||||||
|
#############.................##
|
||||||
|
#############G.........G....#.##
|
||||||
|
###########G..........E........#
|
||||||
|
###########...#####............#
|
||||||
|
###########..#######...........#
|
||||||
|
#######.....#########........###
|
||||||
|
#######....G#########.......####
|
||||||
|
##...G.G....#########...#....###
|
||||||
|
#...G..G...G#########.###E...###
|
||||||
|
##.......#..#########.#####..E##
|
||||||
|
#............#######..##########
|
||||||
|
#.GG........G.#####...##########
|
||||||
|
#................E.....#########
|
||||||
|
########..........##.###########
|
||||||
|
#########.....###.....##########
|
||||||
|
##########.E..##......##########
|
||||||
|
#######..#....###.E...##########
|
||||||
|
######.........###.E############
|
||||||
|
######.#..G....##..#############
|
||||||
|
######.....##..##.E#############
|
||||||
|
#######....##.E...E#############
|
||||||
|
######....G#......##############
|
||||||
|
################################
|
|
@ -0,0 +1,364 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
extern crate pretty_env_logger;
|
||||||
|
|
||||||
|
use std::collections::{HashSet, VecDeque};
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
|
|
||||||
|
type MapType = [[char; MAP_SIZE]; MAP_SIZE];
|
||||||
|
const MAP_SIZE: usize = 32;
|
||||||
|
const EMPTY_SPACE: char = '.';
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
struct Player {
|
||||||
|
id: usize,
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
dead: bool,
|
||||||
|
attack: i16,
|
||||||
|
hp: i16,
|
||||||
|
player_type: char,
|
||||||
|
enemy_type: char,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct PlayerVector {
|
||||||
|
weight: usize,
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_enemy_neighbor(player: &Player, players: &Vec<Player>, map: &MapType) -> Option<usize> {
|
||||||
|
let mut hps = [0i16; 4];
|
||||||
|
let mut min_hp = std::i16::MAX;
|
||||||
|
let mut indexes = [0usize; 4];
|
||||||
|
if map[player.x][player.y - 1] == player.enemy_type {
|
||||||
|
let (i, target) = players
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|p| !p.1.dead && p.1.x == player.x && p.1.y == player.y - 1)
|
||||||
|
.expect("could not find the target north");
|
||||||
|
hps[0] = target.hp;
|
||||||
|
indexes[0] = i;
|
||||||
|
if target.hp < min_hp {
|
||||||
|
min_hp = target.hp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if map[player.x - 1][player.y] == player.enemy_type {
|
||||||
|
let (i, target) = players
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|p| !p.1.dead && p.1.x == player.x - 1 && p.1.y == player.y)
|
||||||
|
.expect("could not find the target west");
|
||||||
|
hps[1] = target.hp;
|
||||||
|
indexes[1] = i;
|
||||||
|
if target.hp < min_hp {
|
||||||
|
min_hp = target.hp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if map[player.x + 1][player.y] == player.enemy_type {
|
||||||
|
let (i, target) = players
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|p| !p.1.dead && p.1.x == player.x + 1 && p.1.y == player.y)
|
||||||
|
.expect("could not find the target east");
|
||||||
|
hps[2] = target.hp;
|
||||||
|
indexes[2] = i;
|
||||||
|
if target.hp < min_hp {
|
||||||
|
min_hp = target.hp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if map[player.x][player.y + 1] == player.enemy_type {
|
||||||
|
let (i, target) = players
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|p| !p.1.dead && p.1.x == player.x && p.1.y == player.y + 1)
|
||||||
|
.expect("could not find the target south");
|
||||||
|
hps[3] = target.hp;
|
||||||
|
indexes[3] = i;
|
||||||
|
if target.hp < min_hp {
|
||||||
|
min_hp = target.hp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hps[0] == min_hp {
|
||||||
|
Some(indexes[0])
|
||||||
|
} else if hps[1] == min_hp {
|
||||||
|
Some(indexes[1])
|
||||||
|
} else if hps[2] == min_hp {
|
||||||
|
Some(indexes[2])
|
||||||
|
} else if hps[3] == min_hp {
|
||||||
|
Some(indexes[3])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_next_move(player: &Player, map: &MapType) -> Option<PlayerVector> {
|
||||||
|
match find_enemy(player, map) {
|
||||||
|
Some(target) => {
|
||||||
|
debug!("found target {:?}", target);
|
||||||
|
let best_direction = find_best_direction_to_player(player, map, &target);
|
||||||
|
debug!("best direction {:?}", best_direction);
|
||||||
|
best_direction
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_enemy(player: &Player, map: &MapType) -> Option<PlayerVector> {
|
||||||
|
let mut visited = HashSet::new();
|
||||||
|
let mut queue = VecDeque::new();
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: player.x,
|
||||||
|
y: player.y,
|
||||||
|
weight: 0,
|
||||||
|
});
|
||||||
|
while let Some(coord) = queue.pop_front() {
|
||||||
|
if !visited.insert((coord.x, coord.y)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if map[coord.x][coord.y] == player.enemy_type {
|
||||||
|
return Some(coord);
|
||||||
|
}
|
||||||
|
if coord.weight > 0 {
|
||||||
|
match map[coord.x][coord.y] {
|
||||||
|
'E' => continue,
|
||||||
|
'G' => continue,
|
||||||
|
'#' => continue,
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: coord.x,
|
||||||
|
y: coord.y - 1,
|
||||||
|
weight: coord.weight + 1,
|
||||||
|
});
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: coord.x - 1,
|
||||||
|
y: coord.y,
|
||||||
|
weight: coord.weight + 1,
|
||||||
|
});
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: coord.x + 1,
|
||||||
|
y: coord.y,
|
||||||
|
weight: coord.weight + 1,
|
||||||
|
});
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: coord.x,
|
||||||
|
y: coord.y + 1,
|
||||||
|
weight: coord.weight + 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_best_direction_to_player(
|
||||||
|
player: &Player,
|
||||||
|
map: &MapType,
|
||||||
|
source: &PlayerVector,
|
||||||
|
) -> Option<PlayerVector> {
|
||||||
|
let mut visited = HashSet::new();
|
||||||
|
let mut queue = VecDeque::new();
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: source.x,
|
||||||
|
y: source.y,
|
||||||
|
weight: 0,
|
||||||
|
});
|
||||||
|
visited.insert((source.x, source.y));
|
||||||
|
let mut destinations = HashSet::new();
|
||||||
|
destinations.insert((player.x, player.y - 1));
|
||||||
|
destinations.insert((player.x - 1, player.y));
|
||||||
|
destinations.insert((player.x + 1, player.y));
|
||||||
|
destinations.insert((player.x, player.y + 1));
|
||||||
|
while let Some(coord) = queue.pop_front() {
|
||||||
|
if coord.weight > 0 {
|
||||||
|
if !visited.insert((coord.x, coord.y)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if map[coord.x][coord.y] != EMPTY_SPACE {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// it's weight - 1 because we are only travelling to the neighbor cell
|
||||||
|
if coord.weight == source.weight - 1 && destinations.contains(&(coord.x, coord.y)) {
|
||||||
|
return Some(coord);
|
||||||
|
}
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: coord.x,
|
||||||
|
y: coord.y - 1,
|
||||||
|
weight: coord.weight + 1,
|
||||||
|
});
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: coord.x - 1,
|
||||||
|
y: coord.y,
|
||||||
|
weight: coord.weight + 1,
|
||||||
|
});
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: coord.x + 1,
|
||||||
|
y: coord.y,
|
||||||
|
weight: coord.weight + 1,
|
||||||
|
});
|
||||||
|
queue.push_back(PlayerVector {
|
||||||
|
x: coord.x,
|
||||||
|
y: coord.y + 1,
|
||||||
|
weight: coord.weight + 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_game(mut players: Vec<Player>, map: &mut MapType) -> (i32, usize) {
|
||||||
|
let mut rounds = 0;
|
||||||
|
let player_count = players.len();
|
||||||
|
loop {
|
||||||
|
info!("round {}", rounds);
|
||||||
|
for i in 0..MAP_SIZE {
|
||||||
|
let mut row = String::new();
|
||||||
|
for j in 0..MAP_SIZE {
|
||||||
|
row.push(map[j][i]);
|
||||||
|
}
|
||||||
|
debug!("{}", row);
|
||||||
|
}
|
||||||
|
players.sort_by(|a, b| {
|
||||||
|
if a.y == b.y {
|
||||||
|
a.x.cmp(&b.x)
|
||||||
|
} else {
|
||||||
|
a.y.cmp(&b.y)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut quit_condition = false;
|
||||||
|
for i in 0..player_count {
|
||||||
|
let mut player = players[i];
|
||||||
|
if player.dead {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
debug!("{:?}", player);
|
||||||
|
|
||||||
|
if !players
|
||||||
|
.iter()
|
||||||
|
.any(|p| !p.dead && p.enemy_type == player.player_type)
|
||||||
|
{
|
||||||
|
if i < player_count - 1 {
|
||||||
|
debug!("quitting before end of round");
|
||||||
|
quit_condition = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
match has_enemy_neighbor(&player, &players, map) {
|
||||||
|
Some(_) => {
|
||||||
|
debug!("have enemy neighbor, no moving allowed");
|
||||||
|
()
|
||||||
|
}
|
||||||
|
None => match find_next_move(&player, map) {
|
||||||
|
Some(new_vect) => {
|
||||||
|
debug!("moving");
|
||||||
|
map[player.x][player.y] = EMPTY_SPACE;
|
||||||
|
players[i].x = new_vect.x;
|
||||||
|
players[i].y = new_vect.y;
|
||||||
|
player.x = new_vect.x;
|
||||||
|
player.y = new_vect.y;
|
||||||
|
map[new_vect.x][new_vect.y] = player.player_type;
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
match has_enemy_neighbor(&player, &players, map) {
|
||||||
|
Some(enemy_index) => {
|
||||||
|
debug!("attacking {:?}", players[enemy_index]);
|
||||||
|
players[enemy_index].hp -= player.attack;
|
||||||
|
if players[enemy_index].hp <= 0 {
|
||||||
|
debug!("enemy is dead");
|
||||||
|
players[enemy_index].dead = true;
|
||||||
|
players[enemy_index].hp = 0;
|
||||||
|
map[players[enemy_index].x][players[enemy_index].y] = EMPTY_SPACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
debug!("no enemy neighbors, ending turn");
|
||||||
|
()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if quit_condition {
|
||||||
|
debug!("quitting condition");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rounds += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sum: i32 = players.iter().map(|p| p.hp as i32).sum();
|
||||||
|
info!("sum {} rounds {}", sum, rounds);
|
||||||
|
let elf_count = players.iter().filter(|p| p.player_type == 'E' && !p.dead).count();
|
||||||
|
(sum * rounds, elf_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
pretty_env_logger::init();
|
||||||
|
let lines: Vec<String> = BufReader::new(File::open("input").unwrap())
|
||||||
|
.lines()
|
||||||
|
.map(|line| line.unwrap())
|
||||||
|
.collect();
|
||||||
|
let mut map = [[EMPTY_SPACE; MAP_SIZE]; MAP_SIZE];
|
||||||
|
let mut y = 0;
|
||||||
|
let mut players: Vec<Player> = Vec::with_capacity(20);
|
||||||
|
let mut id = 0;
|
||||||
|
let mut elf_count = 0;
|
||||||
|
for line in lines.iter() {
|
||||||
|
for (x, c) in line.char_indices() {
|
||||||
|
map[x][y] = c;
|
||||||
|
if c == '.' {
|
||||||
|
map[x][y] = EMPTY_SPACE;
|
||||||
|
}
|
||||||
|
if c != 'E' && c != 'G' {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if c == 'E' {
|
||||||
|
elf_count += 1;
|
||||||
|
}
|
||||||
|
let enemy_type = if c == 'E' { 'G' } else { 'E' };
|
||||||
|
id += 1;
|
||||||
|
players.push(Player {
|
||||||
|
id,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
dead: false,
|
||||||
|
attack: 3,
|
||||||
|
hp: 200,
|
||||||
|
player_type: c,
|
||||||
|
enemy_type,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
y += 1;
|
||||||
|
}
|
||||||
|
let (score, _elves_remaining) = play_game(players.clone(), &mut map.clone());
|
||||||
|
println!("score of winning team is {}", score);
|
||||||
|
for i in 4..50 {
|
||||||
|
let new_players: Vec<Player> = players.clone().into_iter().map(|p| {
|
||||||
|
if p.player_type == 'G' {
|
||||||
|
p
|
||||||
|
} else {
|
||||||
|
Player {
|
||||||
|
id: p.id,
|
||||||
|
x: p.x,
|
||||||
|
y: p.y,
|
||||||
|
dead: false,
|
||||||
|
attack: i,
|
||||||
|
hp: 200,
|
||||||
|
player_type: 'E',
|
||||||
|
enemy_type: 'G'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
let (score, elves_remaining) = play_game(new_players, &mut map.clone());
|
||||||
|
if elves_remaining == elf_count {
|
||||||
|
println!("all elves survived with a score of {} with attack of {}", score, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue