Rusty approach using custom Numerals struct and duplicate counting.
Intuition\n"Hey, this should be easy, right?" I mean, it\'s just like part 1 but with two swaps instead of one. How hard could it be? Famous last words. Turns o
# Intuition\n"Hey, this should be easy, right?" I mean, it\'s just like part 1 but with two swaps instead of one. How hard could it be? Famous last words. Turns out, adding that second swap opens up a world of pain, and what seemed like a minor tweak quickly snowballed into a full-blown headache.\n\n# Approach\nIf I\'m going to have to write so much, I might as well take a Rusty approach and build something that bears a passing resemblance to real code.\n\nI created a Numerals type because, why not? It lets me get the performance of using numbers directly but with the convenience of strings\u2014because sometimes you just need the best of both worlds.\n\nNow, instead of doing something ridiculous like sorting every possible permutation of digits (ugh), I keyed everything on a simple digit count slice. Way quicker, way cleaner. Also, I figured out a neat little trick: counting repeating numbers in order to save time and memory. It\u2019s like LeetCode set me up, but I came prepared with a rusty hammer and nailed it anyway.\n\n# Complexity\n- Time complexity:\n$$O(n^2)$$\nMaybe? It\'s definitely a lot slower on big sets. I\'m not paying premium and this is chatgpt\'s best guess.\n\n- Space complexity:\n$$O(n)$$\nWe only store a single, linear version of the data. The `i32`s get turned into `[u8; 8]`s and we add a few `[u8; 10s]`s as digit counts we can use to hash the numbers with the same digits together. We\'ll also remove duplicates, so on the balance it\'ll take a little more or a little less than 2x the input vec.\n\nIf you\'re really strapped for memory, you can do the old leetcode trick of changing the function arg to make the input vec mutable. I didn\'t since I think it\'s a cheap trick, but it does save you a little.\n\n# Code\n```rust []\nuse std::collections::HashMap;\n\nconst MAXNUMS: usize = 7;\n\n#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, PartialOrd)]\nstruct Numerals([u8; MAXNUMS]);\nimpl Numerals {\n    // A little count of how often each digit comes up, for using as a hash key\n    // to match when two nums have the same digits\n    fn digit_count(self) -> [u8; 10] {\n        let mut count = [0; 10];\n        for numeral in self.0.iter() {\n            count[*numeral as usize] += 1;\n        }\n        count\n    }\n}\n\nimpl From<i32> for Numerals {\n    // Take the digits from the number into our vec\n    fn from(n: i32) -> Self {\n        let mut n = n;\n        let mut v = [0; MAXNUMS];\n        for i in 0..MAXNUMS {\n            v[MAXNUMS - 1 - i] = (n % 10) as u8;\n            n /= 10;\n        }\n        Self(v)\n    }\n}\n\nimpl From<&i32> for Numerals {\n    fn from(n: &i32) -> Self {\n        Self::from(*n)\n    }\n}\n\n// Helper function to check if two strings are almost equal (differ by up to two characters)\nfn can_be_equal_with_two_swaps(s1: Numerals, s2: Numerals) -> bool {\n    // If they\'re equal, they\'re also almost equal.\n    if s1 == s2 {\n        return true;\n    }\n\n    // Collect the differing u8 between the two numerals\n    let dp: Vec<(u8, u8)> =\n        s1.0.iter()\n            .zip(s2.0.iter())\n            .filter_map(|(&c1, &c2)| if c1 == c2 { None } else { Some((c1, c2)) })\n            .take(5)\n            .collect();\n\n    // If there\'s only one diff when the numerals are the same, it\'s almost.\n    if dp.len() == 2 {\n        return true;\n    }\n\n    // Can\'t get to matching in more than 2 swaps then\n    if dp.len() > 4 {\n        return false;\n    }\n\n    // First pass: Direct swaps that cancel out a pair\n    let mut marked: Vec<Option<(u8, u8)>> = dp.iter().map(|p| Some(*p)).collect();\n    let mut swapcount = 0;\n    for i in 0..marked.len() {\n        if marked[i].is_none() {\n            continue;\n        }\n        for j in i + 1..marked.len() {\n            // flip and see if the swap cancels\n            if let Some((c1, c2)) = marked[j] {\n                if Some((c2, c1)) == marked[i] {\n                    marked[i] = None;\n                    marked[j] = None;\n                    swapcount += 1;\n                    break;\n                }\n            }\n        }\n    }\n    if swapcount == 2 {\n        true\n    } else if dp.len() == 4 {\n        false\n    } else {\n        // Graph through the 3 nodes looking for a loop. If it does, we\'ve got a 2-swap\n        (dp[0].1 == dp[1].0 && dp[1].1 == dp[2].0 && dp[2].1 == dp[0].0)\n            || (dp[0].1 == dp[2].0 && dp[2].1 == dp[1].0 && dp[1].1 == dp[0].0)\n    }\n}\n\nimpl Solution {\n    pub fn count_pairs(nums: Vec<i32>) -> i32 {\n        let mut nums = nums.clone();\n        nums.sort_unstable();\n        nums.into_iter()\n            .fold(Vec::new(), |mut nc: Vec<(i32, usize)>, e| {\n                if let Some(last) = nc.pop() {\n                    if e == last.0 {\n                        nc.push((e, last.1 + 1));\n                    } else {\n                        nc.push(last);\n                        nc.push((e, 1));\n                    }\n                } else {\n                    nc.push((e, 1));\n                }\n                nc\n            })\n            .iter()\n            .map(|(num, count)| (Numerals::from(num), *count))\n            .fold(\n                HashMap::new(),\n                |mut sorted_map: HashMap<[u8; 10], Vec<(Numerals, usize)>>, original| {\n                    let key = original.0.digit_count();\n                    sorted_map.entry(key).or_default().push(original);\n                    sorted_map\n                },\n            )\n            .values()\n            // Count up in each group that has the same digits, which can be swapped together\n            .fold(0usize, |mut count, group| {\n                let len = group.len();\n                for i in 0..len {\n                    // Shaped like itself\n                    // Count pairs of identical numbers\n                    count += group[i].1 * (group[i].1 - 1) / 2;\n                    for j in i + 1..len {\n                        count += (can_be_equal_with_two_swaps(group[i].0, group[j].0) as usize)\n                            * group[i].1\n                            * group[j].1;\n                    }\n                }\n                count\n            }) as i32\n    }\n}\n```
['Rust']