├── Exercises ├── geoangelotti │ ├── go.mod │ ├── src │ │ ├── smallest_two │ │ │ ├── core.clj │ │ │ └── main.clj │ │ └── unique_count │ │ │ ├── core.clj │ │ │ └── main.clj │ ├── UniqueCount.kts │ ├── deno.json │ ├── project.clj │ ├── main_test.ts │ ├── test │ │ ├── unique_count │ │ │ └── core_test.clj │ │ └── smallest_two │ │ │ └── core_test.clj │ ├── unique_count.jl │ ├── go.md │ ├── deno.lock │ ├── SmallestTwo.kts │ ├── main.ts │ ├── unique_count.go │ ├── smallest_two.go │ ├── unique_count_test.go │ ├── smallest_two_test.go │ └── .gitignore ├── jglara │ ├── max_min │ │ ├── src │ │ │ ├── main.rs │ │ │ └── lib.rs │ │ ├── Cargo.toml │ │ └── benches │ │ │ └── minmax.rs │ └── lecture1 │ │ ├── count_unique.q │ │ ├── Cargo.toml │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ └── src │ │ └── main.rs ├── conor_hoekstra │ ├── 02.uiua │ ├── 02.bqn │ ├── 02.apl │ ├── 02.kap │ ├── 01.bqn │ ├── 03.bqn │ ├── 01.rs │ ├── 03.rs │ ├── 02.rs │ ├── 01.cpp │ └── README.md ├── ryan_sullivant │ ├── 01_unique_count │ │ ├── benchmarks.png │ │ ├── README.md │ │ ├── Cargo.toml │ │ └── benches │ │ │ └── unique.rs │ └── 02_minmax_element │ │ ├── benchmarks.png │ │ ├── README.md │ │ ├── Cargo.toml │ │ ├── benches │ │ └── minmax_element.rs │ │ └── src │ │ └── lib.rs ├── pmcgee │ ├── Project_epwc.dpr │ ├── instrumented │ │ ├── U_Instrumented.pas │ │ └── U_Test_Instrumented.pas │ ├── U_Gen_Data.pas │ ├── unique_count │ │ └── U_unique_count.pas │ └── minmax_elem │ │ └── U_MinMax_Element.pas ├── jonocarroll │ ├── 01.md │ ├── 02.md │ └── 03.md └── segreaves │ ├── Instrumented │ ├── Singleton.h │ ├── Pair.h │ └── EfficientProgrammingWithComponents.cpp │ └── FindUniqueElementsInArray.cpp ├── .github ├── auto-assign-config.yml └── workflows │ └── auto-assign.yml ├── README.md ├── LICENSE ├── LINKS.md ├── .gitignore └── Demo └── binary_counter.cpp /Exercises/geoangelotti/go.mod: -------------------------------------------------------------------------------- 1 | module epwc 2 | 3 | go 1.24.1 4 | -------------------------------------------------------------------------------- /Exercises/jglara/max_min/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | fn main() { 3 | println!("Hello, world!"); 4 | } 5 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/02.uiua: -------------------------------------------------------------------------------- 1 | MinMax ← ⊂⊃/↧/↥ 2 | 3 | # Tests 4 | MinMax ⇡5 5 | MinMax 4_3_10 6 | -------------------------------------------------------------------------------- /Exercises/jglara/lecture1/count_unique.q: -------------------------------------------------------------------------------- 1 | cu:{ sum differ asc x } 2 | 3 | cu 1 3 1 4 1 5 / should be 4 4 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/02.bqn: -------------------------------------------------------------------------------- 1 | MinMax ← ⌊´⋈⌈´ 2 | 3 | # Tests 4 | •Show MinMax ↕5 5 | •Show MinMax 4‿3‿10 6 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/02.apl: -------------------------------------------------------------------------------- 1 | MinMax ← ⌊/,⌈/ 2 | 3 | ⍝ Tests 4 | MinMax ⍳5 ⍝ 1 5 5 | MinMax 4 3 10 ⍝ 3 10 6 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/02.kap: -------------------------------------------------------------------------------- 1 | MinMax ⇐ (⌊/)«,»(⌈/) 2 | 3 | ⍝ Tests 4 | MinMax ⍳5 ⍝ 0 4 5 | MinMax 4 3 10 ⍝ 3 10 6 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/src/smallest_two/core.clj: -------------------------------------------------------------------------------- 1 | (ns smallest-two.core) 2 | 3 | (defn smallest-two [arr] 4 | (take 2 (sort arr))) 5 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/src/unique_count/core.clj: -------------------------------------------------------------------------------- 1 | (ns unique-count.core) 2 | 3 | (defn unique-count-set [arr] 4 | (count (set arr))) 5 | -------------------------------------------------------------------------------- /Exercises/jglara/lecture1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lecture1" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /Exercises/ryan_sullivant/01_unique_count/benchmarks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonocarroll/EPwC-2025/main/Exercises/ryan_sullivant/01_unique_count/benchmarks.png -------------------------------------------------------------------------------- /Exercises/ryan_sullivant/02_minmax_element/benchmarks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonocarroll/EPwC-2025/main/Exercises/ryan_sullivant/02_minmax_element/benchmarks.png -------------------------------------------------------------------------------- /Exercises/geoangelotti/UniqueCount.kts: -------------------------------------------------------------------------------- 1 | fun uniqueCount(nums: IntArray): Int = 2 | nums.groupBy { it }.size 3 | 4 | println(uniqueCount(intArrayOf(1, 3, 1, 4, 1, 5))) 5 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "dev": "deno run --watch main.ts" 4 | }, 5 | "imports": { 6 | "@std/assert": "jsr:@std/assert@1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/project.clj: -------------------------------------------------------------------------------- 1 | (defproject unique-count "0.1.0-SNAPSHOT" 2 | :dependencies [[org.clojure/clojure "1.11.1"]] 3 | :repl-options {:init-ns unique-count.core}) 4 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/01.bqn: -------------------------------------------------------------------------------- 1 | DistinctCount ← ≠⍷ # deduplicate 2 | DistinctCount2 ← +´∊ # unique mask 3 | 4 | # Tests 5 | •Show DistinctCount •Show 1‿3‿1‿4‿1‿5 # 4 6 | •Show DistinctCount2 •Show 1‿3‿1‿4‿1‿5 # 4 7 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/src/smallest_two/main.clj: -------------------------------------------------------------------------------- 1 | (ns smallest-two.main 2 | (:require [smallest-two.core :refer :all])) 3 | 4 | (defn -main 5 | "Smallest Two" 6 | [& args] 7 | (println (smallest-two-set [1 -1 1 4 1 0]))) 8 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/src/unique_count/main.clj: -------------------------------------------------------------------------------- 1 | (ns unique-count.main 2 | (:require [unique-count.core :refer :all])) 3 | 4 | (defn -main 5 | "Unique Count" 6 | [& args] 7 | (println (unique-count-set [1 3 1 4 1 5]))) 8 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/main_test.ts: -------------------------------------------------------------------------------- 1 | import { assertEquals } from "@std/assert"; 2 | import { uniqueCount } from "./main.ts"; 3 | 4 | Deno.test(function uniqueCountTest() { 5 | assertEquals(uniqueCount([1, 3, 1, 4, 1, 5]), 4); 6 | }); 7 | -------------------------------------------------------------------------------- /Exercises/ryan_sullivant/02_minmax_element/README.md: -------------------------------------------------------------------------------- 1 | # Benchmarking minmax_element 2 | 3 | Three implementations 4 | 1. `min_then_max` 5 | 2. `minmax_element_iter` 6 | 3. `minmax_element` (imperative) 7 | 8 | ![Benchmark plot](benchmarks.png) 9 | 10 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/03.bqn: -------------------------------------------------------------------------------- 1 | SmallestTwoWithSort ← 2↑∧ 2 | SmallestTwo ← { 2>≠𝕩? 𝕩 ; (2↑𝕩) { x𝕊a‿b: {x) -> usize { 4 | data.into_iter() 5 | .sorted() 6 | .tuple_windows() 7 | .filter(|(a, b)| a != b) 8 | .count() + 1 9 | } 10 | 11 | fn main() { 12 | let arr = vec![1, 3, 1, 4, 1, 5]; 13 | println!("{}", distinct_count(arr)); // outputs 4 14 | } 15 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/03.rs: -------------------------------------------------------------------------------- 1 | fn min2(values: Vec) -> Option<(i32, i32)> { 2 | if values.is_empty() { return None; } 3 | let f = values[0]; 4 | if values.len() == 1 { return Some((f, f)); } 5 | Some(values.iter().skip(1).fold((f, f), |(a, b), &x| { 6 | if x < a { (x, a) } 7 | else if x < b { (a, x) } 8 | else { (a, b) } 9 | })) 10 | } 11 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/02.rs: -------------------------------------------------------------------------------- 1 | fn min_max(values: Vec) -> Option<(i32, i32)> { 2 | values.iter().fold(None, |acc, &value| { 3 | match acc { 4 | None => Some((value, value)), 5 | Some((min, max)) => { 6 | match value { 7 | v if v < min => Some((v, max)), 8 | v if v > max => Some((min, v)), 9 | _ => Some((min, max)) 10 | } 11 | } 12 | } 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/unique_count.jl: -------------------------------------------------------------------------------- 1 | function unique_count(data::Vector{Int32})::Int 2 | sorted_data = sort(data) 3 | count = 0 4 | if !isempty(sorted_data) 5 | count = 1 6 | for i in 2:length(sorted_data) 7 | if sorted_data[i] != sorted_data[i-1] 8 | count += 1 9 | end 10 | end 11 | end 12 | return count 13 | end 14 | 15 | function main() 16 | arr = Int32[1, 3, 1, 4, 1, 5] 17 | println(unique_count(arr)) 18 | end 19 | 20 | main() -------------------------------------------------------------------------------- /Exercises/geoangelotti/go.md: -------------------------------------------------------------------------------- 1 | goos: darwin 2 | goarch: arm64 3 | pkg: epwc 4 | cpu: Apple M2 Pro 5 | BenchmarkSmallestTwoSort-10 13023129 89.30 ns/op 6 | BenchmarkSmallestTwoSortInts-10 14239942 84.66 ns/op 7 | BenchmarkSmallestTwo-10 11893950 104.1 ns/op 8 | BenchmarkUniqueSortSlice-10 19879988 59.18 ns/op 9 | BenchmarkUniqueSlicesSort-10 122104620 9.822 ns/op 10 | BenchmarkUniqueMap-10 27111878 44.00 ns/op 11 | PASS 12 | ok epwc 9.267s 13 | -------------------------------------------------------------------------------- /Exercises/jglara/lecture1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20.0) 2 | project(lecture1 VERSION 0.1.0 LANGUAGES C CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 23) 5 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 6 | 7 | set(CMAKE_CXX_EXTENSIONS OFF) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | add_compile_options(-pedantic -Wall -Wextra -Werror) 10 | 11 | add_executable(lecture1 main.cpp) 12 | 13 | -------------------------------------------------------------------------------- /Exercises/pmcgee/Project_epwc.dpr: -------------------------------------------------------------------------------- 1 | {$APPTYPE CONSOLE} 2 | program Project_epwc; 3 | uses 4 | System.SysUtils, 5 | U_unique_count in 'unique_count\U_unique_count.pas', 6 | U_MinMax_Element in 'minmax_elem\U_MinMax_Element.pas', 7 | U_Gen_Data in 'U_Gen_Data.pas', 8 | U_Test_Instrumented in 'instrumented\U_Test_Instrumented.pas', 9 | U_Instrumented in 'instrumented\U_Instrumented.pas'; 10 | 11 | begin 12 | Unique_Count_Main; 13 | MinMax_Main; 14 | Instrumented_Main; 15 | 16 | readln; 17 | end. 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/01.cpp: -------------------------------------------------------------------------------- 1 | // https://godbolt.org/z/s9xGde6xP 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | auto distinct_count(auto rng) -> int { 9 | std::ranges::sort(rng); 10 | return std::ranges::fold_left_first( 11 | std::views::adjacent_transform<2>(rng, std::not_equal_to{}), 12 | std::plus{}) 13 | .value() + 14 | 1; 15 | } 16 | 17 | auto main() -> int { 18 | auto arr = std::array{1, 3, 1, 4, 1, 5}; 19 | std::print("{}", distinct_count(arr)); // outputs 4 20 | } -------------------------------------------------------------------------------- /Exercises/geoangelotti/deno.lock: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4", 3 | "specifiers": { 4 | "jsr:@std/assert@1": "1.0.12", 5 | "jsr:@std/internal@^1.0.6": "1.0.6" 6 | }, 7 | "jsr": { 8 | "@std/assert@1.0.12": { 9 | "integrity": "08009f0926dda9cbd8bef3a35d3b6a4b964b0ab5c3e140a4e0351fbf34af5b9a", 10 | "dependencies": [ 11 | "jsr:@std/internal" 12 | ] 13 | }, 14 | "@std/internal@1.0.6": { 15 | "integrity": "9533b128f230f73bd209408bb07a4b12f8d4255ab2a4d22a1fd6d87304aca9a4" 16 | } 17 | }, 18 | "workspace": { 19 | "dependencies": [ 20 | "jsr:@std/assert@1" 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Exercises/jglara/lecture1/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | namespace vws = std::views; 7 | namespace rngs = std::ranges; 8 | 9 | // Assuming rng is sorted, count unique elements in a range 10 | unsigned int count_unique(auto &&rng) 11 | { 12 | 13 | return rngs::fold_left( 14 | rng | vws::adjacent_transform<2>(std::not_equal_to{}) 15 | 1, std::plus{} 16 | ); 17 | } 18 | 19 | int main() 20 | { 21 | auto arr = std::array{1, 3, 1, 4, 1, 5}; 22 | rngs::sort(arr); 23 | std::cout << "Count: " << count_unique(arr) << std::endl; 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /Exercises/jglara/max_min/src/lib.rs: -------------------------------------------------------------------------------- 1 | use num_traits::Bounded; 2 | 3 | pub fn min_max(values: &[T]) -> (T, T) { 4 | values 5 | .iter() 6 | .fold((T::max_value(), T::min_value()), |(ac_min, ac_max), &x| { 7 | ( 8 | if x < ac_min { x } else { ac_min }, 9 | if x > ac_max { x } else { ac_max }, 10 | ) 11 | }) 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use super::*; 17 | 18 | #[test] 19 | fn test_min_max() { 20 | let values = [3, 1, 4, 1, 5, 9, 2, 6, 5]; 21 | let result = min_max(&values); 22 | assert_eq!(result, (1, 9)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/SmallestTwo.kts: -------------------------------------------------------------------------------- 1 | fun smallestTwoSort(nums: IntArray): Pair { 2 | if (nums.size < 2) { 3 | throw IllegalArgumentException("Need at least 2 numbers") 4 | } 5 | nums.sort() 6 | return Pair(nums[0], nums[1]) 7 | } 8 | 9 | fun smallestTwo(nums: IntArray): Pair { 10 | if (nums.size < 2) { 11 | throw IllegalArgumentException("Need at least 2 numbers") 12 | } 13 | val initial = Pair(Int.MAX_VALUE, Int.MAX_VALUE) 14 | return nums.fold(initial) { (smallest, secondSmallest), current -> 15 | when { 16 | current < smallest -> Pair(current, smallest) 17 | current < secondSmallest && current != smallest -> Pair(smallest, current) 18 | else -> Pair(smallest, secondSmallest) 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Exercises/jonocarroll/01.md: -------------------------------------------------------------------------------- 1 | ## APL 2 | 3 | ```apl 4 | x←1 3 1 4 1 5 5 | ≢∪x 6 | ≢((⍳⍴x)=x⍳x)/x 7 | +/((⍳⍴x)=x⍳x) 8 | +/(⍳⍤⍴=⍳⍨)x 9 | +/≠x 10 | ``` 11 | 12 | ## Uiua 13 | 14 | ```uiua 15 | ⧻▽⊸◰1_3_1_4_1_5 16 | ⧻◴1_3_1_4_1_5 17 | ``` 18 | 19 | ## Julia 20 | 21 | ```julia 22 | x=[1, 3, 1, 4, 1, 5] 23 | length(unique(x)) 24 | length(Set(x)) 25 | ``` 26 | 27 | ## R 28 | 29 | ```r 30 | x<-c(1, 3, 1, 4, 1, 5) 31 | length(unique(x)) 32 | length(table(x)) 33 | length(levels(factor(x))) 34 | ``` 35 | 36 | ## Haskell 37 | 38 | ```haskell 39 | import Data.List 40 | let x = [1, 3, 1, 4, 1, 5] 41 | length . nub $ x 42 | 43 | count_unique :: [Int] -> Int 44 | count_unique x = 1 + n_adjDiff 45 | where n_adjDiff = length . filter (uncurry (/=)) $ adj 46 | adj = zip sorted (drop 1 sorted) 47 | sorted = sort x 48 | ``` 49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## EPwC-2025 2 | 3 | This is the material (code and presentation slide decks) that correspond to the [Programming Languages Virtual Meetup](https://www.meetup.com/Programming-Languages-Toronto-Meetup/) course that covered the A9 Playlist **Efficient Programming with Components**. 4 | 5 | * **Playlist:** [Efficient Programming with Components](https://www.youtube.com/playlist?list=PLHxtyCq_WDLXryyw91lahwdtpZsmo4BGD) 6 | * **Content:** [Code and Papers GitHub Repo](https://github.com/rjernst/stepanov-components-course/tree/master) 7 | * **Course Notes:** https://www.jmeiners.com/efficient-programming-with-components 8 | 9 | #### Other Links 10 | 11 | * [www.stepanovpapers.com](https://www.stepanovpapers.com) 12 | * [ISO C++ Comments](https://isocpp.org/blog/2013/06/efficient-programming-with-components-by-alexander-stepanov) 👀 13 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/main.ts: -------------------------------------------------------------------------------- 1 | function windows(arr: Array, size: number): Array> { 2 | if (!arr || arr.length < size || size <0) { 3 | return []; 4 | } 5 | const acc: Array> = []; 6 | for (let i = 0; i <= arr.length - size; i++) { 7 | const window = []; 8 | for (let j = 0; j < size; j++) { 9 | window.push(arr[i + j]); 10 | } 11 | acc.push(window); 12 | } 13 | return acc; 14 | } 15 | 16 | function tupleWindows(arr: Array): Array> { 17 | return windows(arr, 2); 18 | } 19 | 20 | export function uniqueCount(arr: Array): number { 21 | return tupleWindows(arr.sort((a,b)=> +a-(+b))).filter((a)=> a[0] !== a[1]).length + 1; 22 | } 23 | 24 | // Learn more at https://docs.deno.com/runtime/manual/examples/module_metadata#concepts 25 | if (import.meta.main) { 26 | console.log(uniqueCount([1, 3, 1, 4, 1, 5])); 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/auto-assign.yml: -------------------------------------------------------------------------------- 1 | name: Auto Assign 2 | on: 3 | issues: 4 | types: [opened] 5 | pull_request: 6 | types: [opened] 7 | pull_request_target: 8 | types: [opened] 9 | 10 | permissions: 11 | issues: write 12 | pull-requests: write 13 | contents: read 14 | 15 | jobs: 16 | assign: 17 | runs-on: ubuntu-latest 18 | steps: 19 | # Handle Issues 20 | - if: github.event_name == 'issues' 21 | uses: pozil/auto-assign-issue@v2 22 | with: 23 | assignees: codereport 24 | numOfAssignee: 1 25 | 26 | # Handle PRs - use one action that can handle both assignments and reviews 27 | - if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' 28 | uses: kentaro-m/auto-assign-action@v1.2.5 29 | with: 30 | configuration-path: .github/auto-assign-config.yml 31 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/unique_count.go: -------------------------------------------------------------------------------- 1 | package epwc 2 | 3 | import ( 4 | "slices" 5 | "sort" 6 | ) 7 | 8 | func UniqueCount1(data []int) int { 9 | sort.Slice(data, func(i, j int) bool { 10 | return data[i] < data[j] 11 | }) 12 | if len(data) == 0 { 13 | return 0 14 | } 15 | count := 1 16 | for i := 1; i < len(data); i++ { 17 | if data[i] != data[i-1] { 18 | count++ 19 | } 20 | } 21 | return count 22 | } 23 | 24 | func UniqueCount2(data []int) int { 25 | slices.Sort(data) 26 | if len(data) == 0 { 27 | return 0 28 | } 29 | count := 1 30 | for i := 1; i < len(data); i++ { 31 | if data[i] != data[i-1] { 32 | count++ 33 | } 34 | } 35 | return count 36 | } 37 | 38 | func UniqueCount3(data []int) int { 39 | uniques := make(map[int]bool) 40 | for _, num := range data { 41 | if !uniques[num] { 42 | uniques[num] = true 43 | } 44 | } 45 | return len(uniques) 46 | } 47 | -------------------------------------------------------------------------------- /Exercises/conor_hoekstra/README.md: -------------------------------------------------------------------------------- 1 | ## `DistinctCount` Summary (Meeting 1) 2 | 3 | TODO update 4 | 5 | ## `MinMax` Summary (Meeting 2) 6 | 7 | | Language | Implementation | 8 | | :------: | :------------: | 9 | | BQN | `⌊´⋈⌈´` | 10 | | APL | `⌊/,⌈/` | 11 | | Uiua | `⊂⊃/↧/↥` | 12 | | Kap | `(⌊/)«,»(⌈/)` | 13 | 14 | Rust: 15 | ```rust 16 | fn min_max(values: Vec) -> Option<(i32, i32)> { 17 | values.iter().fold(None, |acc, &value| { 18 | match acc { 19 | None => Some((value, value)), 20 | Some((min, max)) => { 21 | Some(if value < min { 22 | (value, max) 23 | } else if value > max { 24 | (min, value) 25 | } else { 26 | (min, max) 27 | }) 28 | } 29 | } 30 | }) 31 | } 32 | ``` 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Exercises/jonocarroll/02.md: -------------------------------------------------------------------------------- 1 | ## APL 2 | 3 | ```apl 4 | (⌊/,⌈/)4 1 3 2 5 7 6 5 | ``` 6 | 7 | ## J 8 | 9 | ```j 10 | (<./,>./) 4 1 3 2 5 7 6 11 | ``` 12 | 13 | ## Uiua 14 | 15 | ```uiua 16 | ⊂⊃/↥/↧[4 1 3 2 5 7 6] 17 | ``` 18 | 19 | ## Julia 20 | 21 | ```julia 22 | x=[4, 1, 3, 2, 5, 7, 6] 23 | (minimum(x), maximum(x)) 24 | extrema(x) 25 | ``` 26 | 27 | ## R 28 | 29 | ```r 30 | x<-c(4, 1, 3, 2, 5, 7, 6) 31 | c(min(x), max(x)) 32 | range(x) 33 | sapply(list(min, max), \(f) f(x)) 34 | ``` 35 | 36 | ## Haskell 37 | 38 | ```haskell 39 | (minimum x, maximum x) 40 | ``` 41 | 42 | ## Python 43 | 44 | ```python 45 | x = [4, 1, 3, 2, 5, 7, 6] 46 | 47 | (min(x), max(x)) 48 | 49 | def minmax(x): 50 | smallest = float('inf') 51 | largest = 0 52 | for val in x: 53 | smallest = min(val, smallest) 54 | largest = max(val, largest) 55 | return (smallest, largest) 56 | 57 | minmax(x) 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/smallest_two.go: -------------------------------------------------------------------------------- 1 | package epwc 2 | 3 | import ( 4 | "math" 5 | "slices" 6 | "sort" 7 | ) 8 | 9 | func SmallestTwoSort(nums []int) []int { 10 | if len(nums) < 2 { 11 | panic("Need at least 2 numbers") 12 | } 13 | slices.Sort(nums) 14 | return []int{nums[0], nums[1]} 15 | } 16 | 17 | func SmallestTwoSortInts(nums []int) []int { 18 | if len(nums) < 2 { 19 | panic("Need at least 2 numbers") 20 | } 21 | sort.Ints(nums) 22 | return []int{nums[0], nums[1]} 23 | } 24 | 25 | func SmallestTwo(nums []int) []int { 26 | if len(nums) < 2 { 27 | panic("Need at least 2 numbers") 28 | } 29 | smallest := math.MaxInt 30 | secondSmallest := math.MaxInt 31 | for _, num := range nums { 32 | if num < smallest { 33 | secondSmallest = smallest 34 | smallest = num 35 | } else if num < secondSmallest && num != smallest { 36 | secondSmallest = num 37 | } 38 | } 39 | return []int{smallest, secondSmallest} 40 | } 41 | -------------------------------------------------------------------------------- /Exercises/jglara/lecture1/src/main.rs: -------------------------------------------------------------------------------- 1 | // Assume v is sorted 2 | fn count_unique (v: &[T]) -> usize { 3 | if v.is_empty() { 4 | return 0; 5 | } 6 | // Count unique elements by comparing adjacent elements 7 | v.iter() 8 | .zip(v[1..].iter()) 9 | .filter(|(a, b)| a != b) 10 | .count() + 1 11 | } 12 | 13 | 14 | fn main() { 15 | let mut v = vec![1, 2, 2, 3, 4, 4, 5]; 16 | v.sort(); 17 | let unique_count = count_unique(&v); 18 | println!("Number of unique elements: {}", unique_count); 19 | } 20 | 21 | #[cfg(test)] 22 | mod tests { 23 | use super::*; 24 | 25 | #[test] 26 | fn test_count_unique() { 27 | assert_eq!(count_unique(&[1, 2, 2, 3, 4, 4, 5]), 5); 28 | assert_eq!(count_unique(&[1, 1, 1]), 1); 29 | assert_eq!(count_unique(&[1, 2, 3]), 3); 30 | assert_eq!(count_unique::(&[]), 0); 31 | assert_eq!(count_unique(&[1]), 1); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /Exercises/jglara/max_min/benches/minmax.rs: -------------------------------------------------------------------------------- 1 | use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; 2 | use max_min::min_max; 3 | use rand::Rng; 4 | 5 | fn random_vec(size: usize) -> Vec { 6 | let mut rng = rand::rng(); 7 | (0..size) 8 | .map(|_| rng.random_range(0..=u64::max_value())) 9 | .collect::>() 10 | } 11 | 12 | fn bench_minmax(c: &mut Criterion) { 13 | let mut size = 1024usize; 14 | 15 | let mut group = c.benchmark_group("min_max_group"); 16 | 17 | while size <= 100_000_000 { 18 | group.sample_size(10).bench_with_input( 19 | BenchmarkId::new("min_max", size), 20 | &size, 21 | |b, &size| { 22 | b.iter_batched( 23 | || random_vec(size), 24 | |v| min_max(&v), 25 | criterion::BatchSize::SmallInput, 26 | ) 27 | }, 28 | ); 29 | 30 | size <<= 4; 31 | } 32 | } 33 | 34 | criterion_group!(benches, bench_minmax); 35 | criterion_main!(benches); 36 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/unique_count_test.go: -------------------------------------------------------------------------------- 1 | package epwc_test 2 | 3 | import ( 4 | "epwc" 5 | "testing" 6 | ) 7 | 8 | func TestEvaluatePolynomial(t *testing.T) { 9 | input := []int{1, 3, 1, 4, 1, 5} 10 | unique1 := epwc.UniqueCount1(input) 11 | unique2 := epwc.UniqueCount2(input) 12 | unique3 := epwc.UniqueCount3(input) 13 | res := 4 14 | if res != unique1 { 15 | t.Errorf("Expected %v but got %v", res, unique1) 16 | } 17 | if res != unique2 { 18 | t.Errorf("Expected %v but got %v", res, unique2) 19 | } 20 | if res != unique3 { 21 | t.Errorf("Expected %v but got %v", res, unique3) 22 | } 23 | } 24 | 25 | func BenchmarkUniqueSortSlice(b *testing.B) { 26 | input := []int{1, 3, 1, 4, 1, 5} 27 | for b.Loop() { 28 | _ = epwc.UniqueCount1(input) 29 | } 30 | } 31 | 32 | func BenchmarkUniqueSlicesSort(b *testing.B) { 33 | input := []int{1, 3, 1, 4, 1, 5} 34 | for b.Loop() { 35 | _ = epwc.UniqueCount2(input) 36 | } 37 | } 38 | 39 | func BenchmarkUniqueMap(b *testing.B) { 40 | input := []int{1, 3, 1, 4, 1, 5} 41 | for b.Loop() { 42 | _ = epwc.UniqueCount3(input) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Conor Hoekstra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LINKS.md: -------------------------------------------------------------------------------- 1 | # Meeting 1 (Apr 16, 2025) 2 | 3 | * https://docs.rs/instrumented-stepanov/ 4 | * https://www.youtube.com/watch?v=jrfZDtDgKYk 5 | * https://www.jmeiners.com/efficient-programming-with-components/ 6 | * https://adspthepodcast.com/2024/05/03/Episode-180.html 7 | 8 | # Meeting 2 (Apr 21, 2025) 9 | 10 | * http://fare.tunes.org/files/cs/poof/slides-2024-lambdaconf.html 11 | * https://www.youtube.com/watch?v=oAzBfY8OtG0 12 | * https://github.com/JuliaLang/julia/blob/760b2e5b7396f9cc0da5efce0cadd5d1974c4069/base/reduce.jl#L862-L870 13 | * https://en.wikipedia.org/wiki/Hacker%27s_Delight 14 | * https://learning.oreilly.com/library/view/-/9780133084993/ 15 | * https://uiua.org/pad?src=0_16_0-dev_1__4oqC4oip4pah4oqD4oeM4qe7IDFfMl8zCg== 16 | * https://jcarroll.com.au/2024/10/26/polyglot-maxxie-and-minnie/ 17 | 18 | # Meeting 3 (Apr 30, 2025) 19 | 20 | * https://www.jmeiners.com/efficient-programming-with-components/10_binary_counter.html#Smallest-and-second-smallest-element 21 | * https://www.youtube.com/watch?v=kc9HwsxE1OY 22 | * https://www.youtube.com/watch?v=OWfxexSE2aM 23 | * https://youtu.be/l2VemFmfkG4si=DpTZMArZgyU__Y8O 24 | * https://youtu.be/l2VemFmfkG4 25 | * https://www.mycompiler.io/view/DT0JYmp5Zk0 26 | -------------------------------------------------------------------------------- /Exercises/segreaves/Instrumented/Singleton.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // T is semiregular or regular or totally-ordered 4 | template 5 | struct Singleton 6 | { 7 | typedef T value_type; 8 | T value; 9 | 10 | // Conversions from T and to T 11 | explicit Singleton(const T& x) : value(x) {} 12 | explicit operator T() const { return value; } 13 | // Templated conversion 14 | template 15 | Singleton(const Singleton& x) : value(x.value) {} 16 | 17 | // Semi-regular requirements 18 | Singleton() {}// Default constructor 19 | Singleton(const Singleton& x) : value(x.value) {}// Copy constructor 20 | ~Singleton() {}// Destructor 21 | 22 | Singleton& operator=(Singleton& x) 23 | { 24 | value = x.value; 25 | return *this; 26 | } 27 | 28 | // Regular 29 | friend bool operator==(const Singleton& l, const Singleton& r) { return l.value == r.value; } 30 | friend bool operator!=(const Singleton& l, const Singleton& r) { return !(l == r); } 31 | // Totally-orderred 32 | friend bool operator<(const Singleton& l, const Singleton& r) { return l.value < r.value; } 33 | friend bool operator>(const Singleton& l, const Singleton& r) { return r < l; } 34 | friend bool operator<=(const Singleton& l, const Singleton& r) { return !(r < l); } 35 | friend bool operator>=(const Singleton& l, const Singleton& r) { return !(l < r); } 36 | }; 37 | -------------------------------------------------------------------------------- /Exercises/jonocarroll/03.md: -------------------------------------------------------------------------------- 1 | ## R 2 | 3 | ```r 4 | pair_sort <- function(a, b) { 5 | if (b < a[1]) { 6 | c(b, a[1]) 7 | } else if (b < a[2]) { 8 | c(a[1], b) 9 | } else { 10 | a 11 | } 12 | } 13 | 14 | smallest_two <- function(x) { 15 | Reduce(pair_sort, x, init = Inf) 16 | } 17 | 18 | smallest_two(c(1, 2, 3, 4, 5, 6)) 19 | #> [1] 1 2 20 | smallest_two(c(200, 40, 21, 13, 2)) 21 | #> [1] 2 13 22 | smallest_two(c(12, 1, 3, 4, 65, 7, -43, 8, 3, 8, 45, 2)) 23 | #> [1] -43 1 24 | ``` 25 | 26 | ## Haskell 27 | 28 | ```haskell 29 | module SecondSmallest where 30 | 31 | pair_sort :: (Int, Int) -> Int -> (Int, Int) 32 | pair_sort (x, y) z 33 | | z < x = (z, x) 34 | | z < y = (x, z) 35 | | otherwise = (x, y) 36 | 37 | smallest_two :: [Int] -> (Int, Int) 38 | smallest_two xs = foldl pair_sort (maxBound, maxBound) xs 39 | 40 | main :: IO() 41 | main = do 42 | print $ smallest_two [1, 2, 3, 4, 5, 6] 43 | print $ smallest_two [200, 40, 21, 13, 2] 44 | print $ smallest_two [12, 1, 3, 4, 65, 7, -43, 8, 3, 8, 45, 2] 45 | ``` 46 | 47 | ## Julia 48 | 49 | ```julia 50 | pair_sort(a, b) = b < a[1] ? [b, a[1]] : b < a[2] ? [a[1], b] : a 51 | smallest_two(xs) = foldl(pair_sort, xs, init=Inf) 52 | 53 | smallest_two([1, 2, 3, 4, 5, 6]) 54 | smallest_two([200, 40, 21, 13, 2]) 55 | smallest_two([12, 1, 3, 4, 65, 7, -43, 8, 3, 8, 45, 2]) 56 | ``` -------------------------------------------------------------------------------- /Exercises/segreaves/Instrumented/Pair.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | template 3 | struct Pair 4 | { 5 | typedef T type_first; 6 | typedef U type_second; 7 | T first; 8 | U second; 9 | 10 | // Conversions from T & U 11 | explicit Pair(const T& x, const U& y) : first(x), second(y) {} 12 | // Templated conversion 13 | template 14 | explicit Pair(const Pair& x) : first(x.first), second(x.second) {} 15 | 16 | // Semi-regular 17 | Pair() {}// Default constructor 18 | Pair(const Pair& x) : first(x.first), second(x.second) {}// Copy constructor 19 | ~Pair() {}// Destructor 20 | 21 | Pair& operator=(const Pair& x) 22 | { 23 | first = x.first; 24 | second = x.second; 25 | return *this; 26 | } 27 | 28 | // Regular 29 | friend bool operator==(const Pair& l, const Pair& r) { return (l.first == r.first) && (l.second == r.second); } 30 | friend bool operator!=(const Pair& l, const Pair& r) { return !(l == r); } 31 | 32 | // Totally-ordered 33 | friend bool operator<(const Pair& l, const Pair& r) { return (l.first < r.first) || (l.first == r.first) && (l.second < r.second); } 34 | friend bool operator>(const Pair& l, const Pair& r) { return r < l; } 35 | friend bool operator<=(const Pair& l, const Pair& r) { return !(r < l); } 36 | friend bool operator>=(const Pair& l, const Pair& r) { return !(l < r); } 37 | }; 38 | 39 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/smallest_two_test.go: -------------------------------------------------------------------------------- 1 | package epwc_test 2 | 3 | import ( 4 | "epwc" 5 | "reflect" 6 | "testing" 7 | ) 8 | 9 | var HundredNumbers = [100]int{ 10 | 81, 878, 421, 695, 133, 376, 703, 255, 358, 165, 11 | 96, 776, 932, 583, 39, 631, 739, 315, 686, 907, 12 | 118, 52, 945, 859, 488, 219, 591, 184, 897, 623, 13 | 750, 46, 308, 827, 191, 663, 984, 28, 515, 792, 14 | 437, 918, 609, 14, 271, 548, 365, 882, 714, 238, 15 | 995, 17, 403, 840, 652, 331, 769, 92, 575, 202, 16 | 499, 867, 294, 105, 679, 343, 786, 953, 410, 536, 17 | 225, 813, 64, 389, 727, 970, 562, 151, 474, 89, 18 | 320, 744, 99, 616, 25, 507, 834, 121, 688, 351, 19 | 798, 939, 452, 188, 59, 264, 871, 396, 70, 519, 20 | } 21 | 22 | func TestEvaluateSmallest(t *testing.T) { 23 | input := []int{1, -1, 1, 4, 1, 0} 24 | smallestTwo1 := epwc.SmallestTwoSort(input) 25 | smallestTwo2 := epwc.SmallestTwoSortInts(input) 26 | smallestTwo3 := epwc.SmallestTwo(input) 27 | res := []int{-1, 0} 28 | assert := func(value []int) { 29 | if !reflect.DeepEqual(res, value) { 30 | t.Errorf("Expected %v but got %v", res, value) 31 | } 32 | } 33 | assert(smallestTwo1) 34 | assert(smallestTwo2) 35 | assert(smallestTwo3) 36 | } 37 | 38 | func BenchmarkSmallestTwoSort(b *testing.B) { 39 | for b.Loop() { 40 | _ = epwc.SmallestTwoSort(HundredNumbers[:]) 41 | } 42 | } 43 | 44 | func BenchmarkSmallestTwoSortInts(b *testing.B) { 45 | for b.Loop() { 46 | _ = epwc.SmallestTwoSortInts(HundredNumbers[:]) 47 | } 48 | } 49 | 50 | func BenchmarkSmallestTwo(b *testing.B) { 51 | for b.Loop() { 52 | _ = epwc.SmallestTwo(HundredNumbers[:]) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Exercises/geoangelotti/.gitignore: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ 19 | 20 | # Go workspace file 21 | go.work 22 | go.work.sum 23 | 24 | # env file 25 | .env 26 | 27 | *.orig 28 | *.pyc 29 | *.swp 30 | .env 31 | 32 | /.cargo_home/ 33 | /.idea/ 34 | /.vs/ 35 | /.vscode/ 36 | gclient_config.py_entries 37 | /target/ 38 | /std/hash/_wasm/target 39 | /tests/wpt/runner/manifest.json 40 | /third_party/ 41 | /tests/napi/node_modules 42 | /tests/napi/build 43 | /tests/napi/third_party_tests/node_modules 44 | 45 | # MacOS generated files 46 | .DS_Store 47 | .DS_Store? 48 | 49 | # Flamegraphs 50 | /flamebench*.svg 51 | /flamegraph*.svg 52 | 53 | # WPT generated cert files 54 | /tests/wpt/runner/certs/index.txt* 55 | /tests/wpt/runner/certs/serial* 56 | 57 | /ext/websocket/autobahn/reports 58 | 59 | # Coverage files 60 | /coverage 61 | 62 | # JUnit files produced by deno test --junit 63 | junit.xml 64 | 65 | # Jupyter files 66 | .ipynb_checkpoints/ 67 | Untitled*.ipynb 68 | 69 | # playwright browser binary cache 70 | /.ms-playwright 71 | 72 | /target 73 | /classes 74 | /checkouts 75 | profiles.clj 76 | pom.xml 77 | pom.xml.asc 78 | *.jar 79 | *.class 80 | /.lein-* 81 | /.nrepl-port 82 | /.prepl-port 83 | .hgignore 84 | .hg/ 85 | -------------------------------------------------------------------------------- /Exercises/pmcgee/instrumented/U_Instrumented.pas: -------------------------------------------------------------------------------- 1 | unit U_Instrumented; 2 | 3 | interface 4 | uses Spring.SystemUtils; 5 | type 6 | TInstrum = record 7 | type 8 | TCounting = (new,kill,assign); 9 | 10 | public 11 | value : T; 12 | class function Create(const _t: T): TInstrum; static; 13 | class procedure Tally; static; 14 | 15 | private 16 | class var counts: array [TCounting] of integer; 17 | 18 | class operator initialize (out Dest: TInstrum); 19 | class operator finalize (var Dest: TInstrum); 20 | class operator assign (var Dest: TInstrum; const[ref] Src: TInstrum); 21 | end; 22 | 23 | 24 | 25 | 26 | implementation 27 | uses System.SysUtils; 28 | 29 | class function TInstrum.Create(const _t: T): TInstrum; 30 | begin 31 | Result.value := _t; 32 | end; 33 | 34 | 35 | class procedure TInstrum.Tally; 36 | begin 37 | writeln('Created : ', counts[new] ); 38 | writeln('Destroyed : ', counts[kill] ); 39 | writeln('Assigned : ', counts[assign]); 40 | end; 41 | 42 | 43 | class operator TInstrum.Assign(var Dest: TInstrum; const[ref] Src: TInstrum ); 44 | begin 45 | inc(counts[assign]); 46 | writeln('assign ' + IntPtr(@Src).ToHexString +' -> '+ IntPtr(@Dest).ToHexString); 47 | end; 48 | 49 | 50 | class operator TInstrum.Initialize(out Dest:TInstrum); 51 | begin 52 | inc(counts[new]); 53 | writeln('create ' + IntPtr(@Dest).ToHexString); 54 | end; 55 | 56 | 57 | class operator TInstrum.Finalize(var Dest:TInstrum); 58 | begin 59 | inc(counts[kill]); 60 | writeln('destroy ' + IntPtr(@Dest).ToHexString); 61 | end; 62 | 63 | 64 | end. 65 | -------------------------------------------------------------------------------- /Exercises/ryan_sullivant/02_minmax_element/benches/minmax_element.rs: -------------------------------------------------------------------------------- 1 | use minmax_element::{min_then_max, minmax_element, minmax_element_iter}; 2 | use rand::seq::SliceRandom; 3 | 4 | use criterion::{BatchSize, BenchmarkId, Criterion, criterion_group, criterion_main}; 5 | 6 | fn random_vec(size: usize) -> Vec { 7 | let mut v: Vec<_> = (0..size as u64).collect(); 8 | let mut rng = rand::rng(); 9 | v.shuffle(&mut rng); 10 | v 11 | } 12 | 13 | fn bench_minmax(c: &mut Criterion) { 14 | let mut group = c.benchmark_group("bench_minmax_element"); 15 | let mut size = 16usize; 16 | while size <= 16 * 1024 * 1024 { 17 | group.bench_with_input(BenchmarkId::new("min_then_max", size), &size, |b, &size| { 18 | b.iter_batched( 19 | || random_vec(size), 20 | |v| min_then_max(&v), 21 | BatchSize::SmallInput, 22 | ) 23 | }); 24 | 25 | group.bench_with_input( 26 | BenchmarkId::new("minmax_element_iter", size), 27 | &size, 28 | |b, &size| { 29 | b.iter_batched( 30 | || random_vec(size), 31 | |v| minmax_element_iter(&v), 32 | BatchSize::SmallInput, 33 | ) 34 | }, 35 | ); 36 | 37 | group.bench_with_input( 38 | BenchmarkId::new("minmax_element", size), 39 | &size, 40 | |b, &size| { 41 | b.iter_batched( 42 | || random_vec(size), 43 | |v| minmax_element(&v), 44 | BatchSize::SmallInput, 45 | ) 46 | }, 47 | ); 48 | size <<= 4; 49 | } 50 | group.finish(); 51 | } 52 | 53 | criterion_group!(benches, bench_minmax); 54 | criterion_main!(benches); 55 | -------------------------------------------------------------------------------- /Exercises/pmcgee/U_Gen_Data.pas: -------------------------------------------------------------------------------- 1 | unit U_Gen_Data; 2 | 3 | interface 4 | uses System.SysUtils, Spring, Spring.Collections; 5 | 6 | type 7 | TPairs = TPair; 8 | 9 | var 10 | data : TArray; 11 | data_arr : TArray; 12 | data_lst : IList; 13 | 14 | procedure generate_pair_data(N,N2:integer); 15 | procedure generate_series_data (N:integer); 16 | procedure generate_uniq_data (N:integer); 17 | 18 | 19 | implementation 20 | 21 | procedure generate_pair_data(N,N2:integer); 22 | begin 23 | setlength(data_arr,N); 24 | TEnumerable.Range(0,N-1) 25 | .ForEach( procedure (const i:integer) 26 | begin data_arr[i] := TPairs.Create(random(N2),random(N2)) end ); 27 | writeln; 28 | end; 29 | 30 | 31 | procedure generate_series_data(N:integer); 32 | begin 33 | data_lst := TCollections.CreateList; 34 | TEnumerable.Range(1,N) 35 | .ForEach( procedure (const i:integer) 36 | begin data_lst.Add( random(N) ) end ); 37 | writeln; 38 | end; 39 | 40 | 41 | procedure generate_uniq_data(N:integer); 42 | begin 43 | setlength(data, N); 44 | TEnumerable.Range(0,N-1) 45 | .ForEach( procedure (const i:integer) begin data[i] := random(N) end ); 46 | writeln; 47 | end; 48 | 49 | end. 50 | 51 | 52 | 53 | //type 54 | // rng_fn = reference to function (start, count: Integer): IReadOnlyList; 55 | //var 56 | // rng := TEnumerable.Range; 57 | // for var i in rng(0,N-1) do data[i] := random(N); 58 | 59 | //type 60 | // chunk_fn = reference to function (const source: IEnumerable; size: Integer) : IEnumerable>; 61 | //var 62 | // chunk : chunk_fn := TEnumerable.Chunk; 63 | // for var ch in chunk(data_lst,2) do z:= minmax(z,ch); 64 | 65 | 66 | -------------------------------------------------------------------------------- /Exercises/pmcgee/unique_count/U_unique_count.pas: -------------------------------------------------------------------------------- 1 | unit U_unique_count; 2 | 3 | interface 4 | 5 | procedure unique_count_main; 6 | 7 | 8 | implementation 9 | uses 10 | System.SysUtils, Spring, Spring.Collections, U_Gen_Data; 11 | 12 | const 13 | N = 20000; 14 | crlf = #13#10; 15 | 16 | 17 | function uniq_spring_set : string; 18 | begin 19 | var s := TCollections.CreateSet(data); 20 | exit('Spring Set : ' + s.Count.ToString + crlf); 21 | end; 22 | 23 | 24 | function uniq_spring_list : string; 25 | begin 26 | var l := TCollections.CreateList(data); 27 | exit('Spring List : ' + l.Distinct.Count.ToString + crlf); 28 | end; 29 | 30 | 31 | function uniq_spring_sortedlist : string; 32 | begin 33 | var l := TCollections.CreateSortedList(data); 34 | exit('Spring SortedList : ' + l.Distinct.Count.ToString + crlf); 35 | end; 36 | 37 | 38 | function uniq_spring_enum : string; 39 | begin 40 | exit('Spring Enumerable : ' + TEnumerable.From(data) 41 | .Distinct 42 | .Count 43 | .ToString + crlf); 44 | end; 45 | 46 | 47 | function uniq_array_int : string; 48 | begin 49 | var last:= -1; 50 | var cnt := 0; 51 | TArray.Sort(data); 52 | for var i in data do 53 | if i<>last then begin 54 | inc(cnt); last := i; 55 | end; 56 | exit('TArray : ' + cnt.ToString + crlf); 57 | end; 58 | 59 | 60 | 61 | procedure unique_count_main; 62 | begin 63 | generate_uniq_data(N); 64 | 65 | writeln(uniq_spring_set); 66 | writeln(uniq_spring_list); 67 | writeln(uniq_spring_sortedlist); 68 | writeln(uniq_spring_enum); 69 | writeln(uniq_array_int); 70 | end; 71 | 72 | end. 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Delphi compiler-generated binaries (safe to delete) 30 | *.exe 31 | *.dll 32 | *.bpl 33 | *.bpi 34 | *.dcp 35 | *.so 36 | *.apk 37 | *.drc 38 | *.map 39 | *.dres 40 | *.rsm 41 | *.tds 42 | *.dcu 43 | *.lib 44 | *.a 45 | *.o 46 | *.ocx 47 | 48 | # Delphi autogenerated files (duplicated info) 49 | *.cfg 50 | *.hpp 51 | *Resource.rc 52 | 53 | # Delphi local files (user-specific info) 54 | *.local 55 | *.identcache 56 | *.projdata 57 | *.tvsconfig 58 | *.dsk 59 | 60 | # Delphi history and backups 61 | __history/ 62 | __recovery/ 63 | *.~* 64 | 65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 66 | *.stat 67 | 68 | # Boss dependency manager vendor folder https://github.com/HashLoad/boss 69 | modules/ 70 | -------------------------------------------------------------------------------- /Exercises/pmcgee/minmax_elem/U_MinMax_Element.pas: -------------------------------------------------------------------------------- 1 | unit U_MinMax_Element; 2 | 3 | interface 4 | 5 | procedure minmax_main; 6 | 7 | 8 | implementation 9 | uses 10 | System.SysUtils, Spring, Spring.Collections, U_Gen_Data; 11 | 12 | const 13 | N1 = 10000; 14 | N2 = 20000; 15 | crlf = #13#10; 16 | zero : TPairs = (Key:N2; Value:0); 17 | zarr : TArray = [N2,0]; 18 | 19 | 20 | 21 | function minmax(a,b:TPairs) : TPairs; overload; 22 | begin 23 | result := a; 24 | if b.Value < b.Key then b:= TPairs.Create(b.Value,b.Key); 25 | if b.Key < a.Key then result.Key := b.Key; 26 | if b.Value > a.Value then result.Value := b.Value; 27 | end; 28 | 29 | function minmax(a,b:TArray) : TArray; overload; // actually Tuple of size 2 😥 30 | begin 31 | result := a; 32 | if b[1] < b[0] then b:= [ b[1],b[0] ]; 33 | if b[0] < a[0] then result[0] := b[0]; 34 | if b[1] > a[1] then result[1] := b[1]; 35 | end; 36 | 37 | 38 | 39 | function minmax_element_pairs : string; 40 | begin 41 | var z := zero; 42 | for var e in data_arr do z:= minmax(z,e); 43 | exit('Array MinMax : Min ' + z.Key.ToString + ' Max ' + z.Value.ToString + crlf); 44 | end; 45 | 46 | 47 | function minmax_element_IList : string; 48 | begin 49 | exit('List MinMax : Min ' + data_lst.Min.ToString + ' Max ' + data_lst.Max.ToString + crlf); 50 | end; 51 | 52 | 53 | function minmax_element_chunk : string; 54 | var z :TArray; 55 | begin 56 | z := zarr; 57 | for var ch in TEnumerable.Chunk(data_lst,2) do z:= minmax(z,ch); 58 | exit('Chunk MinMax : Min ' + z[0].ToString + ' Max ' + z[1].ToString + crlf); 59 | end; 60 | 61 | 62 | 63 | procedure minmax_main; 64 | begin 65 | generate_pair_data(N1,N2); 66 | generate_series_data(N2); 67 | 68 | writeln( minmax_element_pairs ); 69 | writeln( minmax_element_IList); 70 | writeln( minmax_element_chunk ); 71 | end; 72 | 73 | end. 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Exercises/pmcgee/instrumented/U_Test_Instrumented.pas: -------------------------------------------------------------------------------- 1 | unit U_Test_Instrumented; 2 | 3 | interface 4 | 5 | procedure Instrumented_Main; 6 | 7 | 8 | 9 | implementation 10 | uses System.SysUtils, System.Types, System.Generics.Collections, System.Generics.Defaults, U_Instrumented; 11 | 12 | 13 | procedure ByValue (rec: TInstrum); begin writeln('Called by value') end; 14 | procedure ByConstValue (const rec: TInstrum); begin writeln('Called as const') end; 15 | procedure ByRef (var rec: TInstrum); begin writeln('Called as ref') end; 16 | procedure ByConstRef (const[ref] rec: TInstrum); begin writeln('Called as const ref') end; 17 | function Returned : TInstrum; begin writeln('Returned by function') end; 18 | 19 | 20 | 21 | procedure Instrumented_Main; 22 | type 23 | TInsInt = TInstrum; 24 | begin 25 | begin 26 | var a:= TInsInt.Create(1); 27 | var b:= TInsInt.Create(2); 28 | 29 | writeln; ByValue (a); 30 | writeln; ByConstValue (a); 31 | writeln; ByRef (a); 32 | writeln; ByConstRef (a); 33 | writeln; b := Returned; 34 | writeln; 35 | end; 36 | 37 | writeln('---'); 38 | 39 | TInstrum.Tally; 40 | end; 41 | 42 | end. 43 | 44 | 45 | 46 | 47 | 48 | 49 | { 50 | var x:TArray< integer >; // TInsInt 51 | Setlength(x,10); 52 | 53 | for var i:= 0 to 9 do x[i] := (10-i); // TInsInt.Create(10-i); 54 | 55 | // TArray.Sort(x, TComparer.Construct( 56 | // function(const Left, Right: TInsInt): Integer 57 | // begin 58 | // Result := Left.value - Right.value; 59 | // end 60 | // ) 61 | // ); 62 | TArray.Sort(x); // weird errors for TInsInt 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /Exercises/segreaves/FindUniqueElementsInArray.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // From Alexander Stepanov's lectures on Efficient Programming With Components 10 | // https://www.youtube.com/watch?v=aIHAEYyoTUc&list=PLHxtyCq_WDLXryyw91lahwdtpZsmo4BGD&index=1 11 | // Find the unique elements in { 1, 3, 1, 4, 1, 5 } 12 | 13 | int findUnique_Set(int arr[], int size) 14 | { 15 | std::set uniq{ arr, arr + size }; 16 | return uniq.size(); 17 | } 18 | 19 | int findUnique_Ptr(int arr[], int size) 20 | { 21 | std::sort(arr, arr + size); 22 | return std::unique(arr, arr + size) - arr; 23 | } 24 | 25 | int findUnique_TwoPtr(int arr[], int size) 26 | { 27 | std::sort(arr, arr + size); 28 | int count{ 0 }; 29 | for (int i = 0; i < size; ++i) 30 | if (i == 0 || arr[i] != arr[i - 1]) ++count; 31 | return count; 32 | } 33 | 34 | void findUnique(int arr[], int size, std::function func) 35 | { 36 | int reps{ 1000000 }; 37 | int i{ 0 }; 38 | int ans; 39 | 40 | std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); 41 | while (i++ < reps) ans = func(arr, size); 42 | std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); 43 | std::chrono::duration elapsed = end - start; 44 | std::cout << "Elapsed time: " << elapsed.count() << " seconds" << std::endl; 45 | } 46 | 47 | int main() 48 | { 49 | int arr[] = { 1, 3, 1, 4, 1, 5 }; 50 | int size{ sizeof(arr) / sizeof(arr[0]) }; 51 | 52 | std::cout << "---------------------"; 53 | std::cout << std::endl << "Using findUnique_Set: " << std::endl; 54 | findUnique(arr, size, findUnique_Set); 55 | 56 | std::cout << std::endl << "Using findUnique_Ptr: " << std::endl; 57 | findUnique(arr, size, findUnique_Ptr); 58 | 59 | std::cout << std::endl << "Using findUnique_TwoPtr: " << std::endl; 60 | findUnique(arr, size, findUnique_TwoPtr); 61 | } 62 | -------------------------------------------------------------------------------- /Exercises/segreaves/Instrumented/EfficientProgrammingWithComponents.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Singleton.h" 3 | #include "Pair.h" 4 | 5 | int main() 6 | { 7 | std::cout << "Singleton" << std::endl; 8 | Singleton s1{ 1 }; 9 | std::cout << "s1: " << s1.value << std::endl; 10 | Singleton copy_of_s1{ s1 }; 11 | std::cout << "copy_of_s1: " << copy_of_s1.value << std::endl; 12 | copy_of_s1.value += 1; 13 | std::cout << "Added 1 to copy_of_s1: " << copy_of_s1.value << std::endl; 14 | Singleton s2; 15 | s2 = copy_of_s1; 16 | std::cout << "s2 = copy_of_s1: " << s2.value << std::endl; 17 | std::cout << "s1 < s2: " << (s1 < s2 ? "true" : "false") << std::endl; 18 | std::cout << "s2 == copy_of_s1: " << (s2 == copy_of_s1 ? "true" : "false") << std::endl; 19 | 20 | std::cout << "\n" << "Pair" << std::endl; 21 | Pair p1{ 1, 1.1 }; 22 | std::cout << "p1: [" << p1.first << ", " << p1.second << "]" << std::endl; 23 | Pair copy_of_p1{ p1 }; 24 | std::cout << "copy_of_p1: [" << copy_of_p1.first << ", " << copy_of_p1.second << "]" << std::endl; 25 | copy_of_p1.first++; 26 | copy_of_p1.second *= 2; 27 | std::cout << "copy_of_p1.first++, copy_of_p1.second *= 2: [" << copy_of_p1.first << ", " << copy_of_p1.second << "]" << std::endl; 28 | Pair p2; 29 | p2 = copy_of_p1; 30 | std::cout << "p2 = copy_of_p1: [" << p2.first << ", " << p2.second << "]" << std::endl; 31 | std::cout << "p1 < p2: " << (p1 < p2 ? "true" : "false") << std::endl; 32 | p1.first++; 33 | std::cout << "p1.first++: [" << p1.first << ", " << p1.second << "]" << std::endl; 34 | std::cout << "p1 < p2: " << (p1 < p2 ? "true" : "false") << std::endl; 35 | std::cout << "p1 > p2: " << (p1 > p2 ? "true" : "false") << std::endl; 36 | std::cout << "p1 == p2: " << (p1 == p2 ? "true" : "false") << std::endl; 37 | p1.second *= 2; 38 | std::cout << "p1.second *= 2: [" << p1.first << ", " << p1.second << "]" << std::endl; 39 | std::cout << "p1 == p2: " << (p1 == p2 ? "true" : "false") << std::endl; 40 | } 41 | -------------------------------------------------------------------------------- /Exercises/ryan_sullivant/01_unique_count/benches/unique.rs: -------------------------------------------------------------------------------- 1 | use rand::seq::SliceRandom; 2 | use std::collections::{BTreeSet, HashSet}; 3 | use std::hash::{BuildHasher, Hash, RandomState}; 4 | 5 | #[inline] 6 | fn unique_btree_set(v: Vec) -> usize 7 | where 8 | T: Ord, 9 | { 10 | let set = BTreeSet::from_iter(v.into_iter()); 11 | set.len() 12 | } 13 | 14 | #[inline] 15 | fn unique_hash_set(v: Vec, _: S) -> usize 16 | where 17 | T: Ord + Hash, 18 | S: BuildHasher + Default, 19 | { 20 | let set: HashSet = HashSet::from_iter(v.into_iter()); 21 | set.len() 22 | } 23 | 24 | #[inline] 25 | fn unique_sort(mut v: Vec) -> usize 26 | where 27 | T: Ord, 28 | { 29 | v.sort(); 30 | v.dedup(); 31 | v.len() 32 | } 33 | 34 | #[inline] 35 | fn unique_unstable_sort(mut v: Vec) -> usize 36 | where 37 | T: Ord, 38 | { 39 | v.sort_unstable(); 40 | v.dedup(); 41 | v.len() 42 | } 43 | 44 | fn random_vec(size: usize) -> Vec { 45 | let mut v: Vec<_> = (0..size as u64).collect(); 46 | let mut rng = rand::rng(); 47 | v.shuffle(&mut rng); 48 | v 49 | } 50 | 51 | use criterion::{BatchSize, BenchmarkId, Criterion, criterion_group, criterion_main}; 52 | 53 | fn bench_uniques(c: &mut Criterion) { 54 | let mut group = c.benchmark_group("bench_uniques"); 55 | let mut size = 16usize; 56 | while size <= 16 * 1024 * 1024 { 57 | group.bench_with_input(BenchmarkId::new("BTreeSet", size), &size, |b, &size| { 58 | b.iter_batched( 59 | || random_vec(size), 60 | |v| unique_btree_set(v), 61 | BatchSize::SmallInput, 62 | ) 63 | }); 64 | 65 | group.bench_with_input(BenchmarkId::new("HashSet", size), &size, |b, &size| { 66 | b.iter_batched( 67 | || random_vec(size), 68 | |v| unique_hash_set(v, RandomState::new()), 69 | BatchSize::SmallInput, 70 | ) 71 | }); 72 | 73 | group.bench_with_input(BenchmarkId::new("Sort", size), &size, |b, &size| { 74 | b.iter_batched( 75 | || random_vec(size), 76 | |v| unique_sort(v), 77 | BatchSize::SmallInput, 78 | ) 79 | }); 80 | 81 | group.bench_with_input(BenchmarkId::new("UnstableSort", size), &size, |b, &size| { 82 | b.iter_batched( 83 | || random_vec(size), 84 | |v| unique_unstable_sort(v), 85 | BatchSize::SmallInput, 86 | ) 87 | }); 88 | 89 | size <<= 4; 90 | } 91 | group.finish(); 92 | } 93 | 94 | criterion_group!(benches, bench_uniques); 95 | criterion_main!(benches); 96 | -------------------------------------------------------------------------------- /Demo/binary_counter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Class implementation. State: 5 | // - vector for the counter 6 | // - zero 7 | // - op 8 | 9 | template class binary_counter { 10 | private: 11 | std::vector counter; 12 | Op op; 13 | T zero; 14 | 15 | public: 16 | // Constructor. Input arguments: op and zero. 17 | binary_counter(const Op &op, const T &zero) : op(op), zero(zero) { 18 | counter.reserve(24); 19 | } 20 | 21 | // add 22 | void add(T x) { 23 | 24 | std::cout << "----" << std::endl; 25 | std::cout << "x: " << *x << std::endl; 26 | for (const auto &elem : counter) { 27 | std::cout << *elem << " "; 28 | } 29 | std::cout << std::endl; 30 | 31 | x = add_to_counter(counter.begin(), counter.end(), op, zero, x); 32 | if (x != zero) 33 | counter.push_back(x); 34 | 35 | std::cout << "becomes " << std::endl; 36 | for (const auto &elem : counter) { 37 | std::cout << *elem << " "; 38 | } 39 | std::cout << std::endl; 40 | } 41 | 42 | // reduce 43 | // returns: value of the counter 44 | T reduce() { 45 | return reduce_counter(counter.begin(), counter.end(), op, zero); 46 | } 47 | }; 48 | 49 | template 50 | // requires Op is BinaryOperation(T) 51 | // and Op is associative 52 | // and I is ForwardIterator and ValueType(I) == T 53 | T add_to_counter(I first, I last, Op op, const T &zero, T carry) { 54 | // precondition: carry != zero 55 | while (first != last) { 56 | if (*first == zero) { 57 | *first = carry; 58 | return zero; 59 | } 60 | carry = op(*first, carry); 61 | *first = zero; 62 | ++first; 63 | } 64 | return carry; 65 | } 66 | 67 | template 68 | // requires Op is BinaryOperation(T) 69 | // and Op is associative 70 | // and I is ForwardIterator and ValueType(I) == T 71 | T reduce_counter(I first, I last, Op op, const T &zero) { 72 | while (first != last && *first == zero) { 73 | ++first; 74 | } 75 | if (first == last) 76 | return zero; 77 | 78 | T result = *first; 79 | while (++first != last) { 80 | if (*first != zero) { 81 | result = op(*first, result); 82 | } 83 | } 84 | return result; 85 | } 86 | 87 | // TODO: implement min_element_binary, using binary_counter 88 | 89 | // - compares two iterators and returns the one 90 | // pointing to the smallest element 91 | template class min_op { 92 | private: 93 | Compare cmp; 94 | 95 | public: 96 | min_op(const Compare &cmp) : cmp(cmp) {} 97 | template I operator()(const I &x, const I &y) { 98 | return cmp(*y, *x) ? y : x; 99 | } 100 | }; 101 | 102 | template 103 | // requires I is a ForwardIterator 104 | // and Compare is a StrictWeakOrdering on ValueType(I) 105 | I min_element_binary(I first, I last, Compare cmp) { 106 | binary_counter> min_counter(min_op(cmp), last); 107 | while (first != last) { 108 | min_counter.add(first++); 109 | } 110 | return min_counter.reduce(); 111 | } 112 | 113 | int main() { 114 | 115 | // plugin whatever numbers you want to test with 116 | auto data = std::vector{9, 13, 7, 124, 32, 17, 8, 32, 117 | 237, 417, 41, 42, 13, 14, 15}; 118 | auto end = data.end(); 119 | auto min = min_element_binary( data.begin(), data.end(), std::less() ); 120 | if (min == end) { 121 | std::cout << "No elements" << std::endl; 122 | } else { 123 | std::cout << "Min is " << *min << std::endl; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Exercises/ryan_sullivant/02_minmax_element/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[inline] 2 | fn minmax2(a: usize, b: usize, s: &[T]) -> (usize, usize) 3 | where 4 | T: Ord, 5 | { 6 | if &s[b] < &s[a] { (b, a) } else { (a, b) } 7 | } 8 | 9 | #[inline] 10 | fn min2(a: usize, b: usize, s: &[T]) -> usize 11 | where 12 | T: Ord, 13 | { 14 | if &s[b] < &s[a] { b } else { a } 15 | } 16 | 17 | #[inline] 18 | fn max2(a: usize, b: usize, s: &[T]) -> usize 19 | where 20 | T: Ord, 21 | { 22 | if &s[b] < &s[a] { a } else { b } 23 | } 24 | 25 | #[inline] 26 | pub fn minmax_element(s: &[T]) -> Option<(usize, usize)> 27 | where 28 | T: Ord, 29 | { 30 | if s.len() < 1 { 31 | return None; 32 | } else if s.len() < 2 { 33 | return Some((0, 0)); 34 | } 35 | let (mut min, mut max) = minmax2(0, 1, s); 36 | let mut curr = 2; 37 | 38 | while curr != s.len() { 39 | let next = curr + 1; 40 | if next < s.len() { 41 | let (p_min, p_max) = minmax2(curr, next, s); 42 | min = min2(min, p_min, s); 43 | max = max2(max, p_max, s); 44 | curr = next + 1; 45 | } else { 46 | min = min2(min, curr, s); 47 | max = max2(max, curr, s); 48 | curr += 1; 49 | } 50 | } 51 | 52 | Some((min, max)) 53 | } 54 | 55 | #[inline] 56 | pub fn minmax_element_iter(s: &[T]) -> Option<(usize, usize)> 57 | where 58 | T: Ord, 59 | { 60 | if s.len() < 1 { 61 | return None; 62 | } 63 | 64 | let minmax2_ind = |s, ind| { 65 | let (min, max) = minmax2(0, 1, s); 66 | (min + 2 * ind, max + 2 * ind) 67 | }; 68 | 69 | let chunks = s.chunks_exact(2); 70 | let remainder = chunks.remainder(); 71 | let mut enumerated = chunks.enumerate(); 72 | let init = if remainder.len() > 0 { 73 | // remainder can only be the last element 74 | (s.len() - 1, s.len() - 1) 75 | } else { 76 | let (ind, sl) = enumerated.next().unwrap(); 77 | minmax2_ind(sl, ind) 78 | }; 79 | 80 | let (min, max) = enumerated.fold(init, |acc, e| { 81 | let ind = e.0; 82 | let sl = e.1; 83 | let (min, max) = minmax2_ind(sl, ind); 84 | (min2(acc.0, min, s), max2(acc.1, max, s)) 85 | }); 86 | 87 | Some((min, max)) 88 | } 89 | 90 | #[inline] 91 | pub fn min_then_max(s: &[T]) -> Option<(usize, usize)> 92 | where 93 | T: Ord, 94 | { 95 | if s.len() < 1 { 96 | return None; 97 | } 98 | if s.len() < 2 { 99 | return Some((0, 0)); 100 | } 101 | let min = (1..s.len()).fold(0, |acc, ind| min2(acc, ind, s)); 102 | let max = (1..s.len()).fold(0, |acc, ind| max2(acc, ind, s)); 103 | Some((min, max)) 104 | } 105 | 106 | #[cfg(test)] 107 | mod tests { 108 | use super::*; 109 | 110 | #[test] 111 | fn test_minmax() { 112 | let v = vec![1, 3, 4, 5, 3, 5]; 113 | assert_eq!(minmax_element(&v), Some((0, 5))); 114 | let v = vec![1, 3, 4, 5, 3]; 115 | assert_eq!(minmax_element(&v), Some((0, 3))); 116 | assert_eq!(minmax_element(&v[0..0]), None); 117 | let v = vec![1]; 118 | assert_eq!(minmax_element(&v), Some((0, 0))); 119 | let v = vec![2, 1]; 120 | assert_eq!(minmax_element(&v), Some((1, 0))); 121 | } 122 | 123 | #[test] 124 | fn test_minmax_iter() { 125 | let v = vec![1, 3, 4, 5, 3, 5]; 126 | assert_eq!(minmax_element_iter(&v), Some((0, 5))); 127 | let v = vec![1, 3, 4, 5, 3]; 128 | assert_eq!(minmax_element_iter(&v), Some((0, 3))); 129 | assert_eq!(minmax_element_iter(&v[0..0]), None); 130 | let v = vec![1]; 131 | assert_eq!(minmax_element_iter(&v), Some((0, 0))); 132 | let v = vec![2, 1]; 133 | assert_eq!(minmax_element_iter(&v), Some((1, 0))); 134 | } 135 | 136 | #[test] 137 | fn test_min_then_max() { 138 | let v = vec![1, 3, 4, 5, 3, 5]; 139 | assert_eq!(min_then_max(&v), Some((0, 5))); 140 | let v = vec![1, 3, 4, 5, 3]; 141 | assert_eq!(min_then_max(&v), Some((0, 3))); 142 | assert_eq!(min_then_max(&v[0..0]), None); 143 | let v = vec![1]; 144 | assert_eq!(min_then_max(&v), Some((0, 0))); 145 | let v = vec![2, 1]; 146 | assert_eq!(min_then_max(&v), Some((1, 0))); 147 | } 148 | } 149 | --------------------------------------------------------------------------------