use bevy::prelude::*; use std::fs::File; use std::io::{BufRead, BufReader}; fn main() { App::build() .add_resource(WindowDescriptor { title: "Advent of Code".to_string(), width: 1920, height: 1080, ..Default::default() }) .add_resource(ClearColor(Color::rgb(0., 0., 0.))) .add_startup_system(setup_camera.system()) .add_startup_system(read_input_file.system()) .add_startup_stage("search") .add_startup_system_to_stage("search", find_unoccupied_seat.system()) .add_startup_stage("metadata") .add_startup_system_to_stage("metadata", add_seat_ids.system()) .add_startup_system_to_stage("metadata", add_seat_sprites.system()) .add_startup_stage("report") .add_startup_system_to_stage("report", print_highest_seat_id.system()) .add_startup_system_to_stage("report", print_my_seat_id.system()) .add_plugins(DefaultPlugins) .run(); } fn setup_camera(mut commands: Commands, mut materials: ResMut>) { commands.spawn(Camera2dComponents { transform: Transform::from_translation(Vec3::new(80. / 2., 1280. / 2., 0.)), ..Default::default() }); commands.insert_resource(Materials { my_seat_material: materials.add(Color::rgb(0., 0., 255.).into()), seat_material: materials.add(Color::rgb(0., 255., 0.).into()), }); } struct Materials { my_seat_material: Handle, seat_material: Handle, } #[derive(PartialEq, Eq)] struct Position { x: u32, y: u32, } struct SeatId(u32); struct MySeat; fn read_input_file(mut commands: Commands) { let f = File::open("./inputs/day_5.txt").unwrap(); for line in BufReader::new(f).lines() { let mut max_y = 128; let mut min_y = 0; let mut max_x = 8; let mut min_x = 0; for c in line.unwrap().trim().chars() { let mid_x = (min_x + max_x) / 2; let mid_y = (min_y + max_y) / 2; match c { 'F' => { max_y = mid_y; } 'B' => { min_y = mid_y; } 'L' => { max_x = mid_x; } 'R' => { min_x = mid_x; } _ => panic!("Unexpected character {}", c), } } assert_eq!(max_y - min_y, 1); assert_eq!(max_x - min_x, 1); commands.spawn((Position { x: min_x, y: min_y },)); } } fn find_unoccupied_seat(mut commands: Commands, seats: Query<&Position>) { for y in 1..127 { for x in 0..8 { let potential_position = Position { x, y }; let required_left = if x == 0 { Position { x: 7, y: y - 1 } } else { Position { x: x - 1, y } }; let required_right = if x == 7 { Position { x: 0, y: y + 1 } } else { Position { x: x + 1, y } }; let required_surrounds = [required_left, required_right]; if !seats.iter().any(|p| p == &potential_position) { if required_surrounds .iter() .all(|required| seats.iter().any(|p| p == required)) { commands.spawn((MySeat, potential_position)); } } } } } fn add_seat_ids(mut commands: Commands, seats: Query<(Entity, &Position)>) { for (entity, position) in seats.iter() { let seat_id = position.y * 8 + position.x; commands.insert_one(entity, SeatId(seat_id)); } } fn add_seat_sprites( mut commands: Commands, materials: Res, seats: Query<(Entity, &Position, Option<&MySeat>)>, ) { for (entity, position, my_seat) in seats.iter() { commands.insert( entity, SpriteComponents { sprite: Sprite::new(Vec2::new(10., 10.)), material: if my_seat.is_some() { materials.my_seat_material.clone() } else { materials.seat_material.clone() }, transform: Transform::from_translation(Vec3::new( position.x as f32 * 10., position.y as f32 * 10., 0., )), ..Default::default() }, ); } } fn print_highest_seat_id(seats: Query<&SeatId>) { let max = seats.iter().map(|s| s.0).max(); println!("Max seat id: {:?}", max); } fn print_my_seat_id(seats: Query>) { for seat_id in seats.iter() { println!("My seat id: {}", seat_id.0); } }