{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c1517920-b1f6-440c-b5c8-4df6bec2fbc1",
   "metadata": {},
   "source": [
    "# Google Colab Rust Setup\n",
    "\n",
    "The following cell is used to set up and spin up a Jupyter Notebook environment with a Rust kernel using Nix and IPC Proxy. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fbf50b02-3730-4aa0-af49-16c1546fd09e",
   "metadata": {},
   "outputs": [],
   "source": [
    "!wget -qO- https://gist.github.com/wiseaidev/2af6bef753d48565d11bcd478728c979/archive/3f6df40db09f3517ade41997b541b81f0976c12e.tar.gz | tar xvz --strip-components=1\n",
    "!bash setup_evcxr_kernel.sh"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60c8d72c-b011-4360-b368-d540b8d7361a",
   "metadata": {},
   "source": [
    "## Iterators and Closures"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38339871-7f3d-49d8-9b4f-e77f9e2a88da",
   "metadata": {},
   "source": [
    "### Anatomy of an Iterator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "a163999f-7353-4fb9-88cf-61ac934c34f0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The sum of the first 10 prime numbers is: 129\n"
     ]
    }
   ],
   "source": [
    "fn is_prime(n: u32) -> bool {\n",
    "    if n <= 1 {\n",
    "        return false;\n",
    "    }\n",
    "    for i in 2..(n / 2 + 1) {\n",
    "        if n % i == 0 {\n",
    "            return false;\n",
    "        }\n",
    "    }\n",
    "    true\n",
    "}\n",
    "\n",
    "fn sum_of_primes(n: u32) -> u32 {\n",
    "    (2..).filter(|&x| is_prime(x)).take(n as usize).sum()\n",
    "}\n",
    "\n",
    "let n = 10;\n",
    "let result = sum_of_primes(n);\n",
    "println!(\"The sum of the first {} prime numbers is: {}\", n, result);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95f2fdfa-0f86-4959-9ab7-5aa92de36ea9",
   "metadata": {},
   "source": [
    "### Key Traits: Iterator and IntoIterator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "125e0cb0-88a3-49c3-bb79-c6b78171ec60",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Item: 42\n",
      "Item: 100\n",
      "Item: 7\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "struct MyCollection {\n",
    "    data: Vec<i32>,\n",
    "}\n",
    "\n",
    "impl MyCollection {\n",
    "    fn new() -> Self {\n",
    "        MyCollection { data: Vec::new() }\n",
    "    }\n",
    "\n",
    "    fn add(&mut self, value: i32) {\n",
    "        self.data.push(value);\n",
    "    }\n",
    "}\n",
    "\n",
    "impl IntoIterator for MyCollection {\n",
    "    type Item = i32;\n",
    "    type IntoIter = std::vec::IntoIter<Self::Item>;\n",
    "\n",
    "    fn into_iter(self) -> Self::IntoIter {\n",
    "        self.data.into_iter()\n",
    "    }\n",
    "}\n",
    "\n",
    "\n",
    "let mut collection = MyCollection::new();\n",
    "\n",
    "collection.add(42);\n",
    "collection.add(100);\n",
    "collection.add(7);\n",
    "\n",
    "for item in collection {\n",
    "    println!(\"Item: {}\", item);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c4bb2d5-57a3-4075-b044-0898cb18a41e",
   "metadata": {},
   "source": [
    "### Creating Iterators with `from_fn` and `successors`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a501d270-db4d-474b-a37c-1439aff79ad6",
   "metadata": {},
   "outputs": [],
   "source": [
    ":dep rand = {version=\"0.8.5\"}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "e43f6159-0e97-40f9-8fb1-702ac600f60c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.026231996097305532, 0.3638420476998353, 0.529187247261019, 0.3697265864723026, 0.9199704902784379, 0.0578703524231724, 0.2434883502345343, 0.1948597360516151, 0.38109952692955174, 0.47026570340584917]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use rand::random;\n",
    "\n",
    "use std::iter::from_fn;\n",
    "\n",
    "let lengths: Vec<f64> =\n",
    "    from_fn(|| Some((random::<f64>() - random::<f64>()).abs()))\n",
    "    .take(1000)\n",
    "    .collect();\n",
    "lengths[..10]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "a27b5c86-6134-4823-8484-019668dd97ad",
   "metadata": {},
   "outputs": [],
   "source": [
    ":dep num = {version=\"0.4.1\"}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "743e0887-3158-4a61-b6c5-152579c472e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Escaped after 96 steps.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use num::Complex;\n",
    "use std::iter::successors;\n",
    "\n",
    "fn escape_time(c: Complex<f64>, limit: usize) -> Option<usize> {\n",
    "    let zero = Complex { re: 0.0, im: 0.0 };\n",
    "\n",
    "    let result = successors(Some(zero), |&z| Some(z * z + c))\n",
    "        .take(limit)\n",
    "        .enumerate()\n",
    "        .find(|(_i, z)| z.norm_sqr() > 4.0);\n",
    "\n",
    "    match result {\n",
    "        Some((i, _z)) => Some(i),\n",
    "        None => None,\n",
    "    }\n",
    "}\n",
    "\n",
    "let c = Complex { re: -0.7, im: 0.27015 };\n",
    "let limit = 1000;\n",
    "\n",
    "match escape_time(c, limit) {\n",
    "    Some(steps) => println!(\"Escaped after {} steps.\", steps),\n",
    "    None => println!(\"Did not escape within {} steps.\", limit),\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "95d8e464-7461-4da3-9378-bfb599a8a864",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fibonacci sequence (first 8 numbers): [1, 1, 2, 3, 5, 8, 13, 21]\n"
     ]
    }
   ],
   "source": [
    "fn fibonacci() -> impl Iterator<Item = usize> {\n",
    "    let mut state = (0, 1);\n",
    "    std::iter::from_fn(move || {\n",
    "        state = (state.1, state.0 + state.1);\n",
    "        Some(state.0)\n",
    "    })\n",
    "}\n",
    "\n",
    "let result: Vec<usize> = fibonacci().take(8).collect();\n",
    "\n",
    "let expected = vec![1, 1, 2, 3, 5, 8, 13, 21];\n",
    "\n",
    "assert_eq!(result, expected);\n",
    "\n",
    "println!(\"Fibonacci sequence (first 8 numbers): {:?}\", result);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb679a2d-a3d3-4e8a-8ac4-e80114bd0040",
   "metadata": {},
   "source": [
    "### Drain Methods"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "512ad7b2-b6ea-4a7b-a02b-04dabe326551",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"art\""
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let mut outer = \"Earth\".to_string();\n",
    "\n",
    "let inner = String::from_iter(outer.drain(1..4));\n",
    "\n",
    "assert_eq!(outer, \"Eh\");\n",
    "\n",
    "inner"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "88919fcd-07ec-47d5-8ca9-7a5ed088420e",
   "metadata": {},
   "source": [
    "### Iterator Adapter Methods"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "004baf75-87f2-469b-93da-f4b16310bd9b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 4, 9, 16, 25]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let numbers = vec![1, 2, 3, 4, 5];\n",
    "\n",
    "let squared: Vec<i32> = numbers.into_iter().map(|x| x * x).collect();\n",
    "\n",
    "squared"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "6c832e12-9e25-44ed-9547-133150726c51",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 8, 10]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let numbers = 1..=10;\n",
    "\n",
    "let evens: Vec<i32> = numbers.into_iter().filter(|x| x % 2 == 0).collect();\n",
    "\n",
    "evens"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63ba2c2d-58e9-4eb4-b80e-59de8af58675",
   "metadata": {},
   "source": [
    "### Building Custom Iterators"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "875abcbf-9769-4347-9f60-b9f42fd7b3fa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "3\n",
      "5\n",
      "7\n",
      "11\n",
      "13\n",
      "17\n",
      "19\n",
      "23\n",
      "29\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "struct PrimeGenerator {\n",
    "    current: u32,\n",
    "}\n",
    "\n",
    "impl Iterator for PrimeGenerator {\n",
    "    type Item = u32;\n",
    "\n",
    "    fn next(&mut self) -> Option<Self::Item> {\n",
    "        loop {\n",
    "            self.current += 1;\n",
    "            if is_prime(self.current) {\n",
    "                return Some(self.current);\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "fn is_prime(num: u32) -> bool {\n",
    "    if num <= 1 {\n",
    "        return false;\n",
    "    }\n",
    "\n",
    "    for i in 2..(num / 2 + 1) {\n",
    "        if num % i == 0 {\n",
    "            return false;\n",
    "        }\n",
    "    }\n",
    "\n",
    "    true\n",
    "}\n",
    "\n",
    "let prime_sequence = PrimeGenerator { current: 1 };\n",
    "\n",
    "for prime in prime_sequence.take(10) {\n",
    "    println!(\"{}\", prime);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90c524bf-4542-4f49-844e-1a23297b8c85",
   "metadata": {},
   "source": [
    "### Lazy Evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "784b82e1-b9c9-4696-a87e-58db53ce046a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 8, 10]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let numbers = vec![1, 2, 3, 4, 5];\n",
    "\n",
    "let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();\n",
    "\n",
    "doubled"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f83b51dd-d82c-477d-922a-bb2d53e230e3",
   "metadata": {},
   "source": [
    "### Advanced Techniques"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "057dbe3d-35b3-4802-a203-be7487390e9d",
   "metadata": {},
   "source": [
    "#### flat_map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "0b06ea30-1017-41f6-a769-ecb23215a3c8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['R', 'u', 's', 't', 'i', 's', 'a', 'w', 'e', 's', 'o', 'm', 'e']"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let words = vec![\"Rust\", \"is\", \"awesome\"];\n",
    "\n",
    "let letters: Vec<char> = words.iter()\n",
    "    .flat_map(|&word| word.chars())\n",
    "    .collect();\n",
    "\n",
    "letters"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ee6c89b-de65-4d46-8bcf-1a0d10839e4c",
   "metadata": {},
   "source": [
    "#### take and skip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "0de6c26a-7933-4981-b3ce-d81dcccfe432",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4, 5, 6, 7]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n",
    "\n",
    "let selected_numbers: Vec<i32> = numbers.iter()\n",
    "    .skip(3)\n",
    "    .take(4)\n",
    "    .cloned()\n",
    "    .collect();\n",
    "\n",
    "selected_numbers"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc860a6f-7390-4e3f-83ba-048755a1aa83",
   "metadata": {},
   "source": [
    "#### peekable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "094ed404-00c2-43ee-a344-4a60765799c8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The next number is: 1\n",
      "The next number is: 2\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let mut numbers = vec![1, 2, 3, 4, 5].into_iter().peekable();\n",
    "\n",
    "if let Some(&next_number) = numbers.peek() {\n",
    "    println!(\"The next number is: {}\", next_number);\n",
    "} else {\n",
    "    println!(\"No more numbers to process.\");\n",
    "}\n",
    "\n",
    "let _ = numbers.next();\n",
    "\n",
    "if let Some(&next_number) = numbers.peek() {\n",
    "    println!(\"The next number is: {}\", next_number);\n",
    "} else {\n",
    "   println!(\"No more numbers to process.\");\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0dbdaca2-fe3f-4b12-bb7e-84c9aec3a5fa",
   "metadata": {},
   "source": [
    "#### filter_map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "f02f50e5-1a2e-4357-af94-7461cd88d1d9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[42, 19, 27, 33]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use std::str::FromStr;\n",
    "\n",
    "let text = \"The numbers are: 42, 19, invalid, 27, 33\";\n",
    "\n",
    "let parsed_numbers: Vec<i32> = text\n",
    "    .split(',')\n",
    "    .map(str::trim)\n",
    "    .filter_map(|s| {\n",
    "        let s = s\n",
    "            .chars()\n",
    "            .skip_while(|&c| !c.is_digit(10))\n",
    "            .collect::<String>();\n",
    "        if !s.is_empty() {\n",
    "            i32::from_str(&s).ok()\n",
    "        } else {\n",
    "            None\n",
    "        }\n",
    "    })\n",
    "    .collect();\n",
    "\n",
    "parsed_numbers"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff04472d-8a50-4a6c-93c2-a724352494be",
   "metadata": {},
   "source": [
    "#### fuse"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "24908d21-f8dc-4408-b449-87164be34a59",
   "metadata": {},
   "outputs": [],
   "source": [
    "struct Unpredictable(bool);\n",
    "\n",
    "impl Iterator for Unpredictable {\n",
    "    type Item = &'static str;\n",
    "\n",
    "    fn next(&mut self) -> Option<Self::Item> {\n",
    "        if self.0 {\n",
    "            self.0 = false;\n",
    "            Some(\"totally the last item\")\n",
    "        } else {\n",
    "            self.0 = true;\n",
    "            None\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "let mut unpredictable = Unpredictable(true);\n",
    "assert_eq!(unpredictable.next(), Some(\"totally the last item\"));\n",
    "assert_eq!(unpredictable.next(), None);\n",
    "assert_eq!(unpredictable.next(), Some(\"totally the last item\"));\n",
    "\n",
    "let mut reliable = Unpredictable(true).fuse();\n",
    "assert_eq!(reliable.next(), Some(\"totally the last item\"));\n",
    "assert_eq!(reliable.next(), None);\n",
    "assert_eq!(reliable.next(), None);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0353fcc-fd74-4934-b49d-89a3e29638f2",
   "metadata": {},
   "source": [
    "#### flatten"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "542051bf-fb22-49f6-bf39-a176129a8eb6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Course: Computer Science, Students Enrolled: 1\n",
      "Course: Physics, Students Enrolled: 2\n",
      "Course: Biology, Students Enrolled: 1\n",
      "Course: Math, Students Enrolled: 1\n",
      "Course: Chemistry, Students Enrolled: 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use std::collections::HashMap;\n",
    "\n",
    "let mut student_courses = HashMap::new();\n",
    "student_courses.insert(\"Alice\", vec![\"Math\", \"Physics\"]);\n",
    "student_courses.insert(\"Bob\", vec![\"Computer Science\", \"Chemistry\"]);\n",
    "student_courses.insert(\"Charlie\", vec![\"Physics\", \"Biology\"]);\n",
    "\n",
    "let course_enrollment: HashMap<&str, usize> = student_courses\n",
    "    .values()\n",
    "    .flatten()\n",
    "    .fold(HashMap::new(), |mut enrollment, course| {\n",
    "        *enrollment.entry(course).or_insert(0) += 1;\n",
    "        enrollment\n",
    "    });\n",
    "\n",
    "for (course, count) in &course_enrollment {\n",
    "    println!(\"Course: {}, Students Enrolled: {}\", course, count);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4ae01099-ab85-47dd-aef9-541f62ba8357",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c1f55e2-ad37-4088-9bc0-802070a5a928",
   "metadata": {},
   "source": [
    "### Closures"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "617c08b2-766e-4bf3-b54c-67f829c08ce1",
   "metadata": {},
   "source": [
    "#### Variable Capture in Closures"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "208fa7f6-9f0b-46c9-a18d-2494e87f3926",
   "metadata": {},
   "source": [
    "#### Borrowing Variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "6fbb30ea-d914-46e2-965f-52f906f05b5a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5, 10, 15, 20, 25]"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let multiplier = 5;\n",
    "let numbers = vec![1, 2, 3, 4, 5];\n",
    "\n",
    "let multiplied: Vec<i32> = numbers.iter().map(|x| x * multiplier).collect();\n",
    "\n",
    "multiplied"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e669bf4a-5ada-47be-b23c-f24343f2642a",
   "metadata": {},
   "source": [
    "#### Moving Variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "63b1e2dd-0f8c-4f8a-8d4d-33a7dc0d2123",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, Rust!\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fn main() {\n",
    "    let message = \"Hello, Rust!\".to_string();\n",
    "\n",
    "    let greet = || {\n",
    "        let message = message;\n",
    "        println!(\"{}\", message);\n",
    "    };\n",
    "\n",
    "    greet();\n",
    "\n",
    "    // greet();\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c581c3fb-bf21-43ad-9aa7-fd8ec0e08831",
   "metadata": {},
   "source": [
    "### Closures and Fn, FnMut, FnOnce Traits"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b3342a7-9a39-45f7-99ba-0118538c9a35",
   "metadata": {},
   "source": [
    "#### Fn Closures"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "22e55751-2627-4683-8d37-9772da5fe813",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Counter: 0\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fn main() {\n",
    "    let counter = 0;\n",
    "\n",
    "    let print_counter = || {\n",
    "        println!(\"Counter: {}\", counter);\n",
    "    };\n",
    "\n",
    "    print_counter();\n",
    "\n",
    "    // counter += 1;\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ff15650-26a4-4a89-86a2-8874decbbfb8",
   "metadata": {},
   "source": [
    "#### FnMut Closures"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "14cb0a3c-7077-4319-8a3d-860b6f4b92ce",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Counter: 1\n",
      "Counter: 2\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fn main() {\n",
    "    let mut counter = 0;\n",
    "    let mut increment = || {\n",
    "        counter += 1; // <3>\n",
    "        println!(\"Counter: {}\", counter);\n",
    "    };\n",
    "\n",
    "    increment();\n",
    "    increment();\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f715e3a-ed2b-4f1a-b74f-65329e1e5fa5",
   "metadata": {},
   "source": [
    "#### FnOnce Closures"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "d5f652b0-1d91-4367-bb6c-3d4ed011798a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sum: 15\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fn main() {\n",
    "    let numbers = vec![1, 2, 3, 4, 5];\n",
    "    let consume_numbers = || {\n",
    "        let numbers = numbers;\n",
    "        let sum: i32 = numbers.iter().sum();\n",
    "        println!(\"Sum: {}\", sum);\n",
    "    };\n",
    "\n",
    "    consume_numbers();\n",
    "    // consume_numbers();  // <7>\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34dce128-1e81-4827-a620-85e6c279ac5a",
   "metadata": {},
   "source": [
    "### Working with Iterators for Efficient Data Processing"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca96c6c4-e099-45ec-b46c-21f2a46f3913",
   "metadata": {},
   "source": [
    "####  Accumulating Data with `fold`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "0ed35e01-80c0-4cdd-b927-dc74a3a2731f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "15"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let numbers = vec![1, 2, 3, 4, 5];\n",
    "\n",
    "let sum: i32 = numbers.iter().fold(0, |acc, x| acc + x);\n",
    "\n",
    "sum"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "960b1d46-2958-448c-b1ed-67c3b6abcfc8",
   "metadata": {},
   "source": [
    "#### Chaining Iterators with `chain`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "b07078ca-97f1-4c80-ac64-7bf24cdae2b1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Combined and doubled: [2, 4, 6, 8, 10, 12]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fn main() {\n",
    "    let numbers1 = vec![1, 2, 3];\n",
    "    let numbers2 = vec![4, 5, 6];\n",
    "\n",
    "    let combined: Vec<i32> = numbers1\n",
    "        .iter()\n",
    "        .chain(numbers2.iter())\n",
    "        .map(|x| x * 2)\n",
    "        .collect();\n",
    "\n",
    "    println!(\"Combined and doubled: {:?}\", combined);\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8fb3bd80-99ab-4ccd-ace5-a567b3c9c099",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30a339d7-6011-42cb-a520-734796fdd507",
   "metadata": {},
   "source": [
    "### Applying Iterators and Closures to Practical Examples"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2e7169d-c9ff-4ac3-9f7a-4b1d7ba655be",
   "metadata": {},
   "source": [
    "#### Use Case 1: Text Analysis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "f6ded3de-6b97-482e-9998-04e6d3782112",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Word Frequencies: {\"learn\": 2, \"fun\": 1, \"makes\": 1, \"to\": 1, \"you\": 1, \"that\": 1, \"and\": 1, \"when\": 1, \"it\": 1, \"language\": 1, \"easy\": 1, \"rust\": 4, \"programming\": 1, \"a\": 1, \"is\": 2}\n"
     ]
    }
   ],
   "source": [
    "let text = \"Rust is a language that makes it easy to learn Rust and Rust programming is fun when you learn Rust\";\n",
    "\n",
    "let word_freq: HashMap<String, u32> = text\n",
    "    .split_whitespace()\n",
    "    .map(|word| word.to_lowercase())\n",
    "    .filter(|word| !word.is_empty())\n",
    "    .fold(HashMap::new(), |mut map, word| {\n",
    "        *map.entry(word.to_string()).or_insert(0) += 1;\n",
    "        map\n",
    "    });\n",
    "\n",
    "println!(\"Word Frequencies: {:?}\", word_freq);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7a000ab6-10bb-4b1b-af1e-a547961212ff",
   "metadata": {},
   "source": [
    "#### Use Case 2: Image Processing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "21c6e430-eb9a-4ddb-a8e4-e87200a74aab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Image after processing: [Pixel { red: 200, green: 100, blue: 50 }, Pixel { red: 144, green: 200, blue: 100 }]\n"
     ]
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct Pixel {\n",
    "    red: u8,\n",
    "    green: u8,\n",
    "    blue: u8,\n",
    "}\n",
    "\n",
    "let mut image: Vec<Pixel> = vec![\n",
    "    Pixel {\n",
    "        red: 100,\n",
    "        green: 50,\n",
    "        blue: 25,\n",
    "    },\n",
    "    Pixel {\n",
    "        red: 200,\n",
    "        green: 100,\n",
    "        blue: 50,\n",
    "    },\n",
    "    // ... more pixels\n",
    "];\n",
    "\n",
    "image.iter_mut().for_each(|pixel| {\n",
    "    pixel.red = pixel.red.wrapping_mul(2);\n",
    "    pixel.green = pixel.green.wrapping_mul(2);\n",
    "    pixel.blue = pixel.blue.wrapping_mul(2);\n",
    "});\n",
    "\n",
    "println!(\"Image after processing: {:?}\", image);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f7e591a-6eda-48db-9887-4399aecea9a8",
   "metadata": {},
   "source": [
    "#### Use Case 3: Data Filtering and Transformation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "a0b355e0-9ee2-4760-a314-d33bdd157aad",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Discounted Products: [Product { name: \"Widget A\", price: 8.0, in_stock: true }]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct Product {\n",
    "    name: String,\n",
    "    price: f64,\n",
    "    in_stock: bool,\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    let products = vec![\n",
    "        Product {\n",
    "            name: String::from(\"Widget A\"),\n",
    "            price: 10.0,\n",
    "            in_stock: true,\n",
    "        },\n",
    "        Product {\n",
    "            name: String::from(\"Widget B\"),\n",
    "            price: 15.0,\n",
    "            in_stock: false,\n",
    "        },\n",
    "        // ... more products\n",
    "    ];\n",
    "\n",
    "    let discount = 0.2;\n",
    "\n",
    "    let discounted_products: Vec<Product> = products\n",
    "        .into_iter()\n",
    "        .filter(|product| product.in_stock)\n",
    "        .map(|mut product| {\n",
    "            product.price -= product.price * discount;\n",
    "            product\n",
    "        })\n",
    "        .collect();\n",
    "\n",
    "    println!(\"Discounted Products: {:?}\", discounted_products);\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa25757d-4d18-4292-b98b-8182ebf9c72f",
   "metadata": {},
   "source": [
    "#### Use Case 4: Processing Sensor Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "319f1ebc-31b6-4a76-88cc-5ba0c5f5f27f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Anomalous Readings: [SensorReading { timestamp: 3, value: 23.0 }]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct SensorReading {\n",
    "    timestamp: u64,\n",
    "    value: f64,\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    let sensor_data = vec![\n",
    "        SensorReading {\n",
    "            timestamp: 1,\n",
    "            value: 20.0,\n",
    "        },\n",
    "        SensorReading {\n",
    "            timestamp: 2,\n",
    "            value: 22.0,\n",
    "        },\n",
    "        SensorReading {\n",
    "            timestamp: 3,\n",
    "            value: 23.0,\n",
    "        },\n",
    "        // ... more readings\n",
    "    ];\n",
    "\n",
    "    let threshold = 22.0;\n",
    "\n",
    "    let anomalies: Vec<&SensorReading> = sensor_data\n",
    "        .iter()\n",
    "        .filter(|&reading| reading.value > threshold)\n",
    "        .collect();\n",
    "\n",
    "    println!(\"Anomalous Readings: {:?}\", anomalies);\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00a5a00e-d53d-4487-8898-de4d0df805f3",
   "metadata": {},
   "source": [
    "#### Use Case 5: Financial Calculations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "fe2ab707-af71-412a-8920-bbdc9eb8693a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Final Balance: 150.0\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct Transaction {\n",
    "    amount: f64,\n",
    "    transaction_type: String,\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    let transactions = vec![\n",
    "        Transaction {\n",
    "            amount: 100.0,\n",
    "            transaction_type: String::from(\"Deposit\"),\n",
    "        },\n",
    "        Transaction {\n",
    "            amount: -50.0,\n",
    "            transaction_type: String::from(\"Withdrawal\"),\n",
    "        },\n",
    "        // ... more transactions\n",
    "    ];\n",
    "\n",
    "    let balance = transactions.iter().fold(0.0, |acc, transaction| {\n",
    "        if transaction.transaction_type == \"Deposit\" {\n",
    "            acc + transaction.amount\n",
    "        } else {\n",
    "            acc - transaction.amount\n",
    "        }\n",
    "    });\n",
    "\n",
    "    println!(\"Final Balance: {:?}\", balance);\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc0df9a2-495b-490a-9b16-f9e5301ea92d",
   "metadata": {},
   "source": [
    "#### Use Case 6: Sorting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "dd450be4-e1b2-4a65-86ea-a7a064df42a6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Product: Headphones - Price: $149.99\n",
      "Product: Smartphone - Price: $599.99\n",
      "Product: Laptop - Price: $799.99\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "struct Product {\n",
    "    name: String,\n",
    "    price: f64,\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    let mut products = vec![\n",
    "        Product {\n",
    "            name: \"Laptop\".to_string(),\n",
    "            price: 799.99,\n",
    "        },\n",
    "        Product {\n",
    "            name: \"Headphones\".to_string(),\n",
    "            price: 149.99,\n",
    "        },\n",
    "        Product {\n",
    "            name: \"Smartphone\".to_string(),\n",
    "            price: 599.99,\n",
    "        },\n",
    "    ];\n",
    "\n",
    "    products.sort_by(|a, b| a.price.partial_cmp(&b.price).unwrap());\n",
    "\n",
    "    for product in &products {\n",
    "        println!(\"Product: {} - Price: ${}\", product.name, product.price);\n",
    "    }\n",
    "}\n",
    "\n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6fb7d6c2-7514-4652-ae01-329df90832ff",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "---"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Rust",
   "language": "rust",
   "name": "rust"
  },
  "language_info": {
   "codemirror_mode": "rust",
   "file_extension": ".rs",
   "mimetype": "text/rust",
   "name": "Rust",
   "pygment_lexer": "rust",
   "version": ""
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}