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-derive = "0.3"
|
||||
lazy_static = "1.4.0"
|
||||
#itertools = "0.10.5"
|
||||
regex = "1.7"
|
||||
ndarray = "0.15"
|
||||
petgraph = "0.6"
|
||||
lyn = "0.1.0"
|
||||
|
|
|
@ -24,10 +24,10 @@ impl Default for Operation {
|
|||
}
|
||||
|
||||
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());
|
||||
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 {
|
||||
out.push((self.target.0, item));
|
||||
} else {
|
||||
|
@ -115,7 +115,7 @@ fn part1(troop: &[Monkey]) -> u128 {
|
|||
for _round in 0..20 {
|
||||
for i in 0..troop.len() {
|
||||
let monkey = &mut troop[i];
|
||||
let items = monkey.inspect();
|
||||
let items = monkey.inspect(&|item| item / 3);
|
||||
for (target, item) in items {
|
||||
let m = &mut troop[target];
|
||||
m.items.push_back(item);
|
||||
|
@ -128,9 +128,23 @@ fn part1(troop: &[Monkey]) -> u128 {
|
|||
|
||||
#[aoc_run(day11, part2)]
|
||||
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)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -172,129 +186,7 @@ Monkey 3:
|
|||
#[test]
|
||||
fn part2_test() {
|
||||
let v = parse_input(INPUT);
|
||||
assert_eq!(part2(&v), 1);
|
||||
}
|
||||
|
||||
#[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);
|
||||
assert_eq!(part2(&v), 2713310158);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
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 d10;
|
||||
mod d11;
|
||||
mod d12;
|
||||
mod d13;
|
||||
|
||||
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