add: some days
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
|
|
||||||
|
use advent_of_code_2024::{add_pair, make_main, mul_pair, next, nexti64, Pair, SResult};
|
||||||
|
|
||||||
|
make_main!();
|
||||||
|
|
||||||
|
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
|
||||||
|
// Parse lines into a grid of ints
|
||||||
|
let width = lines.len();
|
||||||
|
let mut grid: Vec<Vec<u32>> = Vec::with_capacity(lines.len());
|
||||||
|
for line in lines {
|
||||||
|
grid.push(
|
||||||
|
line.trim()
|
||||||
|
.chars()
|
||||||
|
.map(|c| c.to_digit(10).unwrap())
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut starts = HashSet::new();
|
||||||
|
for (i, row) in grid.iter().enumerate() {
|
||||||
|
for (j, v) in row.iter().enumerate() {
|
||||||
|
if *v == 0 {
|
||||||
|
starts.insert((i, j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut total = 0;
|
||||||
|
for start in starts.into_iter() {
|
||||||
|
let mut visited = HashSet::new();
|
||||||
|
let mut stack = VecDeque::new();
|
||||||
|
stack.push_back(start);
|
||||||
|
while stack.len() > 0 {
|
||||||
|
let cur = stack.pop_front().unwrap();
|
||||||
|
visited.insert(cur);
|
||||||
|
if grid[cur.0][cur.1] == 9 {
|
||||||
|
total += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for vel in [(1, 0), (-1, 0), (0, 1), (0, -1)] {
|
||||||
|
if let Some(n) = next(cur, vel, width) {
|
||||||
|
if grid[n.0][n.1] == grid[cur.0][cur.1] + 1 && !visited.contains(&n) {
|
||||||
|
stack.push_front(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((total, 0))
|
||||||
|
}
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use advent_of_code_2024::input;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn sample_input() {
|
||||||
|
let strings: Vec<String> = input!("d10p1.txt");
|
||||||
|
let got = solve(strings).unwrap();
|
||||||
|
assert_eq!(got, (36, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
89010123
|
||||||
|
78121874
|
||||||
|
87430965
|
||||||
|
96549874
|
||||||
|
45678903
|
||||||
|
32019012
|
||||||
|
01329801
|
||||||
|
10456732
|
||||||
+115
-48
@@ -1,25 +1,73 @@
|
|||||||
use std::{collections::HashSet, str::Chars};
|
use advent_of_code_2024::{make_main, SResult};
|
||||||
|
|
||||||
use advent_of_code_2024::{make_main, next, Pair, SResult};
|
|
||||||
|
|
||||||
make_main!();
|
make_main!();
|
||||||
|
|
||||||
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
|
fn solve(lines: Vec<String>) -> SResult<(i64, i64)> {
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
|
let mut total2 = 0;
|
||||||
for line in lines {
|
for line in lines {
|
||||||
let (_, (target, trip)) = parse_problem(&line).unwrap();
|
if let (target, true) = dumb(&line) {
|
||||||
for opt in trip.make_opts() {
|
|
||||||
if opt.eval() == target {
|
|
||||||
total += target;
|
total += target;
|
||||||
}
|
}
|
||||||
|
if let (target, true) = dumb2(&line) {
|
||||||
|
//println!("{line}");
|
||||||
|
total2 += target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((total as usize, 0))
|
Ok((total, total2))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dumb(s: &str) -> (i64, bool) {
|
||||||
|
let (value, parts) = s.split_once(":").unwrap();
|
||||||
|
let value = value.parse::<i64>().unwrap();
|
||||||
|
let parts: Vec<i64> = parts.split_ascii_whitespace().map(|s| s.parse::<i64>().unwrap()).collect();
|
||||||
|
let results = dumb_solve(parts[0], &parts[1..]);
|
||||||
|
|
||||||
|
(value, results.contains(&value))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dumb2(s: &str) -> (i64, bool) {
|
||||||
|
let (value, parts) = s.split_once(":").unwrap();
|
||||||
|
let value = value.parse::<i64>().unwrap();
|
||||||
|
let parts: Vec<i64> = parts.split_ascii_whitespace().map(|s| s.parse::<i64>().unwrap()).collect();
|
||||||
|
let results = dumb_solve2(parts[0], &parts[1..]);
|
||||||
|
|
||||||
|
(value, results.contains(&value))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dumb_solve(total: i64, parts: &[i64]) -> Vec<i64> {
|
||||||
|
if parts.len() == 1 {
|
||||||
|
return vec![total + parts[0], total * parts[0]];
|
||||||
|
}
|
||||||
|
let mut ret = vec!();
|
||||||
|
ret.append(&mut dumb_solve(total + parts[0], &parts[1..]));
|
||||||
|
ret.append(&mut dumb_solve(total * parts[0], &parts[1..]));
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dumb_solve2(total: i64, parts: &[i64]) -> Vec<i64> {
|
||||||
|
if parts.len() == 1 {
|
||||||
|
return vec![total + parts[0], total * parts[0], concat(total, parts[0])];
|
||||||
|
}
|
||||||
|
let mut ret = vec!();
|
||||||
|
ret.append(&mut dumb_solve2(total + parts[0], &parts[1..]));
|
||||||
|
ret.append(&mut dumb_solve2(total * parts[0], &parts[1..]));
|
||||||
|
ret.append(&mut dumb_solve2(concat(total, parts[0]), &parts[1..]));
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn concat(mut a: i64, b: i64) -> i64 {
|
||||||
|
let mut bb = b;
|
||||||
|
while bb > 0 {
|
||||||
|
bb /= 10;
|
||||||
|
a *= 10;
|
||||||
|
}
|
||||||
|
a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
type PResult<'a, S> = Result<(&'a str, S), &'static str>;
|
type PResult<'a, S> = Result<(&'a str, S), &'static str>;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
struct Triple {
|
struct Triple {
|
||||||
left: Op,
|
left: Op,
|
||||||
right: Op,
|
right: Op,
|
||||||
@@ -31,11 +79,15 @@ impl Triple {
|
|||||||
if self.oper != Oper::UNKNOWN {
|
if self.oper != Oper::UNKNOWN {
|
||||||
return vec![self.clone()];
|
return vec![self.clone()];
|
||||||
}
|
}
|
||||||
let mut ret = vec!();
|
let mut ret = vec![];
|
||||||
for oper in [Oper::ADD, Oper::MUL] {
|
|
||||||
for left in self.left.make_opts() {
|
for left in self.left.make_opts() {
|
||||||
for right in self.right.make_opts() {
|
for right in self.right.make_opts() {
|
||||||
ret.push(Triple{left: left.clone(), right, oper});
|
for oper in [Oper::ADD, Oper::MUL] {
|
||||||
|
ret.push(Triple {
|
||||||
|
left: left.clone(),
|
||||||
|
right: right.clone(),
|
||||||
|
oper,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +103,8 @@ impl Triple {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
|
||||||
enum Op {
|
enum Op {
|
||||||
Const(i64),
|
Const(i64),
|
||||||
Triple(Box<Triple>),
|
Triple(Box<Triple>),
|
||||||
@@ -62,7 +115,7 @@ impl Op {
|
|||||||
match self {
|
match self {
|
||||||
Op::Const(x) => vec![Op::Const(*x)],
|
Op::Const(x) => vec![Op::Const(*x)],
|
||||||
Op::Triple(t) => {
|
Op::Triple(t) => {
|
||||||
let mut ret = vec!();
|
let mut ret = vec![];
|
||||||
for triple in t.make_opts() {
|
for triple in t.make_opts() {
|
||||||
ret.push(Op::Triple(Box::new(triple)));
|
ret.push(Op::Triple(Box::new(triple)));
|
||||||
}
|
}
|
||||||
@@ -79,7 +132,7 @@ impl Op {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||||
enum Oper {
|
enum Oper {
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
ADD,
|
ADD,
|
||||||
@@ -93,47 +146,61 @@ fn parse_problem(s: &str) -> PResult<(i64, Triple)> {
|
|||||||
Ok((s, (target.eval(), triple)))
|
Ok((s, (target.eval(), triple)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_one(s: &str) -> PResult<char> {
|
|
||||||
let c = s.chars().next().ok_or("missing char")?;
|
|
||||||
Ok((s, c))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn take_ws(s: &str) -> PResult<()> {
|
|
||||||
let mut chars = s,chars();
|
|
||||||
let mut i = 0;
|
|
||||||
|
|
||||||
Ok((s.split_at(i), ()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_triple(s: &str) -> PResult<Triple> {
|
fn parse_triple(s: &str) -> PResult<Triple> {
|
||||||
let (s, _) = take_ws(s)?;
|
let (s, _) = take_ws(s)?;
|
||||||
let (s, left) = take_int(s)?;
|
let (mut s, mut left) = take_int(s)?;
|
||||||
let (s, _) = take_ws(s)?;
|
while s.len() > 0 {
|
||||||
let oper = Oper::UNKNOWN;
|
let (_s, _) = take_ws(s)?;
|
||||||
let (s, _) = take_ws(s)?;
|
let (_s, right) = take_int(_s)?;
|
||||||
let (s, right) = match parse_triple(s) {
|
left = Op::Triple(Box::new(Triple {
|
||||||
Ok((s, triple)) => (s, Op::Triple(Box::new(triple))),
|
left,
|
||||||
Err(_) => take_int(s)?,
|
right,
|
||||||
};
|
oper: Oper::UNKNOWN,
|
||||||
let (s, _) = take_ws(s)?;
|
}));
|
||||||
|
s = _s;
|
||||||
|
}
|
||||||
|
|
||||||
Ok((s, Triple{left, right, oper}))
|
if let Op::Triple(x) = left {
|
||||||
|
Ok((s, *x))
|
||||||
|
} else {
|
||||||
|
Err("not even one triple")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_one(s: &str) -> PResult<char> {
|
||||||
|
let mut chars = s.chars();
|
||||||
|
let c = chars.next().ok_or("missing char")?;
|
||||||
|
Ok((chars.as_str(), c))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_while<'a, F: Fn(char) -> bool>(mut s: &'a str, f: F) -> PResult<&'a str> {
|
||||||
|
let og = s;
|
||||||
|
let mut mid = 0;
|
||||||
|
let mut chars = s.chars();
|
||||||
|
while let Some(c) = chars.next() {
|
||||||
|
if !f(c) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mid += 1;
|
||||||
|
}
|
||||||
|
let (first, rest) = og.split_at(mid);
|
||||||
|
Ok((rest, first))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_ws<'a>(s: &'a str) -> PResult<&'a str> {
|
||||||
|
take_while(s, |c| c.is_whitespace())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_int(s: &str) -> PResult<Op> {
|
fn take_int(s: &str) -> PResult<Op> {
|
||||||
|
let (rest, digit) = take_while(s, |c| c.is_digit(10))?;
|
||||||
|
if digit.len() == 0 {
|
||||||
|
return Err("no digit");
|
||||||
|
}
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
let mut i = 0;
|
for c in digit.chars() {
|
||||||
let mut chars = s.chars();
|
|
||||||
while let Some(c) = chars.by_ref().peekable().next_if(|c| c.is_digit(10)) {
|
|
||||||
total = total * 10 + c.to_digit(10).unwrap();
|
total = total * 10 + c.to_digit(10).unwrap();
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
if i == 0 {
|
|
||||||
panic!("here");
|
|
||||||
Err("no digits")
|
|
||||||
} else {
|
|
||||||
Ok((chars.as_str(), Op::Const(total as i64)))
|
|
||||||
}
|
}
|
||||||
|
Ok((rest, Op::Const(total as i64)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -145,6 +212,6 @@ mod tests {
|
|||||||
fn sample_input() {
|
fn sample_input() {
|
||||||
let strings: Vec<String> = input!("d7p1.txt");
|
let strings: Vec<String> = input!("d7p1.txt");
|
||||||
let got = solve(strings).unwrap();
|
let got = solve(strings).unwrap();
|
||||||
assert_eq!(got, (3749, 0));
|
assert_eq!(got, (3749, 11387));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use advent_of_code_2024::{add_pair, make_main, mul_pair, next, nexti64, Pair, SResult};
|
||||||
|
|
||||||
|
make_main!();
|
||||||
|
|
||||||
|
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
|
||||||
|
// Convert to a grid of chars for easy searching
|
||||||
|
// Also record locations of ants and
|
||||||
|
let mut ants: HashMap<char, Vec<Pair<i64>>> = HashMap::default();
|
||||||
|
let mut grid = vec![];
|
||||||
|
let limit = lines.len() as i64;
|
||||||
|
for (i, line) in lines.into_iter().enumerate() {
|
||||||
|
let line: Vec<char> = line.chars().collect();
|
||||||
|
for (j, c) in line.iter().enumerate() {
|
||||||
|
if *c == '.' {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ants.entry(*c)
|
||||||
|
.or_insert_with(|| Vec::new())
|
||||||
|
.push((i as i64, j as i64));
|
||||||
|
}
|
||||||
|
grid.push(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut anodes: HashSet<Pair<i64>> = HashSet::new();
|
||||||
|
let mut anodes2: HashSet<Pair<i64>> = HashSet::new();
|
||||||
|
|
||||||
|
for (_, pairs) in ants {
|
||||||
|
for (i, p0) in pairs.iter().enumerate() {
|
||||||
|
for p1 in &pairs[(i+1)..] {
|
||||||
|
let (p0, p1) = (*p0, *p1);
|
||||||
|
let vel: (i64, i64) = add_pair(p0, mul_pair(p1, -1));
|
||||||
|
assert_ne!(vel, (0, 0), "{:?} vs {:?}", p0, p1);
|
||||||
|
|
||||||
|
for p in [p0, p1] {
|
||||||
|
for pp in [add_pair(p, vel), add_pair(p, mul_pair(vel, -1))] {
|
||||||
|
if pp == p0 || pp == p1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if pp.0 < 0 || pp.0 >= limit || pp.1 < 0 || pp.1 >= limit {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
anodes.insert(pp);
|
||||||
|
}
|
||||||
|
let mut cur_pos = p;
|
||||||
|
while let Some(pp) = nexti64(cur_pos, vel, limit as usize) {
|
||||||
|
cur_pos = pp;
|
||||||
|
anodes2.insert(pp);
|
||||||
|
}
|
||||||
|
let mut cur_pos = p;
|
||||||
|
let vel = mul_pair(vel, -1);
|
||||||
|
while let Some(pp) = nexti64(cur_pos, vel, limit as usize) {
|
||||||
|
cur_pos = pp;
|
||||||
|
anodes2.insert(pp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((anodes.len(), anodes2.len()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use advent_of_code_2024::input;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn sample_input() {
|
||||||
|
let strings: Vec<String> = input!("d8p1.txt");
|
||||||
|
let got = solve(strings).unwrap();
|
||||||
|
assert_eq!(got, (14, 34));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
............
|
||||||
|
........0...
|
||||||
|
.....0......
|
||||||
|
.......0....
|
||||||
|
....0.......
|
||||||
|
......A.....
|
||||||
|
............
|
||||||
|
............
|
||||||
|
........A...
|
||||||
|
.........A..
|
||||||
|
............
|
||||||
|
............
|
||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use advent_of_code_2024::{add_pair, make_main, mul_pair, next, nexti64, Pair, SResult};
|
||||||
|
|
||||||
|
make_main!();
|
||||||
|
|
||||||
|
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
|
||||||
|
let line = &lines[0];
|
||||||
|
|
||||||
|
let mut data: Vec<i16> = vec!();
|
||||||
|
let mut counts: HashMap<i16, usize> = HashMap::default();
|
||||||
|
|
||||||
|
let mut file_index = 0;
|
||||||
|
for (i, c) in line.chars().enumerate() {
|
||||||
|
if i % 2 == 0 {
|
||||||
|
let count = c.to_digit(10).unwrap() as usize;
|
||||||
|
data.append(&mut vec![file_index; count]);
|
||||||
|
counts.insert(file_index, count);
|
||||||
|
file_index += 1;
|
||||||
|
} else {
|
||||||
|
data.append(&mut vec![-1; c.to_digit(10).unwrap() as usize]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut data2 = data.clone();
|
||||||
|
|
||||||
|
let mut starti = 0;
|
||||||
|
let mut endi = data.len()-1;
|
||||||
|
while endi > starti {
|
||||||
|
if data[endi] == -1 {
|
||||||
|
endi -= 1;
|
||||||
|
} else {
|
||||||
|
let (data, file) = data.split_at_mut(endi);
|
||||||
|
let count = move_file(&mut data[starti..], &mut file[..1]);
|
||||||
|
starti += count;
|
||||||
|
endi -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut processed: HashSet<i16> = HashSet::new();
|
||||||
|
processed.insert(-1);
|
||||||
|
let mut endi = data.len();
|
||||||
|
while endi > 1 {
|
||||||
|
// Go back until we find a start point
|
||||||
|
while endi > 1 && processed.contains(&data2[endi-1]) {
|
||||||
|
endi -= 1;
|
||||||
|
}
|
||||||
|
if endi == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Now go back until we are no longer in the same block
|
||||||
|
let mut fstart = endi-1;
|
||||||
|
let bid = data2[fstart];
|
||||||
|
while fstart > 0 && data2[fstart-1] == bid {
|
||||||
|
fstart -= 1;
|
||||||
|
}
|
||||||
|
processed.insert(data2[fstart]);
|
||||||
|
let (data, file) = data2.split_at_mut(fstart);
|
||||||
|
move_file(&mut data[..], &mut file[..endi-fstart]);
|
||||||
|
endi = fstart;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((checksum(&data), checksum(&data2)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn checksum(data: &[i16]) -> usize {
|
||||||
|
let mut checksum = 0;
|
||||||
|
for (i, id) in data.iter().enumerate() {
|
||||||
|
if *id == -1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
checksum += (*id as usize) * i;
|
||||||
|
}
|
||||||
|
checksum
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_file(data: &mut [i16], file: &mut [i16]) -> usize {
|
||||||
|
let empty = vec![-1; file.len()];
|
||||||
|
let mut i = 0;
|
||||||
|
while i+file.len() <= data.len() {
|
||||||
|
if &data[i..i+file.len()] == empty {
|
||||||
|
for j in 0..file.len() {
|
||||||
|
(data[i+j], file[j]) = (file[j], data[i+j]);
|
||||||
|
}
|
||||||
|
i += file.len();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
i
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use advent_of_code_2024::input;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn sample_input() {
|
||||||
|
let strings: Vec<String> = input!("d9p1.txt");
|
||||||
|
let got = solve(strings).unwrap();
|
||||||
|
assert_eq!(got, (1928, 2858));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
2333133121414131402
|
||||||
+20
@@ -22,6 +22,16 @@ pub type SResult<T> = Result<T, Box<dyn std::error::Error>>;
|
|||||||
|
|
||||||
pub type Pair<T = usize> = (T, T);
|
pub type Pair<T = usize> = (T, T);
|
||||||
|
|
||||||
|
pub fn mul_pair<T>(p: Pair<T>, val: T) -> Pair<T>
|
||||||
|
where T: Copy + std::ops::Mul<Output = T> {
|
||||||
|
(p.0*val, p.1*val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_pair<T>(p: Pair<T>, val: Pair<T>) -> Pair<T>
|
||||||
|
where T: Copy + std::ops::Add<Output = T> {
|
||||||
|
(p.0+val.0, p.1+val.1)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn next((x, y): Pair, (xvel, yvel): Pair<i64>, width: usize) -> Option<Pair> {
|
pub fn next((x, y): Pair, (xvel, yvel): Pair<i64>, width: usize) -> Option<Pair> {
|
||||||
let x = x as i64 + xvel;
|
let x = x as i64 + xvel;
|
||||||
let y = y as i64 + yvel;
|
let y = y as i64 + yvel;
|
||||||
@@ -31,3 +41,13 @@ pub fn next((x, y): Pair, (xvel, yvel): Pair<i64>, width: usize) -> Option<Pair>
|
|||||||
Some((x as usize, y as usize))
|
Some((x as usize, y as usize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn nexti64((x, y): Pair<i64>, (xvel, yvel): Pair<i64>, width: usize) -> Option<Pair<i64>> {
|
||||||
|
let x = x + xvel;
|
||||||
|
let y = y + yvel;
|
||||||
|
if x < 0 || y < 0 || x >= width as i64 || y >= width as i64 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((x, y))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user