diff --git a/Cargo.lock b/Cargo.lock index 6815a795..8c5231c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -322,10 +322,6 @@ version = "0.1.0" name = "lc-0053-maximum-subarray" version = "0.1.0" -[[package]] -name = "lc-0142-linked-list-cycle-ii" -version = "0.1.0" - [[package]] name = "lc-0191-number-of-1-bits" version = "0.1.0" @@ -338,6 +334,10 @@ version = "0.1.0" name = "lc-1115-print-foobar-alternately" version = "0.1.0" +[[package]] +name = "lc-1116-print-zero-even-odd" +version = "0.1.0" + [[package]] name = "lc-704-binary-search" version = "0.1.0" diff --git a/leetcode/1116.print-zero-even-odd/Cargo.toml b/leetcode/1116.print-zero-even-odd/Cargo.toml new file mode 100644 index 00000000..c785bdbe --- /dev/null +++ b/leetcode/1116.print-zero-even-odd/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "lc-1116-print-zero-even-odd" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/leetcode/1116.print-zero-even-odd/src/main.rs b/leetcode/1116.print-zero-even-odd/src/main.rs new file mode 100644 index 00000000..3a9bbc29 --- /dev/null +++ b/leetcode/1116.print-zero-even-odd/src/main.rs @@ -0,0 +1,11 @@ +// Copyright (c) 2023 Xu Shaohua . All rights reserved. +// Use of this source is governed by General Public License that can be +// found in the LICENSE file. + +mod with_atomic; +mod with_condvar; + +fn main() { + with_atomic::run(); + //with_condvar::run(); +} diff --git a/leetcode/1116.print-zero-even-odd/src/with_atomic.rs b/leetcode/1116.print-zero-even-odd/src/with_atomic.rs new file mode 100644 index 00000000..b01f9d3a --- /dev/null +++ b/leetcode/1116.print-zero-even-odd/src/with_atomic.rs @@ -0,0 +1,92 @@ +// Copyright (c) 2023 Xu Shaohua . All rights reserved. +// Use of this source is governed by General Public License that can be +// found in the LICENSE file. + +use std::hint; +use std::sync::atomic::{AtomicI32, Ordering}; +use std::sync::Arc; +use std::thread; + +struct ZeroEvenOdd { + n: i32, + counter: AtomicI32, +} + +fn print_number(x: i32) { + print!("{x}"); +} + +impl ZeroEvenOdd { + const ZERO: i32 = 0; + const ODD: i32 = 1; + const EVEN: i32 = 2; + + pub fn new(n: i32) -> Self { + Self { + n, + counter: AtomicI32::new(Self::ZERO), + } + } + + pub fn zero(&self) { + for i in 0..self.n { + while self.counter.load(Ordering::SeqCst) != Self::ZERO { + hint::spin_loop(); + } + + print_number(0); + let is_even = if (i + 1) % 2 == 0 { + Self::EVEN + } else { + Self::ODD + }; + self.counter.store(is_even, Ordering::SeqCst); + } + } + + pub fn even(&self) { + for i in (2..=self.n).step_by(2) { + while self.counter.load(Ordering::SeqCst) != Self::EVEN { + hint::spin_loop(); + } + + print_number(i); + self.counter.store(Self::ZERO, Ordering::SeqCst); + } + } + + pub fn odd(&self) { + for i in (1..=self.n).step_by(2) { + while self.counter.load(Ordering::SeqCst) != Self::ODD { + hint::spin_loop(); + } + + print_number(i); + self.counter.store(Self::ZERO, Ordering::SeqCst); + } + } +} + +pub fn run() { + //let n = 2; + let n = 5; + let zero_even_odd = Arc::new(ZeroEvenOdd::new(n)); + let a = { + let zero_even_odd = Arc::clone(&zero_even_odd); + thread::spawn(move || { + zero_even_odd.zero(); + }) + }; + let b = { + let zero_even_odd = Arc::clone(&zero_even_odd); + thread::spawn(move || { + zero_even_odd.even(); + }) + }; + let c = thread::spawn(move || { + zero_even_odd.odd(); + }); + let _ = a.join(); + let _ = b.join(); + let _ = c.join(); +} diff --git a/leetcode/1116.print-zero-even-odd/src/with_condvar.rs b/leetcode/1116.print-zero-even-odd/src/with_condvar.rs new file mode 100644 index 00000000..00935bb7 --- /dev/null +++ b/leetcode/1116.print-zero-even-odd/src/with_condvar.rs @@ -0,0 +1,98 @@ +// Copyright (c) 2023 Xu Shaohua . All rights reserved. +// Use of this source is governed by General Public License that can be +// found in the LICENSE file. + +#![allow(dead_code)] + +use std::sync::{Arc, Condvar, Mutex}; +use std::thread; + +struct ZeroEvenOdd { + n: i32, + mutex: Mutex, + cvar: Condvar, +} + +fn print_number(x: i32) { + print!("{x}"); +} + +impl ZeroEvenOdd { + const ZERO: i32 = 0; + const ODD: i32 = 1; + const EVEN: i32 = 2; + + pub fn new(n: i32) -> Self { + Self { + n, + mutex: Mutex::new(Self::ODD), + cvar: Condvar::new(), + } + } + + pub fn zero(&self) { + for i in 0..self.n { + eprintln!("zero() {i}"); + let mut counter = self.mutex.lock().unwrap(); + while *counter != Self::ZERO { + eprintln!("zero counter: {}", *counter); + counter = self.cvar.wait(counter).unwrap(); + } + print_number(0); + *counter = if i % 2 == 0 { Self::EVEN } else { Self::ODD }; + self.cvar.notify_all(); + } + } + + pub fn even(&self) { + for i in (0..self.n).step_by(2) { + eprintln!("even() {i}"); + let mut counter = self.mutex.lock().unwrap(); + while *counter != Self::EVEN { + eprintln!("even counter: {}", *counter); + counter = self.cvar.wait(counter).unwrap(); + } + print_number(i); + *counter = Self::ZERO; + self.cvar.notify_all(); + } + } + + pub fn odd(&self) { + for i in (1..self.n).step_by(2) { + eprintln!("odd() {i}"); + let mut counter = self.mutex.lock().unwrap(); + while *counter != Self::ODD { + eprintln!("odd counter: {}", *counter); + counter = self.cvar.wait(counter).unwrap(); + } + + print_number(i); + *counter = Self::ZERO; + self.cvar.notify_all(); + } + } +} + +pub fn run() { + let n = 1; + let zero_even_odd = Arc::new(ZeroEvenOdd::new(n)); + let a = { + let zero_even_odd = Arc::clone(&zero_even_odd); + thread::spawn(move || { + zero_even_odd.zero(); + }) + }; + let b = { + let zero_even_odd = Arc::clone(&zero_even_odd); + thread::spawn(move || { + zero_even_odd.even(); + }) + }; + let c = thread::spawn(move || { + zero_even_odd.odd(); + }); + let _ = a.join(); + let _ = b.join(); + let _ = c.join(); +}