From 24d2d2390b4cc9e8ef13899aca19dc4c0139eb91 Mon Sep 17 00:00:00 2001 From: pebloop Date: Sat, 5 Jul 2025 15:43:41 +0200 Subject: [PATCH] Add ships parser --- src/parser.rs | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 src/parser.rs diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..941ab9d --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,171 @@ +use std::{fs::File, io::Read, path::Path}; + +#[derive(Debug)] +pub enum ParserError { + InvalidShipCount, + InvalidCoordCount, + InvalidCoord, + IO(std::io::Error), +} + +impl From for ParserError { + fn from(value: std::io::Error) -> Self { + ParserError::IO(value) + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Vector2u16 { + x: u16, + y: u16, +} + +impl Vector2u16 { + pub fn new(x: u16, y: u16) -> Self { + Vector2u16 {x: x, y: y} + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Boat { + first_pos: Vector2u16, + last_pos: Vector2u16, +} + +impl Boat { + pub fn new(first_pos: Vector2u16, last_pos: Vector2u16) -> Self { + Boat { first_pos: first_pos, last_pos: last_pos } + } +} + +pub fn parse_file(file_path: &Path) -> Result<[Boat; 4], ParserError> { + let mut file = File::open(file_path)?; + Ok(parse_ships(&mut file)?) +} + +pub fn parse_ships(file: &mut T) -> Result<[Boat; 4], ParserError> { + let mut content = String::new(); + + file.read_to_string(&mut content)?; + let lines: Vec<&str> = content.lines().collect(); + + if lines.len() != 4 { + return Err(ParserError::InvalidShipCount); + } + + let boats = [ + create_ship(lines[0])?, + create_ship(lines[1])?, + create_ship(lines[2])?, + create_ship(lines[3])?, + ]; + + Ok(boats) +} + +fn create_ship(line: &str) -> Result { + let coordinates: Vec<&str> = line.split(":").collect(); + + if coordinates.len() != 2 { + return Err(ParserError::InvalidCoordCount); + } + + + Ok(Boat::new(create_coord(coordinates[0])?, create_coord(coordinates[1])?)) +} + +fn create_coord(coord_str: &str) -> Result { + let mut str_iter = coord_str.chars(); + + let Some(col_c) = str_iter.next() else { + return Err(ParserError::InvalidCoord); + }; + let col = (col_c as u16) - ('A' as u16); + + let Some(row_c) = str_iter.next() else { + return Err(ParserError::InvalidCoord); + }; + let row = (row_c as u16) - ('0' as u16) - 1; + + if col > 7 || row > 7 { + return Err(ParserError::InvalidCoord); + } + + Ok(Vector2u16::new(col, row)) + +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_create_coord() -> Result<(), ParserError> { + let coord1 = create_coord("D5")?; + + assert_eq!(coord1.x, 3); + assert_eq!(coord1.y, 4); + + let coord2 = create_coord("A1")?; + + assert_eq!(coord2.x, 0); + assert_eq!(coord2.y, 0); + + let coord3 = create_coord("H8")?; + + assert_eq!(coord3.x, 7); + assert_eq!(coord3.y, 7); + + Ok(()) + } + + #[test] + fn test_create_install_coord() { + let coord = create_coord("G9"); + + assert!(coord.is_err()); + } + + #[test] + fn test_create_bad_coord() { + let coord = create_coord("bad"); + + assert!(coord.is_err()); + } + + #[test] + fn test_create_ship() -> Result<(), ParserError> { + let ship = create_ship("C4:B1")?; + + assert_eq!(ship.first_pos.x, 2); + assert_eq!(ship.first_pos.y, 3); + assert_eq!(ship.last_pos.x, 1); + assert_eq!(ship.last_pos.y, 0); + Ok(()) + } + + #[test] + fn test_create_bad_ship() { + let ship = create_ship("invalid"); + assert!(ship.is_err()); + + let ship2 = create_ship("C9:B4"); + assert!(ship2.is_err()); + } + + #[test] + fn test_parse_ships() -> Result<(), ParserError> { + let file = b"B4:C2\nD1:F3\nF1:F5\nA1:A2"; + + let ships = parse_ships(&mut &file[..])?; + + assert_eq!(ships[0], Boat::new(Vector2u16::new(1, 3), Vector2u16::new(2, 1))); + assert_eq!(ships[1], Boat::new(Vector2u16::new(3, 0), Vector2u16::new(5, 2))); + assert_eq!(ships[2], Boat::new(Vector2u16::new(5, 0), Vector2u16::new(5, 4))); + assert_eq!(ships[3], Boat::new(Vector2u16::new(0, 0), Vector2u16::new(0, 1))); + + Ok(()) + } + + +} \ No newline at end of file -- 2.49.0 From c6e20024d99d2fb4cc88e0da79b520a411085027 Mon Sep 17 00:00:00 2001 From: pebloop Date: Sat, 5 Jul 2025 15:45:07 +0200 Subject: [PATCH] Format document --- src/parser.rs | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 941ab9d..589f4ef 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -22,7 +22,7 @@ pub struct Vector2u16 { impl Vector2u16 { pub fn new(x: u16, y: u16) -> Self { - Vector2u16 {x: x, y: y} + Vector2u16 { x: x, y: y } } } @@ -34,7 +34,10 @@ pub struct Boat { impl Boat { pub fn new(first_pos: Vector2u16, last_pos: Vector2u16) -> Self { - Boat { first_pos: first_pos, last_pos: last_pos } + Boat { + first_pos: first_pos, + last_pos: last_pos, + } } } @@ -70,8 +73,10 @@ fn create_ship(line: &str) -> Result { return Err(ParserError::InvalidCoordCount); } - - Ok(Boat::new(create_coord(coordinates[0])?, create_coord(coordinates[1])?)) + Ok(Boat::new( + create_coord(coordinates[0])?, + create_coord(coordinates[1])?, + )) } fn create_coord(coord_str: &str) -> Result { @@ -92,7 +97,6 @@ fn create_coord(coord_str: &str) -> Result { } Ok(Vector2u16::new(col, row)) - } #[cfg(test)] @@ -112,7 +116,7 @@ mod tests { assert_eq!(coord2.y, 0); let coord3 = create_coord("H8")?; - + assert_eq!(coord3.x, 7); assert_eq!(coord3.y, 7); @@ -136,7 +140,7 @@ mod tests { #[test] fn test_create_ship() -> Result<(), ParserError> { let ship = create_ship("C4:B1")?; - + assert_eq!(ship.first_pos.x, 2); assert_eq!(ship.first_pos.y, 3); assert_eq!(ship.last_pos.x, 1); @@ -159,13 +163,23 @@ mod tests { let ships = parse_ships(&mut &file[..])?; - assert_eq!(ships[0], Boat::new(Vector2u16::new(1, 3), Vector2u16::new(2, 1))); - assert_eq!(ships[1], Boat::new(Vector2u16::new(3, 0), Vector2u16::new(5, 2))); - assert_eq!(ships[2], Boat::new(Vector2u16::new(5, 0), Vector2u16::new(5, 4))); - assert_eq!(ships[3], Boat::new(Vector2u16::new(0, 0), Vector2u16::new(0, 1))); + assert_eq!( + ships[0], + Boat::new(Vector2u16::new(1, 3), Vector2u16::new(2, 1)) + ); + assert_eq!( + ships[1], + Boat::new(Vector2u16::new(3, 0), Vector2u16::new(5, 2)) + ); + assert_eq!( + ships[2], + Boat::new(Vector2u16::new(5, 0), Vector2u16::new(5, 4)) + ); + assert_eq!( + ships[3], + Boat::new(Vector2u16::new(0, 0), Vector2u16::new(0, 1)) + ); Ok(()) } - - -} \ No newline at end of file +} -- 2.49.0