├── .travis.yml ├── LICENSE ├── README.md ├── algorithms ├── graphs │ ├── bfs-shortest-path │ │ ├── bfs_shortest_path.go │ │ └── bfs_shortest_path_test.go │ ├── bfs │ │ ├── bfs.go │ │ └── bfs_test.go │ ├── dfs │ │ ├── dfs.go │ │ └── dfs_test.go │ ├── dijkstra │ │ ├── dijkstra.go │ │ └── dijkstra_test.go │ ├── kosaraju │ │ ├── kosaraju.go │ │ └── kosaraju_test.go │ └── topological-sort │ │ ├── topological.go │ │ └── topological_test.go ├── maths │ ├── RSelect │ │ ├── README.md │ │ ├── RSelect.go │ │ └── RSelect_test.go │ ├── closest-pair │ │ ├── README.md │ │ ├── closest_pair.go │ │ └── closest_pair_test.go │ ├── eratosthenes-sieve │ │ ├── README.md │ │ ├── benchmark.png │ │ ├── primes.go │ │ ├── primes_benchmark.go │ │ └── primes_test.go │ ├── euclide │ │ ├── README.md │ │ ├── extended_gcd.go │ │ └── extended_gcd_test.go │ ├── fast-power │ │ ├── README.md │ │ ├── fast_power.go │ │ └── fast_power_test.go │ ├── fibonacci │ │ ├── README.md │ │ ├── fibonacci.go │ │ └── fibonacci_test.go │ ├── fisher-yates │ │ ├── README.md │ │ └── fisherYates.go │ ├── karatsuba │ │ ├── README.md │ │ ├── karatsuba.go │ │ └── karatsuba_test.go │ ├── newton-sqrt │ │ ├── README.md │ │ ├── newton_sqrt.go │ │ └── newton_sqrt_test.go │ ├── permutations-count │ │ ├── README.md │ │ ├── permutations.go │ │ └── permutations_test.go │ ├── stein │ │ ├── README.md │ │ ├── gcd.go │ │ └── gcd_test.go │ └── strassen │ │ ├── README.md │ │ ├── strassen.go │ │ └── strassen_test.go ├── searching │ └── binary-search │ │ ├── binary_search.go │ │ └── binary_search_test.go └── sorting │ ├── README.md │ ├── bubble-sort │ ├── bubble.go │ └── bubble_test.go │ ├── heap-sort │ ├── heap.go │ └── heap_test.go │ ├── insertion-sort │ ├── insertion.go │ └── insertion_test.go │ ├── merge-sort │ ├── merge.go │ └── merge_test.go │ ├── quick-sort │ ├── quick.go │ └── quick_test.go │ ├── selection-sort │ ├── selection.go │ └── selection_test.go │ ├── shell-sort │ ├── shell.go │ └── shell_test.go │ └── utils │ ├── IntegerArray.txt │ ├── utils.go │ └── utils_test.go └── data-structures ├── binary-tree ├── bst.go └── bst_test.go ├── graph ├── README.md ├── directed_graph.go ├── graph.go ├── graph_test.go └── undirected_graph.go ├── hash-tables ├── ht.go └── ht_test.go ├── heap ├── heap.go ├── heap_test.go └── util.go ├── linked-list ├── linked_list.go └── linked_list_test.go ├── matrix ├── README.md ├── matrix.go └── matrix_test.go ├── priority-queue ├── priority_queue.go └── priority_queue_test.go ├── queue ├── queue.go └── queue_test.go └── stack ├── stack.go └── stack_test.go /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.3 5 | - tip 6 | 7 | before_install: 8 | - go get github.com/axw/gocov/gocov 9 | - go get github.com/mattn/goveralls 10 | - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi 11 | 12 | script: 13 | - go build -x -v ./... 14 | - go test -x -v ./... 15 | 16 | notifications: 17 | email: 18 | recipients: 19 | - arnaud.drizard@gmail.com 20 | on_success: change 21 | on_failure: always 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Go Algorithms is Copyright (c) 2015 Arnaud Drizard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms [![Build Status](https://travis-ci.org/arnauddri/algorithms.svg?branch=master)](https://travis-ci.org/arnauddri/algorithms) 2 | 3 | Classic algorithms and data structures implemented in Go. Not for production use, it is mostly an attempt to get comfortable both with Go and key CS concepts. 4 | 5 | ### Contents 6 | 7 | #### Data Structures 8 | 9 | * [Binary Search Tree](https://github.com/arnauddri/algorithms/tree/master/data-structures/binary-tree) [(wiki)](http://en.wikipedia.org/wiki/Binary_tree) 10 | * [Graph](https://github.com/arnauddri/algorithms/tree/master/data-structures/graph) [(wiki)](http://en.wikipedia.org/wiki/Graph_%28abstract_data_type) 11 | * [Hash Tables](https://github.com/arnauddri/algorithms/tree/master/data-structures/hash-tables) [(wiki)](http://en.wikipedia.org/wiki/Hash_table) 12 | * [Linked List](https://github.com/arnauddri/algorithms/tree/master/data-structures/linked-list) [(wiki)](http://en.wikipedia.org/wiki/Linked_list) 13 | * [Matrix](https://github.com/arnauddri/algorithms/tree/master/data-structures/matrix) [(wiki)](http://en.wikipedia.org/wiki/Matrix_(mathematics)) 14 | * [Min/Max Heap](https://github.com/arnauddri/algorithms/tree/master/data-structures/heap) [(wiki)](http://en.wikipedia.org/wiki/Heap_%28data_structure%29) 15 | * [Priority Queue](https://github.com/arnauddri/algorithms/tree/master/data-structures/priority-queue) [(wiki)](http://en.wikipedia.org/wiki/Priority_queue) 16 | * [Queue](https://github.com/arnauddri/algorithms/tree/master/data-structures/queue) [(wiki)](http://en.wikipedia.org/wiki/Queue_%28abstract_data_type%29) 17 | * [Stack](https://github.com/arnauddri/algorithms/tree/master/data-structures/stack) [(wiki)](http://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29) 18 | 19 | #### Graph algorithms 20 | 21 | **Searching:** 22 | * [Depth First Search](https://github.com/arnauddri/algorithms/tree/master/algorithms/graphs/dfs) [(wiki)](http://en.wikipedia.org/wiki/Depth-first_search) 23 | * [Breadth First Search](https://github.com/arnauddri/algorithms/tree/master/algorithms/graphs/bfs) [(wiki)](http://en.wikipedia.org/wiki/Breadth-first_search) 24 | * [Kosaraju's Algorithm (find all SCCs)](https://github.com/arnauddri/algorithms/tree/master/algorithms/graphs/kosaraju) [(wiki)](http://en.wikipedia.org/wiki/Kosaraju%27s_algorithm) 25 | 26 | **Shortest path:** 27 | * [Breadth First Search Shortest Path](https://github.com/arnauddri/algorithms/tree/master/algorithms/graphs/bfs-shortest-path) [(wiki)](http://en.wikipedia.org/wiki/Breadth-first_search) 28 | * [Dijkstra](https://github.com/arnauddri/algorithms/tree/master/algorithms/graphs/dijkstra) [(wiki)](http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) 29 | 30 | **Sorting:** 31 | * [Topological Sort](https://github.com/arnauddri/algorithms/tree/master/algorithms/graphs/topological-sort) [(wiki)](http://en.wikipedia.org/wiki/Topological_sorting) 32 | 33 | 34 | 35 | #### Maths algorithms 36 | 37 | * [Binary GCD algorithm](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/stein) [(wiki)](https://en.wikipedia.org/wiki/Binary_GCD_algorithm) 38 | * [Closest pairs](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/closest-pair) [(wiki)](http://en.wikipedia.org/wiki/Closest_pair_of_points_problem) 39 | * [FastPower](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/fast-power) [(wiki)](http://en.wikipedia.org/wiki/Exponentiation_by_squaring) 40 | * [Fibonacci](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/fibonacci) [(wiki)](http://en.wikipedia.org/wiki/Fibonacci_number) 41 | * [Fisher-Yates Shuffle](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/fisher-yates) [(wiki)](http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) 42 | * [Erastothenes Sieve](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/eratosthenes-sieve) [(wiki)](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) 43 | * [Extented GCD algorithm](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/euclide) [(wiki)](http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm) 44 | * [Karatsuba's Multiplication](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/karatsuba) [(wiki)](http://en.wikipedia.org/wiki/Karatsuba_algorithm) 45 | * [Newton's Square Root](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/newton-sqrt) [(wiki)](http://en.wikipedia.org/wiki/Newton%27s_method) 46 | * [Permutations Count](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/permutations-count) 47 | * [Strassen's matrix multiplication](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/strassen) [(wiki)](http://en.wikipedia.org/wiki/Strassen_algorithm) 48 | * [Randomized Selection](https://github.com/arnauddri/algorithms/tree/master/algorithms/maths/RSelect) 49 | 50 | #### Sorting algorithms 51 | 52 | * [Bubble Sort](https://github.com/arnauddri/algorithms/tree/master/algorithms/sorting/bubble-sort) [(wiki)](http://en.wikipedia.org/wiki/Bubble_sort) 53 | * [Heap Sort](https://github.com/arnauddri/algorithms/tree/master/algorithms/sorting/heap-sort) [(wiki)](http://en.wikipedia.org/wiki/Heapsort) 54 | * [Quick Sort](https://github.com/arnauddri/algorithms/tree/master/algorithms/sorting/quick-sort) [(wiki)](http://en.wikipedia.org/wiki/Quicksort) 55 | * [Merge Sort](https://github.com/arnauddri/algorithms/tree/master/algorithms/sorting/merge-sort) [(wiki)](http://en.wikipedia.org/wiki/Merge_sort) 56 | * [Insertion Sort](https://github.com/arnauddri/algorithms/tree/master/algorithms/sorting/insertion-sort) [(wiki)](http://en.wikipedia.org/wiki/Insertion_sort) 57 | * [Shell Sort](https://github.com/arnauddri/algorithms/tree/master/algorithms/sorting/shell-sort) [(wiki)](http://en.wikipedia.org/wiki/Shellsort) 58 | * [Selection Sort](https://github.com/arnauddri/algorithms/tree/master/algorithms/sorting/selection-sort) [(wiki)](http://en.wikipedia.org/wiki/Selection_sort) 59 | 60 | #### Searching algorithms 61 | 62 | * [Binary Search](https://github.com/arnauddri/algorithms/tree/master/algorithms/searching/binary-search) [(wiki)](http://en.wikipedia.org/wiki/Binary_search_algorithm) 63 | -------------------------------------------------------------------------------- /algorithms/graphs/bfs-shortest-path/bfs_shortest_path.go: -------------------------------------------------------------------------------- 1 | package bfs 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/algorithms/graphs/bfs" 5 | "github.com/arnauddri/algorithms/data-structures/graph" 6 | ) 7 | 8 | func ShortestPath(g *graph.DirGraph, start graph.VertexId) (dist map[graph.VertexId]int) { 9 | dist = make(map[graph.VertexId]int) 10 | visited := make(map[graph.VertexId]bool) 11 | 12 | getDist := func(v graph.VertexId) { 13 | neighbours := g.GetNeighbours(v).VerticesIter() 14 | visited[v] = true 15 | 16 | for neighbour := range neighbours { 17 | 18 | ok, _ := visited[neighbour] 19 | if !ok { 20 | dist[neighbour] = dist[v] + 1 21 | } 22 | } 23 | } 24 | 25 | bfs.Bfs(g, start, getDist) 26 | 27 | return 28 | } 29 | 30 | func GetDist(g *graph.DirGraph, from graph.VertexId, to graph.VertexId) int { 31 | return ShortestPath(g, from)[to] 32 | } 33 | -------------------------------------------------------------------------------- /algorithms/graphs/bfs-shortest-path/bfs_shortest_path_test.go: -------------------------------------------------------------------------------- 1 | package bfs 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/data-structures/graph" 5 | "testing" 6 | ) 7 | 8 | func TestBfsShortestPath(t *testing.T) { 9 | h := graph.NewDirected() 10 | 11 | for i := 0; i < 10; i++ { 12 | v := graph.VertexId(i) 13 | h.AddVertex(v) 14 | } 15 | 16 | for i := 0; i < 9; i++ { 17 | h.AddEdge(graph.VertexId(i), graph.VertexId(i+1), 1) 18 | } 19 | 20 | distance := ShortestPath(h, graph.VertexId(0)) 21 | 22 | for i := 0; i < len(distance); i++ { 23 | if distance[graph.VertexId(i)] != i { 24 | t.Error() 25 | } 26 | 27 | if GetDist(h, graph.VertexId(0), graph.VertexId(i)) != i { 28 | t.Error() 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /algorithms/graphs/bfs/bfs.go: -------------------------------------------------------------------------------- 1 | package bfs 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/data-structures/graph" 5 | ) 6 | 7 | func Bfs(g *graph.DirGraph, start graph.VertexId, fn func(graph.VertexId)) { 8 | queue := []graph.VertexId{start} 9 | visited := make(map[graph.VertexId]bool) 10 | var next []graph.VertexId 11 | 12 | for len(queue) > 0 { 13 | next = []graph.VertexId{} 14 | for _, vertex := range queue { 15 | visited[vertex] = true 16 | neighbours := g.GetNeighbours(vertex).VerticesIter() 17 | fn(vertex) 18 | 19 | for neighbour := range neighbours { 20 | 21 | _, ok := visited[neighbour] 22 | if !ok { 23 | next = append(next, neighbour) 24 | } 25 | } 26 | } 27 | queue = next 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /algorithms/graphs/bfs/bfs_test.go: -------------------------------------------------------------------------------- 1 | package bfs 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/data-structures/graph" 6 | "testing" 7 | ) 8 | 9 | func TestBfs(t *testing.T) { 10 | h := graph.NewDirected() 11 | 12 | for i := 0; i < 10; i++ { 13 | v := graph.VertexId(i) 14 | h.AddVertex(v) 15 | } 16 | 17 | for i := 0; i < 9; i++ { 18 | h.AddEdge(graph.VertexId(i), graph.VertexId(i+1), 1) 19 | } 20 | 21 | bfsMap := make(map[graph.VertexId]bool) 22 | checkVertices := func(v graph.VertexId) { 23 | bfsMap[v] = true 24 | } 25 | 26 | Bfs(h, graph.VertexId(3), checkVertices) 27 | 28 | for i := 3; i < len(bfsMap); i++ { 29 | if _, ok := bfsMap[graph.VertexId(i)]; !ok { 30 | fmt.Println(bfsMap) 31 | t.Error() 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /algorithms/graphs/dfs/dfs.go: -------------------------------------------------------------------------------- 1 | package dfs 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/data-structures/graph" 5 | "github.com/arnauddri/algorithms/data-structures/stack" 6 | ) 7 | 8 | func UndirectedDfs(g *graph.UnGraph, v graph.VertexId, fn func(graph.VertexId)) { 9 | s := stack.New() 10 | s.Push(v) 11 | visited := make(map[graph.VertexId]bool) 12 | 13 | for s.Len() > 0 { 14 | v := s.Pop().(graph.VertexId) 15 | 16 | if _, ok := visited[v]; !ok { 17 | visited[v] = true 18 | fn(v) 19 | neighbours := g.GetNeighbours(v).VerticesIter() 20 | for neighbour := range neighbours { 21 | s.Push(neighbour) 22 | } 23 | } 24 | } 25 | } 26 | 27 | func DirectedDfs(g *graph.DirGraph, v graph.VertexId, fn func(graph.VertexId)) { 28 | s := stack.New() 29 | s.Push(v) 30 | visited := make(map[graph.VertexId]bool) 31 | 32 | for s.Len() > 0 { 33 | v = s.Pop().(graph.VertexId) 34 | 35 | if _, ok := visited[v]; !ok { 36 | visited[v] = true 37 | fn(v) 38 | neighbours := g.GetSuccessors(v).VerticesIter() 39 | for neighbour := range neighbours { 40 | s.Push(neighbour) 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /algorithms/graphs/dfs/dfs_test.go: -------------------------------------------------------------------------------- 1 | package dfs 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/data-structures/graph" 6 | "testing" 7 | ) 8 | 9 | func TestUndirectedDfs(t *testing.T) { 10 | h := graph.NewUndirected() 11 | 12 | for i := 0; i < 10; i++ { 13 | v := graph.VertexId(i) 14 | h.AddVertex(v) 15 | } 16 | 17 | for i := 0; i < 9; i++ { 18 | h.AddEdge(graph.VertexId(i), graph.VertexId(i+1), 1) 19 | } 20 | 21 | counter := 0 22 | UndirectedDfs(h, graph.VertexId(3), func(v graph.VertexId) { 23 | counter += int(v) 24 | }) 25 | 26 | if counter != 45 { 27 | fmt.Println(counter) 28 | t.Error() 29 | } 30 | } 31 | 32 | func TestDirectedDfs(t *testing.T) { 33 | h := graph.NewDirected() 34 | 35 | for i := 0; i < 10; i++ { 36 | v := graph.VertexId(i) 37 | h.AddVertex(v) 38 | } 39 | 40 | for i := 0; i < 9; i++ { 41 | h.AddEdge(graph.VertexId(i), graph.VertexId(i+1), 1) 42 | } 43 | 44 | counter := 0 45 | DirectedDfs(h, graph.VertexId(3), func(v graph.VertexId) { 46 | counter += int(v) 47 | }) 48 | 49 | if counter != 42 { 50 | fmt.Println(counter) 51 | t.Error() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /algorithms/graphs/dijkstra/dijkstra.go: -------------------------------------------------------------------------------- 1 | // Dijkstra algorithm for undirected weighed graph 2 | // Pseudo-code: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Using_a_priority_queue 3 | package dijkstra 4 | 5 | import ( 6 | "github.com/arnauddri/algorithms/data-structures/graph" 7 | "github.com/arnauddri/algorithms/data-structures/priority-queue" 8 | ) 9 | 10 | func ShortestPath(g *graph.UnGraph, source graph.VertexId) map[graph.VertexId]graph.VertexId { 11 | visited := make(map[graph.VertexId]bool, g.VerticesCount()) 12 | dist := make(map[graph.VertexId]int) 13 | prev := make(map[graph.VertexId]graph.VertexId) 14 | Q := pq.NewMin() 15 | vertices := g.VerticesIter() 16 | 17 | dist[source] = 0 18 | for vertex := range vertices { 19 | if source != vertex { 20 | dist[vertex] = 1000 21 | prev[vertex] = 0 22 | } 23 | Q.Insert(*pq.NewItem(vertex, dist[vertex])) 24 | } 25 | 26 | for Q.Len() > 0 { 27 | u := Q.Extract().Value.(graph.VertexId) 28 | visited[u] = true 29 | 30 | for neighbour := range g.GetNeighbours(u).VerticesIter() { 31 | if !visited[neighbour] { 32 | alt := dist[u] + g.GetEdge(u, neighbour) 33 | 34 | if alt < dist[neighbour] { 35 | dist[neighbour] = alt 36 | prev[neighbour] = u 37 | Q.ChangePriority(neighbour, alt) 38 | } 39 | } 40 | } 41 | } 42 | return prev 43 | } 44 | -------------------------------------------------------------------------------- /algorithms/graphs/dijkstra/dijkstra_test.go: -------------------------------------------------------------------------------- 1 | package dijkstra 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/data-structures/graph" 6 | "testing" 7 | ) 8 | 9 | func TestDijkstra(t *testing.T) { 10 | h := graph.NewUndirected() 11 | 12 | for i := 0; i < 5; i++ { 13 | h.AddVertex(graph.VertexId(i)) 14 | } 15 | 16 | h.AddEdge(graph.VertexId(0), graph.VertexId(1), 10) 17 | h.AddEdge(graph.VertexId(1), graph.VertexId(2), 20) 18 | h.AddEdge(graph.VertexId(2), graph.VertexId(3), 40) 19 | h.AddEdge(graph.VertexId(0), graph.VertexId(2), 50) 20 | h.AddEdge(graph.VertexId(0), graph.VertexId(3), 80) 21 | h.AddEdge(graph.VertexId(0), graph.VertexId(4), 10) 22 | h.AddEdge(graph.VertexId(4), graph.VertexId(3), 10) 23 | 24 | prev := ShortestPath(h, graph.VertexId(0)) 25 | 26 | if prev[1] != graph.VertexId(0) || 27 | prev[2] != graph.VertexId(1) || 28 | prev[3] != graph.VertexId(4) || 29 | prev[4] != graph.VertexId(0) { 30 | 31 | fmt.Println(prev) 32 | t.Error() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /algorithms/graphs/kosaraju/kosaraju.go: -------------------------------------------------------------------------------- 1 | package kosaraju 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/algorithms/graphs/dfs" 6 | "github.com/arnauddri/algorithms/data-structures/graph" 7 | "github.com/arnauddri/algorithms/data-structures/stack" 8 | ) 9 | 10 | func Scc(g *graph.DirGraph) []stack.Stack { 11 | s := stack.New() 12 | n := g.Order() 13 | SCCs := make([]stack.Stack, 0) 14 | visited := make(map[graph.VertexId]bool) 15 | vertices := g.VerticesIter() 16 | 17 | for s.Len() != n { 18 | vertex := <-vertices 19 | dfs.DirectedDfs(g, vertex, func(v graph.VertexId) { 20 | if visited[v] == false { 21 | fmt.Println(vertex, v) 22 | s.Push(v) 23 | visited[v] = true 24 | } 25 | }) 26 | } 27 | 28 | fmt.Println(s) 29 | 30 | r := g.Reverse() 31 | visited = make(map[graph.VertexId]bool) 32 | for s.Len() > 0 { 33 | vertex := s.Pop().(graph.VertexId) 34 | scc := stack.New() 35 | 36 | if visited[vertex] == false { 37 | dfs.DirectedDfs(r, vertex, func(v graph.VertexId) { 38 | fmt.Println(vertex, v) 39 | if visited[graph.VertexId(v)] == false { 40 | visited[graph.VertexId(v)] = true 41 | fmt.Println(vertex, v) 42 | scc.Push(v) 43 | } 44 | }) 45 | } 46 | if scc.Len() > 1 { 47 | SCCs = append(SCCs, *scc) 48 | } 49 | } 50 | return SCCs 51 | } 52 | -------------------------------------------------------------------------------- /algorithms/graphs/kosaraju/kosaraju_test.go: -------------------------------------------------------------------------------- 1 | package kosaraju 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/algorithms/graphs/dfs" 6 | "github.com/arnauddri/algorithms/data-structures/graph" 7 | "testing" 8 | ) 9 | 10 | func TestTopologicalSort(t *testing.T) { 11 | h := graph.NewDirected() 12 | addEdge := func(h *graph.DirGraph, i, j int) { 13 | h.AddEdge(graph.VertexId(i), graph.VertexId(j), 1) 14 | } 15 | 16 | for i := 1; i < 10; i++ { 17 | h.AddVertex(graph.VertexId(i)) 18 | } 19 | 20 | addEdge(h, 1, 7) 21 | addEdge(h, 7, 4) 22 | addEdge(h, 4, 1) 23 | 24 | addEdge(h, 7, 9) 25 | 26 | addEdge(h, 9, 6) 27 | addEdge(h, 6, 3) 28 | addEdge(h, 3, 9) 29 | 30 | addEdge(h, 6, 8) 31 | 32 | addEdge(h, 5, 8) 33 | addEdge(h, 2, 5) 34 | addEdge(h, 8, 2) 35 | 36 | dfs.DirectedDfs(h, graph.VertexId(9), func(v graph.VertexId) { 37 | //fmt.Println(v) 38 | }) 39 | 40 | s := Scc(h) 41 | fmt.Println(s) 42 | 43 | } 44 | -------------------------------------------------------------------------------- /algorithms/graphs/topological-sort/topological.go: -------------------------------------------------------------------------------- 1 | package topological 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/data-structures/graph" 5 | "github.com/arnauddri/algorithms/data-structures/stack" 6 | ) 7 | 8 | func Sort(g *graph.DirGraph) *stack.Stack { 9 | var visit func(v graph.VertexId) 10 | sorted := stack.New() 11 | visited := make(map[graph.VertexId]bool) 12 | marked := make(map[graph.VertexId]bool) 13 | 14 | visit = func(v graph.VertexId) { 15 | if marked[v] { 16 | panic("Not a Directed Acyclic Graph (DAG)") 17 | } 18 | 19 | marked[v] = true 20 | successors := g.GetSuccessors(v).VerticesIter() 21 | 22 | for successor := range successors { 23 | if !marked[successor] && !visited[successor] { 24 | visit(successor) 25 | } 26 | } 27 | 28 | visited[v] = true 29 | marked[v] = false 30 | sorted.Push(v) 31 | } 32 | 33 | vertices := g.VerticesIter() 34 | for vertex := range vertices { 35 | if !visited[vertex] { 36 | visit(vertex) 37 | } 38 | } 39 | 40 | return sorted 41 | } 42 | -------------------------------------------------------------------------------- /algorithms/graphs/topological-sort/topological_test.go: -------------------------------------------------------------------------------- 1 | package topological 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/data-structures/graph" 6 | "testing" 7 | ) 8 | 9 | func TestTopologicalSort(t *testing.T) { 10 | h := graph.NewDirected() 11 | 12 | h.AddVertex(graph.VertexId(2)) 13 | h.AddVertex(graph.VertexId(3)) 14 | h.AddVertex(graph.VertexId(5)) 15 | h.AddVertex(graph.VertexId(7)) 16 | h.AddVertex(graph.VertexId(8)) 17 | h.AddVertex(graph.VertexId(9)) 18 | h.AddVertex(graph.VertexId(10)) 19 | h.AddVertex(graph.VertexId(11)) 20 | 21 | h.AddEdge(graph.VertexId(7), graph.VertexId(8), 1) 22 | h.AddEdge(graph.VertexId(7), graph.VertexId(11), 1) 23 | h.AddEdge(graph.VertexId(5), graph.VertexId(11), 1) 24 | h.AddEdge(graph.VertexId(3), graph.VertexId(8), 1) 25 | h.AddEdge(graph.VertexId(3), graph.VertexId(10), 1) 26 | h.AddEdge(graph.VertexId(8), graph.VertexId(9), 1) 27 | h.AddEdge(graph.VertexId(11), graph.VertexId(10), 1) 28 | h.AddEdge(graph.VertexId(11), graph.VertexId(2), 1) 29 | h.AddEdge(graph.VertexId(11), graph.VertexId(9), 1) 30 | 31 | s := Sort(h) 32 | 33 | first := int(s.Pop().(graph.VertexId)) 34 | if first != 7 && 35 | first != 5 && 36 | first != 3 { 37 | fmt.Print(first, first != 7) 38 | t.Error() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /algorithms/maths/RSelect/README.md: -------------------------------------------------------------------------------- 1 | # Randomized Selection Algorithm 2 | 3 | Find the k-th smallest element in an array without sorting (works in-place). 4 | 5 | Time complexity: **O(n)** 6 | -------------------------------------------------------------------------------- /algorithms/maths/RSelect/RSelect.go: -------------------------------------------------------------------------------- 1 | package rselect 2 | 3 | import ( 4 | "math/rand" 5 | ) 6 | 7 | func RSelect(arr []int, n, i int) int { 8 | pivot := rand.Intn(n) 9 | v := arr[pivot] 10 | left := 0 11 | 12 | arr[pivot], arr[n-1] = arr[n-1], arr[pivot] 13 | 14 | for j := 0; j < n-1; j++ { 15 | if arr[j] <= v { 16 | arr[j], arr[left] = arr[left], arr[j] 17 | left++ 18 | } 19 | } 20 | 21 | if left+1 >= n { 22 | return arr[n-1] 23 | } 24 | 25 | arr[left+1], arr[n-1] = arr[n-1], arr[left+1] 26 | 27 | j := left 28 | 29 | if j < 2 { 30 | return arr[j] 31 | } 32 | 33 | if j == i { 34 | return arr[j] 35 | } else if j > i { 36 | return RSelect(arr[:j], j-1, i) 37 | } else { 38 | return RSelect(arr[j:], n-j, i-j) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /algorithms/maths/RSelect/RSelect_test.go: -------------------------------------------------------------------------------- 1 | package rselect 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestRSelect(t *testing.T) { 9 | arr := []int{5, 2, 6, 8, 3, 1} 10 | 11 | i0 := RSelect(arr, 6, 0) 12 | i1 := RSelect(arr, 6, 1) 13 | i2 := RSelect(arr, 6, 2) 14 | i3 := RSelect(arr, 6, 3) 15 | i4 := RSelect(arr, 6, 4) 16 | i5 := RSelect(arr, 6, 5) 17 | if i0 != 1 && 18 | i1 != 2 && 19 | i2 != 3 && 20 | i3 != 5 && 21 | i4 != 6 && 22 | i5 != 8 { 23 | fmt.Println("Error: ", i0, i1, i2, i3, i4, i5) 24 | t.Error() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /algorithms/maths/closest-pair/README.md: -------------------------------------------------------------------------------- 1 | # Benchmark 2 | 3 | ``` 4 | BenchmarkBruteForce 5000000 698 ns/op 5 | BenchmarkDivideAndConquer 1000000 3566 ns/op 6 | ``` 7 | -------------------------------------------------------------------------------- /algorithms/maths/closest-pair/closest_pair.go: -------------------------------------------------------------------------------- 1 | package closest_pair 2 | 3 | import ( 4 | "math" 5 | "strconv" 6 | ) 7 | 8 | type point struct { 9 | x float64 10 | y float64 11 | } 12 | 13 | type Point interface { 14 | toString() string 15 | } 16 | 17 | func makePoint(x float64, y float64) *point { 18 | A := new(point) 19 | A.x = x 20 | A.y = y 21 | 22 | return A 23 | } 24 | 25 | func (A *point) toString() string { 26 | return "(" + strconv.FormatFloat(A.x, 'f', -1, 64) + "," + strconv.FormatFloat(A.y, 'f', -1, 64) + ")" 27 | } 28 | 29 | type pair struct { 30 | point1 point 31 | point2 point 32 | distance float64 33 | } 34 | 35 | type Pair interface { 36 | calcDistance() float64 37 | toString() string 38 | } 39 | 40 | func makePair(A point, B point) *pair { 41 | P := new(pair) 42 | P.point1 = A 43 | P.point2 = B 44 | P.distance = calcDistance(A, B) 45 | 46 | return P 47 | } 48 | 49 | func calcDistance(A point, B point) float64 { 50 | xdist := A.x - B.x 51 | ydist := A.y - B.y 52 | 53 | return math.Sqrt(float64(xdist*xdist + ydist*ydist)) 54 | } 55 | 56 | func (P *pair) toString() string { 57 | return P.point1.toString() + "-" + P.point2.toString() + "-" + strconv.FormatFloat(P.distance, 'f', -1, 64) 58 | } 59 | 60 | func DivideAndConquer(P []point) *pair { 61 | n := len(P) 62 | 63 | if n == 2 { 64 | return makePair(P[0], P[1]) 65 | } 66 | 67 | xP := make([]point, n) 68 | yP := make([]point, n) 69 | 70 | for i := 0; i < n; i++ { 71 | xP[i] = P[i] 72 | yP[i] = P[i] 73 | } 74 | 75 | _, pair := divideAndConquer(xP, yP) 76 | 77 | return pair 78 | } 79 | 80 | func divideAndConquer(xP, yP []point) (float64, *pair) { 81 | n := len(xP) 82 | 83 | if n <= 3 { 84 | p := BruteForce(xP) 85 | return p.distance, p 86 | } 87 | 88 | xL := xP[:n>>1] 89 | xR := xP[n>>1:] 90 | 91 | var yL, yR []point 92 | xMiddle := xL[0].x 93 | 94 | // yL ← { p ∈ yP : px ≤ xMiddle } 95 | // yR ← { p ∈ yP : px > xMiddle } 96 | for _, p := range yP { 97 | if p.x <= xMiddle { 98 | yL = append(yL, p) 99 | } else { 100 | yR = append(yL, p) 101 | } 102 | } 103 | 104 | // (dL, pairL) ← closestPair of (xL, yL) 105 | // (dR, pairR) ← closestPair of (xR, yR) 106 | dL, pairL := divideAndConquer(xL, yL) 107 | dR, pairR := divideAndConquer(xR, yR) 108 | 109 | dMin, pairMin := dR, pairR 110 | 111 | if dL < dR { 112 | dMin, pairMin = dL, pairL 113 | } 114 | 115 | var yS []point 116 | 117 | // yS ← { p ∈ yP : |xMiddle - px| < dMin } 118 | for i := 0; i < len(yP); i++ { 119 | if math.Abs(yP[i].x-xMiddle) < dMin { 120 | yS = append(yS, yP[i]) 121 | } 122 | } 123 | 124 | nS := len(yS) 125 | 126 | if nS > 1 { 127 | closestPair := pairMin 128 | for i := 1; i < nS-1; i++ { 129 | k := i + 1 130 | for k <= nS && math.Abs(yS[k].y-yS[i].y) < dMin { 131 | tempPair := makePair(yS[k], yS[i]) 132 | if tempPair.distance < closestPair.distance { 133 | closestPair = tempPair 134 | } 135 | k++ 136 | } 137 | } 138 | return closestPair.distance, closestPair 139 | } else { 140 | return dMin, pairMin 141 | } 142 | } 143 | 144 | func BruteForce(P []point) *pair { 145 | n := len(P) 146 | 147 | if n < 2 { 148 | return nil 149 | } 150 | 151 | minPair := makePair(P[0], P[1]) 152 | tempPair := makePair(P[0], P[1]) 153 | 154 | min := minPair.distance 155 | for i := 0; i < n-1; i++ { 156 | tempPair.point1 = P[i] 157 | for j := 0; j < n; j++ { 158 | tempPair.point2 = P[j] 159 | if min > tempPair.distance { 160 | minPair = tempPair 161 | min = tempPair.distance 162 | } 163 | } 164 | } 165 | 166 | return minPair 167 | } 168 | -------------------------------------------------------------------------------- /algorithms/maths/closest-pair/closest_pair_test.go: -------------------------------------------------------------------------------- 1 | package closest_pair 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestDivideAndConquer(t *testing.T) { 9 | Points := make([]point, 10) 10 | for i := 0; i < 10; i++ { 11 | a := makePoint(float64(i), float64(i*i)) 12 | 13 | Points[i] = *a 14 | } 15 | 16 | A := makePoint(float64(0), float64(0)) 17 | B := makePoint(float64(1), float64(1)) 18 | P := DivideAndConquer(Points) 19 | if P.point1 != *A || P.point2 != *B { 20 | fmt.Println(Points) 21 | fmt.Println(P) 22 | t.Error() 23 | } 24 | } 25 | func TestBruteForce(t *testing.T) { 26 | Points := make([]point, 10) 27 | for i := 0; i < 10; i++ { 28 | a := makePoint(float64(i), float64(i*i)) 29 | 30 | Points[i] = *a 31 | } 32 | 33 | A := makePoint(float64(0), float64(0)) 34 | B := makePoint(float64(1), float64(1)) 35 | P := BruteForce(Points) 36 | if P.point1 != *A || P.point2 != *B { 37 | fmt.Println(P.point1, *A, *B) 38 | t.Error() 39 | } 40 | } 41 | 42 | func BenchmarkBruteForce(b *testing.B) { 43 | Points := make([]point, 10) 44 | for i := 0; i < 10; i++ { 45 | a := makePoint(float64(i), float64(i*i)) 46 | 47 | Points[i] = *a 48 | } 49 | 50 | for i := 0; i < b.N; i++ { 51 | BruteForce(Points) 52 | } 53 | } 54 | 55 | func benchmarkDivideAndConquer(n int, b *testing.B) { 56 | Points := make([]point, n) 57 | for i := 0; i < n; i++ { 58 | a := makePoint(float64(i), float64(i*i)) 59 | 60 | Points[i] = *a 61 | } 62 | 63 | for i := 0; i < b.N; i++ { 64 | DivideAndConquer(Points) 65 | } 66 | } 67 | 68 | //func BenchmarkDivideAndConquer100(b *testing.B) { benchmarkDivideAndConquer(100, b) } 69 | //func BenchmarkDivideAndConquer1000(b *testing.B) { benchmarkDivideAndConquer(1000, b) } 70 | //func BenchmarkDivideAndConquer10000(b *testing.B) { benchmarkDivideAndConquer(10000, b) } 71 | //func BenchmarkDivideAndConquer100000(b *testing.B) { benchmarkDivideAndConquer(100000, b) } 72 | //func BenchmarkDivideAndConquer1000000(b *testing.B) { benchmarkDivideAndConquer(1000000, b) } 73 | //func BenchmarkDivideAndConquer10000000(b *testing.B) { benchmarkDivideAndConquer(10000000, b) } 74 | 75 | func BenchmarkDivideAndConquer(b *testing.B) { 76 | for i := 0; i < 10; i++ { 77 | 78 | benchmarkDivideAndConquer(100, b) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /algorithms/maths/eratosthenes-sieve/README.md: -------------------------------------------------------------------------------- 1 | # Implementation of the Sieve of Eratosthenes algorithm. 2 | 3 | ### Sieve of Eratosthenes Overview: 4 | 5 | It is a simple, ancient algorithm for finding all prime numbers 6 | up to any given limit. It does so by iteratively marking as composite (i.e. not prime) 7 | the multiples of each prime, starting with the multiples of 2. 8 | The sieve of Eratosthenes is one of the most efficient ways 9 | to find all of the smaller primes (below 10 million or so). 10 | 11 | **Time Complexity:** O(n log log n) 12 | 13 | Pseudocode: [https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) 14 | 15 | ### Benchmark 16 | 17 | Executed in ```44.334s```: 18 | 19 | ``` 20 | BenchmarkGetAllPrimesTo10 5000000 496 ns/op 21 | BenchmarkGetAllPrimesTo100 1000000 1196 ns/op 22 | BenchmarkGetAllPrimesTo1000 200000 7724 ns/op 23 | BenchmarkGetAllPrimesTo10000 50000 58489 ns/op 24 | BenchmarkGetAllPrimesTo100000 5000 514589 ns/op 25 | BenchmarkGetAllPrimesTo1000000 500 5590372 ns/op 26 | BenchmarkGetAllPrimesTo10000000 20 96922714 ns/op 27 | BenchmarkGetAllPrimesTo100000000 1 1431869649 ns/op 28 | BenchmarkGetAllPrimesTo1000000000 1 24368113980 ns/op 29 | ``` 30 | -------------------------------------------------------------------------------- /algorithms/maths/eratosthenes-sieve/benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arnauddri/algorithms/736f5ebe59cfd72b778704fe9ba5e0ba25c775fe/algorithms/maths/eratosthenes-sieve/benchmark.png -------------------------------------------------------------------------------- /algorithms/maths/eratosthenes-sieve/primes.go: -------------------------------------------------------------------------------- 1 | package primes 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | func getAllPrimesTo(n int) (primes []int) { 8 | checked := make([]bool, n) 9 | sqrt_n := int(math.Sqrt(float64(n))) 10 | 11 | for i := 2; i <= sqrt_n; i++ { 12 | if !checked[i] { 13 | for j := i * i; j < n; j += i { 14 | checked[j] = true 15 | } 16 | } 17 | } 18 | 19 | for i := 1; i < n; i++ { 20 | if !checked[i] { 21 | primes = append(primes, i) 22 | } 23 | } 24 | 25 | return 26 | } 27 | -------------------------------------------------------------------------------- /algorithms/maths/eratosthenes-sieve/primes_benchmark.go: -------------------------------------------------------------------------------- 1 | package primes 2 | 3 | import ( 4 | "code.google.com/p/plotinum/plot" 5 | "code.google.com/p/plotinum/plotter" 6 | "code.google.com/p/plotinum/plotutil" 7 | "testing" 8 | ) 9 | 10 | func benchmarkGetAllPrimesTo(n int, b *testing.B) { 11 | for i := 0; i < b.N; i++ { 12 | getAllPrimesTo(n) 13 | } 14 | } 15 | 16 | func BenchmarkGetAllPrimesTo10(b *testing.B) { benchmarkGetAllPrimesTo(10, b) } 17 | func BenchmarkGetAllPrimesTo100(b *testing.B) { benchmarkGetAllPrimesTo(100, b) } 18 | func BenchmarkGetAllPrimesTo1000(b *testing.B) { benchmarkGetAllPrimesTo(1000, b) } 19 | func BenchmarkGetAllPrimesTo10000(b *testing.B) { benchmarkGetAllPrimesTo(10000, b) } 20 | func BenchmarkGetAllPrimesTo100000(b *testing.B) { benchmarkGetAllPrimesTo(100000, b) } 21 | func BenchmarkGetAllPrimesTo1000000(b *testing.B) { benchmarkGetAllPrimesTo(1000000, b) } 22 | func BenchmarkGetAllPrimesTo10000000(b *testing.B) { benchmarkGetAllPrimesTo(10000000, b) } 23 | func BenchmarkGetAllPrimesTo100000000(b *testing.B) { benchmarkGetAllPrimesTo(100000000, b) } 24 | func BenchmarkGetAllPrimesTo1000000000(b *testing.B) { benchmarkGetAllPrimesTo(1000000000, b) } 25 | 26 | func TestBenchmark(t *testing.T) { 27 | points := make(plotter.XYs, 9) 28 | 29 | points[0].X = 10 30 | points[1].X = 100 31 | points[2].X = 1000 32 | points[3].X = 10000 33 | points[4].X = 100000 34 | points[5].X = 1000000 35 | points[6].X = 10000000 36 | points[7].X = 100000000 37 | points[8].X = 1000000000 38 | points[0].Y = 496.0 39 | points[1].Y = 1196 40 | points[2].Y = 7724 41 | points[3].Y = 58489 42 | points[4].Y = 414589 43 | points[5].Y = 5590372 44 | points[6].Y = 96922714 45 | points[7].Y = 1431869649 46 | points[8].Y = 24368113980 47 | 48 | p, err := plot.New() 49 | if err != nil { 50 | panic(err) 51 | } 52 | 53 | p.Title.Text = "Calculation of the primes between 0 and n" 54 | p.X.Label.Text = "Primes Range" 55 | p.Y.Label.Text = "Running Time (ns/op)" 56 | 57 | err = plotutil.AddLines(p, 58 | "Sieve", points) 59 | if err != nil { 60 | panic(err) 61 | } 62 | 63 | // Save the plot to a PNG file. 64 | if err := p.Save(14, 10, "benchmark.png"); err != nil { 65 | panic(err) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /algorithms/maths/eratosthenes-sieve/primes_test.go: -------------------------------------------------------------------------------- 1 | package primes 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "testing" 7 | ) 8 | 9 | func TestGetAllPrimesTo(t *testing.T) { 10 | primes := getAllPrimesTo(60) 11 | expected := []int{1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59} 12 | if !reflect.DeepEqual(primes, expected) { 13 | fmt.Println(primes) 14 | t.Error() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /algorithms/maths/euclide/README.md: -------------------------------------------------------------------------------- 1 | # Extended Euclidean Algorithm 2 | 3 | This module implements the extended greatest common divider algorithm. 4 | 5 | *Pre:* two integers a and b 6 | 7 | *Post:* a tuple ```(x, y)``` where ```a*x + b*y = gcd(a, b)``` (bezout coefficients) 8 | 9 | Pseudo Code: [http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm](http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm) 10 | 11 | ### Benchmark 12 | 13 | for ```a :=131313131```, ```b := 121212121```, the benchmark ran in 6.338s: 14 | ``` 15 | BenchmarkGetCoeff 1 6255517486 ns/op 16 | ``` 17 | -------------------------------------------------------------------------------- /algorithms/maths/euclide/extended_gcd.go: -------------------------------------------------------------------------------- 1 | package division 2 | 3 | import () 4 | 5 | func divide(a, b int) int { 6 | if a < b { 7 | return a 8 | } else { 9 | return divide(a-b, b) 10 | } 11 | } 12 | 13 | func getCoeff(a, b int) (int, int) { 14 | _a := a 15 | _b := b 16 | 17 | if a < 0 { 18 | a *= -1 19 | } 20 | if b < 0 { 21 | b *= -1 22 | } 23 | 24 | x0, y0 := 0, 1 25 | x1, y1 := 1, 0 26 | 27 | for b != 0 { 28 | quotient := a / b 29 | a, b = b, divide(a, b) 30 | x1, x0 = x0-quotient*x1, x1 31 | y1, y0 = y0-quotient*y1, y1 32 | } 33 | 34 | if _a < 0 { 35 | y0 *= -1 36 | } 37 | if _b < 0 { 38 | x0 *= -1 39 | } 40 | 41 | return y0, x0 42 | } 43 | -------------------------------------------------------------------------------- /algorithms/maths/euclide/extended_gcd_test.go: -------------------------------------------------------------------------------- 1 | package division 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestDivide(t *testing.T) { 9 | if divide(10, 2) != 0 && divide(10, 3) != 1 { 10 | t.Error() 11 | } 12 | } 13 | 14 | func TestGetCoeff(t *testing.T) { 15 | a, b := 11, 6 16 | bezout_a, bezout_b := getCoeff(11, 6) 17 | 18 | if bezout_a*a+bezout_b*b != 1 { 19 | fmt.Println(a, b, a*11+b*6) 20 | t.Error() 21 | } 22 | 23 | a, b = 12, 6 24 | bezout_a, bezout_b = getCoeff(12, 6) 25 | 26 | if bezout_a*a+bezout_b*b != 6 { 27 | fmt.Println(a, b, a*11+b*6) 28 | t.Error() 29 | } 30 | } 31 | 32 | func BenchmarkGetCoeff(b *testing.B) { 33 | for i := 0; i < b.N; i++ { 34 | getCoeff(131313131, 121212121) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /algorithms/maths/fast-power/README.md: -------------------------------------------------------------------------------- 1 | # Power Computation 2 | 3 | Raises an uint32 integer to the n-th power 4 | 5 | ### Benchmark 6 | 7 | Computes 2^100000: 8 | ``` 9 | BenchmarkFastPower 50000000 41.6 ns/op 10 | BenchmarkSlowPower 10000 115484 ns/op 11 | ``` 12 | -------------------------------------------------------------------------------- /algorithms/maths/fast-power/fast_power.go: -------------------------------------------------------------------------------- 1 | package fast_power 2 | 3 | import ( 4 | "errors" 5 | "math" 6 | ) 7 | 8 | // Recursive - O(log n) 9 | func fast_power(n uint32, power int) (uint32, error) { 10 | if power < 0 && math.Floor(float64(power)) == float64(power) { 11 | return uint32(math.NaN()), errors.New("Power must be a positive integer or zero") 12 | } 13 | 14 | if power == 0 { 15 | return 1, nil 16 | } 17 | 18 | var factor uint32 19 | var result uint32 20 | 21 | mul := func(v uint32) { 22 | if result == 0 { 23 | result = v 24 | } else { 25 | result *= v 26 | } 27 | } 28 | 29 | for factor = n; power > 0; power, factor = power>>1, factor*factor { 30 | if power&1 == 1 { 31 | mul(factor) 32 | } 33 | } 34 | 35 | return result, nil 36 | } 37 | 38 | // Iterative - O(n) 39 | func slow_power(n uint32, power int) (uint32, error) { 40 | if power < 0 && math.Floor(float64(power)) == float64(power) { 41 | return uint32(math.NaN()), errors.New("Power must be a positive integer or zero") 42 | } 43 | 44 | a := uint32(1) 45 | for i := 0; i < power; i++ { 46 | a *= n 47 | } 48 | return a, nil 49 | } 50 | -------------------------------------------------------------------------------- /algorithms/maths/fast-power/fast_power_test.go: -------------------------------------------------------------------------------- 1 | package fast_power 2 | 3 | import ( 4 | "math" 5 | "testing" 6 | ) 7 | 8 | func TestFastPower(t *testing.T) { 9 | a := uint32(2) 10 | 11 | for i := 0; i < 100000; i++ { 12 | n, ok := fast_power(a, i) 13 | 14 | if ok != nil || n != uint32(math.Pow(float64(a), float64(i))) { 15 | t.Error() 16 | } 17 | } 18 | } 19 | 20 | func TestSlowPower(t *testing.T) { 21 | a := uint32(2) 22 | 23 | for i := 0; i < 100000; i++ { 24 | n, ok := slow_power(a, i) 25 | 26 | if ok != nil || n != uint32(math.Pow(float64(a), float64(i))) { 27 | t.Error() 28 | } 29 | } 30 | } 31 | 32 | func BenchmarkFastPower(b *testing.B) { 33 | a := uint32(2) 34 | 35 | for i := 0; i < b.N; i++ { 36 | fast_power(a, 100000) 37 | } 38 | } 39 | 40 | func BenchmarkSlowPower(b *testing.B) { 41 | a := uint32(2) 42 | 43 | for i := 0; i < b.N; i++ { 44 | slow_power(a, 100000) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /algorithms/maths/fibonacci/README.md: -------------------------------------------------------------------------------- 1 | # Fibonacci's Sequence 2 | 3 | Get the n-th Fibonacci's number by 3 different methods: 4 | * Iterative (O (n)) 5 | * Recursive (O (exp n)) 6 | * Matrix (O (log n)) 7 | 8 | Pseudo-code [http://en.wikipedia.org/wiki/Fibonacci_number](http://en.wikipedia.org/wiki/Fibonacci_number) 9 | 10 | ### Benchmark 11 | 12 | The recursive method was not tested due to its computation time. 13 | 14 | Passed in ```30,110s```: 15 | 16 | ``` 17 | BenchmarkIter10 100000000 13.3 ns/op 18 | BenchmarkIter100 20000000 109 ns/op 19 | BenchmarkIter1000 2000000 937 ns/op 20 | BenchmarkIter10000 200000 9108 ns/op 21 | BenchmarkIter100000 20000 93367 ns/op 22 | BenchmarkIter1000000 2000 1017469 ns/op 23 | BenchmarkIter10000000 100 10168824 ns/op 24 | 25 | BenchmarkMatrix10 1000000 2314 ns/op 26 | BenchmarkMatrix100 500000 3984 ns/op 27 | BenchmarkMatrix1000 500000 8713 ns/op 28 | BenchmarkMatrix10000 200000 9513 ns/op 29 | BenchmarkMatrix100000 100000 13452 ns/op 30 | BenchmarkMatrix1000000 100000 15263 ns/op 31 | BenchmarkMatrix10000000 100000 15554 ns/op 32 | ``` 33 | -------------------------------------------------------------------------------- /algorithms/maths/fibonacci/fibonacci.go: -------------------------------------------------------------------------------- 1 | package fibonacci 2 | 3 | import ( 4 | "math" 5 | "strconv" 6 | ) 7 | 8 | func getIter(n int) int { 9 | if n == 0 { 10 | return 0 11 | } 12 | a := 0 13 | for i, j, k := 1, 1, 1; k < n; i, j, k = i+j, i, k+1 { 14 | a = i 15 | } 16 | 17 | return a 18 | } 19 | 20 | func getRecurse(n int) int { 21 | if n == 0 || n == 1 { 22 | return n 23 | } 24 | if n == 2 { 25 | return 1 26 | } 27 | 28 | return getRecurse(n-1) + getRecurse(n-2) 29 | } 30 | 31 | func getMatrix(n int) int { 32 | memo := make(map[int][4]int) 33 | 34 | return _getMatrix(n, memo) 35 | } 36 | 37 | func _getMatrix(n int, memo map[int][4]int) int { 38 | if n == 0 { 39 | return 0 40 | } 41 | if n == 1 { 42 | return 1 43 | } 44 | 45 | power := string(strconv.FormatInt(int64(n-1), 2)) 46 | powers := make([]int, 0) 47 | 48 | for i, r := range power { 49 | if string(r) == "1" { 50 | powers = append([]int{int(math.Pow(2, float64(len(power)-i-1)))}, powers...) 51 | } 52 | } 53 | 54 | Q := [4]int{1, 1, 1, 0} 55 | matrices := make([][4]int, 0) 56 | 57 | for _, p := range powers { 58 | matrices = append(matrices, _raiseToPower(Q, p, memo)) 59 | } 60 | 61 | for len(matrices) > 1 { 62 | M1 := matrices[0] 63 | M2 := matrices[1] 64 | R := _multiplyMatrix(M1, M2) 65 | matrices = matrices[2:len(matrices)] 66 | matrices = append(matrices, R) 67 | } 68 | 69 | return matrices[0][0] 70 | } 71 | 72 | func _multiplyMatrix(A [4]int, B [4]int) [4]int { 73 | var result [4]int 74 | 75 | result[0] = A[0]*B[0] + A[1]*B[2] 76 | result[1] = A[0]*B[1] + A[1]*B[3] 77 | result[2] = A[2]*B[0] + A[3]*B[2] 78 | result[3] = A[2]*B[1] + A[3]*B[3] 79 | 80 | return result 81 | } 82 | 83 | func _raiseToPower(A [4]int, p int, memo map[int][4]int) [4]int { 84 | var result [4]int 85 | 86 | if p == 1 { 87 | return A 88 | } 89 | 90 | if cache, ok := memo[p]; ok { 91 | return cache 92 | } 93 | 94 | result = _raiseToPower(A, p/2, memo) 95 | R := _multiplyMatrix(result, result) 96 | 97 | memo[p] = R 98 | 99 | return R 100 | } 101 | -------------------------------------------------------------------------------- /algorithms/maths/fibonacci/fibonacci_test.go: -------------------------------------------------------------------------------- 1 | package fibonacci 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestIter(t *testing.T) { 9 | if getIter(25) != 75025 { 10 | fmt.Println(getIter(25)) 11 | t.Error() 12 | } 13 | } 14 | 15 | func TestRecurse(t *testing.T) { 16 | if getRecurse(25) != 75025 { 17 | fmt.Println(getRecurse(25)) 18 | t.Error() 19 | } 20 | } 21 | 22 | func TestMatrix(t *testing.T) { 23 | if getMatrix(25) != 75025 { 24 | fmt.Println(getMatrix(25)) 25 | t.Error() 26 | } 27 | } 28 | 29 | func benchmarkIter(n int, b *testing.B) { 30 | for i := 0; i < b.N; i++ { 31 | getIter(n) 32 | } 33 | } 34 | 35 | func benchmarkRecurse(n int, b *testing.B) { 36 | for i := 0; i < b.N; i++ { 37 | getRecurse(n) 38 | } 39 | } 40 | 41 | func benchmarkMatrix(n int, b *testing.B) { 42 | for i := 0; i < b.N; i++ { 43 | getMatrix(n) 44 | } 45 | } 46 | 47 | func BenchmarkIter10(b *testing.B) { benchmarkIter(10, b) } 48 | func BenchmarkIter100(b *testing.B) { benchmarkIter(100, b) } 49 | func BenchmarkIter1000(b *testing.B) { benchmarkIter(1000, b) } 50 | func BenchmarkIter10000(b *testing.B) { benchmarkIter(10000, b) } 51 | func BenchmarkIter100000(b *testing.B) { benchmarkIter(100000, b) } 52 | func BenchmarkIter1000000(b *testing.B) { benchmarkIter(1000000, b) } 53 | func BenchmarkIter10000000(b *testing.B) { benchmarkIter(10000000, b) } 54 | 55 | //func BenchmarkRecurse10(b *testing.B) { benchmarkRecurse(10, b) } 56 | //func BenchmarkRecurse100(b *testing.B) { benchmarkRecurse(100, b) } 57 | //func BenchmarkRecurse1000(b *testing.B) { benchmarkRecurse(1000, b) } 58 | //func BenchmarkRecurse10000(b *testing.B) { benchmarkRecurse(10000, b) } 59 | //func BenchmarkRecurse100000(b *testing.B) { benchmarkRecurse(100000, b) } 60 | 61 | func BenchmarkMatrix10(b *testing.B) { benchmarkMatrix(10, b) } 62 | func BenchmarkMatrix100(b *testing.B) { benchmarkMatrix(100, b) } 63 | func BenchmarkMatrix1000(b *testing.B) { benchmarkMatrix(1000, b) } 64 | func BenchmarkMatrix10000(b *testing.B) { benchmarkMatrix(10000, b) } 65 | func BenchmarkMatrix100000(b *testing.B) { benchmarkMatrix(100000, b) } 66 | func BenchmarkMatrix1000000(b *testing.B) { benchmarkMatrix(1000000, b) } 67 | func BenchmarkMatrix10000000(b *testing.B) { benchmarkMatrix(10000000, b) } 68 | -------------------------------------------------------------------------------- /algorithms/maths/fisher-yates/README.md: -------------------------------------------------------------------------------- 1 | # Knuth / Fisher-Yates Shuffle 2 | 3 | Implementation of the Fisher-Yates/Knuth shuffle 4 | 5 | ## Fisher-Yates/Knuth Overview: 6 | 7 | Randomly picks integers to swap elements in an ubiased manner. 8 | 9 | **Time Complexity:** O(n) 10 | 11 | **Space Complexity:** O(n) 12 | 13 | Pseudocode: [http://en.wikipedia.org/wiki/Fisher-Yates_shuffle](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) 14 | -------------------------------------------------------------------------------- /algorithms/maths/fisher-yates/fisherYates.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | arr := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 11 | 12 | fmt.Println(shuffle(arr)) 13 | } 14 | 15 | func shuffle(a []int) []int { 16 | rand.Seed(time.Now().UTC().UnixNano()) 17 | 18 | for i := len(a) - 1; i > 0; i-- { 19 | j := rand.Intn(i + 1) 20 | a[i], a[j] = a[j], a[i] 21 | } 22 | 23 | return a 24 | } 25 | -------------------------------------------------------------------------------- /algorithms/maths/karatsuba/README.md: -------------------------------------------------------------------------------- 1 | # Karatsuba Multiplication 2 | 3 | Benchmarked against the built-in big.Mult which use karatsuba as well for int larger than 40 4 | 5 | My implementation is much much slower, probably due to my use of big int types. 6 | 7 | See here for some optimizations: [stackoverflow: C++ fast bignum square computation](http://stackoverflow.com/questions/18465326/fast-bignum-square-computation) 8 | -------------------------------------------------------------------------------- /algorithms/maths/karatsuba/karatsuba.go: -------------------------------------------------------------------------------- 1 | // Karatsuba Big Int multiplication 2 | package karatsuba 3 | 4 | import ( 5 | "math" 6 | "math/big" 7 | ) 8 | 9 | func k_multiply(a, b *big.Int) *big.Int { 10 | if a.Cmp(big.NewInt(10)) < 1 || b.Cmp(big.NewInt(10)) < 1 { 11 | return mul(a, b) 12 | } 13 | 14 | m := _pivot(a, b) 15 | 16 | leftA, rightA := _split(a, uint(m)) 17 | leftB, rightB := _split(b, uint(m)) 18 | 19 | z0 := k_multiply(leftA, leftB) 20 | z1 := k_multiply(rightA, rightB) 21 | z2 := k_multiply(add(leftA, rightA), add(leftB, rightB)) 22 | z2 = sub(z2, add(z0, z1)) 23 | 24 | temp0 := mul(z0, big.NewInt(int64(math.Pow(10.0, 2.0*float64(m))))) 25 | temp1 := mul(z2, big.NewInt(int64(math.Pow(10.0, float64(m))))) 26 | temp2 := add(temp0, temp1) 27 | 28 | return add(temp2, z1) 29 | } 30 | 31 | func _split(a *big.Int, m uint) (left, right *big.Int) { 32 | denominator := big.NewInt(int64(math.Pow(10.0, float64(m)))) 33 | 34 | left = big.NewInt(0).Div(a, denominator) 35 | right = sub(a, big.NewInt(0).Mul(left, denominator)) 36 | 37 | return 38 | } 39 | 40 | func _pivot(a, b *big.Int) int { 41 | len_a := len(a.String()) 42 | len_b := len(b.String()) 43 | 44 | if len_a > len_b { 45 | return len_a / 2 46 | } else { 47 | return len_b / 2 48 | } 49 | } 50 | 51 | func add(a, b *big.Int) *big.Int { 52 | return big.NewInt(0).Add(a, b) 53 | } 54 | 55 | func mul(a, b *big.Int) *big.Int { 56 | return big.NewInt(0).Mul(a, b) 57 | } 58 | 59 | func sub(a, b *big.Int) *big.Int { 60 | return big.NewInt(0).Sub(a, b) 61 | } 62 | -------------------------------------------------------------------------------- /algorithms/maths/karatsuba/karatsuba_test.go: -------------------------------------------------------------------------------- 1 | // Karatsuba Big Int multiplication 2 | package karatsuba 3 | 4 | import ( 5 | "fmt" 6 | "math/big" 7 | "testing" 8 | ) 9 | 10 | func TestMultipyOdd(t *testing.T) { 11 | a := big.NewInt(1234567890123456789) 12 | 13 | if k_multiply(a, a).Cmp(mul(a, a)) != 0 { 14 | fmt.Println(k_multiply(a, a), mul(a, a)) 15 | t.Fatal("Wrong result") 16 | } 17 | } 18 | 19 | func TestMultipyEven(t *testing.T) { 20 | a := big.NewInt(123456789012345678) 21 | 22 | if k_multiply(a, a).Cmp(mul(a, a)) != 0 { 23 | fmt.Println(k_multiply(a, a), mul(a, a)) 24 | t.Fatal("Wrong result") 25 | } 26 | } 27 | 28 | func BenchmarkMultiply(b *testing.B) { 29 | for i := 0; i < b.N; i++ { 30 | a := big.NewInt(1234567890123456789) 31 | mul(a, a) 32 | } 33 | } 34 | 35 | func BenchmarkKaratsubaMultiply(b *testing.B) { 36 | for i := 0; i < b.N; i++ { 37 | a := big.NewInt(1234567890123456789) 38 | k_multiply(a, a) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /algorithms/maths/newton-sqrt/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arnauddri/algorithms/736f5ebe59cfd72b778704fe9ba5e0ba25c775fe/algorithms/maths/newton-sqrt/README.md -------------------------------------------------------------------------------- /algorithms/maths/newton-sqrt/newton_sqrt.go: -------------------------------------------------------------------------------- 1 | package newton_sqrt 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | func newton_sqrt(n float64, precision, maxIterations float64) float64 { 8 | upperBound := float64(n) 9 | lowerBound := float64(0) 10 | 11 | var square float64 12 | var i int 13 | var x float64 14 | 15 | for math.Abs(square-n) > precision && float64(i) < maxIterations { 16 | i++ 17 | x = (upperBound-lowerBound)/2 + lowerBound 18 | square = x * x 19 | 20 | if square < n { 21 | lowerBound = x 22 | } else { 23 | upperBound = x 24 | } 25 | } 26 | 27 | floorX := math.Floor(x) 28 | 29 | if floorX*floorX == n { 30 | x = floorX 31 | } else if (floorX+1)*(floorX+1) == n { 32 | x = floorX + 1 33 | } 34 | 35 | return x 36 | } 37 | -------------------------------------------------------------------------------- /algorithms/maths/newton-sqrt/newton_sqrt_test.go: -------------------------------------------------------------------------------- 1 | package newton_sqrt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNewtonSqrt(t *testing.T) { 8 | if newton_sqrt(333, 1e-7, 1e7) != 18.248287591617554 || 9 | newton_sqrt(61009, 1e-7, 1e7) != 247 || 10 | newton_sqrt(9, 1e-7, 1e7) != 3 { 11 | t.Error() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /algorithms/maths/permutations-count/README.md: -------------------------------------------------------------------------------- 1 | # Permutations Count 2 | 3 | Count the number of inversions in an integer array 4 | 5 | An inversion occurs when for ```i```, ```j``` such as ```0 < i < j```, ```A[i] > A[j]``` 6 | 7 | ### Benchmark 8 | ``` 9 | BenchmarkRecursive 20 55381896 ns/op 10 | BenchmarkIterative 1 17762797326 ns/op 11 | ``` 12 | -------------------------------------------------------------------------------- /algorithms/maths/permutations-count/permutations.go: -------------------------------------------------------------------------------- 1 | package permutations 2 | 3 | import () 4 | 5 | func recursiveCount(a []int) ([]int, int) { 6 | n := len(a) 7 | if n < 2 { 8 | return a, 0 9 | } 10 | 11 | b, left := recursiveCount(a[:n>>1]) 12 | c, right := recursiveCount(a[n>>1:]) 13 | d := make([]int, 0) 14 | 15 | i, j := 0, 0 16 | inversions := 0 17 | 18 | for k := 0; k < n; k++ { 19 | if b[i] < c[j] { 20 | d = append(d, b[i]) 21 | i++ 22 | if i == len(b) { 23 | for j < len(c) { 24 | d = append(d, c[j]) 25 | j++ 26 | } 27 | break 28 | } 29 | } else { 30 | d = append(d, c[j]) 31 | j++ 32 | inversions += len(b) - i 33 | if j == len(c) { 34 | for i < len(b) { 35 | d = append(d, b[i]) 36 | i++ 37 | } 38 | break 39 | } 40 | } 41 | } 42 | 43 | return d, left + right + inversions 44 | } 45 | 46 | func iterativeCount(array []int) int { 47 | n := len(array) 48 | count := 0 49 | 50 | for i := 0; i < n; i++ { 51 | for j := i + 1; j < n; j++ { 52 | if array[j] < array[i] { 53 | count++ 54 | } 55 | } 56 | } 57 | return count 58 | } 59 | -------------------------------------------------------------------------------- /algorithms/maths/permutations-count/permutations_test.go: -------------------------------------------------------------------------------- 1 | package permutations 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/algorithms/sorting/utils" 5 | "testing" 6 | ) 7 | 8 | func TestIterative(t *testing.T) { 9 | a := []int{1, 3, 5, 2, 4, 6} 10 | count := iterativeCount(a) 11 | 12 | if count != 3 { 13 | t.Error("iterative count failed") 14 | } 15 | } 16 | 17 | func TestRecursive(t *testing.T) { 18 | a := []int{1, 3, 5, 2, 4, 6} 19 | _, count := recursiveCount(a) 20 | 21 | if count != 3 { 22 | t.Error("iterative count failed") 23 | } 24 | } 25 | 26 | func BenchmarkRecursive(b *testing.B) { 27 | array := utils.GetArrayOfSize(10000) 28 | 29 | for i := 0; i < b.N; i++ { 30 | recursiveCount(array) 31 | } 32 | } 33 | 34 | func BenchmarkIterative(b *testing.B) { 35 | array := utils.GetArrayOfSize(10000) 36 | 37 | for i := 0; i < b.N; i++ { 38 | iterativeCount(array) 39 | } 40 | } 41 | 42 | func check(e error) { 43 | if e != nil { 44 | panic(e) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /algorithms/maths/stein/README.md: -------------------------------------------------------------------------------- 1 | # Stein's Algorithm for computing GCD 2 | 3 | The binary GCD algorithm, also known as Stein's algorithm, is an algorithm that computes the greatest common divisor of two nonnegative integers. 4 | 5 | ### Benchmark 6 | 7 | ``` 8 | BenchmarkRecurse 10000000 292 ns/op 9 | BenchmarkIter 50000000 51.3 ns/op 10 | ``` 11 | -------------------------------------------------------------------------------- /algorithms/maths/stein/gcd.go: -------------------------------------------------------------------------------- 1 | package gcd 2 | 3 | import () 4 | 5 | func recurse(a, b int) int { 6 | if a == b { 7 | return a 8 | } 9 | if a == 0 || b == 0 { 10 | return a + b 11 | } 12 | 13 | if a%2 == 0 { 14 | if b%2 == 1 { 15 | return recurse(a>>1, b) 16 | } else { 17 | return recurse(a>>1, b>>1) << 1 18 | } 19 | } 20 | 21 | if b%2 == 0 { 22 | return recurse(a, b>>1) 23 | } 24 | 25 | if a > b { 26 | return recurse((a-b)>>1, b) 27 | } 28 | 29 | return recurse((b-a)>>1, a) 30 | } 31 | 32 | func iter(a, b int) int { 33 | if a == b { 34 | return a 35 | } 36 | if a == 0 || b == 0 { 37 | return a + b 38 | } 39 | 40 | shift := 0 41 | for shift = 0; ((a | b) & 1) == 0; shift++ { 42 | a >>= 1 43 | b >>= 1 44 | } 45 | 46 | for (a & 1) == 0 { 47 | a >>= 1 48 | } 49 | 50 | for b != 0 { 51 | for b&1 == 0 { 52 | b >>= 1 53 | } 54 | if a > b { 55 | b, a = a, b 56 | } 57 | b -= a 58 | } 59 | 60 | return a << uint32(shift) 61 | } 62 | -------------------------------------------------------------------------------- /algorithms/maths/stein/gcd_test.go: -------------------------------------------------------------------------------- 1 | package gcd 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestRecurse(t *testing.T) { 8 | if recurse(14, 7) != 7 || 9 | recurse(4, 2) != 2 || 10 | recurse(31, 2) != 1 || 11 | recurse(33, 11) != 11 { 12 | t.Error() 13 | } 14 | } 15 | 16 | func TestIterative(t *testing.T) { 17 | if iter(14, 7) != 7 || 18 | iter(4, 2) != 2 || 19 | iter(31, 2) != 1 || 20 | iter(33, 11) != 11 { 21 | t.Error() 22 | } 23 | } 24 | 25 | func BenchmarkRecurse(b *testing.B) { 26 | for i := 0; i < b.N; i++ { 27 | recurse(131313131, 12343545) 28 | } 29 | } 30 | 31 | func BenchmarkIter(b *testing.B) { 32 | for i := 0; i < b.N; i++ { 33 | iter(131313131, 12343545) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /algorithms/maths/strassen/README.md: -------------------------------------------------------------------------------- 1 | # Strassen Algorithm 2 | 3 | The Strassen algorithm is faster than the standard matrix multiplication algorithm and is useful in practice for large matrices. 4 | 5 | **Time complexity:** O(n ^ 2.80) 6 | 7 | Pseudocode: [Strassen (McGill University)](http://www.cs.mcgill.ca/~pnguyen/251F09/matrix-mult.pdf) 8 | -------------------------------------------------------------------------------- /algorithms/maths/strassen/strassen.go: -------------------------------------------------------------------------------- 1 | package strassen 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/data-structures/matrix" 5 | "math" 6 | ) 7 | 8 | func Multiply(A *matrix.Matrix, B *matrix.Matrix) *matrix.Matrix { 9 | n := A.CountRows() 10 | bigN := scaleSize(n) 11 | 12 | bigA := matrix.MakeMatrix(make([]float64, bigN*bigN), bigN, bigN) 13 | bigB := matrix.MakeMatrix(make([]float64, bigN*bigN), bigN, bigN) 14 | 15 | for i := 0; i < n; i++ { 16 | for j := 0; j < n; j++ { 17 | bigA.SetElm(i, j, A.GetElm(i, j)) 18 | bigB.SetElm(i, j, B.GetElm(i, j)) 19 | } 20 | } 21 | 22 | bigC := recurse(bigA, bigB) 23 | 24 | C := matrix.MakeMatrix(make([]float64, n*n), n, n) 25 | for i := 0; i < n; i++ { 26 | for j := 0; j < n; j++ { 27 | C.SetElm(i, j, bigC.GetElm(i, j)) 28 | } 29 | } 30 | 31 | return C 32 | } 33 | 34 | func recurse(A *matrix.Matrix, B *matrix.Matrix) *matrix.Matrix { 35 | n := A.CountRows() 36 | 37 | newSize := n / 2 38 | 39 | if n < 2 { 40 | return matrix.MakeMatrix([]float64{A.GetElm(0, 0) * B.GetElm(0, 0)}, 1, 1) 41 | } 42 | 43 | A11 := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 44 | A12 := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 45 | A21 := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 46 | A22 := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 47 | 48 | B11 := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 49 | B12 := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 50 | B21 := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 51 | B22 := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 52 | 53 | for i := 0; i < newSize; i++ { 54 | for j := 0; j < newSize; j++ { 55 | A11.SetElm(i, j, A.GetElm(i, j)) 56 | A12.SetElm(i, j, A.GetElm(i, j+newSize)) 57 | A21.SetElm(i, j, A.GetElm(i+newSize, j)) 58 | A22.SetElm(i, j, A.GetElm(i+newSize, j+newSize)) 59 | 60 | B11.SetElm(i, j, B.GetElm(i, j)) 61 | B12.SetElm(i, j, B.GetElm(i, j+newSize)) 62 | B21.SetElm(i, j, B.GetElm(i+newSize, j)) 63 | B22.SetElm(i, j, B.GetElm(i+newSize, j+newSize)) 64 | } 65 | } 66 | 67 | a := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 68 | b := matrix.MakeMatrix(make([]float64, newSize*newSize), newSize, newSize) 69 | 70 | // P1 = (A11 + A22) * (B11 + B22) 71 | a = matrix.Add(A11, A22) 72 | b = matrix.Add(B11, B22) 73 | P1 := recurse(a, b) 74 | 75 | // P2 = (A21 + A22) * (B11) 76 | a = matrix.Add(A21, A22) 77 | P2 := recurse(a, B11) 78 | 79 | // P3 = (A11) * (B12 - B11) 80 | b = matrix.Substract(B12, B22) 81 | P3 := recurse(A11, b) 82 | 83 | // P4 = A22 * (B21 - B22) 84 | b = matrix.Substract(B21, B11) 85 | P4 := recurse(A22, b) 86 | 87 | // P5 = (A11 + A12) * B22 88 | a = matrix.Add(A11, A12) 89 | P5 := recurse(a, B22) 90 | 91 | // P6 = (A21 - A11) * (B11 + B12) 92 | a = matrix.Substract(A21, A11) 93 | b = matrix.Add(B11, B12) 94 | P6 := recurse(a, b) 95 | 96 | // P7 = (A12 - A22) * (B21 + B22) 97 | a = matrix.Substract(A12, A22) 98 | b = matrix.Add(B21, B22) 99 | P7 := recurse(a, b) 100 | 101 | // Aggregates the result into C 102 | C12 := matrix.Add(P3, P5) 103 | C21 := matrix.Add(P2, P4) 104 | 105 | a = matrix.Add(P1, P4) 106 | b = matrix.Add(a, P7) 107 | C11 := matrix.Substract(b, P5) 108 | 109 | a = matrix.Add(P1, P3) 110 | b = matrix.Add(a, P6) 111 | C22 := matrix.Substract(b, P2) 112 | 113 | C := matrix.MakeMatrix(make([]float64, n*n), n, n) 114 | 115 | for i := 0; i < newSize; i++ { 116 | for j := 0; j < newSize; j++ { 117 | C.SetElm(i, j, C11.GetElm(i, j)) 118 | C.SetElm(i, j+newSize, C12.GetElm(i, j)) 119 | C.SetElm(i+newSize, j, C21.GetElm(i, j)) 120 | C.SetElm(i+newSize, j+newSize, C22.GetElm(i, j)) 121 | } 122 | } 123 | 124 | return C 125 | } 126 | 127 | func scaleSize(n int) int { 128 | log2 := math.Ceil(math.Log(float64(n)) / math.Log(float64(2))) 129 | return int(math.Pow(2, log2)) 130 | } 131 | -------------------------------------------------------------------------------- /algorithms/maths/strassen/strassen_test.go: -------------------------------------------------------------------------------- 1 | package strassen 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/data-structures/matrix" 5 | "testing" 6 | ) 7 | 8 | func TestStrassen(t *testing.T) { 9 | A := matrix.MakeMatrix([]float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, 4, 4) 10 | B := matrix.MakeMatrix([]float64{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, 4, 4) 11 | 12 | C := Multiply(A, B) 13 | D := matrix.Multiply(A, B) 14 | if !FloatArrayEquals(C.Elements, D.Elements) { 15 | t.Error() 16 | } 17 | 18 | A = matrix.MakeMatrix([]float64{1, 1, 1, 1}, 2, 2) 19 | B = matrix.MakeMatrix([]float64{1, 1, 1, 1}, 2, 2) 20 | 21 | C = Multiply(A, B) 22 | D = matrix.Multiply(A, B) 23 | if !FloatArrayEquals(C.Elements, D.Elements) { 24 | t.Error() 25 | } 26 | 27 | A = matrix.MakeMatrix([]float64{1, 1, 1, 1, 1, 1, 1, 1, 1}, 3, 3) 28 | B = matrix.MakeMatrix([]float64{1, 1, 1, 1, 1, 1, 1, 1, 1}, 3, 3) 29 | 30 | C = Multiply(A, B) 31 | D = matrix.Multiply(A, B) 32 | if !FloatArrayEquals(C.Elements, D.Elements) { 33 | t.Error() 34 | } 35 | } 36 | 37 | func FloatArrayEquals(a []float64, b []float64) bool { 38 | if len(a) != len(b) { 39 | return false 40 | } 41 | for i, v := range a { 42 | if v != b[i] { 43 | return false 44 | } 45 | } 46 | return true 47 | } 48 | 49 | func BenchmarkStrassen(b *testing.B) { 50 | a := make([]float64, 100000000, 100000000) 51 | c := make([]float64, 100000000, 100000000) 52 | for i := 0; i < 100000000; i++ { 53 | a[i] = float64(i) 54 | c[i] = float64(100000000 - i) 55 | } 56 | A := matrix.MakeMatrix(a, 10000, 10000) 57 | B := matrix.MakeMatrix(c, 10000, 10000) 58 | 59 | for i := 0; i < b.N; i++ { 60 | Multiply(A, B) 61 | } 62 | } 63 | 64 | func BenchmarkMultiply(b *testing.B) { 65 | a := make([]float64, 100000000, 100000000) 66 | c := make([]float64, 100000000, 100000000) 67 | 68 | for i := 0; i < 100000000; i++ { 69 | a[i] = float64(i) 70 | c[i] = float64(100000000 - i) 71 | } 72 | A := matrix.MakeMatrix(a, 10000, 10000) 73 | B := matrix.MakeMatrix(c, 10000, 10000) 74 | 75 | for i := 0; i < b.N; i++ { 76 | matrix.Multiply(A, B) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /algorithms/searching/binary-search/binary_search.go: -------------------------------------------------------------------------------- 1 | package bs 2 | 3 | import () 4 | 5 | func search(sortedArray []int, el int) int { 6 | init, end := 0, len(sortedArray)-1 7 | 8 | for init <= end { 9 | middle := ((end - init) >> 1) + init 10 | 11 | if sortedArray[middle] == el { 12 | return middle 13 | } 14 | 15 | if sortedArray[middle] < el { 16 | init = middle + 1 17 | } else { 18 | end = middle - 1 19 | } 20 | } 21 | 22 | return -1 23 | } 24 | -------------------------------------------------------------------------------- /algorithms/searching/binary-search/binary_search_test.go: -------------------------------------------------------------------------------- 1 | package bs 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestSearch(t *testing.T) { 9 | sorted := make([]int, 10000) 10 | 11 | for i := 0; i < 10000; i++ { 12 | sorted[i] = 2 * i 13 | } 14 | 15 | for i := 0; i < 10000; i++ { 16 | index := search(sorted, 2*i) 17 | 18 | if index != i { 19 | fmt.Println(index) 20 | t.Error() 21 | } 22 | } 23 | 24 | if search(sorted, 3) != -1 { 25 | t.Error() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /algorithms/sorting/README.md: -------------------------------------------------------------------------------- 1 | # Sorting 2 | 3 | ### Heapsort 4 | 5 | ***Time Complexity:*** 6 | * Worst case: O(n log(n)) 7 | * Average case: O(n log(n)) 8 | * Best case: O(n log(n)) 9 | 10 | ***Space Complexity:*** 11 | * O(1) 12 | 13 | ### Quicksort 14 | 15 | **Time Complexity:** 16 | * Worst case: O(n log(n)) 17 | * Average case: O(n log(n)) 18 | * Best case: O(n^2) 19 | 20 | **Space Complexity:** 21 | * O(n) 22 | 23 | ### Mergesort 24 | 25 | **Time Complexity:** 26 | * Best case: O(n log(n)) 27 | * Average case: O(n log(n)) 28 | * Worst case: O(n log(n)) 29 | 30 | **Space Complexity:** 31 | * O(n) 32 | 33 | ### Bubble 34 | 35 | **Time Complexity:** 36 | * Best case: O(n) 37 | * Average case: O(n^2) 38 | * Worst case: O(n^2) 39 | 40 | **Space Complexity:** 41 | * O(1) 42 | 43 | ### Insertion 44 | 45 | **Time Complexity:** 46 | * Best case: O(n) 47 | * Average case: O(n^n) 48 | * Worst case: O(n^2) 49 | 50 | **Space Complexity:** 51 | * O(n) 52 | 53 | ### Select 54 | 55 | **Time Complexity:** 56 | * Best case: O(n^2) 57 | * Average case: O(n^2) 58 | * Worst case: O(n^2) 59 | 60 | **Space Complexity:** 61 | * O(1) 62 | 63 | 64 | ### Benchmark Results 65 | 66 | ``` 67 | PASS 68 | BenchmarkBubbleSort100 10000000 145 ns/op 69 | BenchmarkBubbleSort1000 2000000 1272 ns/op 70 | BenchmarkBubbleSort10000 100000 14371 ns/op 71 | BenchmarkBubbleSort100000 1 24769404949 ns/op 72 | ok github.com/arnauddri/algorithms/algorithms/sorting/bubble-sort 33.273s 73 | 74 | PASS 75 | BenchmarkHeapSort100 20000 95676 ns/op 76 | BenchmarkHeapSort1000 500 3613389 ns/op 77 | BenchmarkHeapSort10000 5 287265292 ns/op 78 | BenchmarkHeapSort100000 1 37184383822 ns/op 79 | ok github.com/arnauddri/algorithms/algorithms/sorting/heap-sort 43.738s 80 | 81 | PASS 82 | BenchmarkInsertionSort100 10000000 228 ns/op 83 | BenchmarkInsertionSort1000 1000000 1857 ns/op 84 | BenchmarkInsertionSort10000 100000 18822 ns/op 85 | BenchmarkInsertionSort100000 1 3949000733 ns/op 86 | ok github.com/arnauddri/algorithms/algorithms/sorting/insertion-sort 12.348s 87 | 88 | PASS 89 | BenchmarkMergeSort100 100000 17563 ns/op 90 | BenchmarkMergeSort1000 10000 186034 ns/op 91 | BenchmarkMergeSort10000 1000 1946963 ns/op 92 | BenchmarkMergeSort100000 50 20140692 ns/op 93 | ok github.com/arnauddri/algorithms/algorithms/sorting/merge-sort 8.193s 94 | 95 | PASS 96 | BenchmarkQuickSort100 500000 3607 ns/op 97 | BenchmarkQuickSort1000 50000 44601 ns/op 98 | BenchmarkQuickSort10000 5000 543711 ns/op 99 | BenchmarkQuickSort100000 500 6070191 ns/op 100 | ok github.com/arnauddri/algorithms/algorithms/sorting/quick-sort 10.821s 101 | 102 | PASS 103 | BenchmarkSelectionSort100 500000 6461 ns/op 104 | BenchmarkSelectionSort1000 2000 547985 ns/op 105 | BenchmarkSelectionSort10000 50 53036282 ns/op 106 | BenchmarkSelectionSort100000 1 5344170280 ns/op 107 | ok github.com/arnauddri/algorithms/algorithms/sorting/selection-sort 12.653s 108 | 109 | PASS 110 | BenchmarkShellSort100 2000000 845 ns/op 111 | BenchmarkShellSort1000 200000 13049 ns/op 112 | BenchmarkShellSort10000 10000 175454 ns/op 113 | BenchmarkShellSort100000 500 2485845 ns/op 114 | ``` 115 | -------------------------------------------------------------------------------- /algorithms/sorting/bubble-sort/bubble.go: -------------------------------------------------------------------------------- 1 | // Package main provides ... 2 | package bubble 3 | 4 | import ( 5 | //"fmt" 6 | ) 7 | 8 | func sort(arr []int) { 9 | for itemCount := len(arr) - 1; ; itemCount-- { 10 | swap := false 11 | for i := 1; i <= itemCount; i++ { 12 | if arr[i-1] > arr[i] { 13 | arr[i-1], arr[i] = arr[i], arr[i-1] 14 | swap = true 15 | } 16 | } 17 | if swap == false { 18 | break 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /algorithms/sorting/bubble-sort/bubble_test.go: -------------------------------------------------------------------------------- 1 | package bubble 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/algorithms/sorting/utils" 6 | "testing" 7 | ) 8 | 9 | func TestBubbleSort(t *testing.T) { 10 | list := utils.GetArrayOfSize(100) 11 | 12 | sort(list) 13 | 14 | for i := 0; i < len(list)-2; i++ { 15 | if list[i] > list[i+1] { 16 | fmt.Println(list) 17 | t.Error() 18 | } 19 | } 20 | } 21 | 22 | func benchmarkBubbleSort(n int, b *testing.B) { 23 | list := utils.GetArrayOfSize(n) 24 | for i := 0; i < b.N; i++ { 25 | sort(list) 26 | } 27 | } 28 | 29 | func BenchmarkBubbleSort100(b *testing.B) { benchmarkBubbleSort(100, b) } 30 | func BenchmarkBubbleSort1000(b *testing.B) { benchmarkBubbleSort(1000, b) } 31 | func BenchmarkBubbleSort10000(b *testing.B) { benchmarkBubbleSort(10000, b) } 32 | func BenchmarkBubbleSort100000(b *testing.B) { benchmarkBubbleSort(100000, b) } 33 | -------------------------------------------------------------------------------- /algorithms/sorting/heap-sort/heap.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/data-structures/heap" 5 | ) 6 | 7 | func sort(arr []int) []int { 8 | h := heap.NewMin() 9 | for i := 0; i < len(arr); i++ { 10 | h.Insert(heap.Int(arr[i])) 11 | } 12 | 13 | for i := 0; i < len(arr); i++ { 14 | arr[i] = int(h.Extract().(heap.Int)) 15 | } 16 | 17 | return arr 18 | } 19 | -------------------------------------------------------------------------------- /algorithms/sorting/heap-sort/heap_test.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/algorithms/sorting/utils" 6 | "testing" 7 | ) 8 | 9 | func TestHeapSort(t *testing.T) { 10 | list := utils.GetArrayOfSize(10) 11 | 12 | sort(list) 13 | 14 | for i := 0; i < len(list)-2; i++ { 15 | if list[i] > list[i+1] { 16 | fmt.Println(list) 17 | t.Error() 18 | } 19 | } 20 | } 21 | 22 | func benchmarkHeapSort(n int, b *testing.B) { 23 | list := utils.GetArrayOfSize(n) 24 | for i := 0; i < b.N; i++ { 25 | sort(list) 26 | } 27 | } 28 | 29 | func BenchmarkHeapSort100(b *testing.B) { benchmarkHeapSort(100, b) } 30 | func BenchmarkHeapSort1000(b *testing.B) { benchmarkHeapSort(1000, b) } 31 | func BenchmarkHeapSort10000(b *testing.B) { benchmarkHeapSort(10000, b) } 32 | func BenchmarkHeapSort100000(b *testing.B) { benchmarkHeapSort(100000, b) } 33 | -------------------------------------------------------------------------------- /algorithms/sorting/insertion-sort/insertion.go: -------------------------------------------------------------------------------- 1 | package insertion 2 | 3 | import () 4 | 5 | func sort(arr []int) { 6 | for i := 1; i < len(arr); i++ { 7 | value := arr[i] 8 | j := i - 1 9 | for j >= 0 && arr[j] > value { 10 | arr[j+1] = arr[j] 11 | j = j - 1 12 | } 13 | arr[j+1] = value 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /algorithms/sorting/insertion-sort/insertion_test.go: -------------------------------------------------------------------------------- 1 | package insertion 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/algorithms/sorting/utils" 6 | "testing" 7 | ) 8 | 9 | func TestInsertionSort(t *testing.T) { 10 | list := utils.GetArrayOfSize(100) 11 | 12 | sort(list) 13 | 14 | for i := 0; i < len(list)-2; i++ { 15 | if list[i] > list[i+1] { 16 | fmt.Println(list) 17 | t.Error() 18 | } 19 | } 20 | } 21 | 22 | func benchmarkInsertionSort(n int, b *testing.B) { 23 | list := utils.GetArrayOfSize(n) 24 | for i := 0; i < b.N; i++ { 25 | sort(list) 26 | } 27 | } 28 | 29 | func BenchmarkInsertionSort100(b *testing.B) { benchmarkInsertionSort(100, b) } 30 | func BenchmarkInsertionSort1000(b *testing.B) { benchmarkInsertionSort(1000, b) } 31 | func BenchmarkInsertionSort10000(b *testing.B) { benchmarkInsertionSort(10000, b) } 32 | func BenchmarkInsertionSort100000(b *testing.B) { benchmarkInsertionSort(100000, b) } 33 | -------------------------------------------------------------------------------- /algorithms/sorting/merge-sort/merge.go: -------------------------------------------------------------------------------- 1 | package merge 2 | 3 | func sort(arr []int) { 4 | var s = make([]int, len(arr)/2+1) 5 | if len(arr) < 2 { 6 | return 7 | } 8 | 9 | mid := len(arr) / 2 10 | 11 | sort(arr[:mid]) 12 | sort(arr[mid:]) 13 | 14 | if arr[mid-1] <= arr[mid] { 15 | return 16 | } 17 | 18 | copy(s, arr[:mid]) 19 | 20 | l, r := 0, mid 21 | 22 | for i := 0; ; i++ { 23 | if s[l] <= arr[r] { 24 | arr[i] = s[l] 25 | l++ 26 | 27 | if l == mid { 28 | break 29 | } 30 | } else { 31 | arr[i] = arr[r] 32 | r++ 33 | if r == len(arr) { 34 | copy(arr[i+1:], s[l:mid]) 35 | break 36 | } 37 | } 38 | } 39 | return 40 | } 41 | -------------------------------------------------------------------------------- /algorithms/sorting/merge-sort/merge_test.go: -------------------------------------------------------------------------------- 1 | package merge 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/algorithms/sorting/utils" 6 | "testing" 7 | ) 8 | 9 | func TestMergeSort(t *testing.T) { 10 | list := utils.GetArrayOfSize(100) 11 | 12 | sort(list) 13 | 14 | for i := 0; i < len(list)-2; i++ { 15 | if list[i] > list[i+1] { 16 | fmt.Println(list) 17 | t.Error() 18 | } 19 | } 20 | } 21 | 22 | func benchmarkMergeSort(n int, b *testing.B) { 23 | list := utils.GetArrayOfSize(n) 24 | for i := 0; i < b.N; i++ { 25 | sort(list) 26 | } 27 | } 28 | 29 | func BenchmarkMergeSort100(b *testing.B) { benchmarkMergeSort(100, b) } 30 | func BenchmarkMergeSort1000(b *testing.B) { benchmarkMergeSort(1000, b) } 31 | func BenchmarkMergeSort10000(b *testing.B) { benchmarkMergeSort(10000, b) } 32 | func BenchmarkMergeSort100000(b *testing.B) { benchmarkMergeSort(100000, b) } 33 | -------------------------------------------------------------------------------- /algorithms/sorting/quick-sort/quick.go: -------------------------------------------------------------------------------- 1 | package quick 2 | 3 | func sort(arr []int) []int { 4 | var recurse func(left int, right int) 5 | var partition func(left int, right int, pivot int) int 6 | 7 | partition = func(left int, right int, pivot int) int { 8 | v := arr[pivot] 9 | right-- 10 | arr[pivot], arr[right] = arr[right], arr[pivot] 11 | 12 | for i := left; i < right; i++ { 13 | if arr[i] <= v { 14 | arr[i], arr[left] = arr[left], arr[i] 15 | left++ 16 | } 17 | } 18 | 19 | arr[left], arr[right] = arr[right], arr[left] 20 | return left 21 | } 22 | 23 | recurse = func(left int, right int) { 24 | if left < right { 25 | pivot := (right + left) / 2 26 | pivot = partition(left, right, pivot) 27 | recurse(left, pivot) 28 | recurse(pivot+1, right) 29 | } 30 | } 31 | 32 | recurse(0, len(arr)) 33 | return arr 34 | } 35 | -------------------------------------------------------------------------------- /algorithms/sorting/quick-sort/quick_test.go: -------------------------------------------------------------------------------- 1 | package quick 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/algorithms/sorting/utils" 6 | "testing" 7 | ) 8 | 9 | func TestQuickSort(t *testing.T) { 10 | list := utils.GetArrayOfSize(100) 11 | 12 | sort(list) 13 | 14 | for i := 0; i < len(list)-2; i++ { 15 | if list[i] > list[i+1] { 16 | fmt.Println(list) 17 | t.Error() 18 | } 19 | } 20 | } 21 | 22 | func benchmarkQuickSort(n int, b *testing.B) { 23 | list := utils.GetArrayOfSize(n) 24 | for i := 0; i < b.N; i++ { 25 | sort(list) 26 | } 27 | } 28 | 29 | func BenchmarkQuickSort100(b *testing.B) { benchmarkQuickSort(100, b) } 30 | func BenchmarkQuickSort1000(b *testing.B) { benchmarkQuickSort(1000, b) } 31 | func BenchmarkQuickSort10000(b *testing.B) { benchmarkQuickSort(10000, b) } 32 | func BenchmarkQuickSort100000(b *testing.B) { benchmarkQuickSort(100000, b) } 33 | -------------------------------------------------------------------------------- /algorithms/sorting/selection-sort/selection.go: -------------------------------------------------------------------------------- 1 | package selection 2 | 3 | func sort(arr []int) []int { 4 | for i := 0; i < len(arr); i++ { 5 | min := i 6 | for j := i + 1; j < len(arr); j++ { 7 | if arr[j] < arr[min] { 8 | min = j 9 | } 10 | } 11 | if min != i { 12 | arr[i], arr[min] = arr[min], arr[i] 13 | } 14 | } 15 | return arr 16 | } 17 | -------------------------------------------------------------------------------- /algorithms/sorting/selection-sort/selection_test.go: -------------------------------------------------------------------------------- 1 | package selection 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/algorithms/sorting/utils" 6 | "testing" 7 | ) 8 | 9 | func TestSelectionSort(t *testing.T) { 10 | list := utils.GetArrayOfSize(100) 11 | 12 | sort(list) 13 | 14 | for i := 0; i < len(list)-2; i++ { 15 | if list[i] > list[i+1] { 16 | fmt.Println(list) 17 | t.Error() 18 | } 19 | } 20 | } 21 | 22 | func benchmarkSelectionSort(n int, b *testing.B) { 23 | list := utils.GetArrayOfSize(n) 24 | for i := 0; i < b.N; i++ { 25 | sort(list) 26 | } 27 | } 28 | 29 | func BenchmarkSelectionSort100(b *testing.B) { benchmarkSelectionSort(100, b) } 30 | func BenchmarkSelectionSort1000(b *testing.B) { benchmarkSelectionSort(1000, b) } 31 | func BenchmarkSelectionSort10000(b *testing.B) { benchmarkSelectionSort(10000, b) } 32 | func BenchmarkSelectionSort100000(b *testing.B) { benchmarkSelectionSort(100000, b) } 33 | -------------------------------------------------------------------------------- /algorithms/sorting/shell-sort/shell.go: -------------------------------------------------------------------------------- 1 | package shell 2 | 3 | func sort(arr []int) { 4 | increment := len(arr) / 2 5 | for increment > 0 { 6 | for i := increment; i < len(arr); i++ { 7 | j := i 8 | temp := arr[i] 9 | 10 | for j >= increment && arr[j-increment] > temp { 11 | arr[j] = arr[j-increment] 12 | j = j - increment 13 | } 14 | arr[j] = temp 15 | } 16 | if increment == 2 { 17 | increment = 1 18 | } else { 19 | increment = int(increment * 5 / 11) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /algorithms/sorting/shell-sort/shell_test.go: -------------------------------------------------------------------------------- 1 | package shell 2 | 3 | import ( 4 | "fmt" 5 | "github.com/arnauddri/algorithms/algorithms/sorting/utils" 6 | "testing" 7 | ) 8 | 9 | func TestShellSort(t *testing.T) { 10 | list := utils.GetArrayOfSize(100) 11 | 12 | sort(list) 13 | 14 | for i := 0; i < len(list)-2; i++ { 15 | if list[i] > list[i+1] { 16 | fmt.Println(list) 17 | t.Error() 18 | } 19 | } 20 | } 21 | 22 | func benchmarkShellSort(n int, b *testing.B) { 23 | list := utils.GetArrayOfSize(n) 24 | for i := 0; i < b.N; i++ { 25 | sort(list) 26 | } 27 | } 28 | 29 | func BenchmarkShellSort100(b *testing.B) { benchmarkShellSort(100, b) } 30 | func BenchmarkShellSort1000(b *testing.B) { benchmarkShellSort(1000, b) } 31 | func BenchmarkShellSort10000(b *testing.B) { benchmarkShellSort(10000, b) } 32 | func BenchmarkShellSort100000(b *testing.B) { benchmarkShellSort(100000, b) } 33 | -------------------------------------------------------------------------------- /algorithms/sorting/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "bufio" 5 | "go/build" 6 | "os" 7 | "path/filepath" 8 | "strconv" 9 | ) 10 | 11 | func GetArrayOfSize(n int) []int { 12 | p, err := build.Default.Import("github.com/arnauddri/algorithms/algorithms/sorting/utils", "", build.FindOnly) 13 | 14 | if err != nil { 15 | // handle error 16 | } 17 | fname := filepath.Join(p.Dir, "IntegerArray.txt") 18 | f, _ := os.Open(fname) 19 | defer f.Close() 20 | 21 | numbers := make([]int, 0) 22 | scanner := bufio.NewScanner(f) 23 | 24 | for scanner.Scan() { 25 | s, _ := strconv.Atoi(scanner.Text()) 26 | numbers = append(numbers, s) 27 | } 28 | 29 | return numbers[0:n] 30 | } 31 | -------------------------------------------------------------------------------- /algorithms/sorting/utils/utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestRead(t *testing.T) { 9 | for i := 0; i < 100000; i++ { 10 | if i%300 == 0 { 11 | array := GetArrayOfSize(i) 12 | 13 | if len(array) != i { 14 | fmt.Println(array) 15 | t.Error() 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /data-structures/binary-tree/bst.go: -------------------------------------------------------------------------------- 1 | package bst 2 | 3 | import () 4 | 5 | type Node struct { 6 | Value int 7 | Parent *Node 8 | Left *Node 9 | Right *Node 10 | } 11 | 12 | func NewNode(i int) *Node { 13 | return &Node{Value: i} 14 | } 15 | 16 | func (n *Node) Compare(m *Node) int { 17 | if n.Value < m.Value { 18 | return -1 19 | } else if n.Value > m.Value { 20 | return 1 21 | } else { 22 | return 0 23 | } 24 | } 25 | 26 | type Tree struct { 27 | Head *Node 28 | Size int 29 | } 30 | 31 | func NewTree(n *Node) *Tree { 32 | if n == nil { 33 | return &Tree{} 34 | } 35 | return &Tree{Head: n, Size: 1} 36 | } 37 | 38 | func (t *Tree) Insert(i int) { 39 | n := &Node{Value: i} 40 | if t.Head == nil { 41 | t.Head = n 42 | t.Size++ 43 | return 44 | } 45 | 46 | h := t.Head 47 | 48 | for { 49 | if n.Compare(h) == -1 { 50 | if h.Left == nil { 51 | h.Left = n 52 | n.Parent = h 53 | break 54 | } else { 55 | h = h.Left 56 | } 57 | } else { 58 | if h.Right == nil { 59 | h.Right = n 60 | n.Parent = h 61 | break 62 | } else { 63 | h = h.Right 64 | } 65 | } 66 | } 67 | t.Size++ 68 | } 69 | 70 | func (t *Tree) Search(i int) *Node { 71 | h := t.Head 72 | n := &Node{Value: i} 73 | 74 | for h != nil { 75 | switch h.Compare(n) { 76 | case -1: 77 | h = h.Right 78 | case 1: 79 | h = h.Left 80 | case 0: 81 | return h 82 | default: 83 | panic("Node not found") 84 | } 85 | } 86 | panic("Node not found") 87 | } 88 | 89 | // returns true if a node with value i was found 90 | // and deleted and returns false otherwise 91 | func (t *Tree) Delete(i int) bool { 92 | var parent *Node 93 | 94 | h := t.Head 95 | n := &Node{Value: i} 96 | for h != nil { 97 | switch n.Compare(h) { 98 | case -1: 99 | parent = h 100 | h = h.Left 101 | case 1: 102 | parent = h 103 | h = h.Right 104 | case 0: 105 | if h.Left != nil { 106 | right := h.Right 107 | h.Value = h.Left.Value 108 | h.Left = h.Left.Left 109 | h.Right = h.Left.Right 110 | 111 | if right != nil { 112 | subTree := &Tree{Head: h} 113 | IterOnTree(right, func(n *Node) { 114 | subTree.Insert(n.Value) 115 | }) 116 | } 117 | t.Size-- 118 | return true 119 | } 120 | 121 | if h.Right != nil { 122 | h.Value = h.Right.Value 123 | h.Left = h.Right.Left 124 | h.Right = h.Right.Right 125 | 126 | t.Size-- 127 | return true 128 | } 129 | 130 | if parent == nil { 131 | t.Head = nil 132 | t.Size-- 133 | return true 134 | } 135 | 136 | if parent.Left == n { 137 | parent.Left = nil 138 | } else { 139 | parent.Right = nil 140 | } 141 | t.Size-- 142 | return true 143 | } 144 | } 145 | return false 146 | } 147 | 148 | func IterOnTree(n *Node, f func(*Node)) bool { 149 | if n == nil { 150 | return true 151 | } 152 | if !IterOnTree(n.Left, f) { 153 | return false 154 | } 155 | 156 | f(n) 157 | 158 | return IterOnTree(n.Right, f) 159 | } 160 | -------------------------------------------------------------------------------- /data-structures/binary-tree/bst_test.go: -------------------------------------------------------------------------------- 1 | package bst 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestTree(t *testing.T) { 9 | n := NewNode(1) 10 | m := NewNode(2) 11 | 12 | // Test compare 13 | if n.Compare(m) != -1 || m.Compare(n) != 1 || n.Compare(n) != 0 { 14 | fmt.Println(n.Compare(m)) 15 | t.Error() 16 | } 17 | 18 | tree := NewTree(n) 19 | 20 | tree.Insert(4) 21 | tree.Insert(2) 22 | tree.Insert(5) 23 | tree.Insert(3) 24 | tree.Insert(6) 25 | 26 | if tree.Size != 6 { 27 | fmt.Println(tree.Size) 28 | t.Error() 29 | } 30 | 31 | five := tree.Search(5) 32 | 33 | if five.Value != 5 || 34 | five.Parent.Value != 4 || 35 | five.Right.Value != 6 || 36 | five.Left != nil { 37 | fmt.Println(*tree.Search(5)) 38 | t.Error() 39 | } 40 | 41 | tree.Delete(5) 42 | 43 | if tree.Size != 5 { 44 | t.Error() 45 | } 46 | 47 | four := *tree.Search(4) 48 | if four.Right.Value != 6 || 49 | four.Left.Value != 2 || 50 | four.Parent.Value != 1 { 51 | fmt.Println(*tree.Search(4)) 52 | t.Error() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /data-structures/graph/README.md: -------------------------------------------------------------------------------- 1 | # graph-go [![Build Status](https://travis-ci.org/arnauddri/graph-go.svg?branch=master)](https://travis-ci.org/arnauddri/graph-go) [![Coverage Status](https://img.shields.io/coveralls/arnauddri/graph-go.svg)](https://coveralls.io/r/arnauddri/graph-go?branch=master) 2 | 3 | An implementation of several graph algorithms in Go 4 | -------------------------------------------------------------------------------- /data-structures/graph/directed_graph.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | type DirGraph struct { 4 | graph 5 | } 6 | 7 | func NewDirected() *DirGraph { 8 | return &DirGraph{ 9 | graph{ 10 | edgesCount: 0, 11 | edges: make(map[VertexId]map[VertexId]int), 12 | isDirected: true, 13 | }, 14 | } 15 | } 16 | 17 | func (g *graph) GetPredecessors(vertex VertexId) VerticesIterable { 18 | iterator := func() <-chan VertexId { 19 | ch := make(chan VertexId) 20 | go func() { 21 | if connected, ok := g.edges[vertex]; ok { 22 | for VertexId, _ := range connected { 23 | if g.IsEdge(VertexId, vertex) { 24 | ch <- VertexId 25 | } 26 | } 27 | } 28 | close(ch) 29 | }() 30 | return ch 31 | } 32 | 33 | return VerticesIterable(&vertexIterableHelper{iterFunc: iterator}) 34 | } 35 | 36 | func (g *graph) GetSuccessors(vertex VertexId) VerticesIterable { 37 | iterator := func() <-chan VertexId { 38 | ch := make(chan VertexId) 39 | go func() { 40 | if connected, ok := g.edges[vertex]; ok { 41 | for VertexId, _ := range connected { 42 | if g.IsEdge(vertex, VertexId) { 43 | ch <- VertexId 44 | } 45 | } 46 | } 47 | close(ch) 48 | }() 49 | return ch 50 | } 51 | 52 | return VerticesIterable(&vertexIterableHelper{iterFunc: iterator}) 53 | } 54 | 55 | func (g *DirGraph) Reverse() *DirGraph { 56 | r := NewDirected() 57 | 58 | vertices := g.VerticesIter() 59 | for vertex := range vertices { 60 | r.AddVertex(vertex) 61 | } 62 | 63 | edges := g.EdgesIter() 64 | for edge := range edges { 65 | r.AddEdge(edge.To, edge.From, 1) 66 | } 67 | 68 | return r 69 | } 70 | -------------------------------------------------------------------------------- /data-structures/graph/graph.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | type VertexId uint 8 | 9 | type Vertices []VertexId 10 | 11 | type Edge struct { 12 | From VertexId 13 | To VertexId 14 | } 15 | 16 | type graph struct { 17 | edges map[VertexId]map[VertexId]int 18 | edgesCount int 19 | isDirected bool 20 | } 21 | 22 | type EdgesIterable interface { 23 | EdgesIter() <-chan Edge 24 | } 25 | 26 | type VerticesIterable interface { 27 | VerticesIter() <-chan VertexId 28 | } 29 | 30 | func (g *graph) EdgesIter() <-chan Edge { 31 | ch := make(chan Edge) 32 | go func() { 33 | for from, connectedVertices := range g.edges { 34 | for to, _ := range connectedVertices { 35 | if g.isDirected { 36 | ch <- Edge{from, to} 37 | } else { 38 | if from < to { 39 | ch <- Edge{from, to} 40 | } 41 | } 42 | } 43 | } 44 | close(ch) 45 | }() 46 | return ch 47 | } 48 | 49 | func (g *graph) VerticesIter() <-chan VertexId { 50 | ch := make(chan VertexId) 51 | go func() { 52 | for vertex, _ := range g.edges { 53 | ch <- vertex 54 | } 55 | close(ch) 56 | }() 57 | return ch 58 | } 59 | 60 | func (g *graph) CheckVertex(vertex VertexId) bool { 61 | _, exists := g.edges[vertex] 62 | 63 | return exists 64 | } 65 | 66 | func (g *graph) TouchVertex(vertex VertexId) { 67 | if _, ok := g.edges[vertex]; !ok { 68 | g.edges[vertex] = make(map[VertexId]int) 69 | } 70 | } 71 | 72 | func (g *graph) AddVertex(vertex VertexId) error { 73 | i, _ := g.edges[vertex] 74 | if i != nil { 75 | return errors.New("Vertex already exists") 76 | } 77 | 78 | g.edges[vertex] = make(map[VertexId]int) 79 | 80 | return nil 81 | } 82 | 83 | func (g *graph) RemoveVertex(vertex VertexId) error { 84 | if !g.IsVertex(vertex) { 85 | return errors.New("Unknown vertex") 86 | } 87 | 88 | delete(g.edges, vertex) 89 | 90 | for _, connectedVertices := range g.edges { 91 | delete(connectedVertices, vertex) 92 | } 93 | 94 | return nil 95 | } 96 | 97 | func (g *graph) IsVertex(vertex VertexId) (exist bool) { 98 | _, exist = g.edges[vertex] 99 | 100 | return 101 | } 102 | 103 | func (g *graph) VerticesCount() int { 104 | return len(g.edges) 105 | } 106 | 107 | func (g *graph) AddEdge(from, to VertexId, weight int) error { 108 | if from == to { 109 | return errors.New("Cannot add self loop") 110 | } 111 | 112 | if !g.CheckVertex(from) || !g.CheckVertex(to) { 113 | return errors.New("Vertices don't exist") 114 | } 115 | 116 | i, _ := g.edges[from][to] 117 | j, _ := g.edges[to][from] 118 | 119 | if i > 0 || j > 0 { 120 | return errors.New("Edge already defined") 121 | } 122 | 123 | g.TouchVertex(from) 124 | g.TouchVertex(to) 125 | 126 | g.edges[from][to] = weight 127 | 128 | if !g.isDirected { 129 | g.edges[to][from] = weight 130 | } 131 | 132 | g.edgesCount++ 133 | 134 | return nil 135 | } 136 | 137 | func (g *graph) RemoveEdge(from, to VertexId) error { 138 | i, _ := g.edges[from][to] 139 | j, _ := g.edges[to][from] 140 | 141 | if i == -1 || j == -1 { 142 | return errors.New("Edge doesn't exist") 143 | } 144 | 145 | g.edges[from][to] = -1 146 | 147 | if !g.isDirected { 148 | g.edges[to][from] = -1 149 | } 150 | 151 | g.edgesCount-- 152 | 153 | return nil 154 | } 155 | 156 | func (g *graph) IsEdge(from, to VertexId) bool { 157 | connected, ok := g.edges[from] 158 | 159 | if !ok { 160 | return false 161 | } 162 | 163 | weight := connected[to] 164 | return weight > 0 165 | } 166 | 167 | func (g *graph) Order() int { 168 | return len(g.edges) 169 | } 170 | 171 | func (g *graph) EdgesCount() int { 172 | return g.edgesCount 173 | } 174 | 175 | func (g *graph) GetEdge(from, to VertexId) int { 176 | return g.edges[from][to] 177 | } 178 | 179 | func (g *graph) GetNeighbours(vertex VertexId) VerticesIterable { 180 | iterator := func() <-chan VertexId { 181 | ch := make(chan VertexId) 182 | go func() { 183 | if connected, ok := g.edges[vertex]; ok { 184 | for VertexId, _ := range connected { 185 | ch <- VertexId 186 | } 187 | } 188 | close(ch) 189 | }() 190 | return ch 191 | } 192 | 193 | return VerticesIterable(&vertexIterableHelper{iterFunc: iterator}) 194 | } 195 | 196 | type vertexIterableHelper struct { 197 | iterFunc func() <-chan VertexId 198 | } 199 | 200 | func (helper *vertexIterableHelper) VerticesIter() <-chan VertexId { 201 | return helper.iterFunc() 202 | } 203 | -------------------------------------------------------------------------------- /data-structures/graph/graph_test.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestUndirectedGraph(t *testing.T) { 9 | g := NewUndirected() 10 | 11 | for i := 0; i < 10; i++ { 12 | v := VertexId(i) 13 | g.AddVertex(v) 14 | } 15 | 16 | if len(g.edges) != 10 { 17 | fmt.Println(g) 18 | t.Error() 19 | } 20 | 21 | for i := 0; i < 10; i++ { 22 | g.AddEdge(VertexId(i), VertexId(i%2), 1) 23 | } 24 | 25 | if g.IsEdge(0, 8) == false || g.IsEdge(0, 9) == true || g.CheckVertex(2) != true { 26 | fmt.Println(g) 27 | t.Error() 28 | } 29 | 30 | // AddEdge should fail for already existing Edge 31 | err := g.AddEdge(0, 2, 1) 32 | if err == nil { 33 | fmt.Println(g) 34 | t.Error() 35 | } 36 | 37 | // AddVertex should fail for already existing vertex 38 | err = g.AddVertex(0) 39 | if err == nil { 40 | fmt.Println(g) 41 | t.Error() 42 | } 43 | 44 | g.RemoveVertex(VertexId(9)) 45 | 46 | if g.IsVertex(VertexId(9)) { 47 | fmt.Println(g.edges[9] == nil) 48 | t.Error() 49 | } 50 | 51 | // RemoveVertex should fail for unknown vertex 52 | err = g.RemoveVertex(VertexId(9)) 53 | 54 | if err == nil { 55 | fmt.Println(g.edges[9] == nil) 56 | t.Error() 57 | } 58 | 59 | g.RemoveEdge(0, 8) 60 | 61 | if g.IsEdge(VertexId(0), VertexId(8)) == true || g.edgesCount != 7 { 62 | fmt.Println(g.IsEdge(VertexId(0), VertexId(8)), g.edgesCount) 63 | t.Error() 64 | } 65 | 66 | // RemoveEdge should fail for unknown egde 67 | err = g.RemoveEdge(0, 8) 68 | 69 | if err == nil { 70 | fmt.Println(g) 71 | t.Error() 72 | } 73 | 74 | c := g.EdgesIter() 75 | 76 | countEdge := 0 77 | for _ = range c { 78 | countEdge++ 79 | } 80 | 81 | if g.EdgesCount() != countEdge { 82 | t.Error() 83 | } 84 | 85 | d := g.VerticesIter() 86 | verticesCount := g.Order() 87 | countVertices := 0 88 | 89 | for _ = range d { 90 | countVertices++ 91 | } 92 | 93 | if countVertices != verticesCount { 94 | fmt.Println(countVertices, g.edges) 95 | t.Error() 96 | } 97 | 98 | g.TouchVertex(9) 99 | if _, ok := g.edges[9]; !ok { 100 | t.Error() 101 | } 102 | } 103 | 104 | func TestDirectedGraph(t *testing.T) { 105 | g := NewDirected() 106 | 107 | for i := 0; i < 10; i++ { 108 | g.AddVertex(VertexId(i)) 109 | } 110 | 111 | if len(g.edges) != 10 { 112 | fmt.Println(g) 113 | t.Error() 114 | } 115 | 116 | for i := 0; i < 10; i++ { 117 | g.AddEdge(VertexId(i), VertexId(i%2), 1) 118 | } 119 | 120 | r := g.Reverse() 121 | if !r.IsEdge(1, 7) || r.IsEdge(8, 0) { 122 | fmt.Println(r.edges) 123 | t.Error() 124 | } 125 | 126 | successors := r.GetSuccessors(1).VerticesIter() 127 | for successor := range successors { 128 | if successor != 3 && 129 | successor != 5 && 130 | successor != 7 && 131 | successor != 9 { 132 | t.Error() 133 | } 134 | } 135 | 136 | predecessors := g.GetPredecessors(1).VerticesIter() 137 | for predecessor := range predecessors { 138 | if predecessor != 3 && 139 | predecessor != 5 && 140 | predecessor != 7 && 141 | predecessor != 9 { 142 | t.Error() 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /data-structures/graph/undirected_graph.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | type UnGraph struct { 4 | graph 5 | } 6 | 7 | func NewUndirected() *UnGraph { 8 | return &UnGraph{ 9 | graph{ 10 | edgesCount: 0, 11 | edges: make(map[VertexId]map[VertexId]int), 12 | isDirected: false, 13 | }, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /data-structures/hash-tables/ht.go: -------------------------------------------------------------------------------- 1 | // Implementation of a Hash Table with Separate Chaining 2 | // with linked lists using Horner's hash function 3 | // http://en.wikipedia.org/wiki/Hash_table#Separate_chaining_with_linked_lists 4 | package ht 5 | 6 | import ( 7 | "errors" 8 | "github.com/arnauddri/algorithms/data-structures/linked-list" 9 | "math" 10 | ) 11 | 12 | type HashTable struct { 13 | Table map[int]*list.List 14 | Size int 15 | Capacity int 16 | } 17 | 18 | type item struct { 19 | key string 20 | value interface{} 21 | } 22 | 23 | func New(cap int) *HashTable { 24 | table := make(map[int]*list.List, cap) 25 | return &HashTable{Table: table, Size: 0, Capacity: cap} 26 | } 27 | 28 | func (ht *HashTable) Get(key string) (interface{}, error) { 29 | index := ht.position(key) 30 | item, err := ht.find(index, key) 31 | 32 | if item == nil { 33 | return "", errors.New("Not Found") 34 | } 35 | 36 | return item.value, err 37 | } 38 | 39 | func (ht *HashTable) Put(key, value string) { 40 | index := ht.position(key) 41 | 42 | if ht.Table[index] == nil { 43 | ht.Table[index] = list.NewList() 44 | } 45 | 46 | item := &item{key: key, value: value} 47 | 48 | a, err := ht.find(index, key) 49 | if err != nil { 50 | // The key doesn't exist in HashTable 51 | ht.Table[index].Append(item) 52 | ht.Size++ 53 | } else { 54 | // The key exists so we overwrite its value 55 | a.value = value 56 | } 57 | } 58 | 59 | func (ht *HashTable) Del(key string) error { 60 | index := ht.position(key) 61 | l := ht.Table[index] 62 | var val *item 63 | 64 | l.Each(func(node list.Node) { 65 | if node.Value.(*item).key == key { 66 | val = node.Value.(*item) 67 | } 68 | }) 69 | 70 | if val == nil { 71 | return nil 72 | } 73 | 74 | ht.Size-- 75 | return l.Remove(val) 76 | } 77 | 78 | func (ht *HashTable) ForEach(f func(*item)) { 79 | for k := range ht.Table { 80 | if ht.Table[k] != nil { 81 | ht.Table[k].Each(func(node list.Node) { 82 | f(node.Value.(*item)) 83 | }) 84 | } 85 | } 86 | } 87 | 88 | func (ht *HashTable) position(s string) int { 89 | return hashCode(s) % ht.Capacity 90 | } 91 | 92 | func (ht *HashTable) find(i int, key string) (*item, error) { 93 | l := ht.Table[i] 94 | var val *item 95 | 96 | l.Each(func(node list.Node) { 97 | if node.Value.(*item).key == key { 98 | val = node.Value.(*item) 99 | } 100 | }) 101 | 102 | if val == nil { 103 | return nil, errors.New("Not Found") 104 | } 105 | 106 | return val, nil 107 | } 108 | 109 | // Horner's Method to hash string of length L (O(L)) 110 | func hashCode(s string) int { 111 | hash := int32(0) 112 | for i := 0; i < len(s); i++ { 113 | hash = int32(hash<<5-hash) + int32(s[i]) 114 | hash &= hash 115 | } 116 | return int(math.Abs(float64(hash))) 117 | } 118 | -------------------------------------------------------------------------------- /data-structures/hash-tables/ht_test.go: -------------------------------------------------------------------------------- 1 | package ht 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestHt(t *testing.T) { 9 | ht := New(1000) 10 | ht.Put("foo", "bar") 11 | ht.Put("fiz", "buzz") 12 | ht.Put("bruce", "wayne") 13 | ht.Put("peter", "parker") 14 | ht.Put("clark", "kent") 15 | 16 | // Test simple get 17 | val, err := ht.Get("foo") 18 | if err != nil || val != "bar" || ht.Size != 5 { 19 | fmt.Println(val, err) 20 | t.Error() 21 | } 22 | 23 | ht.Put("peter", "bob") 24 | // Test "peter" has been updated 25 | val, err = ht.Get("peter") 26 | if err != nil && val == "bob" || ht.Size != 5 { 27 | fmt.Println(val, err) 28 | t.Error() 29 | } 30 | 31 | // Test delete 32 | ht.Del("peter") 33 | val, err = ht.Get("peter") 34 | if val != "" || err == nil || ht.Size != 4 { 35 | t.Error() 36 | } 37 | 38 | counter := 0 39 | f := func(a *item) { 40 | counter++ 41 | } 42 | 43 | ht.ForEach(f) 44 | 45 | if counter != 4 { 46 | t.Error() 47 | } 48 | } 49 | 50 | func TestHash(t *testing.T) { 51 | test := "Hello World!" 52 | 53 | if hashCode(test) != 969099747 { 54 | fmt.Println(hashCode(test)) 55 | t.Error() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /data-structures/heap/heap.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type Item interface { 8 | Less(than Item) bool 9 | } 10 | 11 | type Heap struct { 12 | sync.Mutex 13 | data []Item 14 | min bool 15 | } 16 | 17 | func New() *Heap { 18 | return &Heap{ 19 | data: make([]Item, 0), 20 | } 21 | } 22 | 23 | func NewMin() *Heap { 24 | return &Heap{ 25 | data: make([]Item, 0), 26 | min: true, 27 | } 28 | } 29 | 30 | func NewMax() *Heap { 31 | return &Heap{ 32 | data: make([]Item, 0), 33 | min: false, 34 | } 35 | } 36 | 37 | func (h *Heap) isEmpty() bool { 38 | return len(h.data) == 0 39 | } 40 | 41 | func (h *Heap) Len() int { 42 | return len(h.data) 43 | } 44 | 45 | func (h *Heap) Get(n int) Item { 46 | return h.data[n] 47 | } 48 | 49 | func (h *Heap) Insert(n Item) { 50 | h.Lock() 51 | defer h.Unlock() 52 | 53 | h.data = append(h.data, n) 54 | h.siftUp() 55 | 56 | return 57 | } 58 | 59 | func (h *Heap) Extract() (el Item) { 60 | h.Lock() 61 | defer h.Unlock() 62 | if h.Len() == 0 { 63 | return 64 | } 65 | 66 | el = h.data[0] 67 | last := h.data[h.Len()-1] 68 | if h.Len() == 1 { 69 | h.data = nil 70 | return 71 | } 72 | 73 | h.data = append([]Item{last}, h.data[1:h.Len()-1]...) 74 | h.siftDown() 75 | 76 | return 77 | } 78 | 79 | func (h *Heap) siftUp() { 80 | for i, parent := h.Len()-1, h.Len()-1; i > 0; i = parent { 81 | parent = i >> 1 82 | if h.Less(h.Get(i), h.Get(parent)) { 83 | h.data[parent], h.data[i] = h.data[i], h.data[parent] 84 | } else { 85 | break 86 | } 87 | } 88 | } 89 | 90 | func (h *Heap) siftDown() { 91 | for i, child := 0, 1; i < h.Len() && i<<1+1 < h.Len(); i = child { 92 | child = i<<1 + 1 93 | 94 | if child+1 <= h.Len()-1 && h.Less(h.Get(child+1), h.Get(child)) { 95 | child++ 96 | } 97 | 98 | if h.Less(h.Get(i), h.Get(child)) { 99 | break 100 | } 101 | 102 | h.data[i], h.data[child] = h.data[child], h.data[i] 103 | } 104 | } 105 | 106 | func (h *Heap) Less(a, b Item) bool { 107 | if h.min { 108 | return a.Less(b) 109 | } else { 110 | return b.Less(a) 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /data-structures/heap/heap_test.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestMinHeap(t *testing.T) { 9 | h := NewMin() 10 | 11 | h.Insert(Int(8)) 12 | h.Insert(Int(7)) 13 | h.Insert(Int(6)) 14 | h.Insert(Int(3)) 15 | h.Insert(Int(1)) 16 | h.Insert(Int(0)) 17 | h.Insert(Int(2)) 18 | h.Insert(Int(4)) 19 | h.Insert(Int(9)) 20 | h.Insert(Int(5)) 21 | 22 | sorted := make([]Int, 0) 23 | for h.Len() > 0 { 24 | sorted = append(sorted, h.Extract().(Int)) 25 | } 26 | 27 | for i := 0; i < len(sorted)-2; i++ { 28 | if sorted[i] > sorted[i+1] { 29 | fmt.Println(sorted) 30 | t.Error() 31 | } 32 | } 33 | } 34 | 35 | func TestMaxHeap(t *testing.T) { 36 | h := NewMax() 37 | 38 | h.Insert(Int(8)) 39 | h.Insert(Int(7)) 40 | h.Insert(Int(6)) 41 | h.Insert(Int(3)) 42 | h.Insert(Int(1)) 43 | h.Insert(Int(0)) 44 | h.Insert(Int(2)) 45 | h.Insert(Int(4)) 46 | h.Insert(Int(9)) 47 | h.Insert(Int(5)) 48 | 49 | sorted := make([]Int, 0) 50 | for h.Len() > 0 { 51 | sorted = append(sorted, h.Extract().(Int)) 52 | } 53 | 54 | for i := 0; i < len(sorted)-2; i++ { 55 | if sorted[i] < sorted[i+1] { 56 | fmt.Println(sorted) 57 | t.Error() 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /data-structures/heap/util.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | type Int int 4 | 5 | func (x Int) Less(than Item) bool { 6 | return x < than.(Int) 7 | } 8 | -------------------------------------------------------------------------------- /data-structures/linked-list/linked_list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | type List struct { 8 | Length int 9 | Head *Node 10 | Tail *Node 11 | } 12 | 13 | func NewList() *List { 14 | l := new(List) 15 | l.Length = 0 16 | return l 17 | } 18 | 19 | type Node struct { 20 | Value interface{} 21 | Prev *Node 22 | Next *Node 23 | } 24 | 25 | func NewNode(value interface{}) *Node { 26 | return &Node{Value: value} 27 | } 28 | 29 | func (l *List) Len() int { 30 | return l.Length 31 | } 32 | 33 | func (l *List) IsEmpty() bool { 34 | return l.Length == 0 35 | } 36 | 37 | func (l *List) Prepend(value interface{}) { 38 | node := NewNode(value) 39 | if l.Len() == 0 { 40 | l.Head = node 41 | l.Tail = l.Head 42 | } else { 43 | formerHead := l.Head 44 | formerHead.Prev = node 45 | 46 | node.Next = formerHead 47 | l.Head = node 48 | } 49 | 50 | l.Length++ 51 | } 52 | 53 | func (l *List) Append(value interface{}) { 54 | node := NewNode(value) 55 | 56 | if l.Len() == 0 { 57 | l.Head = node 58 | l.Tail = l.Head 59 | } else { 60 | formerTail := l.Tail 61 | formerTail.Next = node 62 | 63 | node.Prev = formerTail 64 | l.Tail = node 65 | } 66 | 67 | l.Length++ 68 | } 69 | 70 | func (l *List) Add(value interface{}, index int) error { 71 | if index > l.Len() { 72 | return errors.New("Index out of range") 73 | } 74 | 75 | node := NewNode(value) 76 | 77 | if l.Len() == 0 || index == 0 { 78 | l.Prepend(value) 79 | return nil 80 | } 81 | 82 | if l.Len()-1 == index { 83 | l.Append(value) 84 | return nil 85 | } 86 | 87 | nextNode, _ := l.Get(index) 88 | prevNode := nextNode.Prev 89 | 90 | prevNode.Next = node 91 | node.Prev = prevNode 92 | 93 | nextNode.Prev = node 94 | node.Next = nextNode 95 | 96 | l.Length++ 97 | 98 | return nil 99 | } 100 | 101 | func (l *List) Remove(value interface{}) error { 102 | if l.Len() == 0 { 103 | return errors.New("Empty list") 104 | } 105 | 106 | if l.Head.Value == value { 107 | l.Head = l.Head.Next 108 | l.Length-- 109 | return nil 110 | } 111 | 112 | found := 0 113 | for n := l.Head; n != nil; n = n.Next { 114 | 115 | if *n.Value.(*Node) == value && found == 0 { 116 | n.Next.Prev, n.Prev.Next = n.Prev, n.Next 117 | l.Length-- 118 | found++ 119 | } 120 | } 121 | 122 | if found == 0 { 123 | return errors.New("Node not found") 124 | } 125 | 126 | return nil 127 | } 128 | 129 | func (l *List) Get(index int) (*Node, error) { 130 | if index > l.Len() { 131 | return nil, errors.New("Index out of range") 132 | } 133 | 134 | node := l.Head 135 | for i := 0; i < index; i++ { 136 | node = node.Next 137 | } 138 | 139 | return node, nil 140 | } 141 | 142 | func (l *List) Find(node *Node) (int, error) { 143 | if l.Len() == 0 { 144 | return 0, errors.New("Empty list") 145 | } 146 | 147 | index := 0 148 | found := -1 149 | l.Map(func(n *Node) { 150 | index++ 151 | if n.Value == node.Value && found == -1 { 152 | found = index 153 | } 154 | }) 155 | 156 | if found == -1 { 157 | return 0, errors.New("Item not found") 158 | } 159 | 160 | return found, nil 161 | } 162 | 163 | func (l *List) Clear() { 164 | l.Length = 0 165 | l.Head = nil 166 | l.Tail = nil 167 | } 168 | 169 | func (l *List) Concat(k *List) { 170 | l.Tail.Next, k.Head.Prev = k.Head, l.Tail 171 | l.Tail = k.Tail 172 | l.Length += k.Length 173 | } 174 | 175 | func (list *List) Map(f func(node *Node)) { 176 | for node := list.Head; node != nil; node = node.Next { 177 | n := node.Value.(*Node) 178 | f(n) 179 | } 180 | } 181 | 182 | func (list *List) Each(f func(node Node)) { 183 | for node := list.Head; node != nil; node = node.Next { 184 | f(*node) 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /data-structures/linked-list/linked_list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestLinkedList(t *testing.T) { 9 | // Test Prepend/Get 10 | l := NewList() 11 | 12 | l.Prepend(NewNode(1)) 13 | l.Prepend(NewNode(2)) 14 | l.Prepend(NewNode(3)) 15 | 16 | zero := *slice(l.Get(0))[0].(*Node).Value.(*Node) 17 | one := *slice(l.Get(1))[0].(*Node).Value.(*Node) 18 | two := *slice(l.Get(2))[0].(*Node).Value.(*Node) 19 | 20 | if zero != *NewNode(3) || 21 | one != *NewNode(2) || 22 | two != *NewNode(1) { 23 | 24 | fmt.Println(*one.Value.(*Node), *NewNode(2)) 25 | fmt.Println(zero.Value) 26 | fmt.Println(one.Value) 27 | fmt.Println(two.Value) 28 | t.Error() 29 | } 30 | 31 | // Test Append 32 | k := NewList() 33 | 34 | k.Append(NewNode(1)) 35 | k.Append(NewNode(2)) 36 | k.Append(NewNode(3)) 37 | 38 | zero = *slice(k.Get(0))[0].(*Node).Value.(*Node) 39 | one = *slice(k.Get(1))[0].(*Node).Value.(*Node) 40 | two = *slice(k.Get(2))[0].(*Node).Value.(*Node) 41 | 42 | if zero != *NewNode(1) || 43 | one != *NewNode(2) || 44 | two != *NewNode(3) { 45 | 46 | fmt.Println(zero.Value) 47 | fmt.Println(one.Value) 48 | fmt.Println(two.Value) 49 | t.Error() 50 | } 51 | 52 | // Test Add 53 | k.Add(NewNode(8), 1) 54 | 55 | zero = *slice(k.Get(0))[0].(*Node).Value.(*Node) 56 | one = *slice(k.Get(1))[0].(*Node).Value.(*Node) 57 | two = *slice(k.Get(2))[0].(*Node).Value.(*Node) 58 | 59 | if zero != *NewNode(1) || 60 | one != *NewNode(8) || 61 | two != *NewNode(2) { 62 | 63 | fmt.Println(zero.Value) 64 | fmt.Println(one.Value) 65 | fmt.Println(two.Value) 66 | 67 | t.Error() 68 | } 69 | 70 | // Test Concat 71 | l.Concat(k) 72 | if l.Len() != 7 { 73 | t.Error() 74 | } 75 | 76 | // Test Each 77 | counter := 0 78 | f := func(node *Node) { 79 | counter += node.Value.(int) 80 | } 81 | 82 | l.Map(f) 83 | if counter != 20 { 84 | t.Error() 85 | } 86 | 87 | // Test Find 88 | index, _ := l.Find(NewNode(1)) 89 | if index != 3 { 90 | fmt.Println(index) 91 | t.Error() 92 | } 93 | 94 | // Test Remove 95 | l.Remove(*NewNode(8)) 96 | 97 | counter = 0 98 | l.Map(func(n *Node) { 99 | counter += n.Value.(int) 100 | }) 101 | 102 | if counter != 12 { 103 | t.Error() 104 | } 105 | 106 | // Test Clear 107 | l.Clear() 108 | if l.Len() != 0 { 109 | t.Error() 110 | } 111 | 112 | } 113 | 114 | func slice(args ...interface{}) []interface{} { 115 | return args 116 | } 117 | -------------------------------------------------------------------------------- /data-structures/matrix/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arnauddri/algorithms/736f5ebe59cfd72b778704fe9ba5e0ba25c775fe/data-structures/matrix/README.md -------------------------------------------------------------------------------- /data-structures/matrix/matrix.go: -------------------------------------------------------------------------------- 1 | // Package Matrix provides some methods to use with Matrix 2 | package matrix 3 | 4 | import ( 5 | "errors" 6 | ) 7 | 8 | //type Matrix interface { 9 | //CountRows() int 10 | //CountCols() int 11 | //GetElm(i int, j int) float64 12 | //trace() float64 13 | 14 | //SetElm(i int, j int, v float64) 15 | //add(*Matrix) error 16 | //substract(*Matrix) error 17 | //scale(float64) 18 | 19 | //copy() []float64 20 | //diagonalCopy() []float64 21 | //} 22 | 23 | type Matrix struct { 24 | // Number of rows 25 | rows int 26 | // Number of columns 27 | cols int 28 | // Matrix stored as a flat array: Aij = Elements[i*step + j] 29 | Elements []float64 30 | // Offset between rows 31 | step int 32 | } 33 | 34 | func MakeMatrix(Elements []float64, rows, cols int) *Matrix { 35 | A := new(Matrix) 36 | A.rows = rows 37 | A.cols = cols 38 | A.step = cols 39 | A.Elements = Elements 40 | 41 | return A 42 | } 43 | func (A *Matrix) CountRows() int { 44 | return A.rows 45 | } 46 | 47 | func (A *Matrix) CountCols() int { 48 | return A.cols 49 | } 50 | 51 | func (A *Matrix) GetElm(i int, j int) float64 { 52 | return A.Elements[i*A.step+j] 53 | } 54 | 55 | func (A *Matrix) SetElm(i int, j int, v float64) { 56 | A.Elements[i*A.step+j] = v 57 | } 58 | 59 | func (A *Matrix) diagonalCopy() []float64 { 60 | diag := make([]float64, A.cols) 61 | for i := 0; i < len(diag); i++ { 62 | diag[i] = A.GetElm(i, i) 63 | } 64 | return diag 65 | } 66 | 67 | func (A *Matrix) copy() *Matrix { 68 | B := new(Matrix) 69 | B.rows = A.rows 70 | B.cols = A.cols 71 | B.step = A.step 72 | 73 | B.Elements = make([]float64, A.cols*A.rows) 74 | 75 | for i := 0; i < A.rows; i++ { 76 | for j := 0; j < A.cols; j++ { 77 | B.Elements[i*A.step+j] = A.GetElm(i, j) 78 | } 79 | } 80 | return B 81 | } 82 | 83 | func (A *Matrix) trace() float64 { 84 | var tr float64 = 0 85 | for i := 0; i < A.cols; i++ { 86 | tr += A.GetElm(i, i) 87 | } 88 | return tr 89 | } 90 | 91 | func (A *Matrix) add(B *Matrix) error { 92 | if A.cols != B.cols && A.rows != B.rows { 93 | return errors.New("Wrong input sizes") 94 | } 95 | for i := 0; i < A.rows; i++ { 96 | for j := 0; j < A.cols; j++ { 97 | A.SetElm(i, j, A.GetElm(i, j)+B.GetElm(i, j)) 98 | } 99 | } 100 | 101 | return nil 102 | } 103 | 104 | func (A *Matrix) substract(B *Matrix) error { 105 | if A.cols != B.cols && A.rows != B.rows { 106 | return errors.New("Wrong input sizes") 107 | } 108 | for i := 0; i < A.rows; i++ { 109 | for j := 0; j < A.cols; j++ { 110 | A.SetElm(i, j, A.GetElm(i, j)-B.GetElm(i, j)) 111 | } 112 | } 113 | 114 | return nil 115 | } 116 | 117 | func (A *Matrix) scale(a float64) { 118 | for i := 0; i < A.rows; i++ { 119 | for j := 0; j < A.cols; j++ { 120 | A.SetElm(i, j, a*A.GetElm(i, j)) 121 | } 122 | } 123 | } 124 | 125 | func Add(A *Matrix, B *Matrix) *Matrix { 126 | result := MakeMatrix(make([]float64, A.cols*A.rows), A.cols, A.rows) 127 | 128 | for i := 0; i < A.rows; i++ { 129 | for j := 0; j < A.cols; j++ { 130 | result.SetElm(i, j, A.GetElm(i, j)+B.GetElm(i, j)) 131 | } 132 | } 133 | 134 | return result 135 | } 136 | 137 | func Substract(A *Matrix, B *Matrix) *Matrix { 138 | result := MakeMatrix(make([]float64, A.cols*A.rows), A.cols, A.rows) 139 | 140 | for i := 0; i < A.rows; i++ { 141 | for j := 0; j < A.cols; j++ { 142 | result.SetElm(i, j, A.GetElm(i, j)-B.GetElm(i, j)) 143 | } 144 | } 145 | 146 | return result 147 | } 148 | 149 | func Multiply(A *Matrix, B *Matrix) *Matrix { 150 | result := MakeMatrix(make([]float64, A.cols*A.rows), A.cols, A.rows) 151 | 152 | for i := 0; i < A.rows; i++ { 153 | for j := 0; j < A.cols; j++ { 154 | sum := float64(0) 155 | for k := 0; k < A.cols; k++ { 156 | sum += A.GetElm(i, k) * B.GetElm(k, j) 157 | } 158 | result.SetElm(i, j, sum) 159 | } 160 | } 161 | 162 | return result 163 | } 164 | -------------------------------------------------------------------------------- /data-structures/matrix/matrix_test.go: -------------------------------------------------------------------------------- 1 | package matrix 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMakeMatrix(t *testing.T) { 8 | a := []float64{1, 2, 3, 4, 5, 6} 9 | A := MakeMatrix(a, 3, 2) 10 | 11 | if A.cols != 2 || 12 | A.rows != 3 || 13 | !FloatArrayEquals(A.Elements, a) { 14 | t.Error() 15 | } 16 | } 17 | 18 | func TestCount(t *testing.T) { 19 | a := []float64{1, 2, 3, 4, 5, 6} 20 | A := MakeMatrix(a, 3, 2) 21 | 22 | if A.CountRows() != 3 { 23 | t.Error() 24 | } 25 | if A.CountCols() != 2 { 26 | t.Error() 27 | } 28 | } 29 | 30 | func TestGetElm(t *testing.T) { 31 | a := []float64{1, 2, 3, 4, 5, 6} 32 | A := MakeMatrix(a, 3, 2) 33 | 34 | for i := 0; i < 3; i++ { 35 | if A.GetElm(0, i) != float64(i+1) { 36 | t.Error() 37 | } 38 | } 39 | } 40 | 41 | func TestSetElm(t *testing.T) { 42 | a := []float64{1, 2, 3, 4, 5, 6} 43 | A := MakeMatrix(a, 3, 2) 44 | 45 | A.SetElm(0, 0, 10) 46 | 47 | if A.GetElm(0, 0) != 10 { 48 | t.Error() 49 | } 50 | } 51 | 52 | func TestTrace(t *testing.T) { 53 | a := []float64{1, 2, 3, 4} 54 | A := MakeMatrix(a, 2, 2) 55 | 56 | if A.trace() != 5 { 57 | t.Error() 58 | } 59 | } 60 | 61 | func TestAdd(t *testing.T) { 62 | a := []float64{1, 1, 1, 1} 63 | A := MakeMatrix(a, 2, 2) 64 | B := MakeMatrix([]float64{2, 2, 2, 2}, 2, 2) 65 | 66 | A.add(A) 67 | if !FloatArrayEquals(A.Elements, B.Elements) { 68 | t.Error() 69 | } 70 | } 71 | 72 | func TestSubstract(t *testing.T) { 73 | a := []float64{1, 1, 1, 1} 74 | A := MakeMatrix(a, 2, 2) 75 | B := MakeMatrix([]float64{2, 2, 2, 2}, 2, 2) 76 | 77 | B.substract(A) 78 | if !FloatArrayEquals(A.Elements, B.Elements) { 79 | t.Error() 80 | } 81 | } 82 | 83 | func TestScale(t *testing.T) { 84 | a := []float64{1, 1, 1, 1} 85 | A := MakeMatrix(a, 2, 2) 86 | B := MakeMatrix([]float64{2, 2, 2, 2}, 2, 2) 87 | 88 | A.scale(2) 89 | 90 | if !FloatArrayEquals(A.Elements, B.Elements) { 91 | t.Error() 92 | } 93 | } 94 | 95 | func FloatArrayEquals(a []float64, b []float64) bool { 96 | if len(a) != len(b) { 97 | return false 98 | } 99 | for i, v := range a { 100 | if v != b[i] { 101 | return false 102 | } 103 | } 104 | return true 105 | } 106 | -------------------------------------------------------------------------------- /data-structures/priority-queue/priority_queue.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "github.com/arnauddri/algorithms/data-structures/heap" 5 | "github.com/arnauddri/algorithms/data-structures/queue" 6 | ) 7 | 8 | type Item struct { 9 | Value interface{} 10 | Priority int 11 | } 12 | 13 | func NewItem(value interface{}, priority int) (i *Item) { 14 | return &Item{ 15 | Value: value, 16 | Priority: priority, 17 | } 18 | } 19 | 20 | func (x Item) Less(than heap.Item) bool { 21 | return x.Priority < than.(Item).Priority 22 | } 23 | 24 | type PQ struct { 25 | data heap.Heap 26 | } 27 | 28 | func NewMax() (q *PQ) { 29 | return &PQ{ 30 | data: *heap.NewMax(), 31 | } 32 | } 33 | 34 | func NewMin() (q *PQ) { 35 | return &PQ{ 36 | data: *heap.NewMin(), 37 | } 38 | } 39 | 40 | func (pq *PQ) Len() int { 41 | return pq.data.Len() 42 | } 43 | 44 | func (pq *PQ) Insert(el Item) { 45 | pq.data.Insert(heap.Item(el)) 46 | } 47 | 48 | func (pq *PQ) Extract() (el Item) { 49 | return pq.data.Extract().(Item) 50 | } 51 | 52 | func (pq *PQ) ChangePriority(val interface{}, priority int) { 53 | var storage = queue.New() 54 | 55 | popped := pq.Extract() 56 | 57 | for val != popped.Value { 58 | if pq.Len() == 0 { 59 | panic("Item not found") 60 | } 61 | 62 | storage.Push(popped) 63 | popped = pq.Extract() 64 | } 65 | 66 | popped.Priority = priority 67 | pq.data.Insert(popped) 68 | 69 | for storage.Len() > 0 { 70 | pq.data.Insert(storage.Shift().(heap.Item)) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /data-structures/priority-queue/priority_queue_test.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestMaxPriorityQueue(t *testing.T) { 9 | h := NewMax() 10 | 11 | h.Insert(*NewItem(8, 10)) 12 | h.Insert(*NewItem(7, 11)) 13 | h.Insert(*NewItem(6, 12)) 14 | h.Insert(*NewItem(3, 13)) 15 | h.Insert(*NewItem(1, 14)) 16 | h.Insert(*NewItem(0, 15)) 17 | h.Insert(*NewItem(2, 16)) 18 | h.Insert(*NewItem(4, 17)) 19 | h.Insert(*NewItem(9, 18)) 20 | h.Insert(*NewItem(5, 19)) 21 | 22 | sorted := make([]Item, 0) 23 | for h.Len() > 0 { 24 | sorted = append(sorted, h.Extract()) 25 | } 26 | 27 | for i := 0; i < len(sorted)-2; i++ { 28 | if sorted[i].Priority < sorted[i+1].Priority { 29 | fmt.Println(sorted) 30 | t.Error() 31 | } 32 | } 33 | } 34 | 35 | func TestMinPriorityQueue(t *testing.T) { 36 | h := NewMin() 37 | 38 | h.Insert(*NewItem(8, 10)) 39 | h.Insert(*NewItem(7, 11)) 40 | h.Insert(*NewItem(6, 12)) 41 | h.Insert(*NewItem(3, 13)) 42 | h.Insert(*NewItem(1, 14)) 43 | h.Insert(*NewItem(0, 15)) 44 | h.Insert(*NewItem(2, 16)) 45 | h.Insert(*NewItem(4, 17)) 46 | h.Insert(*NewItem(9, 18)) 47 | h.Insert(*NewItem(5, 19)) 48 | 49 | sorted := make([]Item, 0) 50 | for h.Len() > 0 { 51 | sorted = append(sorted, h.Extract()) 52 | } 53 | 54 | for i := 0; i < len(sorted)-2; i++ { 55 | if sorted[i].Priority > sorted[i+1].Priority { 56 | fmt.Println(sorted) 57 | t.Error() 58 | } 59 | } 60 | } 61 | 62 | func TestChangePriority(t *testing.T) { 63 | h := NewMax() 64 | 65 | h.Insert(*NewItem(8, 10)) 66 | h.Insert(*NewItem(7, 11)) 67 | h.Insert(*NewItem(6, 12)) 68 | h.Insert(*NewItem(3, 13)) 69 | h.Insert(*NewItem(1, 14)) 70 | h.Insert(*NewItem(0, 15)) 71 | h.Insert(*NewItem(2, 16)) 72 | h.Insert(*NewItem(4, 17)) 73 | h.Insert(*NewItem(9, 18)) 74 | h.Insert(*NewItem(5, 19)) 75 | 76 | h.ChangePriority(8, 66) 77 | popped := h.Extract() 78 | 79 | if popped.Value != 8 { 80 | t.Error() 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /data-structures/queue/queue.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | import "sync" 4 | 5 | type Queue struct { 6 | queue []interface{} 7 | len int 8 | lock *sync.Mutex 9 | } 10 | 11 | func New() *Queue { 12 | queue := &Queue{} 13 | queue.queue = make([]interface{}, 0) 14 | queue.len = 0 15 | queue.lock = new(sync.Mutex) 16 | 17 | return queue 18 | } 19 | 20 | func (q *Queue) Len() int { 21 | //q.lock.Lock() 22 | //defer q.lock.Unlock() 23 | 24 | return q.len 25 | } 26 | 27 | func (q *Queue) isEmpty() bool { 28 | q.lock.Lock() 29 | defer q.lock.Unlock() 30 | 31 | return q.len == 0 32 | } 33 | 34 | func (q *Queue) Shift() (el interface{}) { 35 | //q.lock.Lock() 36 | //defer q.lock.Unlock() 37 | 38 | el, q.queue = q.queue[0], q.queue[1:] 39 | q.len-- 40 | return 41 | } 42 | 43 | func (q *Queue) Push(el interface{}) { 44 | //q.lock.Lock() 45 | //defer q.lock.Unlock() 46 | 47 | q.queue = append(q.queue, el) 48 | q.len++ 49 | 50 | return 51 | } 52 | 53 | func (q *Queue) Peek() interface{} { 54 | q.lock.Lock() 55 | defer q.lock.Unlock() 56 | 57 | return q.queue[0] 58 | } 59 | -------------------------------------------------------------------------------- /data-structures/queue/queue_test.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | q := New() 10 | 11 | if !q.isEmpty() || 12 | q.len != 0 || 13 | q.Len() != 0 { 14 | t.Error() 15 | } 16 | 17 | q.Push(1) 18 | q.Push(2) 19 | q.Push(3) 20 | 21 | if q.queue[0] != 1 || 22 | q.queue[1] != 2 || 23 | q.queue[2] != 3 { 24 | fmt.Println(q.queue) 25 | t.Error() 26 | } 27 | 28 | if q.Len() != 3 { 29 | t.Error() 30 | } 31 | 32 | a := q.Shift() 33 | 34 | if a != 1 || q.Len() != 2 { 35 | t.Error() 36 | } 37 | 38 | b := q.Peek() 39 | 40 | if b != 2 { 41 | t.Error() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /data-structures/stack/stack.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import "sync" 4 | 5 | type Stack struct { 6 | stack []interface{} 7 | len int 8 | lock sync.Mutex 9 | } 10 | 11 | func New() *Stack { 12 | s := &Stack{} 13 | s.stack = make([]interface{}, 0) 14 | s.len = 0 15 | 16 | return s 17 | } 18 | 19 | func (s *Stack) Len() int { 20 | s.lock.Lock() 21 | defer s.lock.Unlock() 22 | 23 | return s.len 24 | } 25 | 26 | func (s *Stack) isEmpty() bool { 27 | s.lock.Lock() 28 | defer s.lock.Unlock() 29 | 30 | return s.len == 0 31 | } 32 | 33 | func (s *Stack) Pop() (el interface{}) { 34 | s.lock.Lock() 35 | defer s.lock.Unlock() 36 | 37 | el, s.stack = s.stack[0], s.stack[1:] 38 | s.len-- 39 | return 40 | } 41 | 42 | func (s *Stack) Push(el interface{}) { 43 | s.lock.Lock() 44 | defer s.lock.Unlock() 45 | 46 | prepend := make([]interface{}, 1) 47 | prepend[0] = el 48 | s.stack = append(prepend, s.stack...) 49 | s.len++ 50 | } 51 | 52 | func (s *Stack) Peek() interface{} { 53 | s.lock.Lock() 54 | defer s.lock.Unlock() 55 | 56 | return s.stack[0] 57 | } 58 | -------------------------------------------------------------------------------- /data-structures/stack/stack_test.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNew(t *testing.T) { 9 | s := New() 10 | 11 | if !s.isEmpty() || 12 | s.len != 0 || 13 | s.Len() != 0 { 14 | t.Error() 15 | } 16 | 17 | s.Push(1) 18 | s.Push(2) 19 | s.Push(3) 20 | 21 | if s.stack[0] != 3 || 22 | s.stack[1] != 2 || 23 | s.stack[2] != 1 { 24 | fmt.Println(s.stack) 25 | t.Error() 26 | } 27 | 28 | if s.Len() != 3 { 29 | t.Error() 30 | } 31 | 32 | a := s.Pop() 33 | 34 | if a != 3 || s.Len() != 2 { 35 | t.Error() 36 | } 37 | 38 | b := s.Peek() 39 | 40 | if b != 2 { 41 | t.Error() 42 | } 43 | } 44 | --------------------------------------------------------------------------------