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
|
||||
|
||||
[[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"
|
||||
|
|
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…
Reference in a new issue