Compare commits
10 commits
da8635c06b
...
8789bbba49
Author | SHA1 | Date | |
---|---|---|---|
|
8789bbba49 | ||
|
15fd997707 | ||
|
06b15921fd | ||
|
34db36cf0b | ||
|
db142ff1df | ||
|
24feb1c127 | ||
|
0423e7a8f3 | ||
|
a62ed3ec13 | ||
|
2cd0dce596 | ||
|
5441906ea8 |
11 changed files with 507 additions and 130 deletions
|
@ -9,6 +9,7 @@ edition = "2021"
|
||||||
aoc-runner = "0.3"
|
aoc-runner = "0.3"
|
||||||
aoc-runner-derive = "0.3"
|
aoc-runner-derive = "0.3"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
#itertools = "0.10.5"
|
|
||||||
regex = "1.7"
|
regex = "1.7"
|
||||||
ndarray = "0.15"
|
ndarray = "0.15"
|
||||||
|
petgraph = "0.6"
|
||||||
|
lyn = "0.1.0"
|
||||||
|
|
|
@ -24,10 +24,10 @@ impl Default for Operation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Monkey {
|
impl Monkey {
|
||||||
pub fn inspect(&mut self) -> Vec<(usize, u128)> {
|
pub fn inspect(&mut self, reducer: &dyn Fn(u128) -> u128) -> Vec<(usize, u128)> {
|
||||||
let mut out = Vec::with_capacity(self.items.len());
|
let mut out = Vec::with_capacity(self.items.len());
|
||||||
while let Some(item) = self.items.pop_front() {
|
while let Some(item) = self.items.pop_front() {
|
||||||
let item = self.op(item) / 3;
|
let item = reducer(self.op(item));
|
||||||
if item % self.tmod == 0 {
|
if item % self.tmod == 0 {
|
||||||
out.push((self.target.0, item));
|
out.push((self.target.0, item));
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,7 +115,7 @@ fn part1(troop: &[Monkey]) -> u128 {
|
||||||
for _round in 0..20 {
|
for _round in 0..20 {
|
||||||
for i in 0..troop.len() {
|
for i in 0..troop.len() {
|
||||||
let monkey = &mut troop[i];
|
let monkey = &mut troop[i];
|
||||||
let items = monkey.inspect();
|
let items = monkey.inspect(&|item| item / 3);
|
||||||
for (target, item) in items {
|
for (target, item) in items {
|
||||||
let m = &mut troop[target];
|
let m = &mut troop[target];
|
||||||
m.items.push_back(item);
|
m.items.push_back(item);
|
||||||
|
@ -128,9 +128,23 @@ fn part1(troop: &[Monkey]) -> u128 {
|
||||||
|
|
||||||
#[aoc_run(day11, part2)]
|
#[aoc_run(day11, part2)]
|
||||||
fn part2(troop: &[Monkey]) -> u128 {
|
fn part2(troop: &[Monkey]) -> u128 {
|
||||||
0
|
let max: u128 = troop.iter().map(|m| m.tmod).product();
|
||||||
|
let mut troop = troop.to_owned();
|
||||||
|
for _round in 0..10_000 {
|
||||||
|
for i in 0..troop.len() {
|
||||||
|
let monkey = &mut troop[i];
|
||||||
|
let items = monkey.inspect(&|item| item % max);
|
||||||
|
for (target, item) in items {
|
||||||
|
let m = &mut troop[target];
|
||||||
|
m.items.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
troop.sort_by(|m1, m2| m2.business.cmp(&m1.business));
|
||||||
|
troop.iter().take(2).map(|m| m.business).product()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -172,129 +186,7 @@ Monkey 3:
|
||||||
#[test]
|
#[test]
|
||||||
fn part2_test() {
|
fn part2_test() {
|
||||||
let v = parse_input(INPUT);
|
let v = parse_input(INPUT);
|
||||||
assert_eq!(part2(&v), 1);
|
assert_eq!(part2(&v), 2713310158);
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn leah_test() {
|
|
||||||
let troop = parse_input(
|
|
||||||
"Monkey 0:
|
|
||||||
Starting items: 54, 82, 90, 88, 86, 54
|
|
||||||
Operation: new = old * 7
|
|
||||||
Test: divisible by 11
|
|
||||||
If true: throw to monkey 2
|
|
||||||
If false: throw to monkey 6
|
|
||||||
|
|
||||||
Monkey 1:
|
|
||||||
Starting items: 91, 65
|
|
||||||
Operation: new = old * 13
|
|
||||||
Test: divisible by 5
|
|
||||||
If true: throw to monkey 7
|
|
||||||
If false: throw to monkey 4
|
|
||||||
|
|
||||||
Monkey 2:
|
|
||||||
Starting items: 62, 54, 57, 92, 83, 63, 63
|
|
||||||
Operation: new = old + 1
|
|
||||||
Test: divisible by 7
|
|
||||||
If true: throw to monkey 1
|
|
||||||
If false: throw to monkey 7
|
|
||||||
|
|
||||||
Monkey 3:
|
|
||||||
Starting items: 67, 72, 68
|
|
||||||
Operation: new = old * old
|
|
||||||
Test: divisible by 2
|
|
||||||
If true: throw to monkey 0
|
|
||||||
If false: throw to monkey 6
|
|
||||||
|
|
||||||
Monkey 4:
|
|
||||||
Starting items: 68, 89, 90, 86, 84, 57, 72, 84
|
|
||||||
Operation: new = old + 7
|
|
||||||
Test: divisible by 17
|
|
||||||
If true: throw to monkey 3
|
|
||||||
If false: throw to monkey 5
|
|
||||||
|
|
||||||
Monkey 5:
|
|
||||||
Starting items: 79, 83, 64, 58
|
|
||||||
Operation: new = old + 6
|
|
||||||
Test: divisible by 13
|
|
||||||
If true: throw to monkey 3
|
|
||||||
If false: throw to monkey 0
|
|
||||||
|
|
||||||
Monkey 6:
|
|
||||||
Starting items: 96, 72, 89, 70, 88
|
|
||||||
Operation: new = old + 4
|
|
||||||
Test: divisible by 3
|
|
||||||
If true: throw to monkey 1
|
|
||||||
If false: throw to monkey 2
|
|
||||||
|
|
||||||
Monkey 7:
|
|
||||||
Starting items: 79
|
|
||||||
Operation: new = old + 8
|
|
||||||
Test: divisible by 19
|
|
||||||
If true: throw to monkey 4
|
|
||||||
If false: throw to monkey 5",
|
|
||||||
);
|
|
||||||
assert_eq!(part1(&troop), 78960);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rippy_part1() {
|
|
||||||
let input = "Monkey 0:
|
|
||||||
Starting items: 96, 60, 68, 91, 83, 57, 85
|
|
||||||
Operation: new = old * 2
|
|
||||||
Test: divisible by 17
|
|
||||||
If true: throw to monkey 2
|
|
||||||
If false: throw to monkey 5
|
|
||||||
|
|
||||||
Monkey 1:
|
|
||||||
Starting items: 75, 78, 68, 81, 73, 99
|
|
||||||
Operation: new = old + 3
|
|
||||||
Test: divisible by 13
|
|
||||||
If true: throw to monkey 7
|
|
||||||
If false: throw to monkey 4
|
|
||||||
|
|
||||||
Monkey 2:
|
|
||||||
Starting items: 69, 86, 67, 55, 96, 69, 94, 85
|
|
||||||
Operation: new = old + 6
|
|
||||||
Test: divisible by 19
|
|
||||||
If true: throw to monkey 6
|
|
||||||
If false: throw to monkey 5
|
|
||||||
|
|
||||||
Monkey 3:
|
|
||||||
Starting items: 88, 75, 74, 98, 80
|
|
||||||
Operation: new = old + 5
|
|
||||||
Test: divisible by 7
|
|
||||||
If true: throw to monkey 7
|
|
||||||
If false: throw to monkey 1
|
|
||||||
|
|
||||||
Monkey 4:
|
|
||||||
Starting items: 82
|
|
||||||
Operation: new = old + 8
|
|
||||||
Test: divisible by 11
|
|
||||||
If true: throw to monkey 0
|
|
||||||
If false: throw to monkey 2
|
|
||||||
|
|
||||||
Monkey 5:
|
|
||||||
Starting items: 72, 92, 92
|
|
||||||
Operation: new = old * 5
|
|
||||||
Test: divisible by 3
|
|
||||||
If true: throw to monkey 6
|
|
||||||
If false: throw to monkey 3
|
|
||||||
|
|
||||||
Monkey 6:
|
|
||||||
Starting items: 74, 61
|
|
||||||
Operation: new = old * old
|
|
||||||
Test: divisible by 2
|
|
||||||
If true: throw to monkey 3
|
|
||||||
If false: throw to monkey 1
|
|
||||||
|
|
||||||
Monkey 7:
|
|
||||||
Starting items: 76, 86, 83, 55
|
|
||||||
Operation: new = old + 4
|
|
||||||
Test: divisible by 5
|
|
||||||
If true: throw to monkey 4
|
|
||||||
If false: throw to monkey 0";
|
|
||||||
let troop = parse_input(input);
|
|
||||||
assert_eq!(part1(&troop), 56595);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
131
2022-aoc/src/d12.rs
Normal file
131
2022-aoc/src/d12.rs
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
use aoc_runner_derive::{aoc as aoc_run, aoc_generator};
|
||||||
|
use petgraph::{algo::dijkstra, prelude::NodeIndex, Graph};
|
||||||
|
|
||||||
|
type GRAPH = Graph<char, ()>;
|
||||||
|
|
||||||
|
type Pos = (usize, usize);
|
||||||
|
|
||||||
|
#[aoc_generator(day12)]
|
||||||
|
fn parse_input(input: &str) -> (NodeIndex, NodeIndex, GRAPH) {
|
||||||
|
let mut out = Graph::default();
|
||||||
|
let mut g = Vec::new();
|
||||||
|
let mut s = NodeIndex::default();
|
||||||
|
let mut e = NodeIndex::default();
|
||||||
|
|
||||||
|
for line in input.lines() {
|
||||||
|
let row = Vec::from_iter(line.chars());
|
||||||
|
g.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
let rows = g.len();
|
||||||
|
let cols = g[0].len();
|
||||||
|
let mut g2 = vec![vec![NodeIndex::default(); cols]; rows];
|
||||||
|
for row in 0..rows {
|
||||||
|
for col in 0..cols {
|
||||||
|
let weight = g[row][col];
|
||||||
|
let node = out.add_node(weight);
|
||||||
|
g2[row][col] = node;
|
||||||
|
if weight == 'S' {
|
||||||
|
s = node;
|
||||||
|
}
|
||||||
|
if weight == 'E' {
|
||||||
|
e = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for row in 0..rows {
|
||||||
|
for col in 0..cols {
|
||||||
|
let node = g2[row][col];
|
||||||
|
for neighbor in neighbors((row, col), &g).iter() {
|
||||||
|
let &(row, col) = neighbor;
|
||||||
|
let neighbor = g2[row][col];
|
||||||
|
out.add_edge(node, neighbor, ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(s, e, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn neighbors((ridx, cidx): Pos, graph: &[Vec<char>]) -> Vec<(usize, usize)> {
|
||||||
|
let n = graph[ridx][cidx];
|
||||||
|
let mut out = Vec::new();
|
||||||
|
for (dr, dc) in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
|
||||||
|
let row = (dr + ridx as i32) as usize;
|
||||||
|
let col = (dc + cidx as i32) as usize;
|
||||||
|
if let Some(r) = graph.get(row) {
|
||||||
|
if let Some(c) = r.get(col) {
|
||||||
|
if reachable(n, *c) {
|
||||||
|
out.push((row, col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reachable(a: char, b: char) -> bool {
|
||||||
|
let a = match a {
|
||||||
|
'S' => 'a',
|
||||||
|
'E' => 'z',
|
||||||
|
_ => a,
|
||||||
|
};
|
||||||
|
let b = match b {
|
||||||
|
'S' => 'a',
|
||||||
|
'E' => 'z',
|
||||||
|
_ => b,
|
||||||
|
};
|
||||||
|
(a as u8 + 1) >= b as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_run(day12, part1)]
|
||||||
|
fn part1((start, end, graph): &(NodeIndex, NodeIndex, GRAPH)) -> i32 {
|
||||||
|
let res = dijkstra(graph, *start, Some(*end), |_| 1);
|
||||||
|
res[end]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_run(day12, part2)]
|
||||||
|
fn part2((start, end, graph): &(NodeIndex, NodeIndex, GRAPH)) -> i32 {
|
||||||
|
let mut roots = Vec::new();
|
||||||
|
roots.push(*start);
|
||||||
|
for (i, w) in graph.node_weights().enumerate() {
|
||||||
|
if w == &'a' {
|
||||||
|
roots.push(NodeIndex::new(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut res = i32::MAX;
|
||||||
|
for root in roots {
|
||||||
|
let p = dijkstra(graph, root, Some(*end), |_| 1);
|
||||||
|
if let Some(&v) = p.get(end) {
|
||||||
|
res = res.min(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
const INPUT: &str = "Sabqponm
|
||||||
|
abcryxxl
|
||||||
|
accszExk
|
||||||
|
acctuvwj
|
||||||
|
abdefghi";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_test() {
|
||||||
|
let v = parse_input(INPUT);
|
||||||
|
|
||||||
|
assert_eq!(part1(&v), 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_test() {
|
||||||
|
let v = parse_input(INPUT);
|
||||||
|
assert_eq!(part2(&v), 29);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
175
2022-aoc/src/d13.rs
Normal file
175
2022-aoc/src/d13.rs
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
use aoc_runner_derive::{aoc as aoc_run, aoc_generator};
|
||||||
|
use lyn::Scanner;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The following grammar can be used at https://bnfplayground.pauliankline.com/ to play with matching
|
||||||
|
|
||||||
|
<packet> ::= <leftbrace> <list>? <rightbrace>
|
||||||
|
<list> ::= <element> (<comma> <element>)*
|
||||||
|
<element> ::= <number> | <leftbrace> <list>* <rightbrace>
|
||||||
|
<comma> ::= "," | ", "
|
||||||
|
<leftbrace> ::= "["
|
||||||
|
<rightbrace> ::= "]"
|
||||||
|
<number> ::= [0-9]+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
|
||||||
|
struct Packet {
|
||||||
|
elements: Vec<Element>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
|
enum Element {
|
||||||
|
Plain(u32),
|
||||||
|
List(Vec<Element>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Element {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
use Element::*;
|
||||||
|
match (self, other) {
|
||||||
|
(Plain(v1), Plain(v2)) => Some(v1.cmp(v2)),
|
||||||
|
(List(v1), List(v2)) => v1.partial_cmp(v2),
|
||||||
|
(Plain(_), List(_)) => List(vec![self.clone()]).partial_cmp(other),
|
||||||
|
(List(_), Plain(_)) => self.partial_cmp(&List(vec![other.clone()])),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Element {
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
self.partial_cmp(other).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_generator(day13)]
|
||||||
|
fn parse_input(input: &str) -> Vec<Packet> {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
for line in input.lines() {
|
||||||
|
if line.trim().is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut scanner = Scanner::new(line);
|
||||||
|
let packet = parse_packet(&mut scanner);
|
||||||
|
out.push(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_packet(scanner: &mut Scanner) -> Packet {
|
||||||
|
// we can pop the first character off, it's the opening brace
|
||||||
|
scanner.pop();
|
||||||
|
let elements = parse_list(scanner);
|
||||||
|
Packet { elements }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_list(scanner: &mut Scanner) -> Vec<Element> {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
while let Some(c) = scanner.peek() {
|
||||||
|
match c {
|
||||||
|
'[' => {
|
||||||
|
scanner.pop();
|
||||||
|
let v = parse_list(scanner);
|
||||||
|
out.push(Element::List(v));
|
||||||
|
}
|
||||||
|
c if c.is_ascii_digit() => {
|
||||||
|
let mut s = String::new();
|
||||||
|
while let Some(c) = scanner.peek() {
|
||||||
|
if c.is_ascii_digit() {
|
||||||
|
let c = scanner.pop().unwrap();
|
||||||
|
s.push(*c);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let num: u32 = s.parse().unwrap();
|
||||||
|
out.push(Element::Plain(num));
|
||||||
|
}
|
||||||
|
']' => {
|
||||||
|
scanner.pop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
scanner.pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_run(day13, part1)]
|
||||||
|
fn part1(input: &[Packet]) -> u32 {
|
||||||
|
let mut out = 0;
|
||||||
|
for (i, packets) in input.chunks(2).enumerate() {
|
||||||
|
//
|
||||||
|
let (left, right) = (&packets[0], &packets[1]);
|
||||||
|
if left < right {
|
||||||
|
out += i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_run(day13, part2)]
|
||||||
|
fn part2(input: &[Packet]) -> u32 {
|
||||||
|
let d1 = &parse_packet(&mut Scanner::new("[[2]]"));
|
||||||
|
let d2 = &parse_packet(&mut Scanner::new("[[6]]"));
|
||||||
|
let mut input = input.to_vec();
|
||||||
|
input.push(d1.clone());
|
||||||
|
input.push(d2.clone());
|
||||||
|
input.sort();
|
||||||
|
let mut out = 1;
|
||||||
|
|
||||||
|
for (i, p) in input.iter().enumerate() {
|
||||||
|
if p == d1 || p == d2 {
|
||||||
|
out *= i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
const INPUT: &str = "[1,1,3,1,1]
|
||||||
|
[1,1,5,1,1]
|
||||||
|
|
||||||
|
[[1],[2,3,4]]
|
||||||
|
[[1],4]
|
||||||
|
|
||||||
|
[9]
|
||||||
|
[[8,7,6]]
|
||||||
|
|
||||||
|
[[4,4],4,4]
|
||||||
|
[[4,4],4,4,4]
|
||||||
|
|
||||||
|
[7,7,7,7]
|
||||||
|
[7,7,7]
|
||||||
|
|
||||||
|
[]
|
||||||
|
[3]
|
||||||
|
|
||||||
|
[[[]]]
|
||||||
|
[[]]
|
||||||
|
|
||||||
|
[1,[2,[3,[4,[5,6,7]]]],8,9]
|
||||||
|
[1,[2,[3,[4,[5,6,0]]]],8,9]";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_test() {
|
||||||
|
let v = parse_input(INPUT);
|
||||||
|
|
||||||
|
assert_eq!(part1(&v), 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_test() {
|
||||||
|
let v = parse_input(INPUT);
|
||||||
|
assert_eq!(part2(&v), 140);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
|
@ -11,5 +11,7 @@ mod d8;
|
||||||
mod d9;
|
mod d9;
|
||||||
mod d10;
|
mod d10;
|
||||||
mod d11;
|
mod d11;
|
||||||
|
mod d12;
|
||||||
|
mod d13;
|
||||||
|
|
||||||
aoc_lib! { year = 2022 }
|
aoc_lib! { year = 2022 }
|
||||||
|
|
6
increasing_triplet_subsequence/Cargo.toml
Normal file
6
increasing_triplet_subsequence/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "increasing_triplet_subsequence"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
23
increasing_triplet_subsequence/src/main.rs
Normal file
23
increasing_triplet_subsequence/src/main.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
fn main() {
|
||||||
|
dbg!(increasing_triplet(&[1, 5, 2, 3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn increasing_triplet(nums: &[i32]) -> bool {
|
||||||
|
let mut sub_seq = [i64::MAX; 4];
|
||||||
|
sub_seq[0] = i64::MIN;
|
||||||
|
for &v in nums {
|
||||||
|
let v = v as i64;
|
||||||
|
for j in 1..4 {
|
||||||
|
if sub_seq[j - 1] < v && v < sub_seq[j] {
|
||||||
|
sub_seq[j] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut m = 0;
|
||||||
|
for &v in &sub_seq[1..] {
|
||||||
|
if v < i64::MAX {
|
||||||
|
m += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m > 2
|
||||||
|
}
|
8
product_of_array_except_self/Cargo.toml
Normal file
8
product_of_array_except_self/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "product_of_array_except_self"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
63
product_of_array_except_self/src/main.rs
Normal file
63
product_of_array_except_self/src/main.rs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
struct Solution;
|
||||||
|
|
||||||
|
enum Zeros {
|
||||||
|
None,
|
||||||
|
One(usize),
|
||||||
|
Many,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Solution {
|
||||||
|
pub fn product_except_self(nums: Vec<i32>) -> Vec<i32> {
|
||||||
|
let mut out = nums;
|
||||||
|
let nums = &mut out;
|
||||||
|
let zeros = count_zeros(nums);
|
||||||
|
|
||||||
|
match zeros {
|
||||||
|
Zeros::None => {
|
||||||
|
let prod: i32 = nums.iter().product();
|
||||||
|
for x in nums.iter_mut() {
|
||||||
|
*x = prod / *x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Zeros::One(z) => {
|
||||||
|
let (left, right) = nums.split_at(z);
|
||||||
|
let left: i32 = left.iter().product();
|
||||||
|
let right: i32 = if right.len() < 2 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
right[1..].iter().product()
|
||||||
|
};
|
||||||
|
for x in nums.iter_mut() {
|
||||||
|
*x = 0;
|
||||||
|
}
|
||||||
|
nums[z] = left * right;
|
||||||
|
}
|
||||||
|
Zeros::Many => *nums = vec![0; nums.len()],
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_zeros(nums: &[i32]) -> Zeros {
|
||||||
|
let mut out = Zeros::None;
|
||||||
|
let mut zs = false;
|
||||||
|
for (i, n) in nums.iter().enumerate() {
|
||||||
|
if *n == 0i32 {
|
||||||
|
if !zs {
|
||||||
|
out = Zeros::One(i);
|
||||||
|
zs = true;
|
||||||
|
} else {
|
||||||
|
out = Zeros::Many;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let p = Solution::product_except_self(vec![-1, 1, 0, -3, 3]);
|
||||||
|
dbg!(p);
|
||||||
|
let p = Solution::product_except_self(vec![1, 2, 0, 3]);
|
||||||
|
dbg!(p);
|
||||||
|
}
|
6
string_compression/Cargo.toml
Normal file
6
string_compression/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "string_compression"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
70
string_compression/src/main.rs
Normal file
70
string_compression/src/main.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
fn main() {
|
||||||
|
let mut a = ['a', 'a', 'b', 'b', 'c', 'c', 'c'];
|
||||||
|
let mut b = ['a', 'a', 'a', 'b', 'b', 'a', 'a'];
|
||||||
|
let mut c = ['a'];
|
||||||
|
let mut d = ['a', 'b', 'b', 'b'];
|
||||||
|
let mut e = ['a', 'b', 'c'];
|
||||||
|
|
||||||
|
let sz = Solution::compress(&mut a);
|
||||||
|
dbg!(sz, a);
|
||||||
|
|
||||||
|
let sz = Solution::compress(&mut b);
|
||||||
|
dbg!(sz, b);
|
||||||
|
|
||||||
|
let sz = Solution::compress(&mut c);
|
||||||
|
dbg!(sz, c);
|
||||||
|
|
||||||
|
let sz = Solution::compress(&mut d);
|
||||||
|
dbg!(sz, d);
|
||||||
|
|
||||||
|
let sz = Solution::compress(&mut e);
|
||||||
|
dbg!(sz, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Solution;
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: the key to making this work was using a separate "start" marker for the start index of the
|
||||||
|
current char; I kept trying to use the "write" variable compared with the read var.
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl Solution {
|
||||||
|
pub fn compress(chars: &mut [char]) -> i32 {
|
||||||
|
let (mut read, mut write) = (1, 0);
|
||||||
|
let len = chars.len();
|
||||||
|
let mut last = chars[0];
|
||||||
|
let mut start = 0;
|
||||||
|
while read < len {
|
||||||
|
let cur = chars[read];
|
||||||
|
if cur != last {
|
||||||
|
chars[write] = last;
|
||||||
|
last = cur;
|
||||||
|
let count = read - start;
|
||||||
|
start = read;
|
||||||
|
if count > 1 {
|
||||||
|
for c in Self::tok(count) {
|
||||||
|
write += 1;
|
||||||
|
chars[write] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write += 1;
|
||||||
|
}
|
||||||
|
read += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
chars[write] = last;
|
||||||
|
let count = read - start;
|
||||||
|
if count > 1 {
|
||||||
|
for c in Self::tok(count) {
|
||||||
|
write += 1;
|
||||||
|
chars[write] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write as i32 + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tok(num: usize) -> Vec<char> {
|
||||||
|
num.to_string().chars().collect()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue