fucking hell

This commit is contained in:
Rph :3
2024-08-21 00:10:50 +02:00
commit 5b949b892c
20 changed files with 11469 additions and 0 deletions

200
src/main.rs Normal file
View File

@@ -0,0 +1,200 @@
use anyhow::Result;
use bmp::Image;
use std::{fs::File, io::{self, BufRead, Cursor}};
use rand::prelude::*;
use rayon::prelude::*;
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
struct Radians(f64);
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
struct Degrees(f64);
impl From<Degrees> for Radians {
fn from(value: Degrees) -> Self {
Radians(value.0 * std::f64::consts::PI / 180f64)
}
}
impl Into<f64> for Radians {
fn into(self) -> f64 {
self.0
}
}
impl From<Radians> for Degrees {
fn from(value: Radians) -> Self {
Degrees(value.0 * (180f64 / std::f64::consts::PI))
}
}
impl Into<f64> for Degrees {
fn into(self) -> f64 {
self.0
}
}
#[derive(PartialEq, Clone, Debug)]
struct Location {
lat: Radians,
lon: Radians,
}
impl From<(Degrees, Degrees)> for Location {
fn from(value: (Degrees, Degrees)) -> Self {
Location {
lat: value.0.into(),
lon: value.1.into()
}
}
}
const IMG_NORTH_BORDER: Radians = Radians(0.9570757299); // Degrees(54.8364);
const IMG_WEST_BORDER: Radians = Radians(0.2464911049); // Degrees(14.1229);
const IMG_SOUTH_BORDER: Radians = Radians(0.8552532214); // Degrees(49.0024);
const IMG_EAST_BORDER: Radians = Radians(0.4214184745); // Degrees(24.1455);
const EPSILON: f64 = 0.00001f64;
struct ImageMeta {
image: Image,
horizontal_scale: f64,
vertical_scale: f64
}
#[inline(always)]
fn gcd(a: &Location, b: &Location) -> f64 {
return f64::acos(
f64::sin(a.lat.into())*f64::sin(b.lat.into()) +
f64::cos(a.lat.into())*f64::cos(b.lat.into())*f64::cos(
f64::abs(a.lon.0 - b.lon.0)
)
)
}
fn dist(location: &Location, shops: &Vec<Location>) -> f64 {
shops.into_iter().map(|a| {
gcd(a, &location)
}).min_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Greater)).unwrap()
}
fn in_poland(
location: &Location,
im: &ImageMeta,
) -> bool {
if location.lat < IMG_SOUTH_BORDER ||
location.lat >= IMG_NORTH_BORDER ||
location.lon < IMG_WEST_BORDER ||
location.lon >= IMG_EAST_BORDER {
return false
}
let offlat = location.lat.0 - IMG_SOUTH_BORDER.0;
let offlon = location.lon.0 - IMG_WEST_BORDER.0;
let ppos: (f64, f64) = (offlon * im.horizontal_scale, offlat * im.vertical_scale);
let ppos = (ppos.0 as u32, im.image.get_height() - (ppos.1 as u32) - 1);
return im.image.get_pixel(ppos.0, ppos.1) == bmp::consts::BLACK;
}
fn start_point(
im: &ImageMeta
) -> Location {
loop {
let loc = Location {
lat: Radians(rand::thread_rng().gen_range(IMG_SOUTH_BORDER.0 .. IMG_NORTH_BORDER.0)),
lon: Radians(rand::thread_rng().gen_range(IMG_WEST_BORDER.0 .. IMG_EAST_BORDER.0) )
};
if in_poland(&loc, im) {
return loc;
}
}
}
fn get_next_point(curr: Location, im: &ImageMeta, shops: &Vec<Location>) -> (f64, Location) {
[
Location {lat: Radians(curr.lat.0 + EPSILON), lon: Radians(curr.lon.0)},
Location {lat: Radians(curr.lat.0 - EPSILON), lon: Radians(curr.lon.0)},
Location {lat: Radians(curr.lat.0), lon: Radians(curr.lon.0 + EPSILON)},
Location {lat: Radians(curr.lat.0), lon: Radians(curr.lon.0 - EPSILON)},
Location {lat: Radians(curr.lat.0 + EPSILON), lon: Radians(curr.lon.0 + EPSILON)},
Location {lat: Radians(curr.lat.0 + EPSILON), lon: Radians(curr.lon.0 - EPSILON)},
Location {lat: Radians(curr.lat.0 - EPSILON), lon: Radians(curr.lon.0 - EPSILON)},
Location {lat: Radians(curr.lat.0 - EPSILON), lon: Radians(curr.lon.0 + EPSILON)},
curr
].into_iter().filter(|loc| {
in_poland(loc, im)
}).map(|loc| {
(dist(&loc, shops), loc)
}).max_by(|x, y| {
x.0.partial_cmp(&y.0).unwrap()
}).unwrap()
}
fn find_local_best(start: Location, im: &ImageMeta, shops: &Vec<Location>) -> (f64, Location) {
let mut curr = start;
loop {
let next = get_next_point(curr.clone(), im, shops);
if curr == next.1 {
return next;
}
curr = next.1;
}
}
fn search(im: &ImageMeta, shops: &Vec<Location>) -> (Location, f64) {
let mut best_dist = 0f64;
let mut best_point = Location {lat: Radians(0f64), lon: Radians(0f64)};
for iter in 0..3000 {
let start = start_point(im);
let local = find_local_best(start, im, shops);
if local.0 > best_dist {
best_dist = local.0;
best_point = local.1.clone();
println!("At iter {}, new best", iter);
}
}
return (best_point, best_dist);
}
fn main() -> Result<()> {
let file = File::open("./pos.txt")?;
let mut frog_shops: Vec<Location> = Vec::with_capacity(10778);
for line in io::BufReader::new(file).lines() {
let line = line?;
let numbers: Vec<f64> = line.split(" ").map(str::parse::<f64>).map(Result::unwrap).collect();
frog_shops.push(Location {
lat: Degrees(numbers[0]).into(),
lon: Degrees(numbers[1]).into()
});
}
let poland = include_bytes!("../poland.bmp");
let mut cursor = Cursor::new(poland);
let img = bmp::from_reader(&mut cursor)?;
// println!("{:?}", img);
// println!("{:?}", dist((
// radians!(52f64), radians!(19f64)
// ), &frog_shops));
// println!("{:?}", in_poland((radians!(52f64), radians!(19f64)), &img, p_horiz_scale, p_verti_scale));
// println!("{:?}", degrees_but_tuple!(start_point(&img, p_horiz_scale, p_verti_scale)));
// println!("{:?}", degrees_but_tuple!(find_local_best(
// (radians!(52f64), radians!(19f64)), &img, p_horiz_scale, p_verti_scale, &frog_shops
// )));
let imagemeta = ImageMeta {
horizontal_scale: (img.get_width() as f64) / (IMG_EAST_BORDER.0 - IMG_WEST_BORDER.0),
vertical_scale: (img.get_height() as f64) / (IMG_NORTH_BORDER.0 - IMG_SOUTH_BORDER.0),
image: img
};
// let result = (0..100)
// .into_iter()
// .into_par_iter()
// .map(|_| search(&imagemeta, &frog_shops))
// .max_by(|a, b| {
// a.1.partial_cmp(&b.1).unwrap()
// }).unwrap();
let result = search(&imagemeta, &frog_shops);
let best_point: (Degrees, Degrees) = (result.0.lat.into(), result.0.lon.into());
println!("Found best point at ({}, {}); Distance is {}", best_point.0.0, best_point.1.0, result.1);
Ok(())
}