Compare commits
No commits in common. "8789bbba49c1484ca52d39cf05096f201bd81545" and "da8635c06b65d92383fdabad4d66503c237db4e0" have entirely different histories.
8789bbba49
...
da8635c06b
11 changed files with 130 additions and 507 deletions
|
@ -9,7 +9,6 @@ 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, reducer: &dyn Fn(u128) -> u128) -> Vec<(usize, u128)> {
|
pub fn inspect(&mut self) -> 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 = reducer(self.op(item));
|
let item = self.op(item) / 3;
|
||||||
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(&|item| item / 3);
|
let items = monkey.inspect();
|
||||||
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,23 +128,9 @@ fn part1(troop: &[Monkey]) -> u128 {
|
||||||
|
|
||||||
#[aoc_run(day11, part2)]
|
#[aoc_run(day11, part2)]
|
||||||
fn part2(troop: &[Monkey]) -> u128 {
|
fn part2(troop: &[Monkey]) -> u128 {
|
||||||
let max: u128 = troop.iter().map(|m| m.tmod).product();
|
0
|
||||||
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::*;
|
||||||
|
@ -186,7 +172,129 @@ Monkey 3:
|
||||||
#[test]
|
#[test]
|
||||||
fn part2_test() {
|
fn part2_test() {
|
||||||
let v = parse_input(INPUT);
|
let v = parse_input(INPUT);
|
||||||
assert_eq!(part2(&v), 2713310158);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
|
@ -1,131 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -1,175 +0,0 @@
|
||||||
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,7 +11,5 @@ 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 }
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "increasing_triplet_subsequence"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
|
@ -1,23 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
[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]
|
|
|
@ -1,63 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "string_compression"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
|
@ -1,70 +0,0 @@
|
||||||
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