Skip to content

Commit

Permalink
fix(backend): fix invalid path marked as solution
Browse files Browse the repository at this point in the history
  • Loading branch information
iagorrr committed Dec 1, 2024
1 parent b32e073 commit b57a83b
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 20 deletions.
29 changes: 25 additions & 4 deletions backend/api/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod game;
use game::GameSchema;
use solver::Coordinate;

mod solver;
use solver::{is_solved, Solution};

use actix_web::{
get,
Expand All @@ -19,15 +21,34 @@ async fn solver_endpoint(data: web::Json<GameSchema>) -> impl Responder {
};
}

#[get("/is_solved")]
async fn is_solvable_endpoint(game: web::Json<GameSchema>) -> impl Responder {
return HttpResponse::Ok().json(is_solved(
&game.0.grid,
Coordinate {
x: game.initial_x,
y: game.initial_y,
},
Coordinate {
x: game.0.target_x,
y: game.0.target_y,
},
));
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
let backend_api_port: u16 = match env::var("BACKEND_API_PORT") {
Ok(val) => val.parse::<u16>().unwrap(),
Err(_e) => 8086,
};

HttpServer::new(|| App::new().service(solver_endpoint))
.bind(("0.0.0.0", backend_api_port))?
.run()
.await
HttpServer::new(|| {
App::new()
.service(solver_endpoint)
.service(is_solvable_endpoint)
})
.bind(("0.0.0.0", backend_api_port))?
.run()
.await
}
132 changes: 116 additions & 16 deletions backend/api/src/solver.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use serde::{Deserialize, Serialize};

use crate::game::can_connect;
use crate::game::CellGrid;
use crate::game::GameSchema;
use std::collections::BinaryHeap;
use std::collections::HashSet;
use std::collections::VecDeque;

// State to be added at the A* min_heap
// TODO: Don't use the the negative of distance and actually implement a Ord properly
Expand All @@ -21,8 +24,6 @@ fn calc_manhattan_negative_distance(u_x: i32, u_y: i32, v_x: i32, v_y: i32) -> i
// TODO: this can be done with traits right ?
fn get_state(game: &GameSchema) -> State {
State {
//manhattan_negative_distance: -((game.initial_x - game.target_x).abs()
// + (game.initial_y - game.target_y).abs()),
manhattan_negative_distance: calc_manhattan_negative_distance(
game.initial_x,
game.initial_y,
Expand All @@ -39,12 +40,30 @@ fn get_state(game: &GameSchema) -> State {
const DELTA_X: [i32; 5] = [0, -1, 0, 1, 0];
const DELTA_Y: [i32; 5] = [0, 0, 1, 0, -1];

pub fn solver(mut game: GameSchema) -> Option<GameSchema> {
game.initial_y -= 1;
game.initial_x -= 1;
game.target_y -= 1;
game.target_x -= 1;
fn print_grid(grid: &CellGrid) {
println!();
for i in 0..grid.len() as usize {
for j in 0..grid[i].len() as usize {
if grid[i][j].l && grid[i][j].r {
print!("═");
} else if grid[i][j].u && grid[i][j].d {
print!("║");
} else if grid[i][j].l && grid[i][j].d {
print!("╗");
} else if grid[i][j].l && grid[i][j].u {
print!("╝");
} else if grid[i][j].u && grid[i][j].r {
print!("╚");
} else if grid[i][j].r && grid[i][j].d {
print!("╔");
}
}
println!();
println!();
}
}

pub fn solver(game: GameSchema) -> Option<GameSchema> {
let mut heap: BinaryHeap<State> = BinaryHeap::new();
let mut vis: HashSet<State> = HashSet::new();

Expand All @@ -65,10 +84,10 @@ pub fn solver(mut game: GameSchema) -> Option<GameSchema> {
// Found solution.
if u_dist == 0 {
return Some(GameSchema {
initial_x: game.initial_x + 1,
initial_y: game.initial_y + 1,
target_x: game.target_x + 1,
target_y: game.target_y + 1,
initial_x: game.initial_x,
initial_y: game.initial_y,
target_x: u_x,
target_y: u_y,
number_of_rows: game.number_of_rows,
number_of_columns: game.number_of_columns,
grid: u_grid,
Expand All @@ -80,14 +99,15 @@ pub fn solver(mut game: GameSchema) -> Option<GameSchema> {
let v_y = u_y + DELTA_Y[d];
if v_x >= 0 && v_x < game.number_of_rows && v_y >= 0 && v_y < game.number_of_columns {
for _r in 0..4 {
if can_connect(
let connectable = can_connect(
u_x,
u_y,
&u_grid[u_x as usize][u_y as usize],
v_x,
v_y,
&u_grid[v_x as usize][v_y as usize],
) {
);
if connectable {
let v = State {
manhattan_negative_distance: calc_manhattan_negative_distance(
v_x, v_y, target_x, target_y,
Expand All @@ -96,16 +116,96 @@ pub fn solver(mut game: GameSchema) -> Option<GameSchema> {
current_y: v_y,
grid: u_grid.clone(),
};
if !vis.contains(&v) {

if is_solved(
&v.grid,
Coordinate {
x: game.initial_x,
y: game.initial_y,
},
Coordinate { x: v_x, y: v_y },
)
.solvable
&& !vis.contains(&v)
{
vis.insert(v.clone());
heap.push(v);
heap.push(v.clone());
}
}
u_grid[v_x as usize][v_y as usize].rotate()

u_grid[v_x as usize][v_y as usize].rotate();
}
}
}
}

None
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Coordinate {
pub x: i32,
pub y: i32,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Solution {
pub solvable: bool,
pub coordinates: Vec<Coordinate>, // TODO: probably better as a result
}

// EEEEEEEEEEEEEEEEEEE trem feio da porra KKKKKKKKKKKKKKKKKKKKKKKK
pub fn is_solved(grid: &CellGrid, source: Coordinate, target: Coordinate) -> Solution {
print_grid(&grid);
let n = grid.len();
let m = grid[0].len();
let mut vis = vec![vec![false; m]; n];

let mut queue = VecDeque::from([Coordinate {
x: source.x,
y: source.y,
}]);

vis[source.x as usize][source.y as usize] = true;

while let Some(u) = queue.pop_front() {
if u.x == target.x && u.y == target.y {
return Solution {
solvable: true,
coordinates: vec![],
};
}

for d in 1..5 {
let v = Coordinate {
x: u.x + DELTA_X[d],
y: u.y + DELTA_Y[d],
};

if v.x >= 0 && v.y >= 0 && v.x < n as i32 && v.y < m as i32 {
if vis[v.x as usize][v.y as usize] {
continue;
}

if !can_connect(
u.x,
u.y,
&grid[u.x as usize][u.y as usize],
v.x,
v.y,
&grid[v.x as usize][v.y as usize],
) {
continue;
}

vis[v.x as usize][v.y as usize] = true;
queue.push_back(v);
}
}
}

Solution {
solvable: false,
coordinates: vec![],
}
}

0 comments on commit b57a83b

Please sign in to comment.