Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::io::{self, Read};
- use regex::Regex;
- fn read_stdin() -> String{
- let mut buffer = String::new();
- io::stdin().read_to_string(&mut buffer).expect("did not recieve anything from stdin");
- return buffer;
- }
- #[derive(Debug, Clone, Hash, PartialEq, Eq)]
- struct Coord{
- x: i64,
- y: i64,
- z: i64
- }
- impl Coord{
- fn add(&self, other: &Coord) -> Coord{
- return Coord{
- x: self.x + other.x,
- y: self.y + other.y,
- z: self.z + other.z
- };
- }
- fn sum_of_absolute_coords(&self) -> i64{
- return self.x.abs() + self.y.abs() + self.z.abs();
- }
- }
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
- struct CBody{
- pos: Coord,
- velocity: Coord
- }
- impl CBody{
- fn new(nx: i64, ny: i64, nz: i64) -> CBody{
- CBody{
- pos: Coord{x: nx, y: ny, z: nz},
- velocity: Coord{x: 0, y: 0, z: 0}
- }
- }
- fn update(&mut self){
- self.pos.x += self.velocity.x;
- self.pos.y += self.velocity.y;
- self.pos.z += self.velocity.z;
- }
- fn total_energy(&self) -> i64{
- return self.pos.sum_of_absolute_coords() * self.velocity.sum_of_absolute_coords();
- }
- }
- fn update_velocities(planets: &mut Vec<CBody>){
- for i in 0..(planets.len()){
- for j in (i + 1)..(planets.len()){
- if planets[i].pos.x < planets[j].pos.x{
- planets[i].velocity.x += 1;
- planets[j].velocity.x -= 1;
- }else if planets[j].pos.x < planets[i].pos.x{
- planets[j].velocity.x += 1;
- planets[i].velocity.x -= 1;
- }
- if planets[i].pos.y < planets[j].pos.y{
- planets[i].velocity.y += 1;
- planets[j].velocity.y -= 1;
- }else if planets[j].pos.y < planets[i].pos.y{
- planets[j].velocity.y += 1;
- planets[i].velocity.y -= 1;
- }
- if planets[i].pos.z < planets[j].pos.z{
- planets[i].velocity.z += 1;
- planets[j].velocity.z -= 1;
- }else if planets[j].pos.z < planets[i].pos.z{
- planets[j].velocity.z += 1;
- planets[i].velocity.z -= 1;
- }
- }
- }
- }
- fn move_planets(planets: &mut Vec<CBody>){
- for i in 0..(planets.len()){
- planets[i].update();
- }
- }
- fn check_loops(planets: &Vec<CBody>, has_looped: &mut Vec<bool>, steps: &usize){
- if !has_looped[0] && planets.iter()
- .filter(
- |p|
- p.velocity.x != 0
- ).count() == 0{
- println!("x looped at {}", steps);
- has_looped[0] = true;
- }
- if !has_looped[1] && planets.iter()
- .filter(
- |p|
- p.velocity.y != 0
- ).count() == 0{
- println!("y looped at {}", steps);
- has_looped[1] = true;
- }
- if !has_looped[2] && planets.iter()
- .filter(
- |p|
- p.velocity.z != 0
- ).count() == 0{
- println!("z looped at {}", steps);
- has_looped[2] = true;
- }
- }
- fn simulate_until(mut planets: Vec<CBody>, count: usize) -> Vec<CBody> {
- let mut steps: usize = 0;
- loop{
- update_velocities(&mut planets);
- move_planets(&mut planets);
- steps += 1;
- if steps % (count / 10) == 0{
- println!("{}", steps);
- }
- if steps == count{
- break;
- }
- }
- return planets;
- }
- fn simulate(planets: Vec<CBody>) -> Vec<CBody>{
- let mut new_planets = planets.clone();
- let mut steps: usize = 0;
- let mut has_looped: Vec<bool> = vec![false,false,false];
- loop{
- update_velocities(&mut new_planets);
- move_planets(&mut new_planets);
- steps += 1;
- check_loops(&new_planets, &mut has_looped, &steps);
- if has_looped.iter().filter(|b| !(**b)).count() == 0{
- return new_planets;
- }
- }
- }
- fn energy(planets: &Vec<CBody>) -> i64{
- return
- planets
- .iter()
- .map(|p|
- {
- //dbg!(&p.pos);
- //dbg!(&p.velocity);
- p.total_energy()
- }
- ).sum();
- }
- fn main(){
- let pattern = Regex::new(r"<x=(-?\d+), y=(-?\d+), z=(-?\d+)>").unwrap();
- let io_input: String = read_stdin();
- let planets: Vec<CBody> =
- pattern
- .captures_iter(&io_input)
- .map(|g|
- CBody::new(
- g[1].parse().unwrap(),
- g[2].parse().unwrap(),
- g[3].parse().unwrap()
- )
- ).collect();
- //let after_sim = simulate(planets);
- let after_sim = simulate_until(planets, 1000000000);
- println!("{:?}", after_sim);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement