Skip to content

Instantly share code, notes, and snippets.

@lloydmeta
Created December 25, 2017 08:49
Show Gist options
  • Save lloydmeta/2129ee73c24a83164e47f30e19294136 to your computer and use it in GitHub Desktop.
Save lloydmeta/2129ee73c24a83164e47f30e19294136 to your computer and use it in GitHub Desktop.
Given the index of a point in an Ulam Spiral, return the cartesian Coordinates in O(1)
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Coords {
pub x: i64,
pub y: i64,
}
/// Given an Ulam spiral index, returns the Cartesian coordiantes
/// for it.
///
/// # Examples
/// ```
/// assert_eq!(idx_to_coords(22), Ok(Coords { x: -1, y: -2 }));
/// ```
pub fn idx_to_coords(idx: u64) -> Result<Coords, &'static str> {
if idx > 0 {
let r = {
let idx_to_check = idx as i64;
let layer = (((idx as f64).sqrt() - 1f64) / 2f64).ceil() as i64;
let points_in_layer = 2 * layer + 1;
// this is the greatest index in the layer
let lower_right_idx = points_in_layer.pow(2);
let side_width = points_in_layer - 1;
if idx_to_check >= (lower_right_idx - side_width) {
// we are on the south-side of the layer
Coords {
x: layer - (lower_right_idx - idx_to_check),
y: -layer,
}
} else {
let lower_left_idx = lower_right_idx - side_width;
if idx_to_check >= (lower_left_idx - side_width) {
Coords {
x: -layer,
y: -layer + (lower_left_idx - idx_to_check),
}
} else {
let upper_left_idx = lower_left_idx - side_width;
if idx_to_check >= upper_left_idx - side_width {
Coords {
x: -layer + (upper_left_idx - idx_to_check),
y: layer,
}
} else {
let upper_right_idx = upper_left_idx - side_width;
Coords {
x: layer,
y: layer - (upper_right_idx - idx_to_check),
}
}
}
}
};
Ok(r)
} else {
Err("Idx must be greater than 0")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment