restructure; add challenge 2 solution
I forgot about atomic commits...
This commit is contained in:
		
					parent
					
						
							
								85a7ee0b8e
							
						
					
				
			
			
				commit
				
					
						bfb7d95aa7
					
				
			
		
					 10 changed files with 207 additions and 64 deletions
				
			
		
							
								
								
									
										16
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										16
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -3,5 +3,19 @@ | ||||||
| version = 3 | version = 3 | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "frzn-challenge" | name = "challenge-1" | ||||||
|  | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "geometry", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "challenge-2" | ||||||
|  | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "geometry", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "geometry" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								Cargo.toml
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								Cargo.toml
									
										
									
									
									
								
							|  | @ -1,6 +1,11 @@ | ||||||
| [package] |  | ||||||
| name = "frzn-challenge" |  | ||||||
| version = "0.1.0" |  | ||||||
| edition = "2021" |  | ||||||
| 
 | 
 | ||||||
| [dependencies] | [workspace] | ||||||
|  | resolver = "2" | ||||||
|  | members = [ | ||||||
|  |     # Common utilities which I may choose to share | ||||||
|  |     "lib/geometry", | ||||||
|  | 
 | ||||||
|  |     # Challenge | ||||||
|  |     "challenges/december-2024/c1", | ||||||
|  |     "challenges/december-2024/c2", | ||||||
|  | ] | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								challenges/december-2024/c1/Cargo.lock
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								challenges/december-2024/c1/Cargo.lock
									
										
									
										generated
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "frzn-challenge" | ||||||
|  | version = "0.1.0" | ||||||
							
								
								
									
										9
									
								
								challenges/december-2024/c1/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								challenges/december-2024/c1/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | [package] | ||||||
|  | name = "challenge-1" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | geometry = {path = "../../../lib/geometry" } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										28
									
								
								challenges/december-2024/c1/src/main.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								challenges/december-2024/c1/src/main.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | use geometry::{read_point, Triangle}; | ||||||
|  | fn main() { | ||||||
|  |     // Read the vertices of the triangle we are calculating the area for.
 | ||||||
|  |     let p1 = read_point("Enter the coordinates for the first vertex of the triangle (x y):"); | ||||||
|  |     let p2 = read_point("Enter the coordinates for the second vertex of the triangle (x y):"); | ||||||
|  |     let p3 = read_point("Enter the coordinates for the third vertex of the triangle (x y):"); | ||||||
|  | 
 | ||||||
|  |     // 'Draw' the triangle.
 | ||||||
|  |     let triangle = Triangle { p1, p2, p3 }; | ||||||
|  | 
 | ||||||
|  |     // Read the point we want to test from user input.
 | ||||||
|  |     // TODO: maybe some kind of input validation/loop would be nice
 | ||||||
|  |     let test_point = read_point("Enter the coordinates for the point to test (x y):"); | ||||||
|  | 
 | ||||||
|  |     // Finally, check if the point is inside the triangle.
 | ||||||
|  |     // TODO: make this a match
 | ||||||
|  |     if triangle.contains_point(&test_point) { | ||||||
|  |         println!( | ||||||
|  |             "The point ({}, {}) lies inside the triangle.", | ||||||
|  |             test_point.x, test_point.y | ||||||
|  |         ); | ||||||
|  |     } else { | ||||||
|  |         println!( | ||||||
|  |             "The point ({}, {}) lies outside the triangle.", | ||||||
|  |             test_point.x, test_point.y | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								challenges/december-2024/c2/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								challenges/december-2024/c2/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | [package] | ||||||
|  | name = "challenge-2" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | geometry = {path = "../../../lib/geometry" } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										24
									
								
								challenges/december-2024/c2/src/main.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								challenges/december-2024/c2/src/main.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | use geometry::{read_point, Triangle}; | ||||||
|  | 
 | ||||||
|  | fn read_triangle(name: &str) -> Triangle { | ||||||
|  |     println!( | ||||||
|  |         "Enter the coordinates for the three vertices of triangle {}:", | ||||||
|  |         name | ||||||
|  |     ); | ||||||
|  |     let p1 = read_point("First vertex (x y):"); | ||||||
|  |     let p2 = read_point("Second vertex (x y):"); | ||||||
|  |     let p3 = read_point("Third vertex (x y):"); | ||||||
|  | 
 | ||||||
|  |     Triangle { p1, p2, p3 } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  |     let triangle1 = read_triangle("1"); | ||||||
|  |     let triangle2 = read_triangle("2"); | ||||||
|  | 
 | ||||||
|  |     if triangle1.overlaps(&triangle2) { | ||||||
|  |         println!("The two triangles overlap."); | ||||||
|  |     } else { | ||||||
|  |         println!("The two triangles do not overlap."); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										4
									
								
								lib/geometry/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								lib/geometry/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | [package] | ||||||
|  | name = "geometry" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
							
								
								
									
										101
									
								
								lib/geometry/src/lib.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								lib/geometry/src/lib.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,101 @@ | ||||||
|  | use std::io; | ||||||
|  | 
 | ||||||
|  | // 'Point' struct represents a 2D point
 | ||||||
|  | // with X and Y coordinates.
 | ||||||
|  | #[derive(Debug, Clone)] | ||||||
|  | pub struct Point { | ||||||
|  |     pub x: f64, | ||||||
|  |     pub y: f64, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // This is a triangle.
 | ||||||
|  | // No seriously, it is.
 | ||||||
|  | #[derive(Debug, Clone)] | ||||||
|  | pub struct Triangle { | ||||||
|  |     pub p1: Point, | ||||||
|  |     pub p2: Point, | ||||||
|  |     pub p3: Point, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Triangle { | ||||||
|  |     // Calculate the area of the triangle
 | ||||||
|  |     fn area(&self) -> f64 { | ||||||
|  |         ((self.p1.x * (self.p2.y - self.p3.y) | ||||||
|  |             + self.p2.x * (self.p3.y - self.p1.y) | ||||||
|  |             + self.p3.x * (self.p1.y - self.p2.y)) | ||||||
|  |             / 2.0) | ||||||
|  |             .abs() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Check if a given point lies within the triangle
 | ||||||
|  |     pub fn contains_point(&self, point: &Point) -> bool { | ||||||
|  |         let area_total = self.area(); | ||||||
|  |         let area1 = Triangle { | ||||||
|  |             p1: point.clone(), | ||||||
|  |             p2: self.p2.clone(), | ||||||
|  |             p3: self.p3.clone(), | ||||||
|  |         } | ||||||
|  |         .area(); | ||||||
|  |         let area2 = Triangle { | ||||||
|  |             p1: self.p1.clone(), | ||||||
|  |             p2: point.clone(), | ||||||
|  |             p3: self.p3.clone(), | ||||||
|  |         } | ||||||
|  |         .area(); | ||||||
|  |         let area3 = Triangle { | ||||||
|  |             p1: self.p1.clone(), | ||||||
|  |             p2: self.p2.clone(), | ||||||
|  |             p3: point.clone(), | ||||||
|  |         } | ||||||
|  |         .area(); | ||||||
|  | 
 | ||||||
|  |         // Check if the sum of sub-areas equals the total area
 | ||||||
|  |         // There is a small treshold of tolerance.
 | ||||||
|  |         (area1 + area2 + area3 - area_total).abs() < 1e-9 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Check if a given triangle overlaps with another
 | ||||||
|  |     // and return true if it does.
 | ||||||
|  |     pub fn overlaps(&self, other: &Triangle) -> bool { | ||||||
|  |         // if any point of `self` lies inside `other`
 | ||||||
|  |         let self_points = [&self.p1, &self.p2, &self.p3]; | ||||||
|  |         for point in self_points { | ||||||
|  |             if other.contains_point(point) { | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // if any point of `other` lies inside `self`
 | ||||||
|  |         let other_points = [&other.p1, &other.p2, &other.p3]; | ||||||
|  |         for point in other_points { | ||||||
|  |             if self.contains_point(point) { | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // No overlap :(
 | ||||||
|  |         false | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Read a point from user input
 | ||||||
|  | // This should be generic enough to reuse.
 | ||||||
|  | pub fn read_point(prompt: &str) -> Point { | ||||||
|  |     println!("{}", prompt); | ||||||
|  |     let mut input = String::new(); | ||||||
|  |     io::stdin().read_line(&mut input).unwrap(); | ||||||
|  |     let coords: Vec<f64> = input | ||||||
|  |         .trim() | ||||||
|  |         .split_whitespace() | ||||||
|  |         .filter_map(|x| x.parse::<f64>().ok()) | ||||||
|  |         .collect(); | ||||||
|  | 
 | ||||||
|  |     if coords.len() != 2 { | ||||||
|  |         panic!("Invalid input: expected two numbers for the point coordinates"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Point { | ||||||
|  |         x: coords[0], | ||||||
|  |         y: coords[1], | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										58
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										58
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -1,58 +0,0 @@ | ||||||
| use std::io; |  | ||||||
| 
 |  | ||||||
| fn triangle_area(x1: f64, y1: f64, x2: f64, y2: f64, x3: f64, y3: f64) -> f64 { |  | ||||||
|     ((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2.0).abs() |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // We use the barycentric coordinate method to decide whether
 |  | ||||||
| // given point lies within the triangle. It took me more than
 |  | ||||||
| // I would like to admit to remember that name.
 |  | ||||||
| fn main() { |  | ||||||
|     let mut input = String::new(); |  | ||||||
| 
 |  | ||||||
|     println!("Enter the coordinates for the triangle's vertices (x1 y1 x2 y2 x3 y3):"); |  | ||||||
|     io::stdin().read_line(&mut input).unwrap(); |  | ||||||
|     let coords: Vec<f64> = input |  | ||||||
|         .trim() |  | ||||||
|         .split_whitespace() |  | ||||||
|         .filter_map(|x| x.parse::<f64>().ok()) |  | ||||||
|         .collect(); |  | ||||||
| 
 |  | ||||||
|     if coords.len() != 6 { |  | ||||||
|         println!("Invalid input: expected 6 numbers for the triangle's vertices."); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     let (x1, y1, x2, y2, x3, y3) = ( |  | ||||||
|         coords[0], coords[1], coords[2], coords[3], coords[4], coords[5], |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     input.clear(); |  | ||||||
|     println!("Enter the coordinates for the point to test (px py):"); |  | ||||||
|     io::stdin().read_line(&mut input).unwrap(); // I'm getting executed for this unwrap
 |  | ||||||
|     let point: Vec<f64> = input |  | ||||||
|         .trim() |  | ||||||
|         .split_whitespace() |  | ||||||
|         .filter_map(|x| x.parse::<f64>().ok()) |  | ||||||
|         .collect(); |  | ||||||
| 
 |  | ||||||
|     if point.len() != 2 { |  | ||||||
|         println!("Invalid input: expected 2 numbers for the point's coordinates."); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     let (px, py) = (point[0], point[1]); |  | ||||||
| 
 |  | ||||||
|     // calculate areas
 |  | ||||||
|     let total_area = triangle_area(x1, y1, x2, y2, x3, y3); |  | ||||||
|     let area1 = triangle_area(px, py, x2, y2, x3, y3); |  | ||||||
|     let area2 = triangle_area(x1, y1, px, py, x3, y3); |  | ||||||
|     let area3 = triangle_area(x1, y1, x2, y2, px, py); |  | ||||||
| 
 |  | ||||||
|     // check if the sum of the smaller areas matches the total area
 |  | ||||||
|     if (area1 + area2 + area3 - total_area).abs() < 1e-9 { |  | ||||||
|         println!("The point ({}, {}) lies inside the triangle.", px, py); |  | ||||||
|     } else { |  | ||||||
|         println!("The point ({}, {}) lies outside the triangle.", px, py); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue