Day 2, 3, and 4.
This commit is contained in:
154
2017/03/src/main.rs
Normal file
154
2017/03/src/main.rs
Normal file
@@ -0,0 +1,154 @@
|
||||
use std::io::{self, Read};
|
||||
use std::iter::Iterator;
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
||||
struct Spiral {
|
||||
x: i32,
|
||||
y: i32,
|
||||
n: usize,
|
||||
d_x: i32,
|
||||
d_y: i32,
|
||||
}
|
||||
|
||||
impl Spiral {
|
||||
fn new() -> Self {
|
||||
Spiral {
|
||||
x: 0,
|
||||
y: 0,
|
||||
n: 0,
|
||||
d_x: 0,
|
||||
d_y: -1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Spiral {
|
||||
type Item = (usize, (i32, i32));
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.n += 1;
|
||||
|
||||
if self.x.abs() == self.y.abs() && !(self.d_x == 1 && self.d_y == 0)
|
||||
|| self.x > 0 && self.y == 1 - self.x
|
||||
{
|
||||
let t = self.d_x;
|
||||
|
||||
self.d_x = -self.d_y;
|
||||
self.d_y = t;
|
||||
}
|
||||
|
||||
let position = Some((self.n, (self.x, self.y)));
|
||||
|
||||
self.x += self.d_x;
|
||||
self.y += self.d_y;
|
||||
|
||||
position
|
||||
}
|
||||
}
|
||||
|
||||
fn position(n: i32) -> (i32, i32) {
|
||||
let mut spiral = Spiral::new();
|
||||
|
||||
let (_, pos) = spiral.nth((n - 1) as usize).unwrap();
|
||||
|
||||
pos
|
||||
}
|
||||
|
||||
fn distance(from: (i32, i32), to: (i32, i32)) -> usize {
|
||||
((to.0 - from.0) + (to.1 - from.1)).abs() as usize
|
||||
}
|
||||
|
||||
fn allocate(input: usize) -> usize {
|
||||
let mut grid: HashMap<(i32, i32), usize> = HashMap::new();
|
||||
|
||||
grid.insert((0, 0), 1);
|
||||
|
||||
let spiral = Spiral::new();
|
||||
|
||||
let mut value = 0;
|
||||
|
||||
for (_, (x, y)) in spiral.skip(1) {
|
||||
value = 0;
|
||||
|
||||
if let Some(v) = grid.get(&(x + 1, y)) {
|
||||
value += v;
|
||||
}
|
||||
if let Some(v) = grid.get(&(x + 1, y + 1)) {
|
||||
value += v;
|
||||
}
|
||||
if let Some(v) = grid.get(&(x, y + 1)) {
|
||||
value += v;
|
||||
}
|
||||
if let Some(v) = grid.get(&(x - 1, y + 1)) {
|
||||
value += v;
|
||||
}
|
||||
if let Some(v) = grid.get(&(x - 1, y)) {
|
||||
value += v;
|
||||
}
|
||||
if let Some(v) = grid.get(&(x - 1, y - 1)) {
|
||||
value += v;
|
||||
}
|
||||
if let Some(v) = grid.get(&(x, y - 1)) {
|
||||
value += v;
|
||||
}
|
||||
if let Some(v) = grid.get(&(x + 1, y - 1)) {
|
||||
value += v;
|
||||
}
|
||||
|
||||
if value > input {
|
||||
break;
|
||||
}
|
||||
|
||||
grid.insert((x, y), value);
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut input = String::new();
|
||||
|
||||
io::stdin()
|
||||
.read_to_string(&mut input)
|
||||
.expect("failed to parse input");
|
||||
|
||||
for line in input
|
||||
.lines()
|
||||
.map(|line| line.trim())
|
||||
.filter(|line| !line.is_empty())
|
||||
{
|
||||
let value = line.parse::<usize>()
|
||||
.expect("failed to parse value as integer");
|
||||
|
||||
println!("distance={:?}", distance(position(value as i32), (0, 0)));
|
||||
println!("allocate={:?}", allocate(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_position() {
|
||||
assert_eq!(position(1), (0, 0));
|
||||
assert_eq!(position(12), (2, 1));
|
||||
assert_eq!(position(23), (0, -2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_distance() {
|
||||
assert_eq!(distance((0, 0), (0, 0)), 0);
|
||||
assert_eq!(distance((2, 1), (0, 0)), 3);
|
||||
assert_eq!(distance((0, -2), (0, 0)), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_allocate() {
|
||||
assert_eq!(allocate(4), 5);
|
||||
assert_eq!(allocate(72), 122);
|
||||
assert_eq!(allocate(500), 747);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user