1#![warn(missing_docs)]
26#![allow(
27 clippy::for_kv_map,
28 clippy::multiple_bound_locations,
29 clippy::needless_range_loop,
30 clippy::type_complexity,
31 clippy::unnecessary_lazy_evaluations,
32 clippy::useless_vec
33)]
34
35use std::cmp::Ordering;
36use std::cmp::Reverse;
37use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
38use std::error::Error as StdError;
39use std::fmt;
40use std::hash::Hash;
41
42#[derive(Debug, Clone, PartialEq)]
44pub enum Error {
45 NotFound,
47 InvalidInput,
49 InvalidGraph,
51 NegativeCycle,
53}
54
55impl fmt::Display for Error {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 match self {
58 Error::NotFound => write!(f, "not found"),
59 Error::InvalidInput => write!(f, "invalid input"),
60 Error::InvalidGraph => write!(f, "invalid graph"),
61 Error::NegativeCycle => write!(f, "negative-weight cycle detected"),
62 }
63 }
64}
65
66impl StdError for Error {}
67
68pub fn quick_sort<T: Ord + Clone>(items: &[T]) -> Vec<T> {
73 if items.len() <= 1 {
74 return items.to_vec();
75 }
76 let pivot = items[items.len() / 2].clone();
77 let mut left = Vec::new();
78 let mut middle = Vec::new();
79 let mut right = Vec::new();
80 for x in items {
81 if *x < pivot {
82 left.push(x.clone());
83 } else if *x > pivot {
84 right.push(x.clone());
85 } else {
86 middle.push(x.clone());
87 }
88 }
89 let mut result = quick_sort(&left);
90 result.extend(middle);
91 result.extend(quick_sort(&right));
92 result
93}
94
95pub fn merge_sort<T: Ord + Clone>(items: &[T]) -> Vec<T> {
97 if items.len() <= 1 {
98 return items.to_vec();
99 }
100 let mid = items.len() / 2;
101 let left = merge_sort(&items[..mid]);
102 let right = merge_sort(&items[mid..]);
103 merge(&left, &right)
104}
105
106fn merge<T: Ord>(left: &[T], right: &[T]) -> Vec<T>
107where
108 T: Clone,
109{
110 let mut merged = Vec::with_capacity(left.len() + right.len());
111 let mut i = 0;
112 let mut j = 0;
113 while i < left.len() && j < right.len() {
114 if left[i] <= right[j] {
115 merged.push(left[i].clone());
116 i += 1;
117 } else {
118 merged.push(right[j].clone());
119 j += 1;
120 }
121 }
122 merged.extend_from_slice(&left[i..]);
123 merged.extend_from_slice(&right[j..]);
124 merged
125}
126
127pub fn heap_sort<T: Ord + Clone>(items: &[T]) -> Vec<T> {
129 let mut arr = items.to_vec();
130 let n = arr.len();
131 if n <= 1 {
132 return arr;
133 }
134 for i in (0..n / 2).rev() {
135 sift_down(&mut arr, n, i);
136 }
137 for end in (1..n).rev() {
138 arr.swap(0, end);
139 sift_down(&mut arr, end, 0);
140 }
141 arr
142}
143
144fn sift_down<T: Ord>(arr: &mut [T], n: usize, i: usize) {
145 let mut largest = i;
146 let left = 2 * i + 1;
147 let right = 2 * i + 2;
148 if left < n && arr[left] > arr[largest] {
149 largest = left;
150 }
151 if right < n && arr[right] > arr[largest] {
152 largest = right;
153 }
154 if largest != i {
155 arr.swap(i, largest);
156 sift_down(arr, n, largest);
157 }
158}
159
160pub fn quick_sort_in_place<T: Ord + Clone>(items: &mut [T]) {
166 let sorted = quick_sort(items);
167 items.clone_from_slice(&sorted);
168}
169
170pub fn merge_sort_in_place<T: Ord + Clone>(items: &mut [T]) {
175 let sorted = merge_sort(items);
176 items.clone_from_slice(&sorted);
177}
178
179pub fn heap_sort_in_place<T: Ord>(items: &mut [T]) {
182 let n = items.len();
183 if n <= 1 {
184 return;
185 }
186 for i in (0..n / 2).rev() {
187 sift_down(items, n, i);
188 }
189 for end in (1..n).rev() {
190 items.swap(0, end);
191 sift_down(items, end, 0);
192 }
193}
194
195pub fn radix_sort(items: &[i64]) -> Result<Vec<i64>, Error> {
197 if items.is_empty() {
198 return Ok(Vec::new());
199 }
200 let mut max_val = 0i64;
201 for &v in items {
202 if v < 0 {
203 return Err(Error::InvalidInput);
204 }
205 if v > max_val {
206 max_val = v;
207 }
208 }
209 let mut arr = items.to_vec();
210 let mut exp: i64 = 1;
211 while max_val / exp > 0 {
212 counting_sort_by_digit(&mut arr, exp);
213 if exp > i64::MAX / 10 {
216 break;
217 }
218 exp *= 10;
219 }
220 Ok(arr)
221}
222
223fn counting_sort_by_digit(arr: &mut [i64], exp: i64) {
224 let n = arr.len();
225 let mut output = vec![0; n];
226 let mut count = vec![0; 10];
227 for &num in arr.iter() {
228 count[((num / exp) % 10) as usize] += 1;
229 }
230 for i in 1..10 {
231 count[i] += count[i - 1];
232 }
233 for i in (0..n).rev() {
234 let index = ((arr[i] / exp) % 10) as usize;
235 output[count[index] - 1] = arr[i];
236 count[index] -= 1;
237 }
238 arr.copy_from_slice(&output);
239}
240
241pub fn native_sort<T: Ord + Clone>(items: &[T]) -> Vec<T> {
245 let mut arr = items.to_vec();
246 arr.sort();
247 arr
248}
249
250pub fn native_sort_in_place<T: Ord>(items: &mut [T]) {
252 items.sort();
253}
254
255fn is_sorted<T: Ord>(arr: &[T]) -> bool {
258 arr.windows(2).all(|w| w[0] <= w[1])
259}
260
261pub fn binary_search<T: Ord>(arr: &[T], target: &T) -> Result<usize, Error> {
275 debug_assert!(is_sorted(arr), "binary_search requires a sorted slice");
276 let mut lo = 0;
277 let mut hi = arr.len() as isize - 1;
278 while lo <= hi {
279 let mid = (lo + hi) / 2;
280 let mid_usize = mid as usize;
281 if &arr[mid_usize] == target {
282 return Ok(mid_usize);
283 }
284 if &arr[mid_usize] < target {
285 lo = mid + 1;
286 } else {
287 hi = mid - 1;
288 }
289 }
290 Err(Error::NotFound)
291}
292
293pub fn binary_search_on_answer(
298 low: i64,
299 high: i64,
300 predicate: impl Fn(i64) -> bool,
301 find: &str,
302) -> Result<i64, Error> {
303 if find != "minimum" && find != "maximum" {
304 return Err(Error::InvalidInput);
305 }
306 if low > high {
307 return Err(Error::NotFound);
308 }
309 let mut left = low;
310 let mut right = high;
311 let mut answer: Option<i64> = None;
312 if find == "minimum" {
313 while left <= right {
314 let mid = left + (right - left) / 2;
315 if predicate(mid) {
316 answer = Some(mid);
317 right = mid - 1;
318 } else {
319 left = mid + 1;
320 }
321 }
322 } else {
323 while left <= right {
324 let mid = left + (right - left) / 2;
325 if predicate(mid) {
326 answer = Some(mid);
327 left = mid + 1;
328 } else {
329 right = mid - 1;
330 }
331 }
332 }
333 answer.ok_or(Error::NotFound)
334}
335
336pub fn interpolation_search(arr: &[i64], target: i64) -> Result<usize, Error> {
342 debug_assert!(
343 is_sorted(arr),
344 "interpolation_search requires a sorted slice"
345 );
346 let mut lo = 0;
347 let mut hi = arr.len() as isize - 1;
348 while lo <= hi && target >= arr[lo as usize] && target <= arr[hi as usize] {
349 if arr[hi as usize] == arr[lo as usize] {
350 if arr[lo as usize] == target {
351 return Ok(lo as usize);
352 }
353 break;
354 }
355 let lo_usize = lo as usize;
356 let hi_usize = hi as usize;
357 let numerator = (target as i128 - arr[lo_usize] as i128) * ((hi_usize - lo_usize) as i128);
360 let denominator = arr[hi_usize] as i128 - arr[lo_usize] as i128;
361 let pos = lo_usize + (numerator / denominator) as usize;
362 if pos < lo_usize || pos > hi_usize {
363 break;
364 }
365 if arr[pos] == target {
366 return Ok(pos);
367 }
368 if arr[pos] < target {
369 lo = pos as isize + 1;
370 } else {
371 hi = pos as isize - 1;
372 }
373 }
374 Err(Error::NotFound)
375}
376
377pub fn jump_search<T: Ord>(arr: &[T], target: &T) -> Result<usize, Error> {
383 debug_assert!(is_sorted(arr), "jump_search requires a sorted slice");
384 let n = arr.len();
385 if n == 0 {
386 return Err(Error::NotFound);
387 }
388 let mut step = (n as f64).sqrt() as usize;
389 if step == 0 {
390 step = 1;
391 }
392 let mut prev = 0;
393 while arr[step.min(n) - 1] < *target {
394 prev = step;
395 step += (n as f64).sqrt() as usize;
396 if prev >= n {
397 return Err(Error::NotFound);
398 }
399 }
400 while arr[prev] < *target {
401 prev += 1;
402 if prev == step.min(n) {
403 return Err(Error::NotFound);
404 }
405 }
406 if &arr[prev] == target {
407 return Ok(prev);
408 }
409 Err(Error::NotFound)
410}
411
412#[derive(Debug, Clone, PartialEq)]
416pub struct Edge {
417 pub to: String,
419 pub weight: f64,
422}
423
424impl Edge {
425 pub fn new(to: &str, weight: f64) -> Self {
427 Edge {
428 to: to.to_string(),
429 weight,
430 }
431 }
432}
433
434fn validate_adjacency_list(graph: &HashMap<String, Vec<String>>) -> Result<(), Error> {
437 for neighbors in graph.values() {
438 for nbr in neighbors {
439 if !graph.contains_key(nbr) {
440 return Err(Error::InvalidGraph);
441 }
442 }
443 }
444 Ok(())
445}
446
447pub fn bfs(graph: &HashMap<String, Vec<String>>, start: &str) -> Result<Vec<String>, Error> {
452 if !graph.contains_key(start) {
453 return Err(Error::InvalidGraph);
454 }
455 validate_adjacency_list(graph)?;
456 let mut visited = HashSet::new();
457 visited.insert(start.to_string());
458 let mut queue = VecDeque::new();
459 queue.push_back(start.to_string());
460 let mut result = Vec::new();
461 while let Some(current) = queue.pop_front() {
462 result.push(current.clone());
463 if let Some(neighbors) = graph.get(¤t) {
464 for nbr in neighbors {
465 if visited.insert(nbr.clone()) {
466 queue.push_back(nbr.clone());
467 }
468 }
469 }
470 }
471 Ok(result)
472}
473
474pub fn dfs(graph: &HashMap<String, Vec<String>>, start: &str) -> Result<Vec<String>, Error> {
479 if !graph.contains_key(start) {
480 return Err(Error::InvalidGraph);
481 }
482 validate_adjacency_list(graph)?;
483 let mut visited = HashSet::new();
484 visited.insert(start.to_string());
485 let mut stack = vec![start.to_string()];
486 let mut result = Vec::new();
487 while let Some(current) = stack.pop() {
488 result.push(current.clone());
489 if let Some(neighbors) = graph.get(¤t) {
490 for nbr in neighbors.iter().rev() {
491 if visited.insert(nbr.clone()) {
492 stack.push(nbr.clone());
493 }
494 }
495 }
496 }
497 Ok(result)
498}
499
500#[derive(Clone)]
501struct State {
502 cost: f64,
503 node: String,
504}
505
506impl PartialEq for State {
507 fn eq(&self, other: &Self) -> bool {
508 self.cost.total_cmp(&other.cost) == Ordering::Equal && self.node == other.node
509 }
510}
511
512impl Eq for State {}
513
514impl PartialOrd for State {
515 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
516 Some(self.cmp(other))
517 }
518}
519
520impl Ord for State {
521 fn cmp(&self, other: &Self) -> Ordering {
522 other
523 .cost
524 .total_cmp(&self.cost)
525 .then_with(|| self.node.cmp(&other.node))
526 }
527}
528
529pub fn dijkstra(
531 graph: &HashMap<String, Vec<Edge>>,
532 start: &str,
533) -> Result<(HashMap<String, f64>, HashMap<String, String>), Error> {
534 if !graph.contains_key(start) {
535 return Err(Error::InvalidGraph);
536 }
537
538 let mut all_nodes: HashSet<String> = graph.keys().cloned().collect();
541 let mut negative = false;
542 for edges in graph.values() {
543 for e in edges {
544 if e.weight < 0.0 || !e.weight.is_finite() {
545 negative = true;
546 }
547 all_nodes.insert(e.to.clone());
548 }
549 }
550 if negative {
551 return Err(Error::InvalidGraph);
552 }
553
554 let mut distances: HashMap<String, f64> = all_nodes
555 .iter()
556 .map(|k| (k.clone(), f64::INFINITY))
557 .collect();
558 distances.insert(start.to_string(), 0.0);
559 let mut predecessors = HashMap::new();
560
561 let mut pq = BinaryHeap::new();
562 pq.push(State {
563 cost: 0.0,
564 node: start.to_string(),
565 });
566
567 while let Some(State { cost, node }) = pq.pop() {
568 if cost > distances[&node] {
569 continue;
570 }
571 if let Some(edges) = graph.get(&node) {
572 for e in edges {
573 let nd = cost + e.weight;
574 let current = distances.get(&e.to).copied().unwrap_or(f64::INFINITY);
575 if nd < current {
576 distances.insert(e.to.clone(), nd);
577 predecessors.insert(e.to.clone(), node.clone());
578 pq.push(State {
579 cost: nd,
580 node: e.to.clone(),
581 });
582 }
583 }
584 }
585 }
586 Ok((distances, predecessors))
587}
588
589pub fn a_star<F>(
597 graph: &HashMap<String, Vec<Edge>>,
598 start: &str,
599 goal: &str,
600 heuristic: F,
601) -> Result<(Vec<String>, f64), Error>
602where
603 F: Fn(&str, &str) -> f64,
604{
605 if !graph.contains_key(start) || !graph.contains_key(goal) {
606 return Err(Error::InvalidGraph);
607 }
608
609 let h = heuristic(start, goal);
610 if h < 0.0 {
611 return Err(Error::InvalidInput);
612 }
613
614 let mut g_score = HashMap::new();
615 g_score.insert(start.to_string(), 0.0);
616 let mut best_f: HashMap<String, f64> = HashMap::new();
617 best_f.insert(start.to_string(), h);
618 let mut came_from = HashMap::new();
619 let mut pq = BinaryHeap::new();
620 pq.push(State {
621 cost: h,
622 node: start.to_string(),
623 });
624
625 while let Some(State { cost, node }) = pq.pop() {
626 if let Some(&best) = best_f.get(&node) {
627 if cost > best {
628 continue;
629 }
630 }
631 if node == goal {
632 return Ok((reconstruct_path(&came_from, &node), g_score[goal]));
633 }
634 if let Some(edges) = graph.get(&node) {
635 for e in edges {
636 if e.weight < 0.0 || !e.weight.is_finite() {
637 return Err(Error::InvalidGraph);
638 }
639 let h_nbr = heuristic(&e.to, goal);
640 if h_nbr < 0.0 {
641 return Err(Error::InvalidInput);
642 }
643 let tentative = g_score[&node] + e.weight;
644 let current = g_score.get(&e.to).copied().unwrap_or(f64::INFINITY);
645 if tentative < current {
646 came_from.insert(e.to.clone(), node.clone());
647 g_score.insert(e.to.clone(), tentative);
648 let f = tentative + h_nbr;
649 let best = best_f.get(&e.to).copied().unwrap_or(f64::INFINITY);
650 if f < best {
651 best_f.insert(e.to.clone(), f);
652 pq.push(State {
653 cost: f,
654 node: e.to.clone(),
655 });
656 }
657 }
658 }
659 }
660 }
661 Err(Error::NotFound)
662}
663
664fn reconstruct_path(came_from: &HashMap<String, String>, goal: &str) -> Vec<String> {
665 let mut current = goal.to_string();
666 let mut path = vec![current.clone()];
667 while let Some(prev) = came_from.get(¤t) {
668 path.push(prev.clone());
669 current = prev.clone();
670 }
671 path.reverse();
672 path
673}
674
675struct Edge3 {
676 from: String,
677 to: String,
678 weight: f64,
679}
680
681pub fn bellman_ford(
683 graph: &HashMap<String, Vec<Edge>>,
684 start: &str,
685) -> Result<(HashMap<String, f64>, HashMap<String, String>), Error> {
686 if !graph.contains_key(start) {
687 return Err(Error::InvalidGraph);
688 }
689 let mut vertices = HashSet::new();
690 let mut edges = Vec::new();
691 for (u, list) in graph {
692 vertices.insert(u.clone());
693 for e in list {
694 vertices.insert(e.to.clone());
695 edges.push(Edge3 {
696 from: u.clone(),
697 to: e.to.clone(),
698 weight: e.weight,
699 });
700 }
701 }
702 let mut distances = HashMap::new();
703 distances.insert(start.to_string(), 0.0);
704 let mut predecessors = HashMap::new();
705
706 for _ in 0..vertices.len().saturating_sub(1) {
707 let mut updated = false;
708 for e in &edges {
709 if let Some(&du) = distances.get(&e.from) {
710 let dv = distances.get(&e.to).copied().unwrap_or(f64::INFINITY);
711 if du + e.weight < dv {
712 distances.insert(e.to.clone(), du + e.weight);
713 predecessors.insert(e.to.clone(), e.from.clone());
714 updated = true;
715 }
716 }
717 }
718 if !updated {
719 break;
720 }
721 }
722
723 for e in &edges {
724 if let Some(&du) = distances.get(&e.from) {
725 let dv = distances.get(&e.to).copied().unwrap_or(f64::INFINITY);
726 if du + e.weight < dv {
727 return Err(Error::NegativeCycle);
728 }
729 }
730 }
731 Ok((distances, predecessors))
732}
733
734pub fn knapsack_01(weights: &[i64], values: &[i64], capacity: i64) -> Result<i64, Error> {
742 if weights.len() != values.len() {
743 return Err(Error::InvalidInput);
744 }
745 let cap = usize::try_from(capacity).map_err(|_| Error::InvalidInput)?;
746 let mut dp = vec![0; cap + 1];
747 for i in 0..weights.len() {
748 let w = usize::try_from(weights[i]).map_err(|_| Error::InvalidInput)?;
749 let v = values[i];
750 for c in (w..=cap).rev() {
751 if dp[c - w] + v > dp[c] {
752 dp[c] = dp[c - w] + v;
753 }
754 }
755 }
756 Ok(dp[cap])
757}
758
759pub fn longest_common_subsequence<T: PartialEq>(a: &[T], b: &[T]) -> usize {
761 let (m, n) = (a.len(), b.len());
762 let mut prev = vec![0; n + 1];
763 for i in 1..=m {
764 let mut curr = vec![0; n + 1];
765 for j in 1..=n {
766 if a[i - 1] == b[j - 1] {
767 curr[j] = prev[j - 1] + 1;
768 } else {
769 curr[j] = prev[j].max(curr[j - 1]);
770 }
771 }
772 prev = curr;
773 }
774 prev[n]
775}
776
777pub fn edit_distance<T: PartialEq>(a: &[T], b: &[T]) -> usize {
779 let (m, n) = (a.len(), b.len());
780 let mut prev: Vec<usize> = (0..=n).collect();
781 for i in 1..=m {
782 let mut curr = vec![0; n + 1];
783 curr[0] = i;
784 for j in 1..=n {
785 let cost = if a[i - 1] == b[j - 1] { 0 } else { 1 };
786 let insertion = curr[j - 1] + 1;
787 let deletion = prev[j] + 1;
788 let substitution = prev[j - 1] + cost;
789 curr[j] = insertion.min(deletion).min(substitution);
790 }
791 prev = curr;
792 }
793 prev[n]
794}
795
796#[derive(Debug, PartialEq, Clone)]
798pub enum EditOp<T: Clone + PartialEq> {
799 Match(T),
801 Delete(T),
803 Insert(T),
805 Substitute {
807 from: T,
809 to: T,
811 },
812}
813
814pub fn edit_distance_reconstruction<T: PartialEq + Clone>(
816 a: &[T],
817 b: &[T],
818) -> (usize, Vec<EditOp<T>>) {
819 let (m, n) = (a.len(), b.len());
820 let mut dp = vec![vec![0; n + 1]; m + 1];
821 for i in 0..=m {
822 dp[i][0] = i;
823 }
824 for j in 0..=n {
825 dp[0][j] = j;
826 }
827 for i in 1..=m {
828 for j in 1..=n {
829 if a[i - 1] == b[j - 1] {
830 dp[i][j] = dp[i - 1][j - 1];
831 } else {
832 dp[i][j] = 1 + dp[i - 1][j].min(dp[i][j - 1]).min(dp[i - 1][j - 1]);
833 }
834 }
835 }
836 let mut script = Vec::new();
837 let (mut i, mut j) = (m, n);
838 while i > 0 || j > 0 {
839 if i == 0 {
840 script.push(EditOp::Insert(b[j - 1].clone()));
841 j -= 1;
842 } else if j == 0 {
843 script.push(EditOp::Delete(a[i - 1].clone()));
844 i -= 1;
845 } else if a[i - 1] == b[j - 1] {
846 script.push(EditOp::Match(a[i - 1].clone()));
847 i -= 1;
848 j -= 1;
849 } else {
850 let best = dp[i][j];
851 if dp[i - 1][j - 1] + 1 == best {
852 script.push(EditOp::Substitute {
853 from: a[i - 1].clone(),
854 to: b[j - 1].clone(),
855 });
856 i -= 1;
857 j -= 1;
858 } else if dp[i][j - 1] + 1 == best {
859 script.push(EditOp::Insert(b[j - 1].clone()));
860 j -= 1;
861 } else {
862 script.push(EditOp::Delete(a[i - 1].clone()));
863 i -= 1;
864 }
865 }
866 }
867 script.reverse();
868 (dp[m][n], script)
869}
870
871pub fn longest_common_subsequence_reconstruction<T: PartialEq + Clone>(
873 a: &[T],
874 b: &[T],
875) -> (usize, Vec<T>) {
876 let (m, n) = (a.len(), b.len());
877 let mut dp = vec![vec![0; n + 1]; m + 1];
878 for i in 1..=m {
879 for j in 1..=n {
880 if a[i - 1] == b[j - 1] {
881 dp[i][j] = dp[i - 1][j - 1] + 1;
882 } else {
883 dp[i][j] = dp[i - 1][j].max(dp[i][j - 1]);
884 }
885 }
886 }
887 let mut result = Vec::with_capacity(dp[m][n]);
888 let (mut i, mut j) = (m, n);
889 while i > 0 && j > 0 {
890 if a[i - 1] == b[j - 1] {
891 result.push(a[i - 1].clone());
892 i -= 1;
893 j -= 1;
894 } else if dp[i - 1][j] >= dp[i][j - 1] {
895 i -= 1;
896 } else {
897 j -= 1;
898 }
899 }
900 result.reverse();
901 (dp[m][n], result)
902}
903
904pub fn kmp_search(text: &str, pattern: &str) -> Result<Vec<usize>, Error> {
912 if pattern.is_empty() {
913 return Err(Error::InvalidInput);
914 }
915 let t = text.as_bytes();
916 let p = pattern.as_bytes();
917 let failure = compute_kmp_failure(p);
918 let mut matches = Vec::new();
919 let mut j = 0;
920 for i in 0..t.len() {
921 while j > 0 && t[i] != p[j] {
922 j = failure[j - 1];
923 }
924 if t[i] == p[j] {
925 j += 1;
926 }
927 if j == p.len() {
928 matches.push(i + 1 - p.len());
929 j = failure[j - 1];
930 }
931 }
932 Ok(matches)
933}
934
935fn compute_kmp_failure(pattern: &[u8]) -> Vec<usize> {
936 let mut failure = vec![0; pattern.len()];
937 let mut j = 0;
938 for i in 1..pattern.len() {
939 while j > 0 && pattern[i] != pattern[j] {
940 j = failure[j - 1];
941 }
942 if pattern[i] == pattern[j] {
943 j += 1;
944 failure[i] = j;
945 }
946 }
947 failure
948}
949
950pub fn rabin_karp_search(
959 text: &str,
960 pattern: &str,
961 base: i64,
962 modulus: i64,
963) -> Result<Vec<usize>, Error> {
964 if pattern.is_empty() {
965 return Err(Error::InvalidInput);
966 }
967 if modulus <= 0 {
968 return Err(Error::InvalidInput);
969 }
970 if base <= 0 {
971 return Err(Error::InvalidInput);
972 }
973
974 let t = text.as_bytes();
975 let p = pattern.as_bytes();
976 let (n, m) = (t.len(), p.len());
977 if m > n {
978 return Ok(Vec::new());
979 }
980
981 let base = base as i128;
982 let modulus = modulus as i128;
983
984 let mut h = 1i128;
985 for _ in 0..m - 1 {
986 h = (h * base) % modulus;
987 }
988 let mut pattern_hash = 0i128;
989 let mut text_hash = 0i128;
990 for i in 0..m {
991 pattern_hash = (pattern_hash * base + p[i] as i128) % modulus;
992 text_hash = (text_hash * base + t[i] as i128) % modulus;
993 }
994 let mut matches = Vec::new();
995 for i in 0..=n - m {
996 if text_hash == pattern_hash && &t[i..i + m] == p {
997 matches.push(i);
998 }
999 if i < n - m {
1000 text_hash = (text_hash - (t[i] as i128) * h).rem_euclid(modulus);
1001 text_hash = (text_hash * base + t[i + m] as i128).rem_euclid(modulus);
1002 }
1003 }
1004 Ok(matches)
1005}
1006
1007pub fn boyer_moore_search(text: &str, pattern: &str) -> Result<Vec<usize>, Error> {
1013 if pattern.is_empty() {
1014 return Err(Error::InvalidInput);
1015 }
1016 let t = text.as_bytes();
1017 let p = pattern.as_bytes();
1018 let (n, m) = (t.len(), p.len());
1019 if m > n {
1020 return Ok(Vec::new());
1021 }
1022 let mut bad_char = HashMap::new();
1023 for (i, &b) in p.iter().enumerate() {
1024 bad_char.insert(b, i);
1025 }
1026 let good_suffix = good_suffix_shifts(p);
1027 let mut matches = Vec::new();
1028 let mut i = 0usize;
1029 while i <= n - m {
1030 let mut j = m as isize - 1;
1031 while j >= 0 && t[i + j as usize] == p[j as usize] {
1032 j -= 1;
1033 }
1034 if j < 0 {
1035 matches.push(i);
1036 i += good_suffix[0];
1037 } else {
1038 let last = bad_char
1039 .get(&t[i + j as usize])
1040 .map(|&l| l as isize)
1041 .unwrap_or(-1);
1042 i += (good_suffix[j as usize + 1] as isize).max(j - last).max(1) as usize;
1043 }
1044 }
1045 Ok(matches)
1046}
1047
1048fn good_suffix_shifts(pattern: &[u8]) -> Vec<usize> {
1053 let m = pattern.len();
1054 let mut shift = vec![0usize; m + 1];
1055 let mut border_pos = vec![0usize; m + 1];
1056 let (mut i, mut j) = (m, m + 1);
1057 border_pos[i] = j;
1058 while i > 0 {
1059 while j <= m && pattern[i - 1] != pattern[j - 1] {
1060 if shift[j] == 0 {
1061 shift[j] = j - i;
1062 }
1063 j = border_pos[j];
1064 }
1065 i -= 1;
1066 j -= 1;
1067 border_pos[i] = j;
1068 }
1069 let mut j = border_pos[0];
1070 for i in 0..=m {
1071 if shift[i] == 0 {
1072 shift[i] = j;
1073 }
1074 if i == j {
1075 j = border_pos[j];
1076 }
1077 }
1078 shift
1079}
1080
1081pub fn activity_selection(activities: &[(i64, i64)]) -> Result<Vec<usize>, Error> {
1085 if activities.is_empty() {
1086 return Ok(Vec::new());
1087 }
1088 #[derive(Clone, Copy)]
1089 struct Indexed {
1090 index: usize,
1091 start: i64,
1092 end: i64,
1093 }
1094 let mut list = Vec::with_capacity(activities.len());
1095 for (i, &(start, end)) in activities.iter().enumerate() {
1096 if start > end {
1097 return Err(Error::InvalidInput);
1098 }
1099 list.push(Indexed {
1100 index: i,
1101 start,
1102 end,
1103 });
1104 }
1105 list.sort_by_key(|a| a.end);
1106 let mut selected = vec![list[0].index];
1107 let mut last_end = list[0].end;
1108 for item in list.iter().skip(1) {
1109 if item.start >= last_end {
1110 selected.push(item.index);
1111 last_end = item.end;
1112 }
1113 }
1114 Ok(selected)
1115}
1116
1117pub fn fractional_knapsack(weights: &[f64], values: &[f64], capacity: f64) -> Result<f64, Error> {
1124 if weights.len() != values.len() {
1125 return Err(Error::InvalidInput);
1126 }
1127 if capacity < 0.0 {
1128 return Err(Error::InvalidInput);
1129 }
1130 #[derive(Clone, Copy)]
1131 struct Item {
1132 ratio: f64,
1133 weight: f64,
1134 }
1135 let mut items = Vec::with_capacity(weights.len());
1136 let mut total = 0.0;
1137 for i in 0..weights.len() {
1138 if weights[i] < 0.0 || weights[i].is_nan() || values[i].is_nan() {
1139 return Err(Error::InvalidInput);
1140 }
1141 if weights[i] == 0.0 {
1142 total += values[i].max(0.0);
1144 continue;
1145 }
1146 items.push(Item {
1147 ratio: values[i] / weights[i],
1148 weight: weights[i],
1149 });
1150 }
1151 items.sort_by(|a, b| b.ratio.partial_cmp(&a.ratio).unwrap_or(Ordering::Equal));
1152 let mut remaining = capacity;
1153 for it in items {
1154 if it.ratio <= 0.0 {
1155 break; }
1157 let take = it.weight.min(remaining);
1158 total += take * it.ratio;
1159 remaining -= take;
1160 if remaining <= 0.0 {
1161 break;
1162 }
1163 }
1164 Ok(total)
1165}
1166
1167struct HuffmanNode {
1168 freq: i64,
1169 char: String,
1170 left: Option<Box<HuffmanNode>>,
1171 right: Option<Box<HuffmanNode>>,
1172}
1173
1174impl PartialEq for HuffmanNode {
1175 fn eq(&self, other: &Self) -> bool {
1176 self.freq == other.freq && self.char == other.char
1177 }
1178}
1179
1180impl Eq for HuffmanNode {}
1181
1182impl PartialOrd for HuffmanNode {
1183 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1184 Some(self.cmp(other))
1185 }
1186}
1187
1188impl Ord for HuffmanNode {
1189 fn cmp(&self, other: &Self) -> Ordering {
1190 self.freq
1191 .cmp(&other.freq)
1192 .then_with(|| self.char.cmp(&other.char))
1193 }
1194}
1195
1196pub fn huffman_coding(
1202 frequencies: &HashMap<String, i64>,
1203) -> Result<HashMap<String, String>, Error> {
1204 if frequencies.is_empty() {
1205 return Err(Error::InvalidInput);
1206 }
1207 if frequencies.values().any(|&f| f <= 0) {
1208 return Err(Error::InvalidInput);
1209 }
1210 let mut pq = BinaryHeap::new();
1211 for (ch, &freq) in frequencies {
1212 pq.push(Reverse(HuffmanNode {
1213 freq,
1214 char: ch.clone(),
1215 left: None,
1216 right: None,
1217 }));
1218 }
1219 if pq.len() == 1 {
1220 let node = pq.pop().unwrap().0;
1221 let mut codes = HashMap::new();
1222 codes.insert(node.char, "0".to_string());
1223 return Ok(codes);
1224 }
1225 while pq.len() > 1 {
1226 let left = pq.pop().unwrap().0;
1227 let right = pq.pop().unwrap().0;
1228 let parent = HuffmanNode {
1229 freq: left.freq + right.freq,
1230 char: String::new(),
1231 left: Some(Box::new(left)),
1232 right: Some(Box::new(right)),
1233 };
1234 pq.push(Reverse(parent));
1235 }
1236 let root = pq.pop().unwrap().0;
1237 let mut codes = HashMap::new();
1238 assign_huffman_codes(&root, "", &mut codes);
1239 Ok(codes)
1240}
1241
1242fn assign_huffman_codes(node: &HuffmanNode, prefix: &str, codes: &mut HashMap<String, String>) {
1243 if node.left.is_none() && node.right.is_none() {
1246 if prefix.is_empty() {
1247 codes.insert(node.char.clone(), "0".to_string());
1248 } else {
1249 codes.insert(node.char.clone(), prefix.to_string());
1250 }
1251 return;
1252 }
1253 if let Some(ref left) = node.left {
1254 assign_huffman_codes(left, &format!("{}0", prefix), codes);
1255 }
1256 if let Some(ref right) = node.right {
1257 assign_huffman_codes(right, &format!("{}1", prefix), codes);
1258 }
1259}
1260
1261pub fn huffman_encode(
1263 symbols: &[String],
1264 code_table: &HashMap<String, String>,
1265) -> Result<String, Error> {
1266 let mut parts = Vec::with_capacity(symbols.len());
1267 for s in symbols {
1268 let code = code_table.get(s).ok_or_else(|| Error::InvalidInput)?;
1269 parts.push(code.clone());
1270 }
1271 Ok(parts.concat())
1272}
1273
1274pub fn huffman_decode(
1276 encoded: &str,
1277 code_table: &HashMap<String, String>,
1278) -> Result<Vec<String>, Error> {
1279 let mut reverse = HashMap::with_capacity(code_table.len());
1280 for (s, code) in code_table {
1281 reverse.insert(code.clone(), s.clone());
1282 }
1283 let mut result = Vec::new();
1284 let mut current = String::new();
1285 for bit in encoded.chars() {
1286 current.push(bit);
1287 if let Some(s) = reverse.get(¤t) {
1288 result.push(s.clone());
1289 current.clear();
1290 }
1291 }
1292 if !current.is_empty() {
1293 return Err(Error::InvalidInput);
1294 }
1295 Ok(result)
1296}
1297
1298pub fn max_subarray(arr: &[i64]) -> Result<i64, Error> {
1302 if arr.is_empty() {
1303 return Err(Error::InvalidInput);
1304 }
1305 Ok(max_subarray_dc(arr, 0, arr.len() - 1))
1306}
1307
1308fn max_subarray_dc(arr: &[i64], left: usize, right: usize) -> i64 {
1309 if left == right {
1310 return arr[left];
1311 }
1312 let mid = (left + right) / 2;
1313 let left_sum = max_subarray_dc(arr, left, mid);
1314 let right_sum = max_subarray_dc(arr, mid + 1, right);
1315 let cross_sum = max_crossing_sum(arr, left, mid, right);
1316 left_sum.max(right_sum).max(cross_sum)
1317}
1318
1319fn max_crossing_sum(arr: &[i64], left: usize, mid: usize, right: usize) -> i64 {
1320 let mut sum = arr[mid];
1321 let mut left_max = arr[mid];
1322 for i in (left..mid).rev() {
1323 sum += arr[i];
1324 if sum > left_max {
1325 left_max = sum;
1326 }
1327 }
1328 sum = arr[mid + 1];
1329 let mut right_max = arr[mid + 1];
1330 for i in mid + 2..=right {
1331 sum += arr[i];
1332 if sum > right_max {
1333 right_max = sum;
1334 }
1335 }
1336 left_max + right_max
1337}
1338
1339pub fn count_inversions<T: Ord + Clone>(arr: &[T]) -> usize {
1341 let (_, count) = sort_and_count(arr);
1342 count
1343}
1344
1345fn sort_and_count<T: Ord + Clone>(arr: &[T]) -> (Vec<T>, usize) {
1346 let n = arr.len();
1347 if n <= 1 {
1348 return (arr.to_vec(), 0);
1349 }
1350 let mid = n / 2;
1351 let (left, lcount) = sort_and_count(&arr[..mid]);
1352 let (right, rcount) = sort_and_count(&arr[mid..]);
1353 let (merged, scount) = merge_and_count(&left, &right);
1354 (merged, lcount + rcount + scount)
1355}
1356
1357fn merge_and_count<T: Ord + Clone>(left: &[T], right: &[T]) -> (Vec<T>, usize) {
1358 let mut merged = Vec::with_capacity(left.len() + right.len());
1359 let mut count = 0;
1360 let mut i = 0;
1361 let mut j = 0;
1362 while i < left.len() && j < right.len() {
1363 if left[i] <= right[j] {
1364 merged.push(left[i].clone());
1365 i += 1;
1366 } else {
1367 merged.push(right[j].clone());
1368 j += 1;
1369 count += left.len() - i;
1370 }
1371 }
1372 merged.extend_from_slice(&left[i..]);
1373 merged.extend_from_slice(&right[j..]);
1374 (merged, count)
1375}
1376
1377pub fn fast_power(base: f64, exponent: i64) -> Result<f64, Error> {
1380 if base == 0.0 && exponent < 0 {
1381 return Err(Error::InvalidInput);
1382 }
1383 let mut exp = exponent.unsigned_abs();
1386 let mut result = 1.0f64;
1387 let mut b = base;
1388 while exp > 0 {
1389 if exp & 1 == 1 {
1390 result *= b;
1391 }
1392 b *= b;
1393 exp >>= 1;
1394 }
1395 if exponent < 0 {
1396 result = 1.0 / result;
1397 }
1398 Ok(result)
1399}
1400
1401pub fn gcd(a: i64, b: i64) -> Result<i64, Error> {
1406 let mut a = a.unsigned_abs();
1407 let mut b = b.unsigned_abs();
1408 while b != 0 {
1409 (a, b) = (b, a % b);
1410 }
1411 if a > i64::MAX as u64 {
1412 return Err(Error::InvalidInput);
1413 }
1414 Ok(a as i64)
1415}
1416
1417pub fn lcm(a: i64, b: i64) -> Result<i64, Error> {
1422 if a == 0 && b == 0 {
1423 return Err(Error::InvalidInput);
1424 }
1425 let g = gcd(a, b)?;
1426 let a_div = (a / g) as i128;
1427 let b_i = b as i128;
1428 let result = (a_div * b_i).abs();
1429 if result > i64::MAX as i128 {
1430 return Err(Error::InvalidInput);
1431 }
1432 Ok(result as i64)
1433}
1434
1435pub fn modular_fast_power(base: i64, exponent: i64, modulus: i64) -> Result<i64, Error> {
1440 if modulus <= 0 {
1441 return Err(Error::InvalidInput);
1442 }
1443 if exponent < 0 {
1444 return Err(Error::InvalidInput);
1445 }
1446 if modulus == 1 {
1447 return Ok(0);
1448 }
1449 let m = modulus as i128;
1450 let mut b = (base % modulus) as i128;
1451 if b < 0 {
1452 b += m;
1453 }
1454 let mut result: i128 = 1;
1455 let mut exp = exponent as u64;
1456 while exp > 0 {
1457 if exp & 1 == 1 {
1458 result = (result * b) % m;
1459 }
1460 b = (b * b) % m;
1461 exp >>= 1;
1462 }
1463 Ok(result as i64)
1464}
1465
1466pub fn quick_select<T: Ord + Clone>(items: &[T], k: usize) -> Result<T, Error> {
1470 if k >= items.len() {
1471 return Err(Error::InvalidInput);
1472 }
1473 let mut arr = items.to_vec();
1474 let mut k = k;
1475 loop {
1476 if arr.len() == 1 {
1477 return Ok(arr[0].clone());
1478 }
1479 let pivot = arr[arr.len() / 2].clone();
1480 let mut lows = Vec::new();
1481 let mut pivots = Vec::new();
1482 let mut highs = Vec::new();
1483 for x in &arr {
1484 match x.cmp(&pivot) {
1485 Ordering::Less => lows.push(x.clone()),
1486 Ordering::Greater => highs.push(x.clone()),
1487 Ordering::Equal => pivots.push(x.clone()),
1488 }
1489 }
1490 if k < lows.len() {
1491 arr = lows;
1492 } else if k < lows.len() + pivots.len() {
1493 return Ok(pivot);
1494 } else {
1495 k -= lows.len() + pivots.len();
1496 arr = highs;
1497 }
1498 }
1499}
1500
1501pub fn sieve_of_eratosthenes(n: i64) -> Result<Vec<i64>, Error> {
1503 if n < 0 {
1504 return Err(Error::InvalidInput);
1505 }
1506 let n = n as usize;
1507 if n < 2 {
1508 return Ok(Vec::new());
1509 }
1510 let mut sieve = vec![true; n + 1];
1511 sieve[0] = false;
1512 sieve[1] = false;
1513 let limit = (n as f64).sqrt() as usize;
1514 for p in 2..=limit {
1515 if sieve[p] {
1516 let mut multiple = p * p;
1517 while multiple <= n {
1518 sieve[multiple] = false;
1519 multiple += p;
1520 }
1521 }
1522 }
1523 Ok(sieve
1524 .iter()
1525 .enumerate()
1526 .filter(|(_, &is_prime)| is_prime)
1527 .map(|(i, _)| i as i64)
1528 .collect())
1529}
1530
1531pub fn topological_sort(graph: &HashMap<String, Vec<String>>) -> Result<Vec<String>, Error> {
1533 validate_adjacency_list(graph)?;
1534 let mut in_degree: HashMap<String, usize> = HashMap::new();
1535 for (node, _) in graph {
1536 in_degree.insert(node.clone(), 0);
1537 }
1538 for (_, neighbors) in graph {
1539 for nbr in neighbors {
1540 *in_degree.get_mut(nbr).unwrap() += 1;
1541 }
1542 }
1543
1544 let mut queue: VecDeque<String> = in_degree
1545 .iter()
1546 .filter(|(_, °)| deg == 0)
1547 .map(|(node, _)| node.clone())
1548 .collect();
1549
1550 let mut order = Vec::new();
1551 while let Some(node) = queue.pop_front() {
1552 order.push(node.clone());
1553 for nbr in graph.get(&node).unwrap_or(&Vec::new()) {
1554 let deg = in_degree.get_mut(nbr).unwrap();
1555 *deg -= 1;
1556 if *deg == 0 {
1557 queue.push_back(nbr.clone());
1558 }
1559 }
1560 }
1561
1562 if order.len() != in_degree.len() {
1563 return Err(Error::InvalidGraph);
1564 }
1565 Ok(order)
1566}
1567
1568pub struct UnionFind<T: Hash + Eq + Clone> {
1570 parent: HashMap<T, T>,
1571 rank: HashMap<T, u32>,
1572}
1573
1574impl<T: Hash + Eq + Clone> UnionFind<T> {
1575 pub fn new(elements: impl IntoIterator<Item = T>) -> Self {
1577 let mut parent = HashMap::new();
1578 let mut rank = HashMap::new();
1579 for x in elements {
1580 parent.insert(x.clone(), x.clone());
1581 rank.insert(x, 0);
1582 }
1583 Self { parent, rank }
1584 }
1585
1586 pub fn find(&mut self, x: &T) -> Result<T, Error> {
1588 if !self.parent.contains_key(x) {
1589 return Err(Error::InvalidInput);
1590 }
1591 let mut root = x.clone();
1592 while self.parent[&root] != root {
1593 root = self.parent[&root].clone();
1594 }
1595 let mut node = x.clone();
1596 while self.parent[&node] != root {
1597 let parent = self.parent[&node].clone();
1598 self.parent.insert(node.clone(), root.clone());
1599 node = parent;
1600 }
1601 Ok(root)
1602 }
1603
1604 pub fn union(&mut self, x: &T, y: &T) -> Result<bool, Error> {
1606 let root_x = self.find(x)?;
1607 let root_y = self.find(y)?;
1608 if root_x == root_y {
1609 return Ok(false);
1610 }
1611 let rank_x = *self.rank.get(&root_x).unwrap_or(&0);
1612 let rank_y = *self.rank.get(&root_y).unwrap_or(&0);
1613 if rank_x < rank_y {
1614 self.parent.insert(root_x, root_y);
1615 } else if rank_x > rank_y {
1616 self.parent.insert(root_y, root_x);
1617 } else {
1618 self.parent.insert(root_y, root_x.clone());
1619 self.rank.insert(root_x, rank_x + 1);
1620 }
1621 Ok(true)
1622 }
1623
1624 pub fn connected(&mut self, x: &T, y: &T) -> Result<bool, Error> {
1626 Ok(self.find(x)? == self.find(y)?)
1627 }
1628
1629 pub fn count(&mut self) -> usize {
1631 let keys: Vec<T> = self.parent.keys().cloned().collect();
1632 let mut roots = HashSet::new();
1633 for k in keys {
1634 if let Ok(root) = self.find(&k) {
1635 roots.insert(root);
1636 }
1637 }
1638 roots.len()
1639 }
1640}
1641
1642pub struct PriorityQueue<T: Ord> {
1644 heap: BinaryHeap<Reverse<T>>,
1645}
1646
1647impl<T: Ord> PriorityQueue<T> {
1648 pub fn new(items: impl IntoIterator<Item = T>) -> Self {
1650 let heap: BinaryHeap<Reverse<T>> = items.into_iter().map(Reverse).collect();
1651 Self { heap }
1652 }
1653
1654 pub fn push(&mut self, item: T) {
1656 self.heap.push(Reverse(item));
1657 }
1658
1659 pub fn pop(&mut self) -> Result<T, Error> {
1661 self.heap.pop().map(|r| r.0).ok_or(Error::InvalidInput)
1662 }
1663
1664 pub fn peek(&self) -> Result<&T, Error> {
1666 self.heap.peek().map(|r| &r.0).ok_or(Error::InvalidInput)
1667 }
1668
1669 pub fn len(&self) -> usize {
1671 self.heap.len()
1672 }
1673
1674 pub fn is_empty(&self) -> bool {
1676 self.heap.is_empty()
1677 }
1678}
1679
1680#[derive(Clone)]
1682pub struct MSTEdge {
1683 pub u: String,
1685 pub v: String,
1687 pub weight: f64,
1689}
1690
1691pub fn minimum_spanning_tree(edges: &[MSTEdge]) -> Result<(f64, Vec<MSTEdge>), Error> {
1693 for e in edges {
1694 if !e.weight.is_finite() {
1695 return Err(Error::InvalidInput);
1696 }
1697 }
1698
1699 let mut sorted: Vec<MSTEdge> = edges.to_vec();
1700 sorted.sort_by(|a, b| a.weight.partial_cmp(&b.weight).unwrap_or(Ordering::Equal));
1701
1702 let mut vertices = HashSet::new();
1703 for e in edges {
1704 vertices.insert(e.u.clone());
1705 vertices.insert(e.v.clone());
1706 }
1707 let mut uf = UnionFind::new(Vec::new());
1708 for v in vertices {
1709 uf.parent.insert(v.clone(), v.clone());
1710 uf.rank.insert(v, 0);
1711 }
1712
1713 let mut total = 0.0;
1714 let mut mst = Vec::new();
1715 for e in sorted {
1716 if e.u == e.v {
1717 continue;
1718 }
1719 if uf.union(&e.u, &e.v)? {
1720 total += e.weight;
1721 mst.push(e);
1722 }
1723 }
1724 Ok((total, mst))
1725}
1726
1727pub fn floyd_warshall(
1729 graph: &HashMap<String, Vec<Edge>>,
1730) -> Result<HashMap<String, HashMap<String, f64>>, Error> {
1731 let mut all_nodes = HashSet::new();
1732 for u in graph.keys() {
1733 all_nodes.insert(u.clone());
1734 }
1735 for edges in graph.values() {
1736 for e in edges {
1737 all_nodes.insert(e.to.clone());
1738 }
1739 }
1740 for (_u, edges) in graph {
1741 for e in edges {
1742 if !all_nodes.contains(&e.to) {
1743 return Err(Error::InvalidGraph);
1744 }
1745 if !e.weight.is_finite() {
1746 return Err(Error::InvalidInput);
1747 }
1748 }
1749 }
1750
1751 let inf = f64::INFINITY;
1752 let mut dist: HashMap<String, HashMap<String, f64>> = HashMap::new();
1753 for u in &all_nodes {
1754 let mut row = HashMap::new();
1755 for v in &all_nodes {
1756 row.insert(v.clone(), if u == v { 0.0 } else { inf });
1757 }
1758 dist.insert(u.clone(), row);
1759 }
1760 for (u, edges) in graph {
1761 for e in edges {
1762 if e.weight < dist[u][&e.to] {
1763 dist.get_mut(u).unwrap().insert(e.to.clone(), e.weight);
1764 }
1765 }
1766 }
1767
1768 for k in &all_nodes {
1769 for i in &all_nodes {
1770 let dik = dist[i][k];
1771 if dik.is_infinite() {
1772 continue;
1773 }
1774 for j in &all_nodes {
1775 let nd = dik + dist[k][j];
1776 if nd < dist[i][j] {
1777 dist.get_mut(i).unwrap().insert(j.clone(), nd);
1778 }
1779 }
1780 }
1781 }
1782
1783 for u in &all_nodes {
1784 if dist[u][u] < 0.0 {
1785 return Err(Error::NegativeCycle);
1786 }
1787 }
1788 Ok(dist)
1789}
1790
1791pub fn strongly_connected_components(
1793 graph: &HashMap<String, Vec<String>>,
1794) -> Result<Vec<Vec<String>>, Error> {
1795 validate_adjacency_list(graph)?;
1796
1797 let mut visited = HashSet::new();
1798 let mut order: Vec<String> = Vec::new();
1799
1800 for u in graph.keys() {
1801 if !visited.contains(u) {
1802 let mut stack: Vec<(String, bool)> = vec![(u.clone(), false)];
1803 while let Some((node, processed)) = stack.pop() {
1804 if processed {
1805 order.push(node);
1806 continue;
1807 }
1808 if visited.contains(&node) {
1809 continue;
1810 }
1811 visited.insert(node.clone());
1812 stack.push((node.clone(), true));
1813 if let Some(neighbors) = graph.get(&node) {
1814 for nbr in neighbors.iter().rev() {
1815 if !visited.contains(nbr) {
1816 stack.push((nbr.clone(), false));
1817 }
1818 }
1819 }
1820 }
1821 }
1822 }
1823
1824 let mut reverse: HashMap<String, Vec<String>> = HashMap::new();
1825 for u in graph.keys() {
1826 reverse.insert(u.clone(), Vec::new());
1827 }
1828 for (u, neighbors) in graph {
1829 for v in neighbors {
1830 reverse.get_mut(v).unwrap().push(u.clone());
1831 }
1832 }
1833
1834 let mut visited = HashSet::new();
1835 let mut components: Vec<Vec<String>> = Vec::new();
1836
1837 for u in order.iter().rev() {
1838 if !visited.contains(u) {
1839 let mut component = Vec::new();
1840 let mut stack = vec![u.clone()];
1841 while let Some(node) = stack.pop() {
1842 if visited.contains(&node) {
1843 continue;
1844 }
1845 visited.insert(node.clone());
1846 component.push(node.clone());
1847 if let Some(neighbors) = reverse.get(&node) {
1848 for nbr in neighbors {
1849 if !visited.contains(nbr) {
1850 stack.push(nbr.clone());
1851 }
1852 }
1853 }
1854 }
1855 components.push(component);
1856 }
1857 }
1858 Ok(components)
1859}
1860
1861pub fn has_cycle(graph: &HashMap<String, Vec<String>>) -> Result<bool, Error> {
1863 validate_adjacency_list(graph)?;
1864
1865 let mut state: HashMap<String, i8> = HashMap::new();
1866 for u in graph.keys() {
1867 state.insert(u.clone(), 0);
1868 }
1869
1870 for u in graph.keys() {
1871 if state[u] != 0 {
1872 continue;
1873 }
1874 let mut stack: Vec<(String, usize)> = vec![(u.clone(), 0)];
1875 while let Some((node, idx)) = stack.pop() {
1876 if *state.get(&node).unwrap() == 2 {
1877 continue;
1878 }
1879 if *state.get(&node).unwrap() == 0 {
1880 state.insert(node.clone(), 1);
1881 }
1882 let neighbors = graph.get(&node).cloned().unwrap_or_default();
1883 if idx < neighbors.len() {
1884 let nbr = &neighbors[idx];
1885 stack.push((node, idx + 1));
1886 match *state.get(nbr).unwrap_or(&0) {
1887 1 => return Ok(true),
1888 0 => stack.push((nbr.clone(), 0)),
1889 _ => {}
1890 }
1891 } else {
1892 state.insert(node, 2);
1893 }
1894 }
1895 }
1896 Ok(false)
1897}