├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── algorithms ├── 01knapsack_dp │ └── 01knapsack_dp.go ├── a_star │ ├── 8_puzzle │ │ ├── 8_puzzle.go │ │ ├── README.md │ │ ├── a_star.go │ │ └── priority_queue.go │ ├── directed_graph │ │ ├── a_star.go │ │ ├── graph.go │ │ └── priority_queue.go │ └── undirected_graph │ │ ├── a_star.go │ │ ├── graph.go │ │ └── priority_queue.go ├── activity_selection_gp │ ├── activity_selection_gp.go │ └── quick_sort.go ├── assembly_line_scheduling │ └── assembly_scheduling.go ├── binary_reflected_gray_codes │ └── brgc.go ├── closest_pair_problem │ ├── cpp_brute_force │ │ ├── cpp_brute_force.go │ │ └── sample.txt │ └── cpp_divide_conquer │ │ ├── cpp_divide_conquer.go │ │ ├── sample.txt │ │ └── sort.go ├── combinations │ ├── with_r │ │ └── combinations.go │ └── without_r │ │ └── combinations.go ├── convex_hull │ ├── ch_brute_force │ │ ├── ch_brute_force.go │ │ ├── helpers.go │ │ └── sample.txt │ └── ch_divide_conquer │ │ ├── ch_divide_conquer.go │ │ ├── helpers.go │ │ ├── sample.txt │ │ └── sort.go ├── expression_conversions │ ├── infix_postfix │ │ └── infix_postfix.go │ ├── infix_prefix │ │ └── infix_prefix.go │ ├── postfix_infix │ │ └── postfix_infix.go │ ├── postfix_prefix │ │ └── postfix_prefix.go │ ├── prefix_infix │ │ └── prefix_infix.go │ └── prefix_postfix │ │ └── prefix_postfix.go ├── gcd │ ├── README.md │ └── gcd.go ├── graphs │ ├── articulation_point_detection │ │ ├── articulation_point.go │ │ ├── graph.go │ │ └── traversal.go │ ├── bellman_ford │ │ ├── bellman_ford.go │ │ └── graph.go │ ├── bridge_detection │ │ ├── bridge_detection.go │ │ ├── graph.go │ │ └── traversal.go │ ├── dijkstra │ │ ├── dijkstra.go │ │ ├── graph.go │ │ └── priority_queue.go │ ├── floyd_warshall │ │ ├── floyd_warshall.go │ │ └── graph.go │ ├── kruskals │ │ ├── graph.go │ │ ├── heap.go │ │ └── kruskals.go │ ├── prims │ │ ├── graph.go │ │ ├── heap.go │ │ └── prims.go │ ├── topological_sort │ │ ├── graph.go │ │ └── topological_sort.go │ ├── traversals │ │ ├── cd_directed_graph_traversals │ │ │ ├── cycle_detection.go │ │ │ ├── graph.go │ │ │ └── traversal.go │ │ └── cd_undirected_graph_traversals │ │ │ ├── cycle_detection.go │ │ │ ├── graph.go │ │ │ └── traversals.go │ ├── tsp │ │ ├── tsp_dynamic │ │ │ ├── directed_graph │ │ │ │ ├── graph.go │ │ │ │ ├── helpers.go │ │ │ │ └── tsp_dynamic.go │ │ │ └── undirected_graph │ │ │ │ ├── graph.go │ │ │ │ ├── helpers.go │ │ │ │ └── tsp_dynamic.go │ │ └── tsp_naive │ │ │ ├── directed_graph │ │ │ ├── graph.go │ │ │ ├── lo_permutations.go │ │ │ └── tsp_naive.go │ │ │ └── undirected_graph │ │ │ ├── graph.go │ │ │ ├── lo_permutations.go │ │ │ └── tsp_naive.go │ └── union_find │ │ ├── graph.go │ │ └── union_find.go ├── huffman_codes │ ├── heap.go │ └── huffman_codes.go ├── job_scheduling_gp │ ├── job_scheduling_gp.go │ └── quick_sort.go ├── lcm │ └── lcm.go ├── lcs │ └── iterative_dp │ │ └── lcs_iterative_dp.go ├── lo_permutations │ └── lo_permutations.go ├── longest_palindrome_substring │ ├── brute_force │ │ └── brute_force.go │ └── manchers │ │ └── manchers.go ├── making_change_dp │ └── making_change_dp.go ├── order_statistics │ ├── naive_approach │ │ ├── heap.go │ │ └── naive_approach.go │ ├── quick_select │ │ └── quick_select.go │ └── worst_case_linear_time │ │ └── wclt.go ├── power_set │ └── power_set.go ├── searching │ ├── binary_search │ │ └── binary_search.go │ ├── interpolation_search │ │ └── interpolation_search.go │ ├── linear_search │ │ └── linear_search.go │ └── ternary_search │ │ └── ternary_search.go ├── sieve_of_eratosthenes │ └── sieve_of_eratosthenes.go ├── sorting │ ├── binary_insertion_sort │ │ └── binary_insertion_sort.go │ ├── bubble_sort │ │ └── bubble_sort.go │ ├── bucket_sort │ │ └── bucket_sort.go │ ├── counting_sort │ │ └── counting_sort.go │ ├── heap_sort │ │ └── heap_sort.go │ ├── insertion_sort │ │ └── insertion_sort.go │ ├── merge_sort │ │ └── merge_sort.go │ ├── quick_sort │ │ └── quick_sort.go │ ├── radix_sort │ │ └── radix_sort.go │ ├── selection_sort │ │ └── selection_sort.go │ └── shell_sort │ │ └── shell_sort.go ├── string_matching │ ├── boyer_moore │ │ └── boyer_moore.go │ ├── horspool │ │ └── horspool.go │ ├── knuth_morris_pratt │ │ └── knuth_morris_pratt.go │ ├── naive_pattern_matching │ │ └── naive_pattern_matching.go │ └── rabin_karp │ │ └── rabin_karp.go └── toh │ └── toh.go ├── graphs ├── directed_unweighted │ ├── graph.go │ └── traversal.go ├── directed_weighted │ ├── graph.go │ └── traversal.go ├── undirected_unweighted │ ├── graph.go │ └── traversal.go └── undirected_weighted │ ├── graph.go │ └── traversal.go ├── heaps ├── max_binary_heap │ └── max_binary_heap.go └── min_binary_heap │ └── min_binary_heap.go ├── linked_lists ├── circular_doubly_ll │ └── circular_doubly_ll.go ├── circular_ll │ └── circular_ll.go ├── doubly_ll │ └── doubly_ll.go ├── pres_rev_single_ll │ ├── RGIF2.gif │ └── pres_single_ll.go └── single_ll │ └── single_ll.go ├── notes ├── graphs │ └── README.md ├── heaps │ └── README.md ├── linked_lists │ └── README.md ├── queues │ └── README.md ├── stack │ └── README.md └── trees │ └── README.md ├── queues ├── cdqueue │ └── cdqueue.go ├── cqueue │ └── cqueue.go ├── dqueue │ └── dqueue.go ├── priority_queue │ └── priority_queue.go └── simple_queue │ └── simple_queue.go ├── resources.md ├── stack └── stack.go └── trees ├── avl_tree_using_ll ├── avl_tree_using_ll.go └── traversal.go ├── bst_using_arr ├── bst_using_arr.go └── traversal.go ├── bst_using_ll ├── bst_using_ll.go └── traversal.go ├── simple_bt_using_arr ├── simple_bt_using_arr.go └── traversal.go └── simple_bt_using_ll ├── simple_bt_using_ll.go └── traversal.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at deveshpatel7643@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Devesh Patel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /algorithms/01knapsack_dp/01knapsack_dp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | func knapsack() { 9 | op := make([][]int, size+1) 10 | for i := range op { 11 | op[i] = make([]int, capacity+1) 12 | for j := range op[i] { 13 | op[i][0] = 0 14 | op[0][j] = 0 15 | } 16 | } 17 | 18 | for i := range op { 19 | for j := range op[i] { 20 | if i == 0 || j == 0 { 21 | continue 22 | } else if j < weights[i] { 23 | op[i][j] = op[i-1][j] 24 | } else if j >= weights[i] { 25 | op[i][j] = int(math.Max(float64(op[i-1][j]), float64(op[i-1][j-weights[i]]+values[i]))) 26 | } 27 | } 28 | } 29 | 30 | // finding the right weights and values from the matrix generated 31 | i := size 32 | j := capacity 33 | var finalWeights []int 34 | var finalValues []int 35 | 36 | for i != 0 { 37 | if op[i][j] == op[i-1][j] { 38 | i-- 39 | } else { 40 | finalWeights = append(finalWeights, weights[i]) 41 | finalValues = append(finalValues, values[i]) 42 | j -= weights[i] 43 | } 44 | } 45 | 46 | // printing the answer 47 | fmt.Println("Matrix formed:") 48 | for i := range op { 49 | fmt.Println(op[i]) 50 | } 51 | fmt.Println("\nWeights taken:") 52 | fmt.Println(finalWeights) 53 | fmt.Println("Values taken:") 54 | fmt.Println(finalValues) 55 | } 56 | 57 | var weights, values []int 58 | var capacity, size int 59 | 60 | func init() { 61 | weights = append(weights, 0) 62 | values = append(values, 0) 63 | } 64 | 65 | func main() { 66 | var temp int 67 | fmt.Println("\n-- 0-1 Knapsack Problem using Dynamic Programming --") 68 | fmt.Print("\nEnter the number of objects: ") 69 | fmt.Scanf("%d\n", &size) 70 | fmt.Println("Start entering weight and value of each object:") 71 | for i := 0; i < size; i++ { 72 | fmt.Print("\nWeight: ") 73 | fmt.Scanf("%d\n", &temp) 74 | weights = append(weights, temp) 75 | fmt.Print("Value: ") 76 | fmt.Scanf("%d\n", &temp) 77 | values = append(values, temp) 78 | } 79 | fmt.Print("\nEnter the capacity of knapsack: ") 80 | fmt.Scanf("%d\n", &capacity) 81 | knapsack() 82 | } 83 | 84 | // FORMULA 85 | // stp1: make v[i][0] and v[0][j] = 0 86 | // stp2: if j < weights[i] then v[i][j] = v[i-1][j] 87 | // stp3: if j >= weights[i] then v[i][j] = max(v[i-1][j], v[i-1][j-weights[i]]+v[i]) 88 | -------------------------------------------------------------------------------- /algorithms/a_star/8_puzzle/8_puzzle.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type matrix [][]int 6 | type sliceOfMatrix []matrix 7 | 8 | // input scrambled puzzle 9 | var inputPuzzle matrix 10 | 11 | // the final required output puzzle 12 | var outputPuzzle matrix 13 | 14 | // the steps taken to reach from scrambled puzzle to required output puzzle 15 | var solvedSteps sliceOfMatrix 16 | 17 | // heap stores the list of nodes and returns the one having the least cost 18 | var heap []*Node 19 | 20 | // Node represents value, path, level and move 21 | // value is the cost of the last matrix in path 22 | // path is the list of matrices which represents the traversal (steps) done from the initial matrix 23 | // level represents the depth at which the current (last matrix from path) state is 24 | // parentBlankCell represents the row and column in which the blank cell was in the parent state 25 | type Node struct { 26 | value int 27 | path sliceOfMatrix 28 | level int 29 | parentBlankCell []int 30 | } 31 | 32 | func init() { 33 | outputPuzzle = make(matrix, 3) 34 | solvedSteps = make(sliceOfMatrix, 0) 35 | heap = make([]*Node, 0) 36 | inputPuzzle = make(matrix, 3) 37 | 38 | // initialize outputPuzzle 39 | for i := range outputPuzzle { 40 | outputPuzzle[i] = make([]int, 3) 41 | for j := range outputPuzzle[i] { 42 | outputPuzzle[i][j] = 0 43 | } 44 | } 45 | 46 | // initialize inputPuzzle 47 | for i := range inputPuzzle { 48 | inputPuzzle[i] = make([]int, 3) 49 | for j := range inputPuzzle[i] { 50 | inputPuzzle[i][j] = 0 51 | } 52 | } 53 | } 54 | 55 | func main() { 56 | // scan the input values 57 | fmt.Println("\n-- 8 Puzzle problem using A* Algorithm --") 58 | fmt.Println("\n-- Note: For blank cell use '0' --") 59 | 60 | fmt.Println("\nStart entering desired 3x3 output puzzle:") 61 | for i := range outputPuzzle { 62 | for j := range outputPuzzle[i] { 63 | value := -1 64 | fmt.Print("Enter for ", i+1, j+1, ": ") 65 | fmt.Scanf("%d\n", &value) 66 | outputPuzzle[i][j] = value 67 | } 68 | fmt.Println("") 69 | } 70 | 71 | if !outputPuzzle.isValid() { 72 | fmt.Println("\n-- Invalid output puzzle. --") 73 | return 74 | } 75 | 76 | fmt.Println("\nStart entering 3x3 scrambled input puzzle:") 77 | for i := range inputPuzzle { 78 | for j := range inputPuzzle[i] { 79 | value := -1 80 | fmt.Print("Enter for ", i+1, j+1, ": ") 81 | fmt.Scanf("%d\n", &value) 82 | inputPuzzle[i][j] = value 83 | } 84 | fmt.Println("") 85 | } 86 | 87 | // print the desired output puzzle 88 | fmt.Println("\nYour desired output puzzle is:") 89 | outputPuzzle.displayMatrix() 90 | 91 | // print the input scrambled puzzle 92 | fmt.Println("\nYour scrambled puzzle is: ") 93 | inputPuzzle.displayMatrix() 94 | 95 | // validate the puzzle 96 | if inputPuzzle.isValid() { 97 | fmt.Println("\nA* Algorithm started...") 98 | inputPuzzle.aStar() 99 | } else { 100 | fmt.Println("-- Your input puzzle is invalid. --") 101 | } 102 | } 103 | 104 | // puzzle = input - output 105 | // puzzle = [][]int{[]int{2, 8, 3}, []int{1, 6, 4}, []int{7, 0, 5}} - [][]int{[]int{1, 2, 3}, []int{8, 0, 4}, []int{7, 6, 5}} 106 | // puzzle = matrix{[]int{1, 8, 2}, []int{0, 4, 3}, []int{7, 6, 5}} - [][]int{[]int{1, 2, 3}, []int{4, 5, 6}, []int{7, 8, 0}} 107 | -------------------------------------------------------------------------------- /algorithms/a_star/8_puzzle/README.md: -------------------------------------------------------------------------------- 1 | #### Memory and Time requirements 2 | 3 | The memory and time requirements to solve the input puzzle depends on the input. For example, consider the below input puzzle: 4 | 5 | **Input** 6 | 7 | ``` 8 | 1 2 3 9 | 0 4 6 10 | 7 5 8 11 | ``` 12 | 13 | **Required Output** 14 | 15 | ``` 16 | 1 2 3 17 | 8 0 4 18 | 7 6 5 19 | ``` 20 | 21 | To transform the above input to required output takes subtantially long time and more memory, and may hang your computer, which happened to me 😜, if the algorithm continues to find the solution further. 22 | 23 | #### Few methods to solve 8 Puzzle problem: 24 | 25 | 1. A\* Algorithm 26 | 2. BFS (Breadth First Search) 27 | 3. DFS (Depth First Search) 28 | 4. Best First Search 29 | 5. Iterative Deepening Search 30 | 31 | #### Calculating Cost 32 | 33 | The `calculateCost` function implemented in this implementation can be changed to calculate cost using different methods. Following are some ways to calculate the cost of any puzzle: 34 | 35 | 1. Number of mismatched tiles (Implemented) 36 | 2. Manhattan distance 37 | 3. Euclidean distance 38 | 39 | #### References 40 | 41 | Live Demo: [http://tristanpenman.com/demos/n-puzzle/](http://tristanpenman.com/demos/n-puzzle/) 42 | 43 | List of sample inputs: [https://www.andrew.cmu.edu/course/15-121/labs/HW-7%20Slide%20Puzzle/lab.html](https://www.andrew.cmu.edu/course/15-121/labs/HW-7%20Slide%20Puzzle/lab.html) 44 | -------------------------------------------------------------------------------- /algorithms/a_star/8_puzzle/priority_queue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Note - Lower priority value processes will be run first. Hence this is implemented using min heap. 4 | 5 | import ( 6 | "fmt" 7 | "math" 8 | ) 9 | 10 | // Enqueue inserts a node in a heap 11 | func Enqueue(node *Node) { 12 | heap = append(heap, node) 13 | minHeapify() 14 | } 15 | 16 | func minHeapify() { 17 | idx := len(heap) - 1 18 | element := heap[idx] 19 | for idx > 0 { 20 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 21 | parent := heap[parentIdx] 22 | if element.value >= parent.value { 23 | break 24 | } 25 | heap[parentIdx] = element 26 | heap[idx] = parent 27 | idx = parentIdx 28 | } 29 | } 30 | 31 | // Dequeue will remove a node from heap 32 | func Dequeue() *Node { 33 | if len(heap) == 0 || heap[0] == nil { 34 | fmt.Println("\n-- Heap is empty. --") 35 | return nil 36 | } 37 | min := heap[0] 38 | end := heap[len(heap)-1] 39 | heap = heap[0 : len(heap)-1] 40 | if len(heap) > 0 { 41 | heap[0] = end 42 | bubbleDown() 43 | } 44 | return min 45 | } 46 | 47 | func bubbleDown() { 48 | idx := 0 49 | length := len(heap) 50 | element := heap[0] 51 | for { 52 | leftChildIdx := (2 * idx) + 1 53 | rightChildIdx := (2 * idx) + 2 54 | var leftChild, rightChild *Node 55 | var swap int 56 | 57 | if leftChildIdx < length { 58 | leftChild = heap[leftChildIdx] 59 | if leftChild.value < element.value { 60 | swap = leftChildIdx 61 | } 62 | } 63 | if rightChildIdx < length { 64 | rightChild = heap[rightChildIdx] 65 | if (rightChild.value < element.value && swap == 0) || (rightChild.value < leftChild.value && swap != 0) { 66 | swap = rightChildIdx 67 | } 68 | } 69 | 70 | if swap == 0 { 71 | break 72 | } 73 | heap[idx] = heap[swap] 74 | heap[swap] = element 75 | idx = swap 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /algorithms/a_star/directed_graph/a_star.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func (g graph) runAStarAlgo(initialVtx, goalVtx string) { 9 | for vtx := range g[initialVtx] { 10 | f := g[initialVtx][vtx].value + vtxWeights[g[initialVtx][vtx].name] 11 | Enqueue(&Node{name: initialVtx + "-" + g[initialVtx][vtx].name, value: f}) 12 | } 13 | path := g.traverseFurther(Dequeue(), goalVtx) 14 | fmt.Println("Best Path is:", path.name) 15 | fmt.Println("The cost is:", path.value) 16 | } 17 | 18 | func (g graph) traverseFurther(bestPath *Node, goalVtx string) *Node { 19 | vertices := strings.Split(bestPath.name, "-") 20 | currVtx := vertices[len(vertices)-1] 21 | for vtx := range g[currVtx] { 22 | visitingVtx := g[currVtx][vtx] 23 | f := bestPath.value - vtxWeights[currVtx] + g[currVtx][vtx].value + vtxWeights[visitingVtx.name] 24 | Enqueue(&Node{name: bestPath.name + "-" + visitingVtx.name, value: f}) 25 | } 26 | 27 | nextBestPath := Dequeue() 28 | vertices = strings.Split(nextBestPath.name, "-") 29 | if vertices[len(vertices)-1] != goalVtx { 30 | return g.traverseFurther(nextBestPath, goalVtx) 31 | } 32 | 33 | return nextBestPath 34 | } 35 | -------------------------------------------------------------------------------- /algorithms/a_star/directed_graph/priority_queue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Note - Lower priority value processes will be run first. Hence this is implemented using min heap. 4 | 5 | import ( 6 | "fmt" 7 | "math" 8 | ) 9 | 10 | var heap []*Node 11 | 12 | // Enqueue inserts a node in a heap 13 | func Enqueue(node *Node) { 14 | heap = append(heap, node) 15 | minHeapify() 16 | } 17 | 18 | func minHeapify() { 19 | idx := len(heap) - 1 20 | element := heap[idx] 21 | for idx > 0 { 22 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 23 | parent := heap[parentIdx] 24 | if element.value >= parent.value { 25 | break 26 | } 27 | heap[parentIdx] = element 28 | heap[idx] = parent 29 | idx = parentIdx 30 | } 31 | } 32 | 33 | // Dequeue will remove a node from heap 34 | func Dequeue() *Node { 35 | if len(heap) == 0 || heap[0] == nil { 36 | fmt.Println("\n-- Heap is empty. --") 37 | return nil 38 | } 39 | min := heap[0] 40 | end := heap[len(heap)-1] 41 | heap = heap[0 : len(heap)-1] 42 | if len(heap) > 0 { 43 | heap[0] = end 44 | bubbleDown() 45 | } 46 | return min 47 | } 48 | 49 | func bubbleDown() { 50 | idx := 0 51 | length := len(heap) 52 | element := heap[0] 53 | for { 54 | leftChildIdx := (2 * idx) + 1 55 | rightChildIdx := (2 * idx) + 2 56 | var leftChild, rightChild *Node 57 | var swap int 58 | 59 | if leftChildIdx < length { 60 | leftChild = heap[leftChildIdx] 61 | if leftChild.value < element.value { 62 | swap = leftChildIdx 63 | } 64 | } 65 | if rightChildIdx < length { 66 | rightChild = heap[rightChildIdx] 67 | if (rightChild.value < element.value && swap == 0) || (rightChild.value < leftChild.value && swap != 0) { 68 | swap = rightChildIdx 69 | } 70 | } 71 | 72 | if swap == 0 { 73 | break 74 | } 75 | heap[idx] = heap[swap] 76 | heap[swap] = element 77 | idx = swap 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /algorithms/a_star/undirected_graph/a_star.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func (g graph) runAStarAlgo(initialVtx, goalVtx string) { 9 | for vtx := range g[initialVtx] { 10 | f := g[initialVtx][vtx].value + vtxWeights[g[initialVtx][vtx].name] 11 | Enqueue(&Node{name: initialVtx + "-" + g[initialVtx][vtx].name, value: f}) 12 | } 13 | path := g.traverseFurther(Dequeue(), goalVtx) 14 | fmt.Println("Best Path is:", path.name) 15 | fmt.Println("The cost is:", path.value) 16 | } 17 | 18 | func (g graph) traverseFurther(bestPath *Node, goalVtx string) *Node { 19 | vertices := strings.Split(bestPath.name, "-") 20 | currVtx := vertices[len(vertices)-1] 21 | for vtx := range g[currVtx] { 22 | visitingVtx := g[currVtx][vtx] 23 | f := bestPath.value - vtxWeights[currVtx] + g[currVtx][vtx].value + vtxWeights[visitingVtx.name] 24 | Enqueue(&Node{name: bestPath.name + "-" + visitingVtx.name, value: f}) 25 | } 26 | 27 | nextBestPath := Dequeue() 28 | vertices = strings.Split(nextBestPath.name, "-") 29 | if vertices[len(vertices)-1] != goalVtx { 30 | return g.traverseFurther(nextBestPath, goalVtx) 31 | } 32 | 33 | return nextBestPath 34 | } 35 | -------------------------------------------------------------------------------- /algorithms/a_star/undirected_graph/priority_queue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Note - Lower priority value processes will be run first. Hence this is implemented using min heap. 4 | 5 | import ( 6 | "fmt" 7 | "math" 8 | ) 9 | 10 | var heap []*Node 11 | 12 | // Enqueue inserts a node in a heap 13 | func Enqueue(node *Node) { 14 | heap = append(heap, node) 15 | minHeapify() 16 | } 17 | 18 | func minHeapify() { 19 | idx := len(heap) - 1 20 | element := heap[idx] 21 | for idx > 0 { 22 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 23 | parent := heap[parentIdx] 24 | if element.value >= parent.value { 25 | break 26 | } 27 | heap[parentIdx] = element 28 | heap[idx] = parent 29 | idx = parentIdx 30 | } 31 | } 32 | 33 | // Dequeue will remove a node from heap 34 | func Dequeue() *Node { 35 | if len(heap) == 0 || heap[0] == nil { 36 | fmt.Println("\n-- Heap is empty. --") 37 | return nil 38 | } 39 | min := heap[0] 40 | end := heap[len(heap)-1] 41 | heap = heap[0 : len(heap)-1] 42 | if len(heap) > 0 { 43 | heap[0] = end 44 | bubbleDown() 45 | } 46 | return min 47 | } 48 | 49 | func bubbleDown() { 50 | idx := 0 51 | length := len(heap) 52 | element := heap[0] 53 | for { 54 | leftChildIdx := (2 * idx) + 1 55 | rightChildIdx := (2 * idx) + 2 56 | var leftChild, rightChild *Node 57 | var swap int 58 | 59 | if leftChildIdx < length { 60 | leftChild = heap[leftChildIdx] 61 | if leftChild.value < element.value { 62 | swap = leftChildIdx 63 | } 64 | } 65 | if rightChildIdx < length { 66 | rightChild = heap[rightChildIdx] 67 | if (rightChild.value < element.value && swap == 0) || (rightChild.value < leftChild.value && swap != 0) { 68 | swap = rightChildIdx 69 | } 70 | } 71 | 72 | if swap == 0 { 73 | break 74 | } 75 | heap[idx] = heap[swap] 76 | heap[swap] = element 77 | idx = swap 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /algorithms/activity_selection_gp/activity_selection_gp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type activity struct { 6 | start float64 7 | finish float64 8 | } 9 | 10 | // ActivitySelection selects the list of activities from given array 11 | func ActivitySelection() { 12 | j := 0 13 | for i := range activities { 14 | if i == 0 { 15 | selected = append(selected, i) 16 | j = i 17 | } else if activities[j].finish < activities[i].start { 18 | selected = append(selected, i) 19 | j = i 20 | } 21 | } 22 | } 23 | 24 | var n int 25 | var activities []activity 26 | var selected []int 27 | 28 | func init() { 29 | selected = make([]int, 0) 30 | } 31 | 32 | func main() { 33 | fmt.Println("\n-- Activity Selection Problem using Greedy Approach --") 34 | 35 | fmt.Print("\nEnter the number of activities: ") 36 | fmt.Scanf("%d\n", &n) 37 | activities = make([]activity, n) 38 | 39 | fmt.Println("Start entering starting and finishing times of each activities:") 40 | var temp float64 41 | for i := 0; i < n; i++ { 42 | fmt.Print("Start: ") 43 | fmt.Scanf("%f\n", &temp) 44 | activities[i].start = temp 45 | fmt.Print("Finish: ") 46 | fmt.Scanf("%f\n", &temp) 47 | activities[i].finish = temp 48 | } 49 | 50 | quicksort(0, n-1) 51 | 52 | ActivitySelection() 53 | 54 | fmt.Println("Selected activities are:") 55 | for i := range selected { 56 | fmt.Println(activities[selected[i]].start, activities[selected[i]].finish) 57 | } 58 | } 59 | 60 | // activities = []activity{ 61 | // activity{start: 1, finish: 4}, 62 | // activity{start: 3, finish: 5}, 63 | // activity{start: 0, finish: 6}, 64 | // activity{start: 5, finish: 7}, 65 | // activity{start: 3, finish: 8}, 66 | // activity{start: 5, finish: 9}, 67 | // activity{start: 6, finish: 10}, 68 | // activity{start: 8, finish: 11}, 69 | // activity{start: 8, finish: 12}, 70 | // activity{start: 2, finish: 13}, 71 | // activity{start: 12, finish: 14}, 72 | // } 73 | // n = 11 74 | -------------------------------------------------------------------------------- /algorithms/activity_selection_gp/quick_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func partition(first, last int) int { 4 | pivot := activities[first].finish 5 | i := first 6 | j := last + 1 7 | 8 | for i < j { 9 | i++ 10 | j-- 11 | for activities[i].finish < pivot && i < last { 12 | i++ 13 | } 14 | for activities[j].finish > pivot && j > first { 15 | j-- 16 | } 17 | if i < j { 18 | activities[i].finish, activities[j].finish = activities[j].finish, activities[i].finish 19 | } 20 | } 21 | activities[j].finish, activities[first].finish = activities[first].finish, activities[j].finish 22 | return j 23 | } 24 | 25 | func quicksort(first, last int) { 26 | var sp int 27 | if first < last { 28 | sp = partition(first, last) 29 | quicksort(first, sp-1) 30 | quicksort(sp+1, last) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /algorithms/assembly_line_scheduling/assembly_scheduling.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | var assembly [][]int 9 | var transport [][]int 10 | var result [][]int 11 | var stations int 12 | 13 | func init() { 14 | assembly = make([][]int, 2) 15 | transport = make([][]int, 2) 16 | result = make([][]int, 2) 17 | } 18 | 19 | func main() { 20 | fmt.Println("\n-- Assembly Line Scheduling --") 21 | fmt.Print("Enter the number of stations in assembly line: ") 22 | fmt.Scanf("%d\n", &stations) 23 | 24 | fmt.Println("Start entering the costs:") 25 | var temp int 26 | for i := 0; i < 2; i++ { 27 | assembly[i] = make([]int, stations+2) 28 | for j := 0; j < stations+2; j++ { 29 | fmt.Print(i, "-", j, ": ") 30 | fmt.Scanf("%d\n", &temp) 31 | assembly[i][j] = temp 32 | } 33 | } 34 | 35 | fmt.Println("Start entering the transport costs:") 36 | for i := 0; i < 2; i++ { 37 | transport[i] = make([]int, stations+2) 38 | for j := 0; j < stations-1; j++ { 39 | fmt.Print(i+1, "-", j+1, ": ") 40 | fmt.Scanf("%d\n", &temp) 41 | transport[i][j+1] = temp 42 | } 43 | } 44 | 45 | assemblySchedule() 46 | 47 | fmt.Println("\nThe matrix formed during calculations:") 48 | fmt.Println(result[0]) 49 | fmt.Println(result[1]) 50 | 51 | if result[0][stations] < result[1][stations] { 52 | fmt.Println("\nCheapest way to assemble the product is:", result[0][stations]) 53 | } else { 54 | fmt.Println("\nCheapest way to assemble the product is:", result[1][stations]) 55 | } 56 | } 57 | 58 | func assemblySchedule() { 59 | i := 0 60 | result[i] = make([]int, stations+1) 61 | result[i+1] = make([]int, stations+1) 62 | for j := 0; j < stations; j++ { 63 | if j == 0 { 64 | result[i][j] = assembly[i][j] + assembly[i][j+1] 65 | result[i+1][j] = assembly[i+1][j] + assembly[i+1][j+1] 66 | } else { 67 | result[i][j] = int(math.Min(float64(result[i][j-1]+assembly[i][j+1]), float64(result[i+1][j-1]+transport[i+1][j]+assembly[i][j+1]))) 68 | result[i+1][j] = int(math.Min(float64(result[i+1][j-1]+assembly[i+1][j+1]), float64(result[i][j-1]+transport[i][j]+assembly[i+1][j+1]))) 69 | } 70 | check := j + 1 71 | if check == stations { 72 | result[i][j+1] = result[i][j] + assembly[i][j+2] 73 | result[i+1][j+1] = result[i+1][j] + assembly[i+1][j+2] 74 | } 75 | } 76 | } 77 | 78 | // assembly[0] = []int{2, 7, 9, 3, 4, 8, 4, 3} 79 | // assembly[1] = []int{4, 8, 5, 6, 4, 5, 7, 2} 80 | 81 | // transport[0] = []int{0, 2, 3, 1, 3, 4, 0, 0} 82 | // transport[1] = []int{0, 2, 1, 2, 2, 1, 0, 0} 83 | -------------------------------------------------------------------------------- /algorithms/binary_reflected_gray_codes/brgc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("\n-- Binary Reflected Gray Codes --") 10 | var value int 11 | fmt.Print("\nEnter a value: ") 12 | fmt.Scanf("%d\n", &value) 13 | if value < 1 { 14 | log.Fatal("Invalid value. Value must be greater than 0.") 15 | } 16 | l := BRGC(value) 17 | fmt.Println("Gray codes for", value, "bits are:") 18 | for i := 0; i < len(l); i++ { 19 | fmt.Println(l[i]) 20 | } 21 | } 22 | 23 | // BRGC generates binary gray codes of given integer 24 | func BRGC(n int) []string { 25 | 26 | // return 0 and 1 as list if n == 1 27 | if n == 1 { 28 | return []string{"0", "1"} 29 | } 30 | 31 | // create list l1 by recursively calling on n-1 32 | l1 := BRGC(n - 1) 33 | l2 := make([]string, 0) 34 | 35 | // create list l2 in reverse order and add prefix 1 on each item 36 | for i := len(l1) - 1; i >= 0; i-- { 37 | l2 = append(l2, "1"+l1[i]) 38 | } 39 | 40 | // add prefix 0 on each item of list l2 41 | for i := 0; i < len(l1); i++ { 42 | l1[i] = "0" + l1[i] 43 | } 44 | 45 | // append l2 to l1 46 | l1 = append(l1, l2...) 47 | 48 | // return generated list 49 | return l1 50 | } 51 | -------------------------------------------------------------------------------- /algorithms/closest_pair_problem/cpp_brute_force/cpp_brute_force.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "log" 7 | "math" 8 | "os" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | // Point represents a point on a 2d plane having x, y coords 14 | type Point struct { 15 | x float64 16 | y float64 17 | } 18 | 19 | var arr []Point 20 | 21 | func init() { 22 | 23 | arr = make([]Point, 0) 24 | 25 | file, err := os.Open("sample.txt") 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | defer file.Close() 30 | 31 | scanner := bufio.NewScanner(file) 32 | for scanner.Scan() { 33 | txt := scanner.Text() 34 | str := strings.Split(txt, " ") 35 | 36 | strx, err := strconv.ParseFloat(str[0], 64) 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | 41 | stry, err := strconv.ParseFloat(str[1], 64) 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | 46 | arr = append(arr, Point{x: strx, y: stry}) 47 | } 48 | 49 | if err := scanner.Err(); err != nil { 50 | log.Fatal(err) 51 | } 52 | } 53 | 54 | func main() { 55 | fmt.Println("\n-- Closest Pair Problem using Brute Force Approach --") 56 | p, dist := ClosestPair(arr) 57 | fmt.Println("\nClosest pair of points are:", p[0], p[1], "whose distance is:", math.Sqrt(dist)) 58 | } 59 | 60 | // ClosestPair finds two points in a given set of 2d points using BruteForce 61 | // Returns a point and distance between those two points 62 | func ClosestPair(pts []Point) ([]Point, float64) { 63 | 64 | dist := math.Inf(1) 65 | p := make([]Point, 2) 66 | 67 | for i := 0; i < len(pts)-1; i++ { 68 | for j := i + 1; j < len(pts); j++ { 69 | d := FindDist(pts[i], pts[j]) 70 | if d < dist { 71 | dist = d 72 | p[0] = pts[i] 73 | p[1] = pts[j] 74 | } 75 | } 76 | } 77 | return p, dist 78 | } 79 | 80 | // FindDist finds distance between two points 81 | func FindDist(p1, p2 Point) float64 { 82 | return math.Pow(p2.x-p1.x, 2) + math.Pow(p2.y-p1.y, 2) 83 | } 84 | -------------------------------------------------------------------------------- /algorithms/closest_pair_problem/cpp_brute_force/sample.txt: -------------------------------------------------------------------------------- 1 | 2 3 2 | 12 30 3 | 40 50 4 | 5 1 5 | 12 10 6 | 3 4 -------------------------------------------------------------------------------- /algorithms/closest_pair_problem/cpp_divide_conquer/sample.txt: -------------------------------------------------------------------------------- 1 | 10 7 2 | 30 12 3 | 8 1 4 | 37 18 5 | 14 15 6 | 6 40 7 | 50 20 8 | 19 2 9 | 4 50 10 | 3 20 -------------------------------------------------------------------------------- /algorithms/closest_pair_problem/cpp_divide_conquer/sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func compareX(p1, p2 Point) bool { 4 | return (p1.x < p2.x) || (p1.x == p2.x && p1.y > p2.y) 5 | } 6 | 7 | func compareY(p1, p2 Point) bool { 8 | return (p1.y < p2.y) || (p1.y == p2.y && p1.x < p2.x) 9 | } 10 | 11 | // Partition splits the arr into two arrays from pivot element 12 | func Partition(pts []Point, first, last int, compare func(p1, p2 Point) bool) int { 13 | pivot := pts[first] 14 | i := first 15 | j := last + 1 16 | 17 | for i < j { 18 | i++ 19 | j-- 20 | for compare(pts[i], pivot) && i < last { 21 | i++ 22 | } 23 | for !compare(pts[j], pivot) && j > first { 24 | j-- 25 | } 26 | if i < j { 27 | pts[i], pts[j] = pts[j], pts[i] 28 | } 29 | } 30 | pts[j], pts[first] = pts[first], pts[j] 31 | return j 32 | } 33 | 34 | // QuickSort algorithms sorts the array using the compare function passed 35 | func QuickSort(pts []Point, first, last int, compare func(p1, p2 Point) bool) { 36 | var sp int 37 | if first < last { 38 | sp = Partition(pts, first, last, compare) 39 | QuickSort(pts, first, sp-1, compare) 40 | QuickSort(pts, sp+1, last, compare) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /algorithms/combinations/with_r/combinations.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("\n-- n C r Combinations with repetition --") 7 | 8 | var n, r int 9 | arr := make([]string, 0) 10 | 11 | fmt.Print("\nEnter the value of n: ") 12 | fmt.Scanf("%d\n", &n) 13 | fmt.Println("Start entering unique values of n:") 14 | for i := 0; i < n; i++ { 15 | var temp string 16 | fmt.Scanf("%s\n", &temp) 17 | arr = append(arr, temp) 18 | } 19 | fmt.Print("Enter the value of r: ") 20 | fmt.Scanf("%d\n", &r) 21 | 22 | data := make([]string, r) 23 | 24 | Combinations(arr, data, 0, n-1, 0, r) 25 | } 26 | 27 | // Combinations prints all possible nCr combinations of given array 28 | func Combinations(arr, data []string, start, end, index, r int) { 29 | if index == r { 30 | fmt.Println(data) 31 | return 32 | } 33 | 34 | for i := start; i <= end; i++ { 35 | data[index] = arr[i] 36 | Combinations(arr, data, i, end, index+1, r) 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /algorithms/combinations/without_r/combinations.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("\n-- n C r Combinations without repetition --") 7 | 8 | var n, r int 9 | arr := make([]string, 0) 10 | 11 | fmt.Print("\nEnter the value of n: ") 12 | fmt.Scanf("%d\n", &n) 13 | fmt.Println("Start entering unique values of n:") 14 | for i := 0; i < n; i++ { 15 | var temp string 16 | fmt.Scanf("%s\n", &temp) 17 | arr = append(arr, temp) 18 | } 19 | fmt.Print("Enter the value of r: ") 20 | fmt.Scanf("%d\n", &r) 21 | 22 | data := make([]string, r) 23 | 24 | Combinations(arr, data, 0, n-1, 0, r) 25 | } 26 | 27 | // Combinations prints all possible nCr combinations of given array 28 | func Combinations(arr, data []string, start, end, index, r int) { 29 | if index == r { 30 | fmt.Println(data) 31 | return 32 | } 33 | 34 | for i := start; i <= end && end-i+1 >= r-index; i++ { 35 | data[index] = arr[i] 36 | Combinations(arr, data, i+1, end, index+1, r) 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /algorithms/convex_hull/ch_brute_force/ch_brute_force.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | // Point represents a point on a 2d plane having x, y coords 13 | type Point struct { 14 | x float64 15 | y float64 16 | } 17 | 18 | var arr []Point 19 | 20 | // pointInConvex keeps a simple check 21 | // whether a given point is considered in convex set or not 22 | var pointInConvex map[string]bool 23 | 24 | func init() { 25 | arr = make([]Point, 0) 26 | pointInConvex = make(map[string]bool) 27 | 28 | file, err := os.Open("sample.txt") 29 | if err != nil { 30 | log.Fatal(err) 31 | } 32 | defer file.Close() 33 | 34 | scanner := bufio.NewScanner(file) 35 | for scanner.Scan() { 36 | txt := scanner.Text() 37 | str := strings.Split(txt, " ") 38 | 39 | strx, err := strconv.ParseFloat(str[0], 64) 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | 44 | stry, err := strconv.ParseFloat(str[1], 64) 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | 49 | arr = append(arr, Point{x: strx, y: stry}) 50 | } 51 | 52 | if err := scanner.Err(); err != nil { 53 | log.Fatal(err) 54 | } 55 | } 56 | 57 | func main() { 58 | fmt.Println("\n-- Convex Hull Brute Force Technique --") 59 | ch := ConvexHull() 60 | ch = SortConvexPoints(ch) 61 | for i := 0; i < len(ch); i++ { 62 | fmt.Println(ch[i]) 63 | } 64 | } 65 | 66 | // ConvexHull finds required set of points which forms a convex 67 | func ConvexHull() []Point { 68 | newArr := make([]Point, 0) 69 | 70 | for i := 0; i < len(arr)-1; i++ { 71 | for j := i + 1; j < len(arr); j++ { 72 | flag := IsConvex(arr[i], arr[j]) 73 | 74 | if !flag { 75 | continue 76 | } 77 | 78 | // float64 to string 79 | xi := fmt.Sprintf("%f\n", arr[i].x) 80 | yi := fmt.Sprintf("%f\n", arr[i].y) 81 | xj := fmt.Sprintf("%f\n", arr[j].x) 82 | yj := fmt.Sprintf("%f\n", arr[j].y) 83 | 84 | //string of x[i] y[i] 85 | strI := xi + yi 86 | //string of x[j] y[j] 87 | strJ := xj + yj 88 | 89 | if !pointInConvex[strI] { 90 | newArr = append(newArr, arr[i]) 91 | pointInConvex[strI] = true 92 | } 93 | 94 | if !pointInConvex[strJ] { 95 | newArr = append(newArr, arr[j]) 96 | pointInConvex[strJ] = true 97 | } 98 | } 99 | } 100 | return newArr 101 | } 102 | 103 | // IsConvex checks whether the given two points should be considered in the solution 104 | func IsConvex(p1, p2 Point) bool { 105 | flag := float64(0) 106 | a := p2.y - p1.y 107 | b := p1.x - p2.x 108 | c := p1.x*p2.y - p1.y*p2.x 109 | 110 | for i := 0; i < len(arr); i++ { 111 | lhs := a*arr[i].x + b*arr[i].y - c 112 | if lhs == 0 { 113 | check := IsLongestPair(p1, p2, arr[i]) 114 | if !check { 115 | return false 116 | } 117 | } 118 | if flag != 0 && lhs != 0 && !((lhs < 0 && flag < 0) || (lhs > 0 && flag > 0)) { 119 | return false 120 | } 121 | if flag == 0 { 122 | flag = lhs 123 | } 124 | } 125 | return true 126 | } 127 | -------------------------------------------------------------------------------- /algorithms/convex_hull/ch_brute_force/helpers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "math" 5 | "sort" 6 | ) 7 | 8 | // IsLongestPair checks whether the given first two set of points (p1, p2) have longest distance or not 9 | // The main idea is not to select all given points in question that lies on the same line 10 | func IsLongestPair(p1, p2, p3 Point) bool { 11 | d12 := math.Pow(p1.x-p2.x, 2) + math.Pow(p1.y-p2.y, 2) 12 | d13 := math.Pow(p1.x-p3.x, 2) + math.Pow(p1.y-p3.y, 2) 13 | d23 := math.Pow(p2.x-p3.x, 2) + math.Pow(p2.y-p3.y, 2) 14 | if d12 >= d13 && d12 >= d23 { 15 | return true 16 | } 17 | return false 18 | } 19 | 20 | // FindAngle finds an angle between lines formed by p1p2 and p2p3 represented as ∠p1p2p3 21 | // 22 | // i.e. angle formed at point p2 23 | func FindAngle(p1, p2, p3 Point) float64 { 24 | deg1 := int(((math.Atan2(p1.x-p2.x, p1.y-p2.y)*180)/math.Pi)+360) % 360 25 | deg2 := int(((math.Atan2(p3.x-p2.x, p3.y-p2.y)*180)/math.Pi)+360) % 360 26 | return float64(deg1 - deg2) 27 | } 28 | 29 | // SortConvexPoints sorts points of convex polygon in clockwise fashion 30 | func SortConvexPoints(pts []Point) []Point { 31 | 32 | // initializations 33 | newPts := make([]Point, 0) 34 | temp := make(map[float64]Point) 35 | center := Point{x: 0, y: 0} 36 | p1 := pts[0] 37 | 38 | // find a point within the convex polygon 39 | for i := 0; i < len(pts); i++ { 40 | center.x += pts[i].x 41 | center.y += pts[i].y 42 | } 43 | 44 | center.x /= float64(len(pts)) 45 | center.y /= float64(len(pts)) 46 | 47 | // find angle of each points formed at center point 48 | for i := 0; i < len(pts); i++ { 49 | angle := FindAngle(pts[i], center, p1) 50 | temp[angle] = pts[i] 51 | } 52 | 53 | // get all keys (angles) 54 | keys := make([]float64, 0) 55 | 56 | for i := range temp { 57 | keys = append(keys, i) 58 | } 59 | 60 | // sort these keys 61 | sort.Float64s(keys) 62 | 63 | // using map access each points in sorted fashion using keys 64 | for i := 0; i < len(keys); i++ { 65 | newPts = append(newPts, temp[keys[i]]) 66 | } 67 | 68 | return newPts 69 | } 70 | -------------------------------------------------------------------------------- /algorithms/convex_hull/ch_brute_force/sample.txt: -------------------------------------------------------------------------------- 1 | 0 0 2 | 0 1 3 | 0 2 4 | 0 3 5 | 1 0 6 | 1 1 7 | 1 2 8 | 1 3 9 | 2 0 10 | 2 1 11 | 2 2 12 | 2 3 13 | 2 4 14 | 2 5 15 | 2 6 16 | 2 7 17 | 2 8 18 | 2 9 19 | 3 0 20 | 3 1 21 | 3 2 22 | 3 3 23 | 4 0 24 | 4 1 25 | 4 2 26 | 4 3 27 | 4 4 28 | 5 1 -------------------------------------------------------------------------------- /algorithms/convex_hull/ch_divide_conquer/helpers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "math" 5 | "sort" 6 | ) 7 | 8 | // FindDist finds distance between two points on a plane 9 | func FindDist(p1, p2 Point) float64 { 10 | return math.Pow(p1.x-p2.x, 2) + math.Pow(p1.y-p2.y, 2) 11 | } 12 | 13 | // FindSide returns an integer specifying whether the point p3 is on left, right or on the line specified by points p1 and p2. 14 | // 15 | // Returns: 16 | // 17 | // -1 if point p3 is on the left side. 18 | // 19 | // 0 if point p3 is on the line. 20 | // 21 | // 1 if point p3 is on the right side. 22 | func FindSide(p1, p2, p3 Point) int { 23 | area := p1.x*p2.y + p3.x*p1.y + p2.x*p3.y - (p3.x*p2.y + p2.x*p1.y + p1.x*p3.y) 24 | if area > 0 { 25 | return 1 26 | } 27 | if area < 0 { 28 | return -1 29 | } 30 | return 0 31 | } 32 | 33 | // IsInside checks whether a given point p4 is inside a traingle of points p1, p2, p3 or not. 34 | // 35 | // Returns: 36 | // 37 | // true if it is inside the triangle 38 | // 39 | // false if it otherwise 40 | func IsInside(p1, p2, p3, p4 Point) bool { 41 | 42 | var a0, a1, a2, a3 float64 43 | 44 | a0 = (p1.x*(p2.y-p3.y) + p2.x*(p3.y-p1.y) + p3.x*(p1.y-p2.y)) / 2 45 | a1 = (p1.x*(p2.y-p4.y) + p2.x*(p4.y-p1.y) + p4.x*(p1.y-p2.y)) / 2 46 | a2 = (p2.x*(p3.y-p4.y) + p3.x*(p4.y-p2.y) + p4.x*(p2.y-p3.y)) / 2 47 | a3 = (p1.x*(p3.y-p4.y) + p3.x*(p4.y-p1.y) + p4.x*(p1.y-p3.y)) / 2 48 | 49 | // removing -ve sign if any 50 | if a0 < 0 { 51 | a0 = -1 * a0 52 | } 53 | if a1 < 0 { 54 | a1 = -1 * a1 55 | } 56 | if a2 < 0 { 57 | a2 = -1 * a2 58 | } 59 | if a3 < 0 { 60 | a3 = -1 * a3 61 | } 62 | 63 | if math.Round(a0) == math.Round(a1+a2+a3) { 64 | return true 65 | } 66 | return false 67 | } 68 | 69 | // FindAngle finds an angle between lines formed by p1p2 and p2p3 represented as ∠p1p2p3 70 | // 71 | // i.e. angle formed at point p2 72 | func FindAngle(p1, p2, p3 Point) float64 { 73 | deg1 := int(((math.Atan2(p1.x-p2.x, p1.y-p2.y)*180)/math.Pi)+360) % 360 74 | deg2 := int(((math.Atan2(p3.x-p2.x, p3.y-p2.y)*180)/math.Pi)+360) % 360 75 | return float64(deg1 - deg2) 76 | } 77 | 78 | // SortConvexPoints sorts points of convex polygon in clockwise fashion 79 | func SortConvexPoints(pts []Point) []Point { 80 | 81 | // initializations 82 | newPts := make([]Point, 0) 83 | temp := make(map[float64]Point) 84 | center := Point{x: 0, y: 0} 85 | p1 := pts[0] 86 | 87 | // find a point within the convex polygon 88 | for i := 0; i < len(pts); i++ { 89 | center.x += pts[i].x 90 | center.y += pts[i].y 91 | } 92 | 93 | center.x /= float64(len(pts)) 94 | center.y /= float64(len(pts)) 95 | 96 | // find angle of each points formed at center point 97 | for i := 0; i < len(pts); i++ { 98 | angle := FindAngle(pts[i], center, p1) 99 | temp[angle] = pts[i] 100 | } 101 | 102 | // get all keys (angles) 103 | keys := make([]float64, 0) 104 | 105 | for i := range temp { 106 | keys = append(keys, i) 107 | } 108 | 109 | // sort these keys 110 | sort.Float64s(keys) 111 | 112 | // using map access each points in sorted fashion using keys 113 | for i := 0; i < len(keys); i++ { 114 | newPts = append(newPts, temp[keys[i]]) 115 | } 116 | 117 | return newPts 118 | } 119 | -------------------------------------------------------------------------------- /algorithms/convex_hull/ch_divide_conquer/sample.txt: -------------------------------------------------------------------------------- 1 | 0 0 2 | 2 0 3 | 0 3 4 | 3 2 5 | 3 3 6 | 0 2 7 | 4 1 8 | 5 1 9 | 2 5 10 | 2 6 11 | 1 1 12 | 1 2 13 | 1 3 14 | 1 0 15 | 2 1 16 | 2 2 17 | 2 3 18 | 2 4 19 | 0 1 20 | 2 7 21 | 4 3 22 | 4 4 23 | 2 8 24 | 2 9 25 | 3 0 26 | 3 1 27 | 4 0 28 | 4 2 -------------------------------------------------------------------------------- /algorithms/convex_hull/ch_divide_conquer/sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func merge(l, m, r int) { 4 | var i, j, k int 5 | nl := m - l + 1 6 | nr := r - m 7 | var left, right []Point 8 | 9 | for i = 0; i < nl; i++ { 10 | left = append(left, arr[l+i]) 11 | } 12 | 13 | for j = 0; j < nr; j++ { 14 | right = append(right, arr[m+1+j]) 15 | } 16 | 17 | i = 0 18 | j = 0 19 | k = l 20 | 21 | for i < nl && j < nr { 22 | if (left[i].x < right[j].x) || (left[i].x == right[j].x && left[i].y < right[j].y) { 23 | arr[k] = left[i] 24 | i++ 25 | k++ 26 | } else { 27 | arr[k] = right[j] 28 | j++ 29 | k++ 30 | } 31 | } 32 | 33 | for i < nl { 34 | arr[k] = left[i] 35 | i++ 36 | k++ 37 | } 38 | for j < nr { 39 | arr[k] = right[j] 40 | j++ 41 | k++ 42 | } 43 | } 44 | 45 | // MergeSort sorts list of points in non decreasing order of x values and ties resolved with y values sorted in non decreasing order 46 | func MergeSort(l, r int) { 47 | var mid int 48 | if l < r { 49 | mid = (l + r) / 2 50 | MergeSort(l, mid) 51 | MergeSort(mid+1, r) 52 | merge(l, mid, r) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /algorithms/expression_conversions/infix_postfix/infix_postfix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // InToPos converts an infix expression to postfix expression 6 | func InToPos() { 7 | if !validate(expression) { 8 | fmt.Println("\n-- Invalid expression --") 9 | return 10 | } 11 | postfix := "" 12 | stack = append(stack, "N") 13 | for i := range expression { 14 | char := string(expression[i]) 15 | if (expression[i] >= 65 && expression[i] <= 90) || (expression[i] >= 97 && expression[i] <= 122) { 16 | postfix += char 17 | } else if char == "(" { 18 | stack = append(stack, char) 19 | } else if char == ")" { 20 | for stack[len(stack)-1] != "N" && stack[len(stack)-1] != "(" { 21 | newChar := stack[len(stack)-1] 22 | stack = stack[0 : len(stack)-1] 23 | postfix += newChar 24 | } 25 | if stack[len(stack)-1] == "(" { 26 | stack = stack[0 : len(stack)-1] 27 | } 28 | } else { 29 | for stack[len(stack)-1] != "N" && Prec(stack[len(stack)-1]) >= Prec(char) { 30 | newChar := stack[len(stack)-1] 31 | stack = stack[0 : len(stack)-1] 32 | postfix += newChar 33 | } 34 | stack = append(stack, char) 35 | } 36 | } 37 | for stack[len(stack)-1] != "N" { 38 | newChar := stack[len(stack)-1] 39 | stack = stack[0 : len(stack)-1] 40 | postfix += newChar 41 | } 42 | fmt.Println("\n" + postfix) 43 | } 44 | 45 | var stack []string 46 | var expression string 47 | 48 | func main() { 49 | fmt.Println("\n-- Infix to Postfix expression conversion --") 50 | i := 0 51 | for i == 0 { 52 | fmt.Print("\nEnter the expression: ") 53 | fmt.Scanf("%s\n", &expression) 54 | InToPos() 55 | var choice string 56 | fmt.Print("\nDo you want to continue y/n? ") 57 | fmt.Scanf("%s\n", &choice) 58 | if choice == "N" || choice == "n" { 59 | break 60 | } else if choice == "Y" || choice == "y" { 61 | continue 62 | } else { 63 | fmt.Println("Command not recognized.") 64 | } 65 | } 66 | } 67 | 68 | // Prec will return a precedence of a given operator 69 | func Prec(c string) int { 70 | if c == "^" { 71 | return 3 72 | } else if c == "*" || c == "/" { 73 | return 2 74 | } else if c == "+" || c == "-" { 75 | return 1 76 | } 77 | return -1 78 | } 79 | 80 | func isOperator(s string) bool { 81 | if s == "^" || s == "*" || s == "/" || s == "+" || s == "-" { 82 | return true 83 | } 84 | return false 85 | } 86 | 87 | func validate(c string) bool { 88 | var check int 89 | for i := range c { 90 | if isOperator(string(c[i])) || string(c[i]) == ")" { 91 | check += -1 92 | } else { 93 | check++ 94 | } 95 | } 96 | return check == 1 97 | } 98 | -------------------------------------------------------------------------------- /algorithms/expression_conversions/infix_prefix/infix_prefix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // InToPos converts an infix expression to prefix expression 8 | func InToPos(expression string) string { 9 | postfix := "" 10 | stack = append(stack, "N") 11 | for i := range expression { 12 | char := string(expression[i]) 13 | if (expression[i] >= 65 && expression[i] <= 90) || (expression[i] >= 97 && expression[i] <= 122) { 14 | postfix += char 15 | } else if char == "(" { 16 | stack = append(stack, char) 17 | } else if char == ")" { 18 | for stack[len(stack)-1] != "N" && stack[len(stack)-1] != "(" { 19 | newChar := stack[len(stack)-1] 20 | stack = stack[0 : len(stack)-1] 21 | postfix += newChar 22 | } 23 | if stack[len(stack)-1] == "(" { 24 | stack = stack[0 : len(stack)-1] 25 | } 26 | } else { 27 | for stack[len(stack)-1] != "N" && Prec(stack[len(stack)-1]) >= Prec(char) { 28 | newChar := stack[len(stack)-1] 29 | stack = stack[0 : len(stack)-1] 30 | postfix += newChar 31 | } 32 | stack = append(stack, char) 33 | } 34 | } 35 | for stack[len(stack)-1] != "N" { 36 | newChar := stack[len(stack)-1] 37 | stack = stack[0 : len(stack)-1] 38 | postfix += newChar 39 | } 40 | return postfix 41 | } 42 | 43 | // InToPre will reverse the expression and will call postfix on it 44 | // will then reverse again the returned expression from postfix call 45 | func InToPre() { 46 | if !validate(inputExp) { 47 | fmt.Println("\n-- Invalid expression --") 48 | return 49 | } 50 | reverseStr := reverse(inputExp) 51 | postfix := InToPos(reverseStr) 52 | prefix := reverse(postfix) 53 | fmt.Println("\n" + prefix) 54 | } 55 | 56 | var stack []string 57 | var inputExp string 58 | 59 | func main() { 60 | fmt.Println("\n-- Infix to Prefix expression conversion --") 61 | i := 0 62 | for i == 0 { 63 | fmt.Print("\nEnter the expression: ") 64 | fmt.Scanf("%s\n", &inputExp) 65 | InToPre() 66 | var choice string 67 | fmt.Print("\nDo you want to continue y/n? ") 68 | fmt.Scanf("%s\n", &choice) 69 | if choice == "N" || choice == "n" { 70 | break 71 | } else if choice == "Y" || choice == "y" { 72 | continue 73 | } else { 74 | fmt.Println("Command not recognized.") 75 | } 76 | } 77 | } 78 | 79 | // Prec will return a precedence of a given operator 80 | func Prec(c string) int { 81 | if c == "^" { 82 | return 3 83 | } else if c == "*" || c == "/" { 84 | return 2 85 | } else if c == "+" || c == "-" { 86 | return 1 87 | } 88 | return 0 89 | } 90 | 91 | func isOperator(s string) bool { 92 | if s == "^" || s == "*" || s == "/" || s == "+" || s == "-" { 93 | return true 94 | } 95 | return false 96 | } 97 | 98 | func reverse(s string) string { 99 | reverseStr := "" 100 | j := len(s) - 1 101 | for j != -1 { 102 | if string(s[j]) == ")" { 103 | reverseStr += "(" 104 | } else if string(s[j]) == "(" { 105 | reverseStr += ")" 106 | } else { 107 | reverseStr += string(s[j]) 108 | } 109 | j-- 110 | } 111 | return reverseStr 112 | } 113 | 114 | func validate(c string) bool { 115 | var check int 116 | for i := range c { 117 | if isOperator(string(c[i])) || string(c[i]) == ")" { 118 | check += -1 119 | } else { 120 | check++ 121 | } 122 | } 123 | return check == 1 124 | } 125 | -------------------------------------------------------------------------------- /algorithms/expression_conversions/postfix_infix/postfix_infix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // PosToIn will convert a given Postfix notation to Infix 6 | func PosToIn() { 7 | if !validate(expression) { 8 | fmt.Println("\n-- Invalid expression --") 9 | return 10 | } 11 | for i := range expression { 12 | char := string(expression[i]) 13 | if (expression[i] >= 65 && expression[i] <= 90) || (expression[i] >= 97 && expression[i] <= 122) { 14 | stack = append(stack, char) 15 | } else { 16 | operand1 := stack[len(stack)-1] // read top of stack 17 | stack = stack[0 : len(stack)-1] // pop from stack 18 | operand2 := stack[len(stack)-1] // read top of stack 19 | stack = stack[0 : len(stack)-1] // pop from stack 20 | temp := "(" + operand2 + char + operand1 + ")" 21 | stack = append(stack, temp) 22 | } 23 | } 24 | infix := stack[len(stack)-1] // read top of stack which is the final infix notation 25 | fmt.Println("\n" + infix) 26 | } 27 | 28 | var stack []string 29 | var expression string 30 | 31 | func main() { 32 | fmt.Println("\n-- Postfix to Infix expression conversion --") 33 | i := 0 34 | for i == 0 { 35 | fmt.Print("\nEnter the expression: ") 36 | fmt.Scanf("%s\n", &expression) 37 | PosToIn() 38 | var choice string 39 | fmt.Print("\nDo you want to continue y/n? ") 40 | fmt.Scanf("%s\n", &choice) 41 | if choice == "N" || choice == "n" { 42 | break 43 | } else if choice == "Y" || choice == "y" { 44 | continue 45 | } else { 46 | fmt.Println("Command not recognized.") 47 | } 48 | } 49 | } 50 | 51 | func isOperator(s string) bool { 52 | if s == "^" || s == "*" || s == "/" || s == "+" || s == "-" { 53 | return true 54 | } 55 | return false 56 | } 57 | 58 | func validate(c string) bool { 59 | var check int 60 | for i := range c { 61 | if isOperator(string(c[i])) || string(c[i]) == ")" { 62 | check += -1 63 | } else { 64 | check++ 65 | } 66 | } 67 | return check == 1 68 | } 69 | -------------------------------------------------------------------------------- /algorithms/expression_conversions/postfix_prefix/postfix_prefix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // PosToPre will convert a given Postfix notation to Prefix 6 | func PosToPre() { 7 | if !validate(expression) { 8 | fmt.Println("\n-- Invalid expression --") 9 | return 10 | } 11 | for i := range expression { 12 | char := string(expression[i]) 13 | if (expression[i] >= 65 && expression[i] <= 90) || (expression[i] >= 97 && expression[i] <= 122) { 14 | stack = append(stack, char) 15 | } else { 16 | operand1 := stack[len(stack)-1] // read top of stack 17 | stack = stack[0 : len(stack)-1] // pop from stack 18 | operand2 := stack[len(stack)-1] // read top of stack 19 | stack = stack[0 : len(stack)-1] // pop from stack 20 | temp := char + operand2 + operand1 21 | stack = append(stack, temp) 22 | } 23 | } 24 | infix := stack[len(stack)-1] // read top of stack which is the final infix notation 25 | fmt.Println("\n" + infix) 26 | } 27 | 28 | var stack []string 29 | var expression string 30 | 31 | func main() { 32 | fmt.Println("\n-- Postfix to Prefix expression conversion --") 33 | i := 0 34 | for i == 0 { 35 | fmt.Print("\nEnter the expression: ") 36 | fmt.Scanf("%s\n", &expression) 37 | PosToPre() 38 | var choice string 39 | fmt.Print("\nDo you want to continue y/n? ") 40 | fmt.Scanf("%s\n", &choice) 41 | if choice == "N" || choice == "n" { 42 | break 43 | } else if choice == "Y" || choice == "y" { 44 | continue 45 | } else { 46 | fmt.Println("Command not recognized.") 47 | } 48 | } 49 | } 50 | 51 | func isOperator(s string) bool { 52 | if s == "^" || s == "*" || s == "/" || s == "+" || s == "-" { 53 | return true 54 | } 55 | return false 56 | } 57 | 58 | func validate(c string) bool { 59 | var check int 60 | for i := range c { 61 | if isOperator(string(c[i])) || string(c[i]) == ")" { 62 | check += -1 63 | } else { 64 | check++ 65 | } 66 | } 67 | return check == 1 68 | } 69 | -------------------------------------------------------------------------------- /algorithms/expression_conversions/prefix_infix/prefix_infix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // PreToIn will convert a given Prefix notation to Infix 6 | func PreToIn() { 7 | if !validate(expression) { 8 | fmt.Println("\n-- Invalid expression --") 9 | return 10 | } 11 | str := reverse(expression) 12 | for i := range str { 13 | char := string(str[i]) 14 | if (str[i] >= 65 && str[i] <= 90) || (str[i] >= 97 && str[i] <= 122) { 15 | stack = append(stack, char) 16 | } else { 17 | operand1 := stack[len(stack)-1] // read top of stack 18 | stack = stack[0 : len(stack)-1] // pop from stack 19 | operand2 := stack[len(stack)-1] // read top of stack 20 | stack = stack[0 : len(stack)-1] // pop from stack 21 | temp := "(" + operand1 + char + operand2 + ")" 22 | stack = append(stack, temp) 23 | } 24 | } 25 | infix := stack[len(stack)-1] // read top of stack which is the final infix notation 26 | fmt.Println("\n" + infix) 27 | } 28 | 29 | var stack []string 30 | var expression string 31 | 32 | func main() { 33 | fmt.Println("\n-- Prefix to Infix expression conversion --") 34 | i := 0 35 | for i == 0 { 36 | fmt.Print("\nEnter the expression: ") 37 | fmt.Scanf("%s\n", &expression) 38 | PreToIn() 39 | var choice string 40 | fmt.Print("\nDo you want to continue y/n? ") 41 | fmt.Scanf("%s\n", &choice) 42 | if choice == "N" || choice == "n" { 43 | break 44 | } else if choice == "Y" || choice == "y" { 45 | continue 46 | } else { 47 | fmt.Println("Command not recognized.") 48 | } 49 | } 50 | } 51 | 52 | func reverse(s string) string { 53 | reverseStr := "" 54 | j := len(s) - 1 55 | for j != -1 { 56 | if string(s[j]) == ")" { 57 | reverseStr += "(" 58 | } else if string(s[j]) == "(" { 59 | reverseStr += ")" 60 | } else { 61 | reverseStr += string(s[j]) 62 | } 63 | j-- 64 | } 65 | return reverseStr 66 | } 67 | 68 | func isOperator(s string) bool { 69 | if s == "^" || s == "*" || s == "/" || s == "+" || s == "-" { 70 | return true 71 | } 72 | return false 73 | } 74 | 75 | func validate(c string) bool { 76 | var check int 77 | for i := range c { 78 | if isOperator(string(c[i])) || string(c[i]) == ")" { 79 | check += -1 80 | } else { 81 | check++ 82 | } 83 | } 84 | return check == 1 85 | } 86 | -------------------------------------------------------------------------------- /algorithms/expression_conversions/prefix_postfix/prefix_postfix.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // PreToPos will convert a given Prefix notation to Postfix 6 | func PreToPos() { 7 | if !validate(expression) { 8 | fmt.Println("\n-- Invalid expression --") 9 | return 10 | } 11 | str := reverse(expression) 12 | for i := range str { 13 | char := string(str[i]) 14 | if (str[i] >= 65 && str[i] <= 90) || (str[i] >= 97 && str[i] <= 122) { 15 | stack = append(stack, char) 16 | } else { 17 | operand1 := stack[len(stack)-1] // read top of stack 18 | stack = stack[0 : len(stack)-1] // pop from stack 19 | operand2 := stack[len(stack)-1] // read top of stack 20 | stack = stack[0 : len(stack)-1] // pop from stack 21 | temp := operand1 + operand2 + char 22 | stack = append(stack, temp) 23 | } 24 | } 25 | infix := stack[len(stack)-1] // read top of stack which is the final infix notation 26 | fmt.Println("\n" + infix) 27 | } 28 | 29 | var stack []string 30 | var expression string 31 | 32 | func main() { 33 | fmt.Println("\n-- Prefix to Postfix expression conversion --") 34 | i := 0 35 | for i == 0 { 36 | fmt.Print("\nEnter the expression: ") 37 | fmt.Scanf("%s\n", &expression) 38 | PreToPos() 39 | var choice string 40 | fmt.Print("\nDo you want to continue y/n? ") 41 | fmt.Scanf("%s\n", &choice) 42 | if choice == "N" || choice == "n" { 43 | break 44 | } else if choice == "Y" || choice == "y" { 45 | continue 46 | } else { 47 | fmt.Println("Command not recognized.") 48 | } 49 | } 50 | } 51 | 52 | func reverse(s string) string { 53 | reverseStr := "" 54 | j := len(s) - 1 55 | for j != -1 { 56 | if string(s[j]) == ")" { 57 | reverseStr += "(" 58 | } else if string(s[j]) == "(" { 59 | reverseStr += ")" 60 | } else { 61 | reverseStr += string(s[j]) 62 | } 63 | j-- 64 | } 65 | return reverseStr 66 | } 67 | 68 | func isOperator(s string) bool { 69 | if s == "^" || s == "*" || s == "/" || s == "+" || s == "-" { 70 | return true 71 | } 72 | return false 73 | } 74 | 75 | func validate(c string) bool { 76 | var check int 77 | for i := range c { 78 | if isOperator(string(c[i])) || string(c[i]) == ")" { 79 | check += -1 80 | } else { 81 | check++ 82 | } 83 | } 84 | return check == 1 85 | } 86 | -------------------------------------------------------------------------------- /algorithms/gcd/README.md: -------------------------------------------------------------------------------- 1 | #### GCD - Greatest Common Divisor 2 | 3 | Euclid of Alexandria outlined an algorithm for solving this problem in one of the volumes of his Elements most famous for its systematic exposition of geometry. In modern terms, Euclid’s algorithm is based on applying repeatedly the equality 4 | 5 | gcd(m, n) = gcd(n, m mod n) 6 | 7 | For e.g: 8 | 9 | gcd(60, 24) = gcd(24, 12) = gcd(12, 0) = 12 10 | -------------------------------------------------------------------------------- /algorithms/gcd/gcd.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var n, m int 7 | fmt.Println("-- GCD --") 8 | fmt.Print("Enter the first number: ") 9 | fmt.Scanf("%d\n", &n) 10 | fmt.Print("Enter the second number: ") 11 | fmt.Scanf("%d\n", &m) 12 | var gcd int 13 | if n < m { 14 | gcd = findGCD(m, n) 15 | } else { 16 | gcd = findGCD(n, m) 17 | } 18 | fmt.Println("GCD of given numbers is:", gcd) 19 | } 20 | 21 | func findGCD(m, n int) int { 22 | if n == 0 { 23 | return m 24 | } 25 | return findGCD(n, m%n) 26 | } 27 | -------------------------------------------------------------------------------- /algorithms/graphs/articulation_point_detection/articulation_point.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | g := make(graph) 7 | i := 0 8 | for i == 0 { 9 | fmt.Println("\n1. ADD A VERTEX") 10 | fmt.Println("2. ADD AN EDGE") 11 | fmt.Println("3. DETECT ARTICULATION POINTS") 12 | fmt.Println("4. SIMPLE DISPLAY") 13 | fmt.Println("5. EXIT") 14 | var choice int 15 | fmt.Print("Enter your choice: ") 16 | fmt.Scanf("%d\n", &choice) 17 | switch choice { 18 | case 1: 19 | g.addVertex() 20 | case 2: 21 | g.addEdge() 22 | case 3: 23 | result := g.findArticulationPoints() 24 | if len(result) != 0 { 25 | fmt.Println("\n-- Articulation point/s exists in a given graph. --") 26 | for i := range result { 27 | if result[i] { 28 | fmt.Println(i) 29 | } 30 | } 31 | } else { 32 | fmt.Println("\n -- No articulation point/s exists in a given graph. --") 33 | } 34 | case 4: 35 | g.simpleDisplay() 36 | default: 37 | fmt.Println("Command not recognized.") 38 | } 39 | } 40 | } 41 | 42 | // c, d, h 43 | // g.addVertexToGraph("a") 44 | // g.addVertexToGraph("b") 45 | // g.addVertexToGraph("c") 46 | // g.addVertexToGraph("d") 47 | // g.addVertexToGraph("e") 48 | // g.addVertexToGraph("f") 49 | // g.addVertexToGraph("g") 50 | // g.addVertexToGraph("h") 51 | // g.addVertexToGraph("i") 52 | // g.addEdgeToGraph("a", "b") 53 | // g.addEdgeToGraph("b", "c") 54 | // g.addEdgeToGraph("c", "a") 55 | // g.addEdgeToGraph("c", "d") 56 | // g.addEdgeToGraph("d", "e") 57 | // g.addEdgeToGraph("e", "f") 58 | // g.addEdgeToGraph("f", "g") 59 | // g.addEdgeToGraph("g", "d") 60 | // g.addEdgeToGraph("c", "h") 61 | // g.addEdgeToGraph("h", "i") 62 | -------------------------------------------------------------------------------- /algorithms/graphs/articulation_point_detection/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type graph map[string][]string 6 | 7 | func (g graph) addVertexToGraph(vtx string) { 8 | if g[vtx] != nil { 9 | fmt.Println("\n-- Vertex already exists. --") 10 | return 11 | } 12 | g[vtx] = make([]string, 0) 13 | } 14 | 15 | func (g graph) addEdgeToGraph(fromVtx, toVtx string) { 16 | if g[fromVtx] == nil { // check if initial vertex exists 17 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 18 | return 19 | } 20 | for i := range g[fromVtx] { // check if edge already exists 21 | if g[fromVtx][i] == toVtx { 22 | fmt.Println("\n-- Edge between " + fromVtx + " and " + toVtx + " already exists. --") 23 | return 24 | } 25 | } 26 | if g[toVtx] == nil { // create new destination vertext if it does not exists 27 | g[toVtx] = make([]string, 0) 28 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 29 | } 30 | 31 | g[fromVtx] = append(g[fromVtx], toVtx) 32 | g[toVtx] = append(g[toVtx], fromVtx) 33 | } 34 | 35 | func (g graph) addVertex() { 36 | var vtxName string 37 | fmt.Print("Enter the name of vertex: ") 38 | fmt.Scanf("%s\n", &vtxName) 39 | g.addVertexToGraph(vtxName) 40 | } 41 | 42 | func (g graph) addEdge() { 43 | var fromVtx, toVtx string 44 | fmt.Print("Enter the initial vertex name: ") 45 | fmt.Scanf("%s\n", &fromVtx) 46 | fmt.Print("Enter the destination vertex name: ") 47 | fmt.Scanf("%s\n", &toVtx) 48 | g.addEdgeToGraph(fromVtx, toVtx) 49 | } 50 | -------------------------------------------------------------------------------- /algorithms/graphs/articulation_point_detection/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | var id float64 9 | var outEdgeCount float64 10 | var ids map[string]float64 11 | var low map[string]float64 12 | var isArt map[string]bool 13 | 14 | func init() { 15 | id = 0 16 | outEdgeCount = 0 17 | ids = make(map[string]float64) 18 | low = make(map[string]float64) 19 | isArt = make(map[string]bool) 20 | } 21 | 22 | // DFS traverses a graph using dfs technique 23 | func (g graph) findArticulationPoints() map[string]bool { 24 | visited := make(map[string]bool) 25 | if len(g) == 0 { 26 | fmt.Println("\n-- Graph is empty. --") 27 | return nil 28 | } 29 | for i := range g { 30 | if !visited[i] { 31 | outEdgeCount = 0 32 | g.dfs(i, visited, i, "-1") 33 | isArt[i] = outEdgeCount > 1 34 | } 35 | } 36 | return isArt 37 | } 38 | 39 | // dfsHelper recursively calls itself to solve dfs traversal 40 | func (g graph) dfs(root string, visited map[string]bool, at string, parent string) { 41 | visited[at] = true 42 | id++ 43 | low[at] = id 44 | ids[at] = id 45 | for i := range g[at] { 46 | to := g[at][i] 47 | if to == parent { 48 | continue 49 | } 50 | if !visited[to] { 51 | g.dfs(root, visited, to, at) 52 | low[at] = math.Min(low[at], low[to]) 53 | if ids[at] < low[to] { 54 | isArt[at] = true 55 | } 56 | if ids[at] == low[to] { 57 | isArt[at] = true 58 | } 59 | } else { 60 | low[at] = math.Min(low[at], ids[to]) 61 | } 62 | } 63 | } 64 | 65 | func (g graph) simpleDisplay() { 66 | fmt.Println("") 67 | for i := range g { 68 | fmt.Print(i, " => ") 69 | for j := range g[i] { 70 | fmt.Print(g[i][j] + " ") 71 | } 72 | fmt.Println("") 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /algorithms/graphs/bellman_ford/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Node is a single node in a graph list 6 | type Node struct { 7 | name string 8 | value int 9 | } 10 | 11 | var graph map[string][]Node 12 | 13 | func init() { 14 | graph = make(map[string][]Node) 15 | } 16 | 17 | func addVertexToGraph(vtx string) { 18 | if graph[vtx] != nil { 19 | fmt.Println("\n-- Vertex already exists. --") 20 | return 21 | } 22 | vertices[vtx] = len(vertices) 23 | graph[vtx] = make([]Node, 0) 24 | } 25 | 26 | func addEdgeToGraph(fromVtx, toVtx string, edgeValue int) { 27 | if graph[fromVtx] == nil { // check if initial vertex exists 28 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 29 | return 30 | } 31 | for i := range graph[fromVtx] { // check if edge already exists 32 | if graph[fromVtx][i].name == toVtx { 33 | fmt.Println("\n-- Edge from " + fromVtx + " to " + toVtx + " already exists. --") 34 | return 35 | } 36 | } 37 | if graph[toVtx] == nil { // create new destination vertex if it does not exists 38 | vertices[toVtx] = len(vertices) 39 | graph[toVtx] = make([]Node, 0) 40 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 41 | } 42 | 43 | graph[fromVtx] = append(graph[fromVtx], Node{name: toVtx, value: edgeValue}) 44 | } 45 | 46 | func addVertex() { 47 | var vtxName string 48 | fmt.Print("Enter the name of vertex: ") 49 | fmt.Scanf("%s\n", &vtxName) 50 | addVertexToGraph(vtxName) 51 | } 52 | 53 | func addEdge() { 54 | var fromVtx, toVtx string 55 | var edgeValue int 56 | fmt.Print("Enter the initial vertex name: ") 57 | fmt.Scanf("%s\n", &fromVtx) 58 | fmt.Print("Enter the destination vertex name: ") 59 | fmt.Scanf("%s\n", &toVtx) 60 | fmt.Print("Enter the weight of edge: ") 61 | fmt.Scanf("%d\n", &edgeValue) 62 | addEdgeToGraph(fromVtx, toVtx, edgeValue) 63 | } 64 | -------------------------------------------------------------------------------- /algorithms/graphs/bridge_detection/bridge_detection.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | g := make(graph) 7 | i := 0 8 | for i == 0 { 9 | fmt.Println("\n1. ADD A VERTEX") 10 | fmt.Println("2. ADD AN EDGE") 11 | fmt.Println("3. DETECT BRIDGES") 12 | fmt.Println("4. SIMPLE DISPLAY") 13 | fmt.Println("5. EXIT") 14 | var choice int 15 | fmt.Print("Enter your choice: ") 16 | fmt.Scanf("%d\n", &choice) 17 | switch choice { 18 | case 1: 19 | g.addVertex() 20 | case 2: 21 | g.addEdge() 22 | case 3: 23 | result := g.findBridges() 24 | prev := "" 25 | if len(result) != 0 { 26 | fmt.Println("\n-- Bridge/s exists in a given graph. --") 27 | for i := range result { 28 | if prev != "" { 29 | fmt.Println("-- Bridge exists between:", prev, "-", result[i]) 30 | prev = "" 31 | } else { 32 | prev = result[i] 33 | } 34 | } 35 | } else { 36 | fmt.Println("\n -- No bridge exists in a given graph. --") 37 | } 38 | case 4: 39 | g.simpleDisplay() 40 | default: 41 | fmt.Println("Command not recognized.") 42 | } 43 | } 44 | } 45 | 46 | // c-d, c-h, h-i 47 | // g.addVertexToGraph("a") 48 | // g.addVertexToGraph("b") 49 | // g.addVertexToGraph("c") 50 | // g.addVertexToGraph("d") 51 | // g.addVertexToGraph("e") 52 | // g.addVertexToGraph("f") 53 | // g.addVertexToGraph("g") 54 | // g.addVertexToGraph("h") 55 | // g.addVertexToGraph("i") 56 | // g.addEdgeToGraph("a", "b") 57 | // g.addEdgeToGraph("b", "c") 58 | // g.addEdgeToGraph("c", "a") 59 | // g.addEdgeToGraph("c", "d") 60 | // g.addEdgeToGraph("d", "e") 61 | // g.addEdgeToGraph("e", "f") 62 | // g.addEdgeToGraph("f", "g") 63 | // g.addEdgeToGraph("g", "d") 64 | // g.addEdgeToGraph("c", "h") 65 | // g.addEdgeToGraph("h", "i") 66 | -------------------------------------------------------------------------------- /algorithms/graphs/bridge_detection/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type graph map[string][]string 6 | 7 | func (g graph) addVertexToGraph(vtx string) { 8 | if g[vtx] != nil { 9 | fmt.Println("\n-- Vertex already exists. --") 10 | return 11 | } 12 | g[vtx] = make([]string, 0) 13 | } 14 | 15 | func (g graph) addEdgeToGraph(fromVtx, toVtx string) { 16 | if g[fromVtx] == nil { // check if initial vertex exists 17 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 18 | return 19 | } 20 | for i := range g[fromVtx] { // check if edge already exists 21 | if g[fromVtx][i] == toVtx { 22 | fmt.Println("\n-- Edge between " + fromVtx + " and " + toVtx + " already exists. --") 23 | return 24 | } 25 | } 26 | if g[toVtx] == nil { // create new destination vertext if it does not exists 27 | g[toVtx] = make([]string, 0) 28 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 29 | } 30 | 31 | g[fromVtx] = append(g[fromVtx], toVtx) 32 | g[toVtx] = append(g[toVtx], fromVtx) 33 | } 34 | 35 | func (g graph) addVertex() { 36 | var vtxName string 37 | fmt.Print("Enter the name of vertex: ") 38 | fmt.Scanf("%s\n", &vtxName) 39 | g.addVertexToGraph(vtxName) 40 | } 41 | 42 | func (g graph) addEdge() { 43 | var fromVtx, toVtx string 44 | fmt.Print("Enter the initial vertex name: ") 45 | fmt.Scanf("%s\n", &fromVtx) 46 | fmt.Print("Enter the destination vertex name: ") 47 | fmt.Scanf("%s\n", &toVtx) 48 | g.addEdgeToGraph(fromVtx, toVtx) 49 | } 50 | -------------------------------------------------------------------------------- /algorithms/graphs/bridge_detection/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | var id float64 9 | var ids map[string]float64 10 | var low map[string]float64 11 | 12 | func init() { 13 | id = 0 14 | ids = make(map[string]float64) 15 | low = make(map[string]float64) 16 | } 17 | 18 | // DFS traverses a graph using dfs technique 19 | func (g graph) findBridges() []string { 20 | visited := make(map[string]bool) 21 | bridges := make([]string, 0) 22 | if len(g) == 0 { 23 | fmt.Println("\n-- Graph is empty. --") 24 | return nil 25 | } 26 | for i := range g { 27 | if !visited[i] { 28 | bridges = g.dfs(i, visited, "-1", bridges) 29 | } 30 | } 31 | return bridges 32 | } 33 | 34 | // dfsHelper recursively calls itself to solve dfs traversal 35 | func (g graph) dfs(at string, visited map[string]bool, parent string, bridges []string) []string { 36 | visited[at] = true 37 | id++ 38 | low[at] = id 39 | ids[at] = id 40 | for i := range g[at] { 41 | to := g[at][i] 42 | if to == parent { 43 | continue 44 | } 45 | if !visited[to] { 46 | bridges = g.dfs(to, visited, at, bridges) 47 | low[at] = math.Min(low[at], low[to]) 48 | if ids[at] < low[to] { 49 | bridges = append(bridges, at) 50 | bridges = append(bridges, to) 51 | } 52 | } else { 53 | low[at] = math.Min(low[at], ids[to]) 54 | } 55 | } 56 | return bridges 57 | } 58 | 59 | func (g graph) simpleDisplay() { 60 | fmt.Println("") 61 | for i := range g { 62 | fmt.Print(i, " => ") 63 | for j := range g[i] { 64 | fmt.Print(g[i][j] + " ") 65 | } 66 | fmt.Println("") 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /algorithms/graphs/dijkstra/dijkstra.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // TODO: replace 999 with infinity 9 | 10 | // Dijkstra starts dijkstra algorithm on a given graph 11 | func Dijkstra(start, finish string) { 12 | var smallest string 13 | for vertex := range graph { 14 | if vertex == start { 15 | distances[vertex] = 0 16 | insertNodeInQueue(vertex, 0) 17 | } else { 18 | distances[vertex] = math.Inf(1) 19 | insertNodeInQueue(vertex, math.Inf(1)) 20 | } 21 | previous[vertex] = "" 22 | } 23 | 24 | for len(pqueue) != 0 { 25 | smallest = Dequeue().name 26 | if smallest == finish { 27 | // Build path here 28 | for i := range previous { 29 | j := i 30 | fmt.Print("\nCost: ", distances[i], " units") 31 | fmt.Print(", Path: ") 32 | for j != "" { 33 | if previous[j] == "" { 34 | fmt.Print(j, "\n") 35 | } else { 36 | fmt.Print(j, " <= ") 37 | } 38 | j = previous[j] 39 | } 40 | } 41 | return 42 | } 43 | if smallest != "" || distances[smallest] != math.Inf(1) { 44 | for neighbor := range graph[smallest] { 45 | nextNode := graph[smallest][neighbor] 46 | least := distances[smallest] + nextNode.weight 47 | if least < distances[nextNode.node] { 48 | distances[nextNode.node] = least 49 | previous[nextNode.node] = smallest 50 | insertNodeInQueue(nextNode.node, least) 51 | } 52 | } 53 | } 54 | } 55 | 56 | } 57 | 58 | var graph map[string][]Node 59 | var pqueue []*QueueNode 60 | var distances map[string]float64 61 | var previous map[string]string 62 | 63 | func init() { 64 | graph = make(map[string][]Node) 65 | distances = make(map[string]float64) 66 | previous = make(map[string]string) 67 | } 68 | 69 | func main() { 70 | i := 0 71 | for i == 0 { 72 | fmt.Println("\n1. ADD A VERTEX") 73 | fmt.Println("2. ADD AN EDGE") 74 | fmt.Println("3. RUN DIJKSTRA ALGORITHM") 75 | fmt.Println("4. EXIT") 76 | var choice int 77 | fmt.Print("Enter your choice: ") 78 | fmt.Scanf("%d\n", &choice) 79 | switch choice { 80 | case 1: 81 | addVertex() 82 | case 2: 83 | addEdge() 84 | case 3: 85 | DijkstraInit() 86 | case 4: 87 | i = 1 88 | default: 89 | fmt.Println("Command not recognized.") 90 | } 91 | } 92 | } 93 | 94 | // DijkstraInit will take necessary input values from user to run 95 | // dijkstra algorithm 96 | func DijkstraInit() { 97 | var start, finish string 98 | fmt.Print("Enter the initial node: ") 99 | fmt.Scanf("%s\n", &start) 100 | fmt.Print("Enter the destination node: ") 101 | fmt.Scanf("%s\n", &finish) 102 | Dijkstra(start, finish) 103 | } 104 | 105 | func simpleDisplay() { 106 | fmt.Println("") 107 | for i := range graph { 108 | fmt.Print(i, " => ") 109 | for j := range graph[i] { 110 | fmt.Print(graph[i][j]) 111 | } 112 | fmt.Println("") 113 | } 114 | } 115 | 116 | // addVertexToGraph("a") 117 | // addVertexToGraph("b") 118 | // addVertexToGraph("c") 119 | // addVertexToGraph("d") 120 | // addVertexToGraph("e") 121 | // addVertexToGraph("f") 122 | // addEdgeToGraph("a", "b", float64(4)) 123 | // addEdgeToGraph("a", "c", float64(2)) 124 | // addEdgeToGraph("b", "e", float64(3)) 125 | // addEdgeToGraph("c", "d", float64(2)) 126 | // addEdgeToGraph("c", "f", float64(4)) 127 | // addEdgeToGraph("d", "e", float64(3)) 128 | // addEdgeToGraph("d", "f", float64(1)) 129 | // addEdgeToGraph("e", "f", float64(1)) 130 | // Dijkstra("a", "e") 131 | -------------------------------------------------------------------------------- /algorithms/graphs/dijkstra/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Node is a single node in a graph list 6 | type Node struct { 7 | node string 8 | weight float64 9 | } 10 | 11 | func addVertexToGraph(vtx string) { 12 | if graph[vtx] != nil { 13 | fmt.Println("\n-- Vertex already exists. --") 14 | return 15 | } 16 | graph[vtx] = make([]Node, 0) 17 | } 18 | 19 | func addEdgeToGraph(fromVtx, toVtx string, edgeValue float64) { 20 | if graph[fromVtx] == nil { // check if initial vertex exists 21 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 22 | return 23 | } 24 | for i := range graph[fromVtx] { // check if edge already exists 25 | if graph[fromVtx][i].node == toVtx { 26 | fmt.Println("\n-- Edge between " + fromVtx + " and " + toVtx + " already exists. --") 27 | return 28 | } 29 | } 30 | if graph[toVtx] == nil { // create new destination vertext if it does not exists 31 | graph[toVtx] = make([]Node, 0) 32 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 33 | } 34 | 35 | graph[fromVtx] = append(graph[fromVtx], Node{node: toVtx, weight: edgeValue}) 36 | graph[toVtx] = append(graph[toVtx], Node{node: fromVtx, weight: edgeValue}) 37 | } 38 | 39 | func addVertex() { 40 | var vtxName string 41 | fmt.Print("Enter the name of vertex: ") 42 | fmt.Scanf("%s\n", &vtxName) 43 | addVertexToGraph(vtxName) 44 | } 45 | 46 | func addEdge() { 47 | var fromVtx, toVtx string 48 | var edgeValue int 49 | fmt.Print("Enter the initial vertex name: ") 50 | fmt.Scanf("%s\n", &fromVtx) 51 | fmt.Print("Enter the destination vertex name: ") 52 | fmt.Scanf("%s\n", &toVtx) 53 | fmt.Print("Enter the weight of edge: ") 54 | fmt.Scanf("%d\n", &edgeValue) 55 | addEdgeToGraph(fromVtx, toVtx, float64(edgeValue)) 56 | } 57 | -------------------------------------------------------------------------------- /algorithms/graphs/dijkstra/priority_queue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // QueueNode is a single node in a queue 9 | type QueueNode struct { 10 | name string 11 | priority float64 12 | } 13 | 14 | // Enqueue inserts a node in a heap 15 | func Enqueue(node *QueueNode) { 16 | pqueue = append(pqueue, node) 17 | minHeapify() 18 | } 19 | 20 | func minHeapify() { 21 | idx := len(pqueue) - 1 22 | element := pqueue[idx] 23 | for idx > 0 { 24 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 25 | parent := pqueue[parentIdx] 26 | if element.priority >= parent.priority { 27 | break 28 | } 29 | pqueue[parentIdx] = element 30 | pqueue[idx] = parent 31 | idx = parentIdx 32 | } 33 | } 34 | 35 | // Dequeue will remove a node from heap 36 | func Dequeue() *QueueNode { 37 | if len(pqueue) == 0 || pqueue[0] == nil { 38 | fmt.Println("\n-- Heap is empty. --") 39 | return nil 40 | } 41 | min := pqueue[0] 42 | end := pqueue[len(pqueue)-1] 43 | pqueue = pqueue[0 : len(pqueue)-1] 44 | if len(pqueue) > 0 { 45 | pqueue[0] = end 46 | bubbleDown() 47 | } 48 | return min 49 | } 50 | 51 | func bubbleDown() { 52 | idx := 0 53 | length := len(pqueue) 54 | element := pqueue[0] 55 | for { 56 | leftChildIdx := (2 * idx) + 1 57 | rightChildIdx := (2 * idx) + 2 58 | var leftChild, rightChild *QueueNode 59 | var swap int 60 | 61 | if leftChildIdx < length { 62 | leftChild = pqueue[leftChildIdx] 63 | if leftChild.priority < element.priority { 64 | swap = leftChildIdx 65 | } 66 | } 67 | if rightChildIdx < length { 68 | rightChild = pqueue[rightChildIdx] 69 | if (rightChild.priority < element.priority && swap == 0) || (rightChild.priority < leftChild.priority && swap != 0) { 70 | swap = rightChildIdx 71 | } 72 | } 73 | 74 | if swap == 0 { 75 | break 76 | } 77 | pqueue[idx] = pqueue[swap] 78 | pqueue[swap] = element 79 | idx = swap 80 | } 81 | } 82 | 83 | func insertNodeInQueue(name string, priority float64) { 84 | newNode := &QueueNode{name: name, priority: priority} 85 | Enqueue(newNode) 86 | } 87 | 88 | func display() { 89 | if len(pqueue) == 0 { 90 | fmt.Println("\n-- Heap is empty. --") 91 | return 92 | } 93 | for i := range pqueue { 94 | fmt.Println(pqueue[i].name, pqueue[i].priority) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /algorithms/graphs/floyd_warshall/floyd_warshall.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Note: Adjacency list representation of graph was already implemented by me in previous graphs section. Hence I have 4 | // modified few things which converts this adjacency list to adjacency matrix and then the floyd warshall algorithm is 5 | // implemented. However you can directly take user inputs and add it in adjacency matrix. 6 | 7 | import ( 8 | "fmt" 9 | "math" 10 | ) 11 | 12 | type vertexNumber struct { 13 | value int 14 | name string 15 | } 16 | 17 | var adjacencyMatrix [][]float64 18 | var vertices map[string]int 19 | 20 | // FloydWarshall calculates all points shortest path from adjacency matrix of a graph 21 | func FloydWarshall() { 22 | for k := range adjacencyMatrix { 23 | for i := range adjacencyMatrix { 24 | for j := range adjacencyMatrix { 25 | adjacencyMatrix[i][j] = math.Min(adjacencyMatrix[i][j], adjacencyMatrix[i][k]+adjacencyMatrix[k][j]) 26 | } 27 | } 28 | } 29 | fmt.Println("\n-- Final Adjacency Matrix --") 30 | for i := range adjacencyMatrix { 31 | fmt.Println(adjacencyMatrix[i]) 32 | } 33 | } 34 | 35 | func init() { 36 | vertices = make(map[string]int) 37 | } 38 | 39 | func main() { 40 | fmt.Println("\n-- Floyd Warshall's Algorithm --") 41 | i := 0 42 | for i == 0 { 43 | fmt.Println("\n1. ADD A VERTEX") 44 | fmt.Println("2. ADD AN EDGE") 45 | fmt.Println("3. SIMPLE DISPLAY") 46 | fmt.Println("4. RUN FLOYD WARSHALL") 47 | fmt.Println("5. EXIT") 48 | var choice int 49 | fmt.Print("Enter your choice: ") 50 | fmt.Scanf("%d\n", &choice) 51 | switch choice { 52 | case 1: 53 | addVertex() 54 | case 2: 55 | addEdge() 56 | case 3: 57 | simpleDisplay() 58 | case 4: 59 | constructMatrix() 60 | FloydWarshall() 61 | case 5: 62 | i = 1 63 | default: 64 | fmt.Println("Command not recognized.") 65 | } 66 | } 67 | } 68 | 69 | // generates a adjacency matrix from adjacency list 70 | func constructMatrix() { 71 | count := 0 72 | adjacencyMatrix = make([][]float64, len(vertices)) 73 | for i := range graph { 74 | adjacencyMatrix[vertices[i]] = make([]float64, len(vertices)) 75 | for j := range graph[i] { 76 | adjacencyMatrix[vertices[i]][vertices[graph[i][j].name]] = float64(graph[i][j].value) 77 | } 78 | count++ 79 | } 80 | 81 | for i := range adjacencyMatrix { 82 | for j := range adjacencyMatrix[i] { 83 | if i != j && adjacencyMatrix[i][j] == 0 { 84 | adjacencyMatrix[i][j] = math.Inf(0) 85 | } 86 | } 87 | } 88 | fmt.Println("\n-- Initial Adjacency Matrix --") 89 | for i := range adjacencyMatrix { 90 | fmt.Println(adjacencyMatrix[i]) 91 | } 92 | } 93 | 94 | func simpleDisplay() { 95 | fmt.Println("") 96 | for i := range graph { 97 | fmt.Print(i, " => ") 98 | for j := range graph[i] { 99 | fmt.Print(graph[i][j]) 100 | } 101 | fmt.Println("") 102 | } 103 | } 104 | 105 | // addVertexToGraph("a") 106 | // addVertexToGraph("b") 107 | // addVertexToGraph("c") 108 | // addVertexToGraph("d") 109 | // addVertexToGraph("e") 110 | // addVertexToGraph("f") 111 | // addEdgeToGraph("a", "b", 18) 112 | // addEdgeToGraph("a", "c", 20) 113 | // addEdgeToGraph("b", "d", 4) 114 | // addEdgeToGraph("c", "e", 10) 115 | // addEdgeToGraph("d", "e", 15) 116 | // addEdgeToGraph("d", "f", 23) 117 | // addEdgeToGraph("e", "f", 7) 118 | // addEdgeToGraph("d", "a", 5) 119 | // addEdgeToGraph("e", "a", 17) 120 | // addEdgeToGraph("b", "e", 21) 121 | -------------------------------------------------------------------------------- /algorithms/graphs/floyd_warshall/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Node is a single node in a graph list 6 | type Node struct { 7 | name string 8 | value int 9 | } 10 | 11 | var graph map[string][]Node 12 | 13 | func init() { 14 | graph = make(map[string][]Node) 15 | } 16 | 17 | func addVertexToGraph(vtx string) { 18 | if graph[vtx] != nil { 19 | fmt.Println("\n-- Vertex already exists. --") 20 | return 21 | } 22 | vertices[vtx] = len(vertices) 23 | graph[vtx] = make([]Node, 0) 24 | } 25 | 26 | func addEdgeToGraph(fromVtx, toVtx string, edgeValue int) { 27 | if graph[fromVtx] == nil { // check if initial vertex exists 28 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 29 | return 30 | } 31 | for i := range graph[fromVtx] { // check if edge already exists 32 | if graph[fromVtx][i].name == toVtx { 33 | fmt.Println("\n-- Edge from " + fromVtx + " to " + toVtx + " already exists. --") 34 | return 35 | } 36 | } 37 | if graph[toVtx] == nil { // create new destination vertext if it does not exists 38 | vertices[toVtx] = len(vertices) 39 | graph[toVtx] = make([]Node, 0) 40 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 41 | } 42 | 43 | graph[fromVtx] = append(graph[fromVtx], Node{name: toVtx, value: edgeValue}) 44 | } 45 | 46 | func addVertex() { 47 | var vtxName string 48 | fmt.Print("Enter the name of vertex: ") 49 | fmt.Scanf("%s\n", &vtxName) 50 | addVertexToGraph(vtxName) 51 | } 52 | 53 | func addEdge() { 54 | var fromVtx, toVtx string 55 | var edgeValue int 56 | fmt.Print("Enter the initial vertex name: ") 57 | fmt.Scanf("%s\n", &fromVtx) 58 | fmt.Print("Enter the destination vertex name: ") 59 | fmt.Scanf("%s\n", &toVtx) 60 | fmt.Print("Enter the weight of edge: ") 61 | fmt.Scanf("%d\n", &edgeValue) 62 | addEdgeToGraph(fromVtx, toVtx, edgeValue) 63 | } 64 | -------------------------------------------------------------------------------- /algorithms/graphs/kruskals/heap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // HeapNode is a single node in a queue 9 | type HeapNode struct { 10 | name string 11 | priority float64 12 | } 13 | 14 | // Enqueue inserts a node in a heap 15 | func Enqueue(node *HeapNode) { 16 | heap = append(heap, node) 17 | hashMap[node.name] = len(heap) - 1 18 | minHeapify(-1) 19 | } 20 | 21 | func minHeapify(idx int) { 22 | if idx == -1 { 23 | idx = len(heap) - 1 24 | } 25 | element := heap[idx] 26 | for idx > 0 { 27 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 28 | parent := heap[parentIdx] 29 | if element.priority >= parent.priority { 30 | break 31 | } 32 | heap[parentIdx] = element 33 | hashMap[element.name] = parentIdx 34 | heap[idx] = parent 35 | hashMap[parent.name] = idx 36 | idx = parentIdx 37 | } 38 | } 39 | 40 | // Dequeue will remove a node from heap 41 | func Dequeue() *HeapNode { 42 | if len(heap) == 0 || heap[0] == nil { 43 | fmt.Println("\n-- Heap is empty. --") 44 | return nil 45 | } 46 | min := heap[0] 47 | end := heap[len(heap)-1] 48 | heap = heap[0 : len(heap)-1] 49 | hashMap[end.name] = 0 50 | if len(heap) > 0 { 51 | heap[0] = end 52 | bubbleDown() 53 | } 54 | delete(hashMap, min.name) 55 | return min 56 | } 57 | 58 | func bubbleDown() { 59 | idx := 0 60 | length := len(heap) 61 | element := heap[0] 62 | for { 63 | leftChildIdx := (2 * idx) + 1 64 | rightChildIdx := (2 * idx) + 2 65 | var leftChild, rightChild *HeapNode 66 | var swap int 67 | 68 | if leftChildIdx < length { 69 | leftChild = heap[leftChildIdx] 70 | if leftChild.priority < element.priority { 71 | swap = leftChildIdx 72 | } 73 | } 74 | if rightChildIdx < length { 75 | rightChild = heap[rightChildIdx] 76 | if (rightChild.priority < element.priority && swap == 0) || (rightChild.priority < leftChild.priority && swap != 0) { 77 | swap = rightChildIdx 78 | } 79 | } 80 | 81 | if swap == 0 { 82 | break 83 | } 84 | heap[idx] = heap[swap] 85 | hashMap[heap[swap].name] = idx 86 | heap[swap] = element 87 | hashMap[element.name] = swap 88 | idx = swap 89 | } 90 | } 91 | 92 | // DecreaseKey will decrease the priority of a given node positioned by index in a heap 93 | // will then call minHeapify to satisfy the min heap property 94 | func DecreaseKey(index int, newValue float64) { 95 | heap[index].priority = newValue 96 | minHeapify(index) 97 | } 98 | 99 | var heap []*HeapNode 100 | 101 | // hasMap maps heap values to heap indexes 102 | var hashMap map[string]int 103 | 104 | func init() { 105 | hashMap = make(map[string]int) 106 | } 107 | 108 | func insertNode(name string, priority float64) { 109 | newNode := &HeapNode{name: name, priority: priority} 110 | Enqueue(newNode) 111 | } 112 | -------------------------------------------------------------------------------- /algorithms/graphs/kruskals/kruskals.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Kruskals will run kruskal's algorithm on a given graph 6 | func (g graph) Kruskals(start string) { 7 | count := 0 8 | mst := make(graph) 9 | for count != len(g)-1 { 10 | node := Dequeue() 11 | mst.addVertexToGraph(string(node.name[0])) 12 | mst.addVertexToGraph(string(node.name[1])) 13 | mst.addEdgeToGraph(string(node.name[0]), string(node.name[1]), node.priority) 14 | isCyclic := mst.DFS(string(node.name[0])) 15 | if isCyclic { 16 | mst.removeEdgeFromGraph(string(node.name[0]), string(node.name[1])) 17 | count-- 18 | } 19 | count++ 20 | } 21 | mst.printKruskals(start) 22 | } 23 | 24 | var uniqueEdges []Edge 25 | 26 | func init() { 27 | uniqueEdges = make([]Edge, 0) 28 | } 29 | 30 | func main() { 31 | g := make(graph) 32 | i := 0 33 | for i == 0 { 34 | fmt.Println("\n1. ADD A VERTEX") 35 | fmt.Println("2. ADD AN EDGE") 36 | fmt.Println("3. RUN PRIM's ALGORITHM") 37 | fmt.Println("4. SIMPLE DISPLAY") 38 | fmt.Println("5. EXIT") 39 | var choice int 40 | fmt.Print("Enter your choice: ") 41 | fmt.Scanf("%d\n", &choice) 42 | switch choice { 43 | case 1: 44 | g.addVertex() 45 | case 2: 46 | g.addEdge() 47 | case 3: 48 | g.startKruskals() 49 | case 4: 50 | g.simpleDisplay() 51 | case 5: 52 | i = 1 53 | default: 54 | fmt.Println("Command not recognized.") 55 | } 56 | } 57 | } 58 | 59 | func (g graph) startKruskals() { 60 | var start string 61 | fmt.Print("Enter the source vertex: ") 62 | fmt.Scanf("%s\n", &start) 63 | for _, edge := range uniqueEdges { 64 | insertNode(edge.src+edge.dest, edge.value) 65 | } 66 | g.Kruskals(start) 67 | } 68 | 69 | func (g graph) printKruskals(start string) { 70 | visited := make(map[string]bool) 71 | for i := range g { 72 | for _, node := range g[i] { 73 | if !visited[node.name+i] { 74 | fmt.Println(i, "-", node.name, "=>", node.value) 75 | } 76 | visited[node.name+i] = true 77 | visited[i+node.name] = true 78 | } 79 | } 80 | } 81 | 82 | // g.addVertexToGraph("0") 83 | // g.addVertexToGraph("1") 84 | // g.addVertexToGraph("2") 85 | // g.addVertexToGraph("3") 86 | // g.addVertexToGraph("4") 87 | // g.addVertexToGraph("5") 88 | // g.addVertexToGraph("6") 89 | // g.addVertexToGraph("7") 90 | // g.addVertexToGraph("8") 91 | // g.addEdgeToGraph("0", "1", 4) 92 | // g.addEdgeToGraph("0", "7", 8) 93 | // g.addEdgeToGraph("1", "2", 8) 94 | // g.addEdgeToGraph("1", "7", 11) 95 | // g.addEdgeToGraph("2", "3", 7) 96 | // g.addEdgeToGraph("2", "5", 4) 97 | // g.addEdgeToGraph("2", "8", 2) 98 | // g.addEdgeToGraph("3", "4", 9) 99 | // g.addEdgeToGraph("3", "5", 14) 100 | // g.addEdgeToGraph("4", "5", 10) 101 | // g.addEdgeToGraph("5", "6", 2) 102 | // g.addEdgeToGraph("6", "8", 6) 103 | // g.addEdgeToGraph("6", "7", 1) 104 | // g.addEdgeToGraph("7", "8", 7) 105 | // g.startKruskals() 106 | -------------------------------------------------------------------------------- /algorithms/graphs/prims/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // GraphNode is a node in a graph list 6 | type GraphNode struct { 7 | name string 8 | value float64 9 | } 10 | 11 | // graph is a data structure which will be holding a graph 12 | type graph map[string][]GraphNode 13 | 14 | // addVertexToGraph adds a vertex to graph 15 | func (g graph) addVertexToGraph(vtx string) { 16 | if g[vtx] != nil { 17 | fmt.Println("\n-- Vertex already exists. --") 18 | return 19 | } 20 | g[vtx] = make([]GraphNode, 0) 21 | } 22 | 23 | // addEdgeToGraph adds an edge to a graph 24 | func (g graph) addEdgeToGraph(fromVtx, toVtx string, edgeValue float64) { 25 | if g[fromVtx] == nil { // check if initial vertex exists 26 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 27 | return 28 | } 29 | for i := range g[fromVtx] { // check if edge already exists 30 | if g[fromVtx][i].name == toVtx { 31 | fmt.Println("\n-- Edge between " + fromVtx + " and " + toVtx + " already exists. --") 32 | return 33 | } 34 | } 35 | if g[toVtx] == nil { // create new destination vertext if it does not exists 36 | g[toVtx] = make([]GraphNode, 0) 37 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 38 | } 39 | 40 | g[fromVtx] = append(g[fromVtx], GraphNode{name: toVtx, value: edgeValue}) 41 | g[toVtx] = append(g[toVtx], GraphNode{name: fromVtx, value: edgeValue}) 42 | } 43 | 44 | // addVertex asks user to enter vertex name 45 | func (g graph) addVertex() { 46 | var vtxName string 47 | fmt.Print("Enter the name of vertex: ") 48 | fmt.Scanf("%s\n", &vtxName) 49 | g.addVertexToGraph(vtxName) 50 | } 51 | 52 | // addEdge asks user to enter necessary values before adding an edge to graph 53 | func (g graph) addEdge() { 54 | var fromVtx, toVtx string 55 | var edgeValue float64 56 | fmt.Print("Enter the initial vertex name: ") 57 | fmt.Scanf("%s\n", &fromVtx) 58 | fmt.Print("Enter the destination vertex name: ") 59 | fmt.Scanf("%s\n", &toVtx) 60 | fmt.Print("Enter the weight of edge: ") 61 | fmt.Scanf("%d\n", &edgeValue) 62 | g.addEdgeToGraph(fromVtx, toVtx, edgeValue) 63 | } 64 | 65 | // simpleDisplay simply displays a graph 66 | func (g graph) simpleDisplay() { 67 | fmt.Println("") 68 | for i := range g { 69 | fmt.Print(i, " => ") 70 | for j := range g[i] { 71 | fmt.Print(g[i][j]) 72 | } 73 | fmt.Println("") 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /algorithms/graphs/prims/heap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // HeapNode is a single node in a queue 9 | type HeapNode struct { 10 | name string 11 | priority float64 12 | } 13 | 14 | // Enqueue inserts a node in a heap 15 | func Enqueue(node *HeapNode) { 16 | heap = append(heap, node) 17 | hashMap[node.name] = len(heap) - 1 18 | minHeapify(-1) 19 | } 20 | 21 | func minHeapify(idx int) { 22 | if idx == -1 { 23 | idx = len(heap) - 1 24 | } 25 | element := heap[idx] 26 | for idx > 0 { 27 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 28 | parent := heap[parentIdx] 29 | if element.priority >= parent.priority { 30 | break 31 | } 32 | heap[parentIdx] = element 33 | hashMap[element.name] = parentIdx 34 | heap[idx] = parent 35 | hashMap[parent.name] = idx 36 | idx = parentIdx 37 | } 38 | } 39 | 40 | // Dequeue will remove a node from heap 41 | func Dequeue() *HeapNode { 42 | if len(heap) == 0 || heap[0] == nil { 43 | fmt.Println("\n-- Heap is empty. --") 44 | return nil 45 | } 46 | min := heap[0] 47 | end := heap[len(heap)-1] 48 | heap = heap[0 : len(heap)-1] 49 | hashMap[end.name] = 0 50 | if len(heap) > 0 { 51 | heap[0] = end 52 | bubbleDown() 53 | } 54 | delete(hashMap, min.name) 55 | return min 56 | } 57 | 58 | func bubbleDown() { 59 | idx := 0 60 | length := len(heap) 61 | element := heap[0] 62 | for { 63 | leftChildIdx := (2 * idx) + 1 64 | rightChildIdx := (2 * idx) + 2 65 | var leftChild, rightChild *HeapNode 66 | var swap int 67 | 68 | if leftChildIdx < length { 69 | leftChild = heap[leftChildIdx] 70 | if leftChild.priority < element.priority { 71 | swap = leftChildIdx 72 | } 73 | } 74 | if rightChildIdx < length { 75 | rightChild = heap[rightChildIdx] 76 | if (rightChild.priority < element.priority && swap == 0) || (rightChild.priority < leftChild.priority && swap != 0) { 77 | swap = rightChildIdx 78 | } 79 | } 80 | 81 | if swap == 0 { 82 | break 83 | } 84 | heap[idx] = heap[swap] 85 | hashMap[heap[swap].name] = idx 86 | heap[swap] = element 87 | hashMap[element.name] = swap 88 | idx = swap 89 | } 90 | } 91 | 92 | // DecreaseKey will decrease the priority of a given node positioned by index in a heap 93 | // will then call minHeapify to satisfy the min heap property 94 | func DecreaseKey(index int, newValue float64) { 95 | heap[index].priority = newValue 96 | minHeapify(index) 97 | } 98 | 99 | var heap []*HeapNode 100 | 101 | // hasMap maps heap values to heap indexes 102 | var hashMap map[string]int 103 | 104 | func init() { 105 | hashMap = make(map[string]int) 106 | } 107 | 108 | func insertNode(name string, priority float64) { 109 | newNode := &HeapNode{name: name, priority: priority} 110 | Enqueue(newNode) 111 | } 112 | -------------------------------------------------------------------------------- /algorithms/graphs/topological_sort/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type graph map[string][]string 6 | 7 | func (g graph) addVertexToGraph(vtx string) { 8 | if g[vtx] != nil { 9 | fmt.Println("\n-- Vertex already exists. --") 10 | return 11 | } 12 | g[vtx] = make([]string, 0) 13 | } 14 | 15 | func (g graph) addEdgeToGraph(fromVtx, toVtx string) { 16 | if g[fromVtx] == nil { // check if initial vertex exists 17 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 18 | return 19 | } 20 | for i := range g[fromVtx] { // check if edge already exists 21 | if g[fromVtx][i] == toVtx { 22 | fmt.Println("\n-- Edge from " + fromVtx + " to " + toVtx + " already exists. --") 23 | return 24 | } 25 | } 26 | if g[toVtx] == nil { // create new destination vertext if it does not exists 27 | g[toVtx] = make([]string, 0) 28 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 29 | } 30 | 31 | g[fromVtx] = append(g[fromVtx], toVtx) 32 | } 33 | 34 | // detectDFS traverses a graph using dfs technique to detect a cycle in a graph 35 | func (g graph) detectDFS() ([]string, bool) { 36 | visited := make(map[string]bool) 37 | stack := make(map[string]string) // keeps track of stack 38 | var cycle bool 39 | var result []string 40 | var finalResult []string 41 | if len(g) == 0 { 42 | fmt.Println("\n-- Graph is empty. --") 43 | return nil, false 44 | } 45 | for i := range g { 46 | if !visited[i] { 47 | stack[i] = i 48 | result, cycle = g.dfsHelper(i, visited, result, stack) 49 | 50 | // appending the result into finalResult in reverse order making topological sort 51 | for i := len(result) - 1; i >= 0; i-- { 52 | finalResult = append(finalResult, result[i]) 53 | } 54 | result = make([]string, 0) 55 | 56 | delete(stack, i) 57 | if cycle { 58 | return nil, cycle 59 | } 60 | } 61 | } 62 | return finalResult, cycle 63 | } 64 | 65 | // dfsHelper recursively calls itself to solve dfs traversal 66 | func (g graph) dfsHelper(vtx string, visited map[string]bool, result []string, stack map[string]string) ([]string, bool) { 67 | visited[vtx] = true 68 | cycle := false 69 | result = append(result, vtx) 70 | for i := range g[vtx] { 71 | if stack[g[vtx][i]] == g[vtx][i] { // cycle detection logic is here 72 | return nil, true 73 | } 74 | if !visited[g[vtx][i]] { 75 | stack[g[vtx][i]] = g[vtx][i] 76 | result, cycle = g.dfsHelper(g[vtx][i], visited, result, stack) 77 | delete(stack, g[vtx][i]) 78 | return result, cycle 79 | } 80 | } 81 | return result, cycle 82 | } 83 | 84 | func (g graph) addVertex() { 85 | var vtxName string 86 | fmt.Print("Enter the name of vertex: ") 87 | fmt.Scanf("%s\n", &vtxName) 88 | g.addVertexToGraph(vtxName) 89 | } 90 | 91 | func (g graph) addEdge() { 92 | var fromVtx, toVtx string 93 | fmt.Print("Enter the initial vertex name: ") 94 | fmt.Scanf("%s\n", &fromVtx) 95 | fmt.Print("Enter the destination vertex name: ") 96 | fmt.Scanf("%s\n", &toVtx) 97 | g.addEdgeToGraph(fromVtx, toVtx) 98 | } 99 | -------------------------------------------------------------------------------- /algorithms/graphs/topological_sort/topological_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | g := make(graph) 7 | i := 0 8 | for i == 0 { 9 | fmt.Println("\n1. ADD A VERTEX") 10 | fmt.Println("2. ADD AN EDGE") 11 | fmt.Println("3. RUN TOPOLOGICAL SORT") 12 | fmt.Println("4. EXIT") 13 | var choice int 14 | fmt.Print("Enter your choice: ") 15 | fmt.Scanf("%d\n", &choice) 16 | switch choice { 17 | case 1: 18 | g.addVertex() 19 | case 2: 20 | g.addEdge() 21 | case 3: 22 | g.runTopological() 23 | case 4: 24 | i = 1 25 | default: 26 | fmt.Println("Command not recognized.") 27 | } 28 | } 29 | } 30 | 31 | func (g graph) runTopological() { 32 | result, cycle := g.detectDFS() 33 | if cycle { 34 | fmt.Println("\n-- Can't run Topological Sort. The graph is cyclic. --") 35 | } else { 36 | fmt.Println("\nSuccessfully ran Topological Sort:") 37 | for i := range result { 38 | fmt.Print(" ", result[i]) 39 | } 40 | fmt.Println("") 41 | } 42 | } 43 | 44 | // cyclic 45 | // g.addVertexToGraph("0") 46 | // g.addVertexToGraph("1") 47 | // g.addVertexToGraph("2") 48 | // g.addVertexToGraph("3") 49 | // g.addVertexToGraph("4") 50 | // g.addEdgeToGraph("0", "1") 51 | // g.addEdgeToGraph("1", "2") 52 | // g.addEdgeToGraph("2", "4") 53 | // g.addEdgeToGraph("2", "3") 54 | // g.addEdgeToGraph("3", "0") 55 | // g.addEdgeToGraph("4", "2") 56 | 57 | // acyclic 58 | // g.addVertexToGraph("0") 59 | // g.addVertexToGraph("1") 60 | // g.addVertexToGraph("2") 61 | // g.addVertexToGraph("3") 62 | // g.addVertexToGraph("4") 63 | // g.addEdgeToGraph("0", "1") 64 | // g.addEdgeToGraph("1", "2") 65 | // g.addEdgeToGraph("2", "3") 66 | // g.addEdgeToGraph("4", "2") 67 | -------------------------------------------------------------------------------- /algorithms/graphs/traversals/cd_directed_graph_traversals/cycle_detection.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | g := make(graph) 7 | i := 0 8 | for i == 0 { 9 | fmt.Println("\n1. ADD A VERTEX") 10 | fmt.Println("2. ADD AN EDGE") 11 | fmt.Println("3. DETECT CYCLE USING DFS") 12 | fmt.Println("4. DETECT CYCLE USING BFS") 13 | fmt.Println("5. SIMPLE DISPLAY") 14 | fmt.Println("6. EXIT") 15 | var choice int 16 | fmt.Print("Enter your choice: ") 17 | fmt.Scanf("%d\n", &choice) 18 | switch choice { 19 | case 1: 20 | g.addVertex() 21 | case 2: 22 | g.addEdge() 23 | case 3: 24 | _, cycle := g.detectDFS() 25 | if cycle { 26 | fmt.Println("\n-- Given graph is cyclic. --") 27 | } else { 28 | fmt.Println("\n-- Given graph is acyclic. --") 29 | } 30 | case 4: 31 | result := g.detectBFS() 32 | fmt.Println(result) 33 | case 5: 34 | g.simpleDisplay() 35 | case 6: 36 | i = 1 37 | default: 38 | fmt.Println("Command not recognized.") 39 | } 40 | } 41 | } 42 | 43 | // cyclic 44 | // g.addVertexToGraph("0") 45 | // g.addVertexToGraph("1") 46 | // g.addVertexToGraph("2") 47 | // g.addVertexToGraph("3") 48 | // g.addVertexToGraph("4") 49 | // g.addEdgeToGraph("0", "1") 50 | // g.addEdgeToGraph("1", "2") 51 | // g.addEdgeToGraph("2", "4") 52 | // g.addEdgeToGraph("2", "3") 53 | // g.addEdgeToGraph("3", "0") 54 | // g.addEdgeToGraph("4", "2") 55 | 56 | // acyclic 57 | // g.addVertexToGraph("0") 58 | // g.addVertexToGraph("1") 59 | // g.addVertexToGraph("2") 60 | // g.addVertexToGraph("3") 61 | // g.addVertexToGraph("4") 62 | // g.addEdgeToGraph("0", "1") 63 | // g.addEdgeToGraph("1", "2") 64 | // g.addEdgeToGraph("2", "3") 65 | // g.addEdgeToGraph("4", "2") 66 | -------------------------------------------------------------------------------- /algorithms/graphs/traversals/cd_directed_graph_traversals/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type graph map[string][]string 6 | 7 | func (g graph) addVertexToGraph(vtx string) { 8 | if g[vtx] != nil { 9 | fmt.Println("\n-- Vertex already exists. --") 10 | return 11 | } 12 | g[vtx] = make([]string, 0) 13 | } 14 | 15 | func (g graph) addEdgeToGraph(fromVtx, toVtx string) { 16 | if g[fromVtx] == nil { // check if initial vertex exists 17 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 18 | return 19 | } 20 | for i := range g[fromVtx] { // check if edge already exists 21 | if g[fromVtx][i] == toVtx { 22 | fmt.Println("\n-- Edge from " + fromVtx + " to " + toVtx + " already exists. --") 23 | return 24 | } 25 | } 26 | if g[toVtx] == nil { // create new destination vertext if it does not exists 27 | g[toVtx] = make([]string, 0) 28 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 29 | } 30 | 31 | g[fromVtx] = append(g[fromVtx], toVtx) 32 | } 33 | 34 | func (g graph) addVertex() { 35 | var vtxName string 36 | fmt.Print("Enter the name of vertex: ") 37 | fmt.Scanf("%s\n", &vtxName) 38 | g.addVertexToGraph(vtxName) 39 | } 40 | 41 | func (g graph) addEdge() { 42 | var fromVtx, toVtx string 43 | fmt.Print("Enter the initial vertex name: ") 44 | fmt.Scanf("%s\n", &fromVtx) 45 | fmt.Print("Enter the destination vertex name: ") 46 | fmt.Scanf("%s\n", &toVtx) 47 | g.addEdgeToGraph(fromVtx, toVtx) 48 | } 49 | -------------------------------------------------------------------------------- /algorithms/graphs/traversals/cd_directed_graph_traversals/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // detectDFS traverses a graph using dfs technique to detect a cycle in a graph 6 | func (g graph) detectDFS() ([]string, bool) { 7 | visited := make(map[string]bool) 8 | stack := make(map[string]string) // keeps track of stack 9 | var cycle bool 10 | var result []string 11 | if len(g) == 0 { 12 | fmt.Println("\n-- Graph is empty. --") 13 | return nil, false 14 | } 15 | for i := range g { 16 | if !visited[i] { 17 | stack[i] = i 18 | result, cycle = g.dfsHelper(i, visited, result, stack) 19 | delete(stack, i) 20 | if cycle { 21 | return nil, cycle 22 | } 23 | } 24 | } 25 | return result, cycle 26 | } 27 | 28 | // dfsHelper recursively calls itself to solve dfs traversal 29 | func (g graph) dfsHelper(vtx string, visited map[string]bool, result []string, stack map[string]string) ([]string, bool) { 30 | visited[vtx] = true 31 | cycle := false 32 | result = append(result, vtx) 33 | for i := range g[vtx] { 34 | if stack[g[vtx][i]] == g[vtx][i] { // cycle detection logic is here 35 | return nil, true 36 | } 37 | if !visited[g[vtx][i]] { 38 | stack[g[vtx][i]] = g[vtx][i] 39 | result, cycle = g.dfsHelper(g[vtx][i], visited, result, stack) 40 | delete(stack, g[vtx][i]) 41 | return result, cycle 42 | } 43 | } 44 | return result, cycle 45 | } 46 | 47 | // TODO: 48 | // detectBFS traverses a graph using dfs technique to detect cycle using BFS 49 | func (g graph) detectBFS() []string { 50 | 51 | if len(g) == 0 { 52 | fmt.Println("\n-- Graph is empty. --") 53 | return nil 54 | } 55 | 56 | visited := make(map[string]bool) 57 | 58 | var queue []string 59 | var result []string 60 | var currentVtx string 61 | 62 | for i := range g { 63 | if !visited[i] { 64 | visited[i] = true 65 | queue = append(queue, i) 66 | 67 | for len(queue) != 0 { 68 | currentVtx = queue[0] // get the element from the queue 69 | queue = queue[1:] // remove element from the queue 70 | result = append(result, currentVtx) // push the current vertex in result 71 | 72 | for j := range g[currentVtx] { 73 | if !visited[g[currentVtx][j]] { 74 | visited[g[currentVtx][j]] = true // mark as visited 75 | queue = append(queue, g[currentVtx][j]) // push neighbors of current vertex in the queue 76 | } 77 | } 78 | 79 | } 80 | 81 | } 82 | } 83 | 84 | return result 85 | } 86 | 87 | func (g graph) simpleDisplay() { 88 | fmt.Println("") 89 | for i := range g { 90 | fmt.Print(i, " => ") 91 | for j := range g[i] { 92 | fmt.Print(g[i][j] + " ") 93 | } 94 | fmt.Println("") 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /algorithms/graphs/traversals/cd_undirected_graph_traversals/cycle_detection.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | g := make(graph) 7 | 8 | i := 0 9 | for i == 0 { 10 | fmt.Println("\n1. ADD A VERTEX") 11 | fmt.Println("2. ADD AN EDGE") 12 | fmt.Println("3. DETECT CYCLE USING DFS") 13 | fmt.Println("4. DETECT CYCLE USING BFS") 14 | fmt.Println("5. SIMPLE DISPLAY") 15 | fmt.Println("6. EXIT") 16 | var choice int 17 | fmt.Print("Enter your choice: ") 18 | fmt.Scanf("%d\n", &choice) 19 | switch choice { 20 | case 1: 21 | g.addVertex() 22 | case 2: 23 | g.addEdge() 24 | case 3: 25 | result, cycle := g.detectDFS() 26 | if cycle { 27 | fmt.Println("\n-- Given graph is cyclic. --") 28 | } else if result != nil && !cycle { 29 | fmt.Println("\n-- Given graph is acyclic. --") 30 | } 31 | case 4: 32 | result := g.detectBFS() 33 | fmt.Println(result) 34 | case 5: 35 | g.simpleDisplay() 36 | case 6: 37 | i = 1 38 | default: 39 | fmt.Println("Command not recognized.") 40 | } 41 | } 42 | } 43 | 44 | func (g graph) simpleDisplay() { 45 | fmt.Println("") 46 | for i := range g { 47 | fmt.Print(i, " => ") 48 | for j := range g[i] { 49 | fmt.Print(g[i][j] + " ") 50 | } 51 | fmt.Println("") 52 | } 53 | } 54 | 55 | // cyclic 56 | // g.addVertexToGraph("0") 57 | // g.addVertexToGraph("1") 58 | // g.addVertexToGraph("2") 59 | // g.addVertexToGraph("3") 60 | // g.addVertexToGraph("4") 61 | // g.addEdgeToGraph("0", "1") 62 | // g.addEdgeToGraph("1", "2") 63 | // g.addEdgeToGraph("2", "4") 64 | // g.addEdgeToGraph("2", "3") 65 | // g.addEdgeToGraph("3", "0") 66 | // g.addEdgeToGraph("4", "2") 67 | 68 | // acyclic 69 | // g.addVertexToGraph("0") 70 | // g.addVertexToGraph("1") 71 | // g.addVertexToGraph("2") 72 | // g.addVertexToGraph("3") 73 | // g.addVertexToGraph("4") 74 | // g.addEdgeToGraph("0", "1") 75 | // g.addEdgeToGraph("1", "2") 76 | // g.addEdgeToGraph("2", "3") 77 | // g.addEdgeToGraph("4", "2") 78 | 79 | // cyclic 80 | // g.addVertexToGraph("0") 81 | // g.addVertexToGraph("1") 82 | // g.addVertexToGraph("2") 83 | // g.addVertexToGraph("3") 84 | // g.addVertexToGraph("4") 85 | // g.addEdgeToGraph("0", "1") 86 | // g.addEdgeToGraph("0", "2") 87 | // g.addEdgeToGraph("2", "3") 88 | // g.addEdgeToGraph("2", "4") 89 | // g.addEdgeToGraph("3", "4") 90 | 91 | // acyclic 92 | // g.addVertexToGraph("0") 93 | // g.addVertexToGraph("1") 94 | // g.addVertexToGraph("2") 95 | // g.addVertexToGraph("3") 96 | // g.addVertexToGraph("4") 97 | // g.addEdgeToGraph("0", "1") 98 | // g.addEdgeToGraph("0", "2") 99 | // g.addEdgeToGraph("2", "3") 100 | // g.addEdgeToGraph("2", "4") 101 | -------------------------------------------------------------------------------- /algorithms/graphs/traversals/cd_undirected_graph_traversals/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type graph map[string][]string 6 | 7 | func (g graph) addVertexToGraph(vtx string) { 8 | if g[vtx] != nil { 9 | fmt.Println("\n-- Vertex already exists. --") 10 | return 11 | } 12 | g[vtx] = make([]string, 0) 13 | } 14 | 15 | func (g graph) addEdgeToGraph(fromVtx, toVtx string) { 16 | if g[fromVtx] == nil { // check if initial vertex exists 17 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 18 | return 19 | } 20 | for i := range g[fromVtx] { // check if edge already exists 21 | if g[fromVtx][i] == toVtx { 22 | fmt.Println("\n-- Edge between " + fromVtx + " and " + toVtx + " already exists. --") 23 | return 24 | } 25 | } 26 | if g[toVtx] == nil { // create new destination vertext if it does not exists 27 | g[toVtx] = make([]string, 0) 28 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 29 | } 30 | 31 | g[fromVtx] = append(g[fromVtx], toVtx) 32 | g[toVtx] = append(g[toVtx], fromVtx) 33 | } 34 | 35 | func (g graph) addVertex() { 36 | var vtxName string 37 | fmt.Print("Enter the name of vertex: ") 38 | fmt.Scanf("%s\n", &vtxName) 39 | g.addVertexToGraph(vtxName) 40 | } 41 | 42 | func (g graph) addEdge() { 43 | var fromVtx, toVtx string 44 | fmt.Print("Enter the initial vertex name: ") 45 | fmt.Scanf("%s\n", &fromVtx) 46 | fmt.Print("Enter the destination vertex name: ") 47 | fmt.Scanf("%s\n", &toVtx) 48 | g.addEdgeToGraph(fromVtx, toVtx) 49 | } 50 | -------------------------------------------------------------------------------- /algorithms/graphs/traversals/cd_undirected_graph_traversals/traversals.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // detectDFS traverses a graph using dfs technique to detect cycle in a graph 6 | func (g graph) detectDFS() ([]string, bool) { 7 | visited := make(map[string]bool) 8 | cycle := false 9 | var result []string 10 | if len(g) == 0 { 11 | fmt.Println("\n-- Graph is empty. --") 12 | return nil, false 13 | } 14 | for i := range g { 15 | if !visited[i] { 16 | result, cycle = g.dfsHelper(i, visited, result, "-1") 17 | if cycle { 18 | return nil, cycle 19 | } 20 | } 21 | } 22 | return result, cycle 23 | } 24 | 25 | // dfsHelper recursively calls itself to solve dfs traversal 26 | func (g graph) dfsHelper(vtx string, visited map[string]bool, result []string, parent string) ([]string, bool) { 27 | visited[vtx] = true 28 | cycle := false 29 | result = append(result, vtx) 30 | for i := range g[vtx] { 31 | fmt.Println(parent, vtx, g[vtx][i]) 32 | if parent != g[vtx][i] && parent != "-1" && visited[g[vtx][i]] { // cycle detection logic here 33 | return nil, true 34 | } 35 | if !visited[g[vtx][i]] { 36 | result, cycle = g.dfsHelper(g[vtx][i], visited, result, vtx) 37 | return result, cycle 38 | } 39 | } 40 | return result, cycle 41 | } 42 | 43 | // TODO: 44 | // detectBFS traverses a graph using dfs technique to detect cycle in a graph 45 | func (g graph) detectBFS() []string { 46 | 47 | if len(g) == 0 { 48 | fmt.Println("\n-- Graph is empty. --") 49 | return nil 50 | } 51 | 52 | visited := make(map[string]bool) 53 | 54 | var queue []string 55 | var result []string 56 | var currentVtx string 57 | 58 | for i := range g { 59 | if !visited[i] { 60 | visited[i] = true 61 | queue = append(queue, i) 62 | 63 | for len(queue) != 0 { 64 | currentVtx = queue[0] // get the element from the queue 65 | queue = queue[1:] // remove element from the queue 66 | result = append(result, currentVtx) // push the current vertex in result 67 | 68 | for i := range g[currentVtx] { 69 | if !visited[g[currentVtx][i]] { 70 | visited[g[currentVtx][i]] = true // mark as visited 71 | queue = append(queue, g[currentVtx][i]) // push neighbors of current vertex in the queue 72 | } 73 | } 74 | 75 | } 76 | 77 | } 78 | } 79 | 80 | return result 81 | } 82 | -------------------------------------------------------------------------------- /algorithms/graphs/tsp/tsp_dynamic/directed_graph/helpers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | func notIn(elem, subset uint32) bool { 8 | return ((1 << elem) & subset) == 0 9 | } 10 | 11 | func combinations(set, at, r, n uint32, subsets *[]uint32) *[]uint32 { 12 | elementsLeftToPick := n - at 13 | if elementsLeftToPick < r { 14 | return subsets 15 | } 16 | 17 | if r == 0 { 18 | *subsets = append(*subsets, set) 19 | } else { 20 | for i := at; i < n; i++ { 21 | set ^= (1 << i) 22 | combinations(set, i+1, r-1, n, subsets) 23 | set ^= (1 << i) 24 | } 25 | } 26 | return subsets 27 | } 28 | 29 | func constructMatrix(g graph) { 30 | numToVtx = make(map[int]string) 31 | vtxToNum = make(map[string]int) 32 | num := 0 33 | for i := range g { 34 | numToVtx[num] = i 35 | vtxToNum[i] = num 36 | num++ 37 | } 38 | 39 | distanceMatrix = make([][]float64, len(numToVtx)) 40 | 41 | for i := range g { 42 | distanceMatrix[vtxToNum[i]] = make([]float64, len(vtxToNum)) 43 | for j := range distanceMatrix[vtxToNum[i]] { 44 | distanceMatrix[vtxToNum[i]][j] = math.Inf(1) 45 | } 46 | for j := range g[i] { 47 | distanceMatrix[vtxToNum[i]][vtxToNum[g[i][j].name]] = float64(g[i][j].value) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /algorithms/graphs/tsp/tsp_dynamic/undirected_graph/helpers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | func notIn(elem, subset uint32) bool { 8 | return ((1 << elem) & subset) == 0 9 | } 10 | 11 | func combinations(set, at, r, n uint32, subsets *[]uint32) *[]uint32 { 12 | elementsLeftToPick := n - at 13 | if elementsLeftToPick < r { 14 | return subsets 15 | } 16 | 17 | if r == 0 { 18 | *subsets = append(*subsets, set) 19 | } else { 20 | for i := at; i < n; i++ { 21 | set ^= (1 << i) 22 | combinations(set, i+1, r-1, n, subsets) 23 | set ^= (1 << i) 24 | } 25 | } 26 | return subsets 27 | } 28 | 29 | func constructMatrix(g graph) { 30 | numToVtx = make(map[int]string) 31 | vtxToNum = make(map[string]int) 32 | num := 0 33 | for i := range g { 34 | numToVtx[num] = i 35 | vtxToNum[i] = num 36 | num++ 37 | } 38 | 39 | distanceMatrix = make([][]float64, len(numToVtx)) 40 | 41 | for i := range g { 42 | distanceMatrix[vtxToNum[i]] = make([]float64, len(vtxToNum)) 43 | for j := range distanceMatrix[vtxToNum[i]] { 44 | distanceMatrix[vtxToNum[i]][j] = math.Inf(1) 45 | } 46 | for j := range g[i] { 47 | distanceMatrix[vtxToNum[i]][vtxToNum[g[i][j].name]] = float64(g[i][j].value) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /algorithms/graphs/tsp/tsp_naive/directed_graph/lo_permutations.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | // LOP performs Lexicographic Order Permutations on a given string. 8 | // Returns all possibilities as a slice of string. 9 | func LOP(str []string) []string { 10 | result := make([]string, 0) 11 | result = append(result, strings.Join(str, "")) 12 | for { 13 | var i int 14 | var j int 15 | 16 | for i = len(str) - 1; i >= 0; i-- { 17 | if i != 0 && str[i-1] < str[i] { 18 | break 19 | } 20 | } 21 | 22 | if i == -1 { 23 | break 24 | } 25 | 26 | for j = len(str) - 1; j >= 0; j-- { 27 | if str[i-1] < str[j] { 28 | str[i-1], str[j] = str[j], str[i-1] 29 | str = Reverse(str, i) 30 | result = append(result, strings.Join(str, "")) 31 | break 32 | } 33 | } 34 | 35 | } 36 | return result 37 | } 38 | 39 | // Reverse reverses a slice of string from it's length to given index 40 | func Reverse(str []string, index int) []string { 41 | newStr := strings.Join(str[0:index], "") 42 | for i := len(str) - 1; i >= index; i-- { 43 | newStr += str[i] 44 | } 45 | return strings.Split(newStr, "") 46 | } 47 | -------------------------------------------------------------------------------- /algorithms/graphs/tsp/tsp_naive/undirected_graph/lo_permutations.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | // LOP performs Lexicographic Order Permutations on a given string. 8 | // Returns all possibilities as a slice of string. 9 | func LOP(str []string) []string { 10 | result := make([]string, 0) 11 | result = append(result, strings.Join(str, "")) 12 | for { 13 | var i int 14 | var j int 15 | 16 | for i = len(str) - 1; i >= 0; i-- { 17 | if i != 0 && str[i-1] < str[i] { 18 | break 19 | } 20 | } 21 | 22 | if i == -1 { 23 | break 24 | } 25 | 26 | for j = len(str) - 1; j >= 0; j-- { 27 | if str[i-1] < str[j] { 28 | str[i-1], str[j] = str[j], str[i-1] 29 | str = Reverse(str, i) 30 | result = append(result, strings.Join(str, "")) 31 | break 32 | } 33 | } 34 | 35 | } 36 | return result 37 | } 38 | 39 | // Reverse reverses a slice of string from it's length to given index 40 | func Reverse(str []string, index int) []string { 41 | newStr := strings.Join(str[0:index], "") 42 | for i := len(str) - 1; i >= index; i-- { 43 | newStr += str[i] 44 | } 45 | return strings.Split(newStr, "") 46 | } 47 | -------------------------------------------------------------------------------- /algorithms/graphs/union_find/graph.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Edge represents an edge between two vertices 6 | type Edge struct { 7 | src string 8 | dest string 9 | } 10 | 11 | var graph map[string][]string 12 | var uniqueEdges []Edge 13 | 14 | func init() { 15 | graph = make(map[string][]string) 16 | uniqueEdges = make([]Edge, 0) 17 | } 18 | 19 | func addVertexToGraph(vtx string) { 20 | if graph[vtx] != nil { 21 | fmt.Println("\n-- Vertex already exists. --") 22 | return 23 | } 24 | vertices[vtx] = len(vertices) 25 | graph[vtx] = make([]string, 0) 26 | } 27 | 28 | func addEdgeToGraph(fromVtx, toVtx string) { 29 | if graph[fromVtx] == nil { // check if initial vertex exists 30 | fmt.Println("\n-- Initial vertex " + fromVtx + " does not exist. --") 31 | return 32 | } 33 | for i := range graph[fromVtx] { // check if edge already exists 34 | if graph[fromVtx][i] == toVtx { 35 | fmt.Println("\n-- Edge between " + fromVtx + " and " + toVtx + " already exists. --") 36 | return 37 | } 38 | } 39 | if graph[toVtx] == nil { // create new destination vertext if it does not exists 40 | graph[toVtx] = make([]string, 0) 41 | vertices[toVtx] = len(vertices) 42 | fmt.Println("\n-- Destination vertex " + toVtx + " created. --") 43 | } 44 | 45 | graph[fromVtx] = append(graph[fromVtx], toVtx) 46 | graph[toVtx] = append(graph[toVtx], fromVtx) 47 | uniqueEdges = append(uniqueEdges, Edge{src: fromVtx, dest: toVtx}) 48 | } 49 | 50 | func addVertex() { 51 | var vtxName string 52 | fmt.Print("Enter the name of vertex: ") 53 | fmt.Scanf("%s\n", &vtxName) 54 | addVertexToGraph(vtxName) 55 | } 56 | 57 | func addEdge() { 58 | var fromVtx, toVtx string 59 | fmt.Print("Enter the initial vertex name: ") 60 | fmt.Scanf("%s\n", &fromVtx) 61 | fmt.Print("Enter the destination vertex name: ") 62 | fmt.Scanf("%s\n", &toVtx) 63 | addEdgeToGraph(fromVtx, toVtx) 64 | } 65 | -------------------------------------------------------------------------------- /algorithms/graphs/union_find/union_find.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // UnionFind run union find algorithm and detects cycle in give graph 6 | func UnionFind() { 7 | flag := 0 8 | for i := 0; i < len(uniqueEdges); i++ { 9 | x := find(uniqueEdges[i].src) 10 | y := find(uniqueEdges[i].dest) 11 | if x == y { 12 | fmt.Println("\n-- Cycle FOUND between:", uniqueEdges[i].src, uniqueEdges[i].dest, ". --") 13 | flag = 1 14 | } else { 15 | union(x, y) 16 | } 17 | } 18 | if flag == 0 { 19 | fmt.Println("\n-- NO cycle found in graph. --") 20 | } 21 | } 22 | 23 | func find(i string) string { 24 | if parent[i] == "-1" { 25 | return i 26 | } 27 | return find(parent[i]) 28 | } 29 | 30 | func union(vtx1, vtx2 string) { 31 | xset := find(vtx1) 32 | yset := find(vtx2) 33 | parent[xset] = yset 34 | } 35 | 36 | var parent map[string]string 37 | var vertices map[string]int 38 | 39 | func init() { 40 | vertices = make(map[string]int) 41 | parent = make(map[string]string) 42 | } 43 | 44 | func main() { 45 | fmt.Println("\n-- Union Find --") 46 | i := 0 47 | for i == 0 { 48 | fmt.Println("\n1. ADD A VERTEX") 49 | fmt.Println("2. ADD AN EDGE") 50 | fmt.Println("3. RUN UNION FIND") 51 | fmt.Println("4. EXIT") 52 | var choice int 53 | fmt.Print("Enter your choice: ") 54 | fmt.Scanf("%d\n", &choice) 55 | switch choice { 56 | case 1: 57 | addVertex() 58 | case 2: 59 | addEdge() 60 | case 3: 61 | UnionFind() 62 | case 4: 63 | i = 1 64 | default: 65 | fmt.Println("Command not recognized.") 66 | } 67 | } 68 | } 69 | 70 | func startUnionFind() { 71 | for i := range vertices { 72 | parent[i] = "-1" 73 | } 74 | UnionFind() 75 | } 76 | 77 | // addVertexToGraph("0") 78 | // addVertexToGraph("1") 79 | // addVertexToGraph("2") 80 | // addVertexToGraph("3") 81 | // addVertexToGraph("4") 82 | // addEdgeToGraph("0", "1") 83 | // addEdgeToGraph("0", "2") 84 | // addEdgeToGraph("1", "3") 85 | // addEdgeToGraph("1", "4") 86 | // addEdgeToGraph("3", "4") 87 | 88 | // addVertexToGraph("1") 89 | // addVertexToGraph("2") 90 | // addVertexToGraph("3") 91 | // addVertexToGraph("4") 92 | // addVertexToGraph("5") 93 | // addVertexToGraph("6") 94 | // addVertexToGraph("7") 95 | // addVertexToGraph("8") 96 | // addEdgeToGraph("1", "3") 97 | // addEdgeToGraph("1", "2") 98 | // addEdgeToGraph("2", "4") 99 | // addEdgeToGraph("3", "4") 100 | // addEdgeToGraph("2", "5") 101 | // addEdgeToGraph("5", "7") 102 | // addEdgeToGraph("5", "6") 103 | // addEdgeToGraph("8", "6") 104 | // addEdgeToGraph("8", "7") 105 | 106 | // addVertexToGraph("0") 107 | // addVertexToGraph("1") 108 | // addVertexToGraph("2") 109 | // addEdgeToGraph("0", "1") 110 | // addEdgeToGraph("1", "2") 111 | // addEdgeToGraph("0", "2") 112 | -------------------------------------------------------------------------------- /algorithms/huffman_codes/heap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // Node represents a single node in a heap 9 | type Node struct { 10 | char string 11 | freq int 12 | left *Node 13 | right *Node 14 | } 15 | 16 | type heap []Node 17 | 18 | // Insert inserts a node in a heap 19 | func (h heap) Insert(node Node) heap { 20 | h = append(h, node) 21 | h = h.minHeapify() 22 | return h 23 | } 24 | 25 | func (h heap) minHeapify() heap { 26 | idx := len(h) - 1 27 | element := h[idx] 28 | for idx > 0 { 29 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 30 | parent := h[parentIdx] 31 | if element.freq >= parent.freq { 32 | break 33 | } 34 | h[parentIdx] = element 35 | h[idx] = parent 36 | idx = parentIdx 37 | } 38 | return h 39 | } 40 | 41 | // ExtractMin will remove a node from heap 42 | func (h heap) ExtractMin() (*Node, heap) { 43 | if len(h) == 0 { 44 | fmt.Println("\n-- Heap is empty. --") 45 | return &Node{}, h 46 | } 47 | min := h[0] 48 | end := h[len(h)-1] 49 | h = h[0 : len(h)-1] 50 | if len(h) > 0 { 51 | h[0] = end 52 | h.bubbleDown() 53 | } 54 | return &min, h 55 | } 56 | 57 | func (h heap) bubbleDown() heap { 58 | idx := 0 59 | length := len(h) 60 | element := h[0] 61 | for { 62 | leftChildIdx := (2 * idx) + 1 63 | rightChildIdx := (2 * idx) + 2 64 | var leftChild, rightChild Node 65 | var swap int 66 | 67 | if leftChildIdx < length { 68 | leftChild = h[leftChildIdx] 69 | if leftChild.freq < element.freq { 70 | swap = leftChildIdx 71 | } 72 | } 73 | if rightChildIdx < length { 74 | rightChild = h[rightChildIdx] 75 | if (rightChild.freq < element.freq && swap == 0) || (rightChild.freq < leftChild.freq && swap != 0) { 76 | swap = rightChildIdx 77 | } 78 | } 79 | 80 | if swap == 0 { 81 | break 82 | } 83 | h[idx] = h[swap] 84 | h[swap] = element 85 | idx = swap 86 | } 87 | return h 88 | } 89 | 90 | func (h heap) insertNodes() heap { 91 | var char string 92 | var freq int 93 | fmt.Print("\nChar: ") 94 | fmt.Scanf("%s\n", &char) 95 | fmt.Print("Freq: ") 96 | fmt.Scanf("%d\n", &freq) 97 | h = h.Insert(Node{char: char, freq: freq}) 98 | return h 99 | } 100 | 101 | func (h heap) display() { 102 | fmt.Println("") 103 | fmt.Println(h) 104 | } 105 | -------------------------------------------------------------------------------- /algorithms/huffman_codes/huffman_codes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func (h heap) genHeap() *Node { 9 | var curr, prev *Node 10 | for len(h) > 1 { 11 | prev, h = h.ExtractMin() 12 | curr, h = h.ExtractMin() 13 | newNode := Node{left: prev, right: curr, freq: (prev.freq + curr.freq)} 14 | h = h.Insert(newNode) 15 | } 16 | return &h[0] 17 | } 18 | 19 | func (ht *Node) printHuffman() { 20 | var code []string 21 | code = make([]string, 0) 22 | ht.printHuffmanUtil(ht, code) 23 | } 24 | 25 | func (ht *Node) printHuffmanUtil(node *Node, code []string) { 26 | if node.left == nil && node.right == nil { 27 | // print 28 | fmt.Println("\n", node.char, "=>", strings.Join(code, "")) 29 | code = code[0:0] 30 | } 31 | if node.left != nil { 32 | code = append(code, "0") 33 | ht.printHuffmanUtil(node.left, code) 34 | code = code[0 : len(code)-1] 35 | } 36 | if node.right != nil { 37 | code = append(code, "1") 38 | ht.printHuffmanUtil(node.right, code) 39 | code = code[0 : len(code)-1] 40 | } 41 | } 42 | 43 | var n int 44 | var nodes []Node 45 | var huffTree *Node 46 | 47 | func main() { 48 | fmt.Println("\n-- Huffman Codes --") 49 | 50 | // initialize min heap 51 | h := make(heap, 0) 52 | 53 | fmt.Print("\nEnter the number of characters: ") 54 | fmt.Scanf("%d\n", &n) 55 | nodes = make([]Node, 0) 56 | 57 | fmt.Println("Start entering character and frequency:") 58 | for i := 0; i < n; i++ { 59 | h = h.insertNodes() 60 | } 61 | 62 | huffTree = h.genHeap() 63 | huffTree.printHuffman() 64 | } 65 | 66 | // a, 5 67 | // b, 9 68 | // c, 12 69 | // d, 13 70 | // e, 16 71 | // f, 45 72 | -------------------------------------------------------------------------------- /algorithms/job_scheduling_gp/job_scheduling_gp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type job struct { 6 | profit float64 7 | deadline float64 8 | } 9 | 10 | // ScheduleJobs will schedule all the jobs maximizing the profit 11 | func ScheduleJobs() { 12 | count := max 13 | i := 0 14 | deadline := -1 15 | for count != 0 { 16 | if i == len(jobs)-1 { // a complete scan of all jobs is completed 17 | break 18 | } 19 | if deadline == -1 { // if deadline gets to -1 it can't be scheduled 20 | deadline = int(jobs[i].deadline) 21 | if deadline == 0 && result[deadline-1] == 0 { // if a job's deadline is 0 22 | result[deadline] = i + 1 23 | deadline = -1 24 | count-- 25 | i++ 26 | continue 27 | } 28 | } 29 | if deadline-1 != -1 && result[deadline-1] == 0 { // check if the job can scheduled 30 | result[deadline-1] = i + 1 31 | deadline = -1 32 | count-- 33 | i++ 34 | } else if deadline-1 == -1 { // check if the deadline is 0 35 | deadline = -1 36 | i++ 37 | } else if result[deadline-1] != 0 { 38 | deadline-- 39 | } 40 | } 41 | } 42 | 43 | var n int 44 | var jobs []job 45 | var result []int 46 | var max float64 47 | 48 | func main() { 49 | fmt.Println("\n-- Job Scheduling using Greedy Programming --") 50 | 51 | fmt.Print("\nEnter the number of jobs: ") 52 | fmt.Scanf("%d\n", &n) 53 | jobs = make([]job, n) 54 | 55 | fmt.Println("Start entering profits and deadlines of each job:") 56 | var temp float64 57 | for i := 0; i < n; i++ { 58 | fmt.Print("Profit: ") 59 | fmt.Scanf("%f\n", &temp) 60 | jobs[i].profit = temp 61 | fmt.Print("Deadline: ") 62 | fmt.Scanf("%f\n", &temp) 63 | jobs[i].deadline = temp 64 | if i == 0 { 65 | max = jobs[i].deadline 66 | } else if max < jobs[i].deadline { 67 | max = jobs[i].deadline 68 | } 69 | } 70 | result = make([]int, int(max)) 71 | quicksort(0, n-1) 72 | ScheduleJobs() 73 | total := float64(0) 74 | for i := range result { 75 | total += jobs[result[i]-1].profit 76 | } 77 | fmt.Println("Jobs", result, "will be scheduled to have", total, "units of profit and will be taken in ascending order of their deadlines.") 78 | } 79 | -------------------------------------------------------------------------------- /algorithms/job_scheduling_gp/quick_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // this quick sort algorithm will sort in descending order 4 | func partition(first, last int) int { 5 | pivot := jobs[first].profit 6 | i := first 7 | j := last + 1 8 | 9 | for i < j { 10 | i++ 11 | j-- 12 | for jobs[i].profit > pivot && i < last { 13 | i++ 14 | } 15 | for jobs[j].profit < pivot && j > first { 16 | j-- 17 | } 18 | if i < j { 19 | jobs[i].profit, jobs[j].profit = jobs[j].profit, jobs[i].profit 20 | } 21 | } 22 | jobs[j].profit, jobs[first].profit = jobs[first].profit, jobs[j].profit 23 | return j 24 | } 25 | 26 | func quicksort(first, last int) { 27 | var sp int 28 | if first < last { 29 | sp = partition(first, last) 30 | quicksort(first, sp-1) 31 | quicksort(sp+1, last) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /algorithms/lcm/lcm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("\n-- Least Common Multiple --") 7 | var m, n, lcm int 8 | fmt.Print("\nEnter the first number: ") 9 | fmt.Scanf("%d\n", &m) 10 | fmt.Print("Enter the second number: ") 11 | fmt.Scanf("%d\n", &n) 12 | if n < m { 13 | lcm = findLCM(m, n) 14 | } else { 15 | lcm = findLCM(n, m) 16 | } 17 | fmt.Println("Least Common Multiple of", m, "and", n, "is:", lcm) 18 | } 19 | 20 | func findLCM(m, n int) int { 21 | val := findGCD(m, n) 22 | return (m * n) / val 23 | } 24 | 25 | func findGCD(m, n int) int { 26 | if n == 0 { 27 | return m 28 | } 29 | return findGCD(n, m%n) 30 | } 31 | -------------------------------------------------------------------------------- /algorithms/lcs/iterative_dp/lcs_iterative_dp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "strings" 7 | ) 8 | 9 | // LCS recursive solution of lcs problem 10 | func LCS() string { 11 | for i := range sequence { 12 | for j := range sequence[i] { 13 | if i == 0 || j == 0 { 14 | continue 15 | } else if string(str01[i]) == string(str02[j]) { 16 | sequence[i][j] = 1 + sequence[i-1][j-1] 17 | } else { 18 | sequence[i][j] = int(math.Max(float64(sequence[i-1][j]), float64(sequence[i][j-1]))) 19 | } 20 | } 21 | } 22 | 23 | i := len(str01) - 1 24 | j := len(str02) - 1 25 | str := make([]string, sequence[i][j]) 26 | for { 27 | if sequence[i][j] == 0 { 28 | break 29 | } else if sequence[i-1][j] == sequence[i][j] { 30 | i-- 31 | } else if sequence[i][j-1] == sequence[i][j] { 32 | j-- 33 | } else { 34 | str[sequence[i][j]-1] += string(str02[j]) 35 | i-- 36 | j-- 37 | } 38 | } 39 | return strings.Join(str, "") 40 | } 41 | 42 | var str01 string 43 | var str02 string 44 | var sequence [][]int 45 | 46 | func main() { 47 | fmt.Println("\n-- Longest Common Subsequence --") 48 | fmt.Print("\nEnter the first string: ") 49 | fmt.Scanf("%s\n", &str01) 50 | fmt.Print("Enter the second string: ") 51 | fmt.Scanf("%s\n", &str02) 52 | str01 = "\n" + str01 53 | str02 = "\n" + str02 54 | sequence = make([][]int, len(str01)) 55 | for i := range sequence { 56 | sequence[i] = make([]int, len(str02)) 57 | } 58 | str := LCS() 59 | i := len(str01) - 1 60 | j := len(str02) - 1 61 | 62 | fmt.Println("The Longest Common Subsequence is of length", sequence[i][j], "which is", "'"+str+"'.") 63 | } 64 | -------------------------------------------------------------------------------- /algorithms/lo_permutations/lo_permutations.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strings" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("-- Lexicographic Ordering Permutations --") 11 | var str string 12 | fmt.Print("Enter a string: ") 13 | fmt.Scanf("%s\n", &str) 14 | arr := strings.Split(str, "") 15 | sort.Strings(arr) 16 | result := LOP(arr) 17 | for i := 0; i < len(result); i++ { 18 | fmt.Println(i+1, "-", result[i]) 19 | } 20 | } 21 | 22 | // LOP performs Lexicographic Order Permutations on a given string. 23 | // Returns all possibilities as a slice of string. 24 | func LOP(str []string) []string { 25 | result := make([]string, 0) 26 | result = append(result, strings.Join(str, "")) 27 | for { 28 | var i int 29 | var j int 30 | 31 | for i = len(str) - 1; i >= 0; i-- { 32 | if i != 0 && str[i-1] < str[i] { 33 | break 34 | } 35 | } 36 | 37 | if i == -1 { 38 | break 39 | } 40 | 41 | for j = len(str) - 1; j >= 0; j-- { 42 | if str[i-1] < str[j] { 43 | str[i-1], str[j] = str[j], str[i-1] 44 | str = Reverse(str, i) 45 | result = append(result, strings.Join(str, "")) 46 | break 47 | } 48 | } 49 | 50 | } 51 | return result 52 | } 53 | 54 | // Reverse reverses a slice of string from it's length to given index 55 | func Reverse(str []string, index int) []string { 56 | newStr := strings.Join(str[:index], "") 57 | for i := len(str) - 1; i >= index; i-- { 58 | newStr += str[i] 59 | } 60 | return strings.Split(newStr, "") 61 | } 62 | -------------------------------------------------------------------------------- /algorithms/longest_palindrome_substring/brute_force/brute_force.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("\n-- Longest Palindrome Substring Brute Force Technique --") 10 | 11 | var str string 12 | var txt []string 13 | 14 | fmt.Print("\nEnter a text string: ") 15 | fmt.Scanf("%s\n", &str) 16 | 17 | txt = strings.Split(str, "") 18 | str = "#" + strings.Join(txt, "#") + "#" 19 | txt = strings.Split(str, "") 20 | 21 | fmt.Println("\nPalindrome\\s are:") 22 | p := BruteForce(txt) 23 | for i := range p { 24 | fmt.Println("'"+i+"'", "of length", p[i]) 25 | } 26 | } 27 | 28 | // BruteForce finds Longest Palindrome Substring in a given string using Brute Force technique 29 | func BruteForce(txt []string) map[string]int { 30 | 31 | pMap := make(map[string]int) 32 | 33 | for i := 0; i < len(txt); i++ { 34 | 35 | k := i + 1 36 | 37 | for j := i; j >= 0 && k <= len(txt); j-- { 38 | 39 | subStr := txt[j:k] 40 | flag := 0 41 | 42 | for p := 0; p < len(subStr); p++ { 43 | if subStr[p] != subStr[len(subStr)-1-p] { 44 | flag = 1 45 | break 46 | } 47 | } 48 | 49 | if flag == 1 { 50 | flag = 0 51 | } else { 52 | pMap[strings.Join(subStr, "")] = len(subStr) 53 | } 54 | k++ 55 | 56 | } 57 | 58 | } 59 | 60 | for i := range pMap { 61 | temp := strings.Split(i, "#") 62 | str := strings.Join(temp, "") 63 | delete(pMap, i) 64 | pMap[str] = len(str) 65 | } 66 | 67 | // key "" generated for # as palindrome in hash map 68 | delete(pMap, "") 69 | 70 | return pMap 71 | } 72 | 73 | // Test strings 74 | // 75 | // ABABABA 76 | // [BABAB:5 ABABABA:7 B:1 A:1 BAB:3 ABABA:5 ABA:3] 77 | // 78 | // ABBAABBA 79 | // [A:1 BAAB:4 ABBA:4 AA:2 BBAABB:6 ABBAABBA:8 B:1 BB:2] 80 | // 81 | // FORGEEKSSKEEGFOR 82 | // [SS:2 R:1 G:1 O:1 EE:2 EEKSSKEE:8 S:1 GEEKSSKEEG:10 KSSK:4 F:1 K:1 EKSSKE:6 E:1] 83 | // 84 | // ABCBABCBABCBA 85 | // [BCBABCBABCB:11 BAB:3 B:1 A:1 BCB:3 C:1 ABCBA:5 BABCBAB:7 CBABC:5 BCBABCB:7 CBABCBABC:9 ABCBABCBABCBA:13 ABCBABCBA:9] 86 | // 87 | // ABAABA 88 | // [ABA:3 ABAABA:6 B:1 BAAB:4 AA:2 A:1] 89 | -------------------------------------------------------------------------------- /algorithms/longest_palindrome_substring/manchers/manchers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "strings" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("\n-- Longest Palindrome Substring Mancher's Algorithm --") 11 | 12 | var str string 13 | var txt []string 14 | 15 | fmt.Print("\nEnter a text string: ") 16 | fmt.Scanf("%s\n", &str) 17 | 18 | txt = strings.Split(str, "") 19 | str = "^" + "#" + strings.Join(txt, "#") + "#" + "$" 20 | txt = strings.Split(str, "") 21 | 22 | fmt.Println("\nPalindrome\\s are:") 23 | p := Manchers(txt) 24 | for i := range p { 25 | fmt.Println("'"+i+"'", "of length", p[i]) 26 | } 27 | } 28 | 29 | // Manchers performs mancher's algorithm which finds longest palindrome substring in a given string 30 | func Manchers(txt []string) map[string]int { 31 | subStr := make([]int, len(txt)) 32 | c := 0 33 | r := 0 34 | 35 | for i := 1; i < len(txt)-1; i++ { 36 | mirror := 2*c - i 37 | if i < r { 38 | subStr[i] = int(math.Min(float64(r-i), float64(subStr[mirror]))) 39 | } 40 | 41 | for txt[i+(1+subStr[i])] == txt[i-(1+subStr[i])] { 42 | subStr[i]++ 43 | } 44 | 45 | if i+subStr[i] > r { 46 | c = i 47 | r = i + subStr[i] 48 | } 49 | 50 | } 51 | 52 | return findPalindromes(txt, subStr) 53 | } 54 | 55 | func findPalindromes(txt []string, subStr []int) map[string]int { 56 | pMap := make(map[string]int) 57 | 58 | for i := 0; i < len(subStr); i++ { 59 | if subStr[i] == 0 { 60 | continue 61 | } 62 | j := i - 1 63 | k := i + 2 64 | jLen := i - subStr[i] 65 | kLen := i + subStr[i] + 1 66 | for j >= jLen && k <= kLen { 67 | temp := strings.Join(txt[j:k], "") 68 | pMap[temp] = 0 69 | j-- 70 | k++ 71 | } 72 | } 73 | 74 | for i := range pMap { 75 | temp := strings.Split(i, "#") 76 | str := strings.Join(temp, "") 77 | 78 | // delete first then insert new map value 79 | delete(pMap, i) 80 | pMap[str] = len(str) 81 | } 82 | 83 | return pMap 84 | } 85 | 86 | // Test strings 87 | // 88 | // ABABABA 89 | // [BABAB:5 ABABABA:7 B:1 A:1 BAB:3 ABABA:5 ABA:3] 90 | // 91 | // ABBAABBA 92 | // [A:1 BAAB:4 ABBA:4 AA:2 BBAABB:6 ABBAABBA:8 B:1 BB:2] 93 | // 94 | // FORGEEKSSKEEGFOR 95 | // [SS:2 R:1 G:1 O:1 EE:2 EEKSSKEE:8 S:1 GEEKSSKEEG:10 KSSK:4 F:1 K:1 EKSSKE:6 E:1] 96 | // 97 | // ABCBABCBABCBA 98 | // [BCBABCBABCB:11 BAB:3 B:1 A:1 BCB:3 C:1 ABCBA:5 BABCBAB:7 CBABC:5 BCBABCB:7 CBABCBABC:9 ABCBABCBABCBA:13 ABCBABCBA:9] 99 | // 100 | // ABAABA 101 | // [ABA:3 ABAABA:6 B:1 BAAB:4 AA:2 A:1] 102 | -------------------------------------------------------------------------------- /algorithms/making_change_dp/making_change_dp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // MakeChange will generate the necessary matrix which will then be evaluated to know 9 | // the number of coins and which coins will be required to have a given change 10 | func MakeChange() { 11 | for i := 0; i < len(matrix); i++ { 12 | for j := 0; j < len(matrix[i]); j++ { 13 | if i == 0 || j == 0 { 14 | continue 15 | } else if i == 1 { 16 | matrix[i][j] = 1 + matrix[i][j-int(coins[i-1])] 17 | } else if j < int(coins[i-1]) { 18 | matrix[i][j] = matrix[i-1][j] 19 | } else { 20 | matrix[i][j] = math.Min(matrix[i-1][j], 1+matrix[i][j-int(coins[i-1])]) 21 | } 22 | } 23 | } 24 | fmt.Println("\nMatrix formed:") 25 | for i := 0; i < len(matrix); i++ { 26 | for j := 0; j < len(matrix[i]); j++ { 27 | fmt.Print(matrix[i][j], " ") 28 | } 29 | fmt.Println() 30 | } 31 | i := len(matrix) - 1 32 | j := len(matrix[0]) - 1 33 | result := make([]float64, 0) 34 | count := matrix[i][j] 35 | for count != 0 { 36 | if matrix[i-1][j] == count { 37 | i-- 38 | } else { 39 | j -= int(coins[i-1]) 40 | result = append(result, coins[i-1]) 41 | count-- 42 | } 43 | } 44 | fmt.Println("You will require", len(result), "coins of values", result, "to make a change for", change, ".") 45 | } 46 | 47 | var change float64 48 | var numCoins float64 49 | var coins []float64 50 | var matrix [][]float64 51 | 52 | func main() { 53 | fmt.Println("\n-- Making Change Problem using Dynamic Programming. --") 54 | fmt.Print("Enter the value for the amount of change you want: ") 55 | fmt.Scanf("%f\n", &change) 56 | fmt.Print("Enter the number of coins you have: ") 57 | fmt.Scanf("%f\n", &numCoins) 58 | var coin float64 59 | fmt.Println("Start enter the values of these coins in increasing order:") 60 | for i := 0; i < int(numCoins); i++ { 61 | fmt.Scanf("%f\n", &coin) 62 | coins = append(coins, coin) 63 | } 64 | matrix = make([][]float64, int(numCoins)+1) 65 | for i := 0; i < len(matrix); i++ { 66 | matrix[i] = make([]float64, int(change)+1) 67 | for j := range matrix[i] { 68 | matrix[i][j] = float64(0) 69 | } 70 | } 71 | MakeChange() 72 | } 73 | -------------------------------------------------------------------------------- /algorithms/order_statistics/naive_approach/heap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | func maxHeapify() { 9 | idx := len(arr) - 1 10 | element := arr[idx] 11 | for idx > 0 { 12 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 13 | parent := arr[parentIdx] 14 | if element <= parent { 15 | break 16 | } 17 | arr[parentIdx] = element 18 | arr[idx] = parent 19 | idx = parentIdx 20 | } 21 | } 22 | 23 | // ExtractMax will remove a node from heap 24 | func ExtractMax() int { 25 | if len(arr) == 0 || arr[0] == 0 { 26 | fmt.Println("\n-- Heap is empty. --") 27 | return 0 28 | } 29 | max := arr[0] 30 | end := arr[len(arr)-1] 31 | arr = arr[0 : len(arr)-1] 32 | if len(arr) > 0 { 33 | arr[0] = end 34 | bubbleDown() 35 | } 36 | return max 37 | } 38 | 39 | func bubbleDown() { 40 | idx := 0 41 | length := len(arr) 42 | element := arr[0] 43 | for { 44 | leftChildIdx := (2 * idx) + 1 45 | rightChildIdx := (2 * idx) + 2 46 | var leftChild, rightChild, swap int 47 | 48 | if leftChildIdx < length { 49 | leftChild = arr[leftChildIdx] 50 | if leftChild > element { 51 | swap = leftChildIdx 52 | } 53 | } 54 | if rightChildIdx < length { 55 | rightChild = arr[rightChildIdx] 56 | if (rightChild > element && swap == 0) || (rightChild > leftChild && swap != 0) { 57 | swap = rightChildIdx 58 | } 59 | } 60 | 61 | if swap == 0 { 62 | break 63 | } 64 | arr[idx] = arr[swap] 65 | arr[swap] = element 66 | idx = swap 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /algorithms/order_statistics/naive_approach/naive_approach.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var arr []int 6 | 7 | func main() { 8 | fmt.Println("\n-- Order Statistics Naive Approach --") 9 | 10 | // initialization 11 | var size int 12 | newArr := make([]int, 0) 13 | var k int 14 | 15 | // user inputs 16 | fmt.Print("\nEnter the size of array: ") 17 | fmt.Scanf("%d\n", &size) 18 | fmt.Println("Start entering elements:") 19 | for i := 0; i < size; i++ { 20 | var value int 21 | fmt.Scanf("%d\n", &value) 22 | newArr = append(newArr, value) 23 | } 24 | fmt.Print("Enter the value of k: ") 25 | fmt.Scanf("%d\n", &k) 26 | 27 | naiveSelect(newArr, k) 28 | 29 | fmt.Println(k, "smallest element is:", arr[0]) 30 | } 31 | 32 | func naiveSelect(newArr []int, k int) { 33 | for i := 0; i < k; i++ { 34 | arr = append(arr, newArr[i]) 35 | maxHeapify() 36 | } 37 | for i := k; i < len(newArr); i++ { 38 | if arr[0] < newArr[i] { 39 | continue 40 | } 41 | arr = append(arr, newArr[i]) 42 | maxHeapify() 43 | ExtractMax() 44 | } 45 | } 46 | 47 | // sorted - {1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 19} 48 | // var newArr = []int{5, 15, 8, 3, 1, 9, 10, 6, 7, 12, 14, 2, 16, 19} 49 | -------------------------------------------------------------------------------- /algorithms/order_statistics/quick_select/quick_select.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("\n-- Order Statistics Quick Select --") 11 | 12 | // initializations 13 | var size, k int 14 | arr := make([]int, 0) 15 | 16 | // user inputs 17 | fmt.Print("\nEnter the size of array: ") 18 | fmt.Scanf("%d\n", &size) 19 | fmt.Println("Start entering elements:") 20 | for i := 0; i < size; i++ { 21 | var value int 22 | fmt.Scanf("%d\n", &value) 23 | arr = append(arr, value) 24 | } 25 | fmt.Print("Enter the value for k: ") 26 | fmt.Scanf("%d\n", &k) 27 | 28 | value := QuickSelect(arr, k) 29 | fmt.Println(k, "smallest element is:", value) 30 | } 31 | 32 | // QuickSelect finds kth smallest element in an array using quick sort - partially 33 | func QuickSelect(arr []int, k int) int { 34 | if len(arr) == 1 { 35 | return arr[0] 36 | } 37 | 38 | pos := partition(arr) 39 | 40 | if pos == k-1 { 41 | return arr[pos] 42 | } else if k-1 < pos { 43 | return QuickSelect(arr[:pos], k) 44 | } 45 | 46 | return QuickSelect(arr[pos+1:], k-pos-1) 47 | } 48 | 49 | func partition(arr []int) int { 50 | 51 | // generate a random number, time as a seed value 52 | rand.Seed(time.Now().UnixNano()) 53 | n := rand.Intn(len(arr) - 1) 54 | 55 | // push the element to last 56 | arr[n], arr[len(arr)-1] = arr[len(arr)-1], arr[n] 57 | n = len(arr) - 1 58 | 59 | pivot := arr[n] 60 | index := 0 61 | for i := 0; i < n; i++ { 62 | if arr[i] < pivot { 63 | arr[i], arr[index] = arr[index], arr[i] 64 | index++ 65 | } 66 | } 67 | arr[index], arr[n] = arr[n], arr[index] 68 | return index 69 | } 70 | 71 | // sorted - {1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 19} 72 | // var arr = []int{5, 15, 8, 3, 1, 9, 10, 6, 7, 12, 14, 2, 16, 19} 73 | -------------------------------------------------------------------------------- /algorithms/order_statistics/worst_case_linear_time/wclt.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "sort" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("\n-- Worst Case Linear Time Order Statistics --") 11 | arr := make([]float64, 0) 12 | var value int 13 | var n int 14 | var k int 15 | fmt.Print("\nEnter the size of an array: ") 16 | fmt.Scanf("%d\n", &n) 17 | fmt.Println("Start entering elements:") 18 | for i := 0; i < n; i++ { 19 | fmt.Scanf("%d\n", &value) 20 | arr = append(arr, float64(value)) 21 | } 22 | fmt.Print("Enter the value for k: ") 23 | fmt.Scanf("%d\n", &k) 24 | if k < 1 || k >= len(arr) { 25 | fmt.Println("You must enter a valid value for k.") 26 | return 27 | } 28 | fmt.Println(k, "smallest element is:", kthSmallest(arr, k)) 29 | } 30 | 31 | // WCLT Worst Case Linear Time Order Statistics 32 | func kthSmallest(arr []float64, k int) float64 { 33 | if len(arr) == 1 { 34 | return arr[0] 35 | } 36 | 37 | median := make([]float64, 0) 38 | upto := int(math.Ceil(float64(len(arr)) / 5)) 39 | // dividing array in n/5 subgroups 40 | for i := 0; i < upto; i++ { 41 | if (i*5)+5 > len(arr) { 42 | newArr := arr[i*5:] 43 | sort.Float64s(newArr) 44 | median = append(median, findMedian(newArr, len(newArr))) 45 | } else { 46 | newArr := arr[i*5 : (i*5)+5] 47 | sort.Float64s(newArr) 48 | median = append(median, findMedian(newArr, 5)) 49 | } 50 | } 51 | 52 | // finding median of medians 53 | medianOfMedian := kthSmallest(median, len(median)/2) 54 | 55 | rank := findRank(arr, medianOfMedian) 56 | 57 | pos := partition(arr, rank) 58 | 59 | if pos == k-1 { 60 | return arr[pos] 61 | } else if pos > k-1 { 62 | return kthSmallest(arr[:pos], k) 63 | } 64 | 65 | return kthSmallest(arr[pos+1:], k-pos-1) 66 | } 67 | 68 | func partition(arr []float64, rank int) int { 69 | arr[rank], arr[len(arr)-1] = arr[len(arr)-1], arr[rank] 70 | pivot := arr[len(arr)-1] 71 | index := 0 72 | for i := 0; i < len(arr)-1; i++ { 73 | if arr[i] < pivot { 74 | arr[i], arr[index] = arr[index], arr[i] 75 | index++ 76 | } 77 | } 78 | arr[index], arr[len(arr)-1] = arr[len(arr)-1], arr[index] 79 | return index 80 | } 81 | 82 | func findMedian(arr []float64, n int) float64 { 83 | return arr[n/2] 84 | } 85 | 86 | func findRank(arr []float64, value float64) int { 87 | for i := 0; i < len(arr); i++ { 88 | if arr[i] == value { 89 | return i 90 | } 91 | } 92 | return -1 93 | } 94 | 95 | // Array 96 | // {5, 15, 8, 3, 1, 9, 10, 6, 7, 12, 14, 2, 16, 19} 97 | // sorted - {1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 19} 98 | -------------------------------------------------------------------------------- /algorithms/power_set/power_set.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("\n-- Generating Power Set (Set of Subsets)--") 11 | 12 | var value int 13 | 14 | fmt.Print("\nEnter a value: ") 15 | fmt.Scanf("%d\n", &value) 16 | 17 | list := PowerSet(value) 18 | 19 | fmt.Println("All possible subsets upto", value, "are:") 20 | for i := 0; i < len(list); i++ { 21 | str := strings.Split(list[i], "") 22 | fmt.Println("{" + strings.Join(str, ", ") + "}") 23 | } 24 | } 25 | 26 | // PowerSet generates a set of all subsets of a given integer 27 | func PowerSet(n int) []string { 28 | 29 | if n == 0 { 30 | return []string{"0"} 31 | } 32 | 33 | list := PowerSet(n - 1) 34 | 35 | newList := make([]string, 0) 36 | 37 | str := strconv.Itoa(n) 38 | newList = append(newList, list...) 39 | newList = append(newList, str) 40 | for i := 1; i < len(list); i++ { 41 | newList = append(newList, list[i]+str) 42 | } 43 | return newList 44 | } 45 | -------------------------------------------------------------------------------- /algorithms/searching/binary_search/binary_search.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func binarySearch(size, key int) int { 6 | var low, middle, high, index int 7 | low = 0 8 | high = size - 1 9 | 10 | for low <= high { 11 | middle = (low + high) / 2 12 | if arr[middle] < key { 13 | low = middle + 1 14 | } else if arr[middle] > key { 15 | high = middle - 1 16 | } else if arr[middle] == key { 17 | index = middle + 1 18 | return index 19 | } 20 | } 21 | return -1 22 | } 23 | 24 | var arr []int 25 | 26 | func main() { 27 | var size, element, key int 28 | fmt.Println("\n-- Binary Search --") 29 | fmt.Print("\nEnter the size of an array: ") 30 | fmt.Scanf("%d\n", &size) 31 | fmt.Println("Start entering elements in sorted manner:") 32 | for i := 0; i < size; i++ { 33 | fmt.Scanf("%d\n", &element) 34 | arr = append(arr, element) 35 | } 36 | fmt.Print("Enter the search key: ") 37 | fmt.Scanf("%d\n", &key) 38 | 39 | index := binarySearch(size, key) 40 | if index == -1 { 41 | fmt.Println("Search key not found.") 42 | } else { 43 | fmt.Println("Search key found at index:") 44 | fmt.Println(index) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /algorithms/searching/interpolation_search/interpolation_search.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("\n-- Interpolation Search --") 7 | 8 | var size, key int 9 | arr := make([]int, 0) 10 | 11 | fmt.Print("\nEnter the size of array: ") 12 | fmt.Scanf("%d\n", &size) 13 | fmt.Println("Start entering elements in sorted order:") 14 | for i := 0; i < size; i++ { 15 | var value int 16 | fmt.Scanf("%d\n", &value) 17 | arr = append(arr, value) 18 | } 19 | fmt.Print("Enter the value for key: ") 20 | fmt.Scanf("%d\n", &key) 21 | 22 | pos := InterpolationSearch(arr, key) 23 | 24 | if pos == -1 { 25 | fmt.Println("\nKey", key, "not found in given array.") 26 | } else { 27 | fmt.Println("\nKey", key, "found at position", pos, "in given array.") 28 | } 29 | } 30 | 31 | // InterpolationSearch searches for a key in an sorted array 32 | func InterpolationSearch(arr []int, key int) int { 33 | l := 0 34 | h := len(arr) - 1 35 | 36 | for arr[l] <= key && arr[h] >= key { 37 | pos := l + (((key - arr[l]) * (h - l)) / (arr[h] - arr[l])) 38 | 39 | if arr[pos] == key { 40 | return pos + 1 41 | } else if key < arr[pos] { 42 | h = pos - 1 43 | } else if key > arr[pos] { 44 | l = pos + 1 45 | } 46 | } 47 | return -1 48 | } 49 | 50 | // var arr = []int{10, 20, 25, 35, 50, 70, 85, 100, 110, 120, 125} 51 | // var arr = []int{5, 10, 15, 20, 25, 30, 35, 40, 45, 50} 52 | -------------------------------------------------------------------------------- /algorithms/searching/linear_search/linear_search.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func linearSearch(size, key int) []int { 6 | var index []int 7 | for i := 0; i < size; i++ { 8 | if key == arr[i] { 9 | index = append(index, i+1) 10 | } 11 | } 12 | return index 13 | } 14 | 15 | var arr []int 16 | 17 | func main() { 18 | var size, element, key int 19 | fmt.Println("\n-- Linear Search --") 20 | fmt.Print("\nEnter the size of an array: ") 21 | fmt.Scanf("%d\n", &size) 22 | fmt.Println("Start entering elements in sorted manner:") 23 | for i := 0; i < size; i++ { 24 | fmt.Scanf("%d\n", &element) 25 | arr = append(arr, element) 26 | } 27 | fmt.Print("Enter the search key: ") 28 | fmt.Scanf("%d\n", &key) 29 | index := linearSearch(size, key) 30 | if len(index) == 0 { 31 | fmt.Println("Key not fount") 32 | } else { 33 | fmt.Println("Key found at following index/indices:") 34 | fmt.Println(index) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /algorithms/searching/ternary_search/ternary_search.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("\n-- Ternary Search --") 7 | 8 | var size, key int 9 | arr := make([]int, 0) 10 | 11 | fmt.Print("\nEnter the size of array: ") 12 | fmt.Scanf("%d\n", &size) 13 | fmt.Println("Start entering elements in sorted order:") 14 | for i := 0; i < size; i++ { 15 | var value int 16 | fmt.Scanf("%d\n", &value) 17 | arr = append(arr, value) 18 | } 19 | fmt.Print("Enter the value for key: ") 20 | fmt.Scanf("%d\n", &key) 21 | 22 | pos := TernarySearch(arr, 0, size-1, key) 23 | 24 | if pos == -1 { 25 | fmt.Println("\nKey", key, "not found in given array.") 26 | } else { 27 | fmt.Println("\nKey", key, "found at position", pos, "in given array.") 28 | } 29 | 30 | } 31 | 32 | // TernarySearch searches for a key in a given array 33 | func TernarySearch(arr []int, l, h, key int) int { 34 | if h < l { 35 | return -1 36 | } 37 | 38 | mid1 := l + (h-l)/3 39 | mid2 := h - (h-l)/3 40 | 41 | if arr[mid1] == key { 42 | return mid1 + 1 43 | } else if arr[mid2] == key { 44 | return mid2 + 1 45 | } else if key < arr[mid1] { 46 | return TernarySearch(arr, l, mid1-1, key) 47 | } else if key > arr[mid1] && key < arr[mid2] { 48 | return TernarySearch(arr, mid1+1, mid2-1, key) 49 | } else if key > arr[mid2] { 50 | return TernarySearch(arr, mid2+1, h, key) 51 | } 52 | return -1 53 | } 54 | 55 | // var arr = []int{1, 3, 4, 6, 8, 9, 12, 15, 17, 18, 23, 25, 27, 31, 32} 56 | -------------------------------------------------------------------------------- /algorithms/sieve_of_eratosthenes/sieve_of_eratosthenes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("-- Sieve of Eratosthenes: Generating consecutive primes numbers not exceeding n --") 10 | var n int 11 | fmt.Print("Enter the number greater than 1: ") 12 | fmt.Scanf("%d\n", &n) 13 | arr := Sieve(n) 14 | fmt.Println("Consecutive prime number not exceeding", n, "are: ") 15 | fmt.Println(arr) 16 | } 17 | 18 | // Sieve implements Sieve of Eratosthenes algorithm 19 | func Sieve(n int) []int { 20 | arr := make([]int, 0) 21 | limit := int(math.Floor(math.Sqrt(float64(n)))) 22 | 23 | for i := 0; i <= n; i++ { 24 | arr = append(arr, i) 25 | } 26 | 27 | arr[1] = 0 28 | 29 | for i := 2; i <= limit; i++ { 30 | if arr[i] != 0 { 31 | j := i * i 32 | for j <= n { 33 | arr[j] = 0 34 | j += i 35 | } 36 | } 37 | } 38 | 39 | newArr := make([]int, 0) 40 | 41 | for i := 0; i < len(arr); i++ { 42 | if arr[i] != 0 { 43 | newArr = append(newArr, arr[i]) 44 | } 45 | } 46 | 47 | return newArr 48 | } 49 | -------------------------------------------------------------------------------- /algorithms/sorting/binary_insertion_sort/binary_insertion_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // InsertionSort performs insertion sort while finding the right position for the key element to be inserted 6 | // using BinarySearch 7 | func InsertionSort() { 8 | var lock int 9 | for i := 0; i < n-1; i++ { 10 | j := i 11 | key := elements[i+1] 12 | lock = BinarySearch(elements, key, 0, j) 13 | for j >= lock { 14 | elements[j+1] = elements[j] 15 | j-- 16 | } 17 | elements[j+1] = key 18 | } 19 | } 20 | 21 | var n int 22 | var elements []int 23 | 24 | func main() { 25 | fmt.Println("\n-- Binary Insertion Sort --") 26 | fmt.Print("\nEnter the number of elements: ") 27 | fmt.Scanf("%d\n", &n) 28 | elements = make([]int, n) 29 | var temp int 30 | fmt.Println("Start entering the elements:") 31 | for i := 0; i < n; i++ { 32 | fmt.Scanf("%d\n", &temp) 33 | elements[i] = temp 34 | } 35 | InsertionSort() 36 | fmt.Println("Sorted Array is: ") 37 | fmt.Println(elements) 38 | } 39 | 40 | // BinarySearch performs binary search on given array 41 | func BinarySearch(arr []int, item, low, high int) int { 42 | if high <= low { 43 | if item > arr[low] { 44 | return low + 1 45 | } 46 | return low 47 | } 48 | mid := (low + high) / 2 49 | if item == arr[mid] { 50 | return mid + 1 51 | } 52 | if item > arr[mid] { 53 | return BinarySearch(arr, item, mid+1, high) 54 | } 55 | return BinarySearch(arr, item, low, mid-1) 56 | } 57 | -------------------------------------------------------------------------------- /algorithms/sorting/bubble_sort/bubble_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var arr []int 6 | 7 | func main() { 8 | var size int 9 | var element int 10 | fmt.Println("\n-- Bubble Sort --") 11 | fmt.Print("\nEnter the size of an array: ") 12 | fmt.Scanf("%d\n", &size) 13 | fmt.Println("Start entering elements:") 14 | for i := 0; i < size; i++ { 15 | fmt.Scanf("%d\n", &element) 16 | arr = append(arr, element) 17 | } 18 | 19 | // sorting 20 | for i := size - 1; i >= 0; i-- { 21 | for j := 0; j < i; j++ { 22 | if arr[j] > arr[j+1] { 23 | arr[j], arr[j+1] = arr[j+1], arr[j] 24 | } 25 | } 26 | } 27 | 28 | fmt.Println("Sorted Array is:") 29 | fmt.Println(arr) 30 | } 31 | -------------------------------------------------------------------------------- /algorithms/sorting/bucket_sort/bucket_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // InsertionSort performs insertion sort on each bucket 9 | func InsertionSort(a []float64, n int) []float64 { 10 | for i := 0; i < n-1; i++ { 11 | j := i 12 | key := a[i+1] 13 | for j >= 0 && key < a[j] { 14 | a[j+1] = a[j] 15 | j-- 16 | } 17 | a[j+1] = key 18 | } 19 | return a 20 | } 21 | 22 | // BucketSort sort the array using bucket sort algorithm 23 | func BucketSort() { 24 | bucket = make([][]float64, size) 25 | for i := 0; i < size; i++ { 26 | index := int(math.Floor((arr[i] / max) * (float64(size - 1)))) 27 | bucket[index] = append(bucket[index], arr[i]) 28 | } 29 | 30 | for i := 0; i < size; i++ { 31 | if i == 0 { 32 | bucket[0] = InsertionSort(bucket[i], len(bucket[i])) 33 | } else { 34 | bucket[0] = append(bucket[0], InsertionSort(bucket[i], len(bucket[i]))...) 35 | } 36 | } 37 | } 38 | 39 | var size int 40 | var max float64 41 | var arr []float64 42 | var bucket [][]float64 43 | 44 | func init() { 45 | arr = make([]float64, 0) 46 | bucket = make([][]float64, 0) 47 | } 48 | 49 | func main() { 50 | fmt.Println("\n-- Insertion Sort --") 51 | fmt.Print("Enter the size of an array: ") 52 | fmt.Scanf("%d\n", &size) 53 | fmt.Println("Start entering the elements:") 54 | var temp float64 55 | for i := 0; i < size; i++ { 56 | if i == 0 { 57 | max = temp 58 | } 59 | fmt.Scanf("%f\n", &temp) 60 | arr = append(arr, temp) 61 | if max < temp { 62 | max = temp 63 | } 64 | } 65 | 66 | BucketSort() 67 | 68 | fmt.Println(bucket[0]) 69 | } 70 | -------------------------------------------------------------------------------- /algorithms/sorting/counting_sort/counting_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | func countingSort(size, max int) []int { 9 | count := make([]int, max) 10 | sorted := make([]int, size) 11 | for i := 0; i < size; i++ { 12 | count[arr[i]]++ 13 | } 14 | for i := 1; i < max; i++ { 15 | count[i] += count[i-1] 16 | } 17 | for i := size - 1; i >= 0; i-- { 18 | sorted[count[arr[i]]-1] = arr[i] 19 | count[arr[i]]-- 20 | } 21 | return sorted 22 | } 23 | 24 | var arr []int 25 | 26 | func main() { 27 | var size, element, min, max int 28 | fmt.Println("\n-- Counting Sort --") 29 | fmt.Print("\nEnter the size of an array: ") 30 | fmt.Scanf("%d\n", &size) 31 | fmt.Println("Start entering elements:") 32 | for i := 0; i < size; i++ { 33 | fmt.Scanf("%d\n", &element) 34 | 35 | if i == 0 { 36 | min = element 37 | max = element 38 | } 39 | 40 | min = int(math.Min(float64(min), float64(element))) 41 | max = int(math.Max(float64(max), float64(element))) 42 | arr = append(arr, element) 43 | } 44 | sorted := countingSort(size, max+1) 45 | fmt.Println("Sorted array is:") 46 | fmt.Println(sorted) 47 | } 48 | -------------------------------------------------------------------------------- /algorithms/sorting/heap_sort/heap_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | func maxHeapify() { 9 | idx := len(arr) - 1 10 | element := arr[idx] 11 | for idx > 0 { 12 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 13 | parent := arr[parentIdx] 14 | if element <= parent { 15 | break 16 | } 17 | arr[parentIdx] = element 18 | arr[idx] = parent 19 | idx = parentIdx 20 | } 21 | } 22 | 23 | // ExtractMax will remove a node from heap 24 | func ExtractMax() int { 25 | if len(arr) == 0 || arr[0] == 0 { 26 | fmt.Println("\n-- Heap is empty. --") 27 | return 0 28 | } 29 | max := arr[0] 30 | end := arr[len(arr)-1] 31 | arr = arr[0 : len(arr)-1] 32 | if len(arr) > 0 { 33 | arr[0] = end 34 | bubbleDown() 35 | } 36 | return max 37 | } 38 | 39 | func bubbleDown() { 40 | idx := 0 41 | length := len(arr) 42 | element := arr[0] 43 | for { 44 | leftChildIdx := (2 * idx) + 1 45 | rightChildIdx := (2 * idx) + 2 46 | var leftChild, rightChild, swap int 47 | 48 | if leftChildIdx < length { 49 | leftChild = arr[leftChildIdx] 50 | if leftChild > element { 51 | swap = leftChildIdx 52 | } 53 | } 54 | if rightChildIdx < length { 55 | rightChild = arr[rightChildIdx] 56 | if (rightChild > element && swap == 0) || (rightChild > leftChild && swap != 0) { 57 | swap = rightChildIdx 58 | } 59 | } 60 | 61 | if swap == 0 { 62 | break 63 | } 64 | arr[idx] = arr[swap] 65 | arr[swap] = element 66 | idx = swap 67 | } 68 | } 69 | 70 | // HeapSort sorts the arr using heap sort technique and returns the sorted arr 71 | func HeapSort(size int) []int { 72 | sorted := make([]int, size) 73 | for i := 0; i < size; i++ { 74 | max := ExtractMax() 75 | sorted[size-1-i] = max 76 | } 77 | return sorted 78 | } 79 | 80 | var arr []int 81 | 82 | func main() { 83 | var size, element int 84 | fmt.Println("\n-- Heap Sort --") 85 | fmt.Print("\nEnter the size of an array: ") 86 | fmt.Scanf("%d\n", &size) 87 | fmt.Println("Start entering elements:") 88 | 89 | for i := 0; i < size; i++ { 90 | fmt.Scanf("%d\n", &element) 91 | arr = append(arr, element) 92 | maxHeapify() 93 | } 94 | 95 | sorted := HeapSort(size) 96 | fmt.Println("Sorted array is:") 97 | fmt.Println(sorted) 98 | } 99 | -------------------------------------------------------------------------------- /algorithms/sorting/insertion_sort/insertion_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var arr []int 6 | 7 | func main() { 8 | var size int 9 | var element int 10 | fmt.Println("\n-- Insertion Sort --") 11 | fmt.Print("\nEnter the size of an array: ") 12 | fmt.Scanf("%d\n", &size) 13 | fmt.Println("Start entering the elements:") 14 | for i := 0; i < size; i++ { 15 | fmt.Scanf("%d\n", &element) 16 | arr = append(arr, element) 17 | } 18 | 19 | for i := 0; i < size-1; i++ { 20 | j := i 21 | key := arr[i+1] 22 | for j >= 0 && key < arr[j] { 23 | arr[j+1] = arr[j] 24 | j-- 25 | } 26 | arr[j+1] = key 27 | } 28 | 29 | fmt.Println("Sorted Array is:") 30 | fmt.Println(arr) 31 | } 32 | -------------------------------------------------------------------------------- /algorithms/sorting/merge_sort/merge_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var arr []int 6 | 7 | func main() { 8 | var size int 9 | var element int 10 | fmt.Println("\n-- Merge Sort --") 11 | fmt.Print("\nEnter the size of an array: ") 12 | fmt.Scanf("%d\n", &size) 13 | fmt.Println("Start entering elements:") 14 | for i := 0; i < size; i++ { 15 | fmt.Scanf("%d\n", &element) 16 | arr = append(arr, element) 17 | } 18 | mergeSort(0, size-1) 19 | fmt.Println("Sorted Array is:") 20 | fmt.Println(arr) 21 | } 22 | 23 | func merge(l, m, r int) { 24 | var i, j, k int 25 | nl := m - l + 1 26 | nr := r - m 27 | var left, right []int 28 | 29 | for i = 0; i < nl; i++ { 30 | left = append(left, arr[l+i]) 31 | } 32 | 33 | for j = 0; j < nr; j++ { 34 | right = append(right, arr[m+1+j]) 35 | } 36 | 37 | i = 0 38 | j = 0 39 | k = l 40 | 41 | for i < nl && j < nr { 42 | if left[i] <= right[j] { 43 | arr[k] = left[i] 44 | i++ 45 | k++ 46 | } else { 47 | arr[k] = right[j] 48 | j++ 49 | k++ 50 | } 51 | } 52 | 53 | for i < nl { 54 | arr[k] = left[i] 55 | i++ 56 | k++ 57 | } 58 | for j < nr { 59 | arr[k] = right[j] 60 | j++ 61 | k++ 62 | } 63 | } 64 | 65 | func mergeSort(l, r int) { 66 | var mid int 67 | if l < r { 68 | mid = (l + r) / 2 69 | mergeSort(l, mid) 70 | mergeSort(mid+1, r) 71 | merge(l, mid, r) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /algorithms/sorting/quick_sort/quick_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var arr []int 6 | 7 | func main() { 8 | var size int 9 | var element int 10 | fmt.Println("\n-- Quick Sort --") 11 | fmt.Print("\nEnter the size of an array: ") 12 | fmt.Scanf("%d\n", &size) 13 | fmt.Println("Start entering elements:") 14 | for i := 0; i < size; i++ { 15 | fmt.Scanf("%d\n", &element) 16 | arr = append(arr, element) 17 | } 18 | 19 | quicksort(0, size-1) 20 | 21 | fmt.Println("Sorted Array is:") 22 | fmt.Println(arr) 23 | } 24 | 25 | func partition(first, last int) int { 26 | pivot := arr[first] 27 | i := first 28 | j := last + 1 29 | 30 | for i < j { 31 | i++ 32 | j-- 33 | for arr[i] < pivot && i < last { 34 | i++ 35 | } 36 | for arr[j] > pivot && j > first { 37 | j-- 38 | } 39 | if i < j { 40 | arr[i], arr[j] = arr[j], arr[i] 41 | } 42 | } 43 | arr[j], arr[first] = arr[first], arr[j] 44 | return j 45 | } 46 | 47 | func quicksort(first, last int) { 48 | var sp int 49 | if first < last { 50 | sp = partition(first, last) 51 | quicksort(first, sp-1) 52 | quicksort(sp+1, last) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /algorithms/sorting/radix_sort/radix_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | var arr []int 9 | 10 | func main() { 11 | var size int 12 | var element int 13 | fmt.Println("\n-- Radix Sort --") 14 | fmt.Print("\nEnter the size of an array: ") 15 | fmt.Scanf("%d\n", &size) 16 | fmt.Println("Start entering elements:") 17 | for i := 0; i < size; i++ { 18 | fmt.Scanf("%d\n", &element) 19 | arr = append(arr, element) 20 | } 21 | radixSort() 22 | fmt.Println("Sorted Array is:") 23 | fmt.Println(arr) 24 | } 25 | 26 | func radixSort() { 27 | maxDigitCount := mostDigits(arr) 28 | 29 | for k := 0; k < maxDigitCount; k++ { 30 | var bucket [10][]int 31 | for i := 0; i < len(arr); i++ { 32 | digit := getDigit(arr[i], k) 33 | bucket[digit] = append(bucket[digit], arr[i]) 34 | } 35 | 36 | // concat numbers back to original array 37 | arr = arr[0:0] 38 | for j := 0; j < 10; j++ { 39 | arr = append(arr, bucket[j]...) 40 | } 41 | } 42 | } 43 | 44 | // getDigit returns an integer whose value is equivalent to index position in given number 45 | func getDigit(value, index int) int { 46 | return int(math.Floor(math.Abs(float64(value)/math.Pow(float64(10), float64(index))))) % 10 47 | } 48 | 49 | // digitCount returns an integer which is the count of number of digits in a given number 50 | func digitCount(value int) int { 51 | if value == 0 { 52 | return 1 53 | } 54 | return int(math.Floor(math.Log10(float64(value)))) + 1 55 | } 56 | 57 | // mostDigits returns a digits count whose length is maximum or say whose value is maximum 58 | func mostDigits(nums []int) int { 59 | maxDigits := 0 60 | for i := 0; i < len(nums); i++ { 61 | maxDigits = int(math.Max(float64(maxDigits), float64(digitCount(nums[i])))) 62 | } 63 | return maxDigits 64 | } 65 | -------------------------------------------------------------------------------- /algorithms/sorting/selection_sort/selection_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var arr []int 6 | 7 | func main() { 8 | var length int 9 | var element int 10 | fmt.Println("\n-- Selection Sort --") 11 | fmt.Print("\nEnter the size of an array: ") 12 | fmt.Scanf("%d\n", &length) 13 | fmt.Println("Start entering the elements: ") 14 | for i := 0; i < length; i++ { 15 | fmt.Scanf("%d\n", &element) 16 | arr = append(arr, element) 17 | } 18 | 19 | // Sorting 20 | for i := 0; i < length; i++ { 21 | for j := i + 1; j < length; j++ { 22 | if arr[i] > arr[j] { 23 | arr[i], arr[j] = arr[j], arr[i] 24 | } 25 | } 26 | } 27 | 28 | fmt.Println("Sorted Array is:") 29 | fmt.Println(arr) 30 | } 31 | -------------------------------------------------------------------------------- /algorithms/sorting/shell_sort/shell_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | func shellSort(size int) { 9 | gap := int(math.Floor(float64(size / 2))) 10 | for { 11 | for i := 0; i < size-((size-1)%gap); i++ { 12 | 13 | // swap the elements 14 | if arr[i] > arr[gap+i] { 15 | arr[i], arr[gap+i] = arr[gap+i], arr[i] 16 | 17 | j := i 18 | // start comparing with previous elements 19 | for { 20 | // swap the elements 21 | if j-gap >= 0 && arr[j-gap] > arr[j] { 22 | arr[j-gap], arr[j] = arr[j], arr[j-gap] 23 | j-- 24 | } else { 25 | break 26 | } 27 | } 28 | } 29 | 30 | // check whether to break the loop 31 | if i == (size-1)-gap { 32 | break 33 | } 34 | } 35 | 36 | gap = int(math.Floor(float64(gap / 2))) // update the gap 37 | 38 | // break the main loop when gap is 0 39 | if gap == 0 { 40 | break 41 | } 42 | } 43 | } 44 | 45 | var arr []int 46 | 47 | func main() { 48 | var size, element int 49 | fmt.Println("\n-- Shell Sort --") 50 | fmt.Print("\nEnter the size of an array: ") 51 | fmt.Scanf("%d\n", &size) 52 | fmt.Println("Start entering elements:") 53 | for i := 0; i < size; i++ { 54 | fmt.Scanf("%d\n", &element) 55 | arr = append(arr, element) 56 | } 57 | shellSort(size) 58 | fmt.Println("Sorted array is:") 59 | fmt.Println(arr) 60 | } 61 | -------------------------------------------------------------------------------- /algorithms/string_matching/horspool/horspool.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("\n-- Boyer Moore Horspool Algorithm --") 10 | 11 | var text, pattern string 12 | 13 | fmt.Print("\nEnter the text string: ") 14 | fmt.Scanf("%s\n", &text) 15 | fmt.Print("Enter the pattern string: ") 16 | fmt.Scanf("%s\n", &pattern) 17 | 18 | st := ShiftTable(strings.Split(pattern, "")) 19 | fmt.Println(st) 20 | index := Search(strings.Split(text, ""), strings.Split(pattern, ""), st) 21 | 22 | if len(index) == 0 { 23 | fmt.Println("\n-- Pattern not found in text! --") 24 | } else { 25 | fmt.Println("\nPattern found at index/ices:") 26 | fmt.Println(index) 27 | } 28 | 29 | } 30 | 31 | // ShiftTable creates shift table for given pattern 32 | func ShiftTable(pt []string) map[string]int { 33 | st := make(map[string]int) 34 | n := len(pt) 35 | for i := 0; i < n-1; i++ { 36 | if i == n-1 { 37 | if st[pt[i]] == 0 { 38 | st[pt[i]] = n 39 | continue 40 | } 41 | continue 42 | } 43 | st[pt[i]] = n - 1 - i 44 | } 45 | 46 | return st 47 | } 48 | 49 | // Search searches for pattern string in given text string and returns the indices values if pattern is found 50 | // else returns empty array 51 | func Search(txt, pt []string, st map[string]int) []int { 52 | 53 | pos := make([]int, 0) 54 | 55 | var j int 56 | for i := len(pt) - 1; i >= 0 && i < len(txt); { 57 | skip := 0 58 | 59 | for j = len(pt) - 1; j >= 0 && pt[j] == txt[i]; j-- { 60 | i-- 61 | if j == 0 { 62 | pos = append(pos, i+2) 63 | i += len(pt) + 1 64 | skip = 1 65 | break 66 | } 67 | } 68 | 69 | if skip == 1 { 70 | continue 71 | } 72 | 73 | stVal := st[txt[i]] 74 | 75 | if stVal == 0 { 76 | stVal = len(pt) - 1 77 | } 78 | 79 | i += stVal 80 | } 81 | 82 | return pos 83 | } 84 | 85 | // Sample test strings 86 | // 87 | // GCAATGCCTATGTGACC 88 | // TATGTG 89 | // 9 90 | // 91 | // AABAACAADAABAABA 92 | // AABA 93 | // [1 10 13] 94 | // 95 | // TRUSTHARDTOOTHBRUSHES 96 | // TOOTH 97 | // 10 98 | // 99 | // GCATATGTGATGCCTATGTGACCTATGTG 100 | // TATGTG 101 | // [4 15 24] 102 | // 103 | // JIM SAW ME IN A BARBER SHOP 104 | // BARBER 105 | // [7] 106 | // 107 | // JIMBARBER SAW ME IN A BARBER SHOP 108 | // BARBER 109 | // [4 23] 110 | -------------------------------------------------------------------------------- /algorithms/string_matching/knuth_morris_pratt/knuth_morris_pratt.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Knp implements Knuth Morris Pratt Algorithms 6 | func Knp() { 7 | computePi() 8 | i := 0 9 | j := 0 10 | m := len(pattern) 11 | n := len(text) 12 | for i < n { 13 | if pattern[j] == text[i] { 14 | i++ 15 | j++ 16 | } 17 | if j == m { 18 | fmt.Println("Pattern found at", i-j) 19 | j = pi[j-1] 20 | } else if i < n && pattern[j] != text[i] { 21 | if j != 0 { 22 | j = pi[j-1] 23 | } else { 24 | i++ 25 | } 26 | } 27 | } 28 | } 29 | 30 | var text string 31 | var pattern string 32 | var pi []int 33 | 34 | func main() { 35 | fmt.Println("\n-- Knuth Morris Pratt Algorithm --") 36 | fmt.Print("\nEnter the initial text: ") 37 | fmt.Scanf("%s\n", &text) 38 | fmt.Print("Enter the pattern: ") 39 | fmt.Scanf("%s\n", &pattern) 40 | Knp() 41 | } 42 | 43 | func computePi() { 44 | pi = make([]int, len(pattern)) 45 | pi[0] = 0 46 | k := 0 47 | for i := 1; i < len(pattern); i++ { 48 | if pattern[i] == pattern[k] { 49 | k++ 50 | pi[i] = k 51 | } else { 52 | if k != 0 { 53 | k = pi[k-1] 54 | } else { 55 | pi[i] = k 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /algorithms/string_matching/naive_pattern_matching/naive_pattern_matching.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func naiveMatch() []int { 6 | var occurance []int 7 | for i := range mainString { 8 | for j := range pattern { 9 | if mainString[i+j] != pattern[j] { 10 | break 11 | } else if j == (len(pattern) - 1) { 12 | occurance = append(occurance, i+1) 13 | } 14 | } 15 | } 16 | return occurance 17 | } 18 | 19 | var mainString, pattern string 20 | 21 | func main() { 22 | fmt.Println("\n-- Naive Pattern Matching --") 23 | fmt.Print("\nEnter the main string: ") 24 | fmt.Scanf("%s\n", &mainString) 25 | fmt.Print("Enter the pattern: ") 26 | fmt.Scanf("%s\n", &pattern) 27 | occurance := naiveMatch() 28 | if len(occurance) == 0 { 29 | fmt.Println("-- No pattern found --") 30 | } else { 31 | for i := range occurance { 32 | fmt.Println("Pattern found at index", occurance[i]) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /algorithms/string_matching/rabin_karp/rabin_karp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "hash/fnv" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("-- Rabin Karp --") 10 | var text, pattern string 11 | fmt.Print("Enter the text string: ") 12 | fmt.Scanf("%s\n", &text) 13 | fmt.Print("Enter the pattern string: ") 14 | fmt.Scanf("%s\n", &pattern) 15 | arr := RabinKarpWithoutHash(text, pattern) 16 | fmt.Println("Without using hash function, pattern found at index/ices:", arr) 17 | arr = RabinKarpWithHash(text, pattern) 18 | fmt.Println("With using hash function, pattern found at index/ices:", arr) 19 | } 20 | 21 | // RabinKarpWithoutHash searches for pattern in a given text string without using language built-in hash function 22 | func RabinKarpWithoutHash(text, pattern string) []int { 23 | arr := make([]int, 0) 24 | d := 256 25 | q := 101 26 | m := len(pattern) 27 | n := len(text) 28 | p := 0 29 | t := 0 30 | h := 1 31 | i := 0 32 | j := 0 33 | 34 | for i = 0; i < m-1; i++ { 35 | h = (h * d) % q 36 | } 37 | 38 | for i = 0; i < m; i++ { 39 | p = ((d * p) + int(pattern[i])) % q 40 | t = ((d * t) + int(text[i])) % q 41 | } 42 | 43 | for i = 0; i <= n-m; i++ { 44 | if p == t { 45 | for j = 0; j < m; j++ { 46 | if text[i+j] != pattern[j] { 47 | break 48 | } 49 | } 50 | if j == m { 51 | arr = append(arr, i+1) 52 | } 53 | } 54 | 55 | if i < n-m { 56 | t = ((d * (t - int(text[i])*h)) + (int(text[i+m]))) % q 57 | if t < 0 { 58 | t += q 59 | } 60 | } 61 | 62 | } 63 | 64 | return arr 65 | } 66 | 67 | // RabinKarpWithHash searches for pattern in a given text string by using language built-in hash function 68 | func RabinKarpWithHash(text, pattern string) []int { 69 | arr := make([]int, 0) 70 | m := len(pattern) 71 | n := len(text) 72 | p := "" 73 | t := "" 74 | i := 0 75 | j := 0 76 | 77 | p = hash(pattern[0:m]) 78 | t = hash(text[0:m]) 79 | 80 | for i = 0; i <= n-m; i++ { 81 | if p == t { 82 | for j = 0; j < m; j++ { 83 | if text[i+j] != pattern[j] { 84 | break 85 | } 86 | } 87 | if j == m { 88 | arr = append(arr, i+1) 89 | } 90 | } 91 | 92 | if i < n-m { 93 | t = hash(text[i : i+m+1]) 94 | } 95 | 96 | } 97 | 98 | return arr 99 | } 100 | 101 | func hash(s string) string { 102 | h := fnv.New32a() 103 | h.Write([]byte(s)) 104 | return string(h.Sum32()) 105 | } 106 | -------------------------------------------------------------------------------- /algorithms/toh/toh.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var n int 7 | fmt.Println("\n-- Tower of Hanoi --") 8 | fmt.Print("\nEnter the number of discs: ") 9 | fmt.Scanf("%d\n", &n) 10 | Toh("A", "B", "C", n) 11 | } 12 | 13 | // Toh recursively calls iteself to implment tower of hanoi algorithm 14 | func Toh(origin, intermediate, destination string, n int) { 15 | if n == 1 { 16 | fmt.Println("Move disc", n, "from", origin, "->", destination) 17 | return 18 | } 19 | Toh(origin, destination, intermediate, n-1) 20 | fmt.Println("Move disc", n, "from", origin, "->", destination) 21 | Toh(intermediate, origin, destination, n-1) 22 | } 23 | -------------------------------------------------------------------------------- /graphs/directed_unweighted/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // DFS traverses a graph using dfs technique 6 | func (g graph) DFS() []string { 7 | visited := make(map[string]bool) 8 | var result []string 9 | if len(g) == 0 { 10 | fmt.Println("\n-- Graph is empty. --") 11 | return nil 12 | } 13 | for i := range g { 14 | if !visited[i] { 15 | result = g.dfsHelper(i, visited, result) 16 | } 17 | } 18 | return result 19 | } 20 | 21 | // dfsHelper recursively calls itself to solve dfs traversal 22 | func (g graph) dfsHelper(vtx string, visited map[string]bool, result []string) []string { 23 | visited[vtx] = true 24 | result = append(result, vtx) 25 | for i := range g[vtx] { 26 | if !visited[g[vtx][i]] { 27 | result = g.dfsHelper(g[vtx][i], visited, result) 28 | } 29 | } 30 | return result 31 | } 32 | 33 | // BFS traverses a graph using dfs technique 34 | func (g graph) BFS() []string { 35 | 36 | if len(g) == 0 { 37 | fmt.Println("\n-- Graph is empty. --") 38 | return nil 39 | } 40 | 41 | visited := make(map[string]bool) 42 | 43 | var queue []string 44 | var result []string 45 | var currentVtx string 46 | 47 | for i := range g { 48 | if !visited[i] { 49 | visited[i] = true 50 | queue = append(queue, i) 51 | 52 | for len(queue) != 0 { 53 | currentVtx = queue[0] // get the element from the queue 54 | queue = queue[1:] // remove element from the queue 55 | result = append(result, currentVtx) // push the current vertex in result 56 | 57 | for j := range g[currentVtx] { 58 | if !visited[g[currentVtx][j]] { 59 | visited[g[currentVtx][j]] = true // mark as visited 60 | queue = append(queue, g[currentVtx][j]) // push neighbors of current vertex in the queue 61 | } 62 | } 63 | 64 | } 65 | 66 | } 67 | } 68 | 69 | return result 70 | } 71 | -------------------------------------------------------------------------------- /graphs/directed_weighted/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // DFS traverses a graph using dfs technique 6 | func (g graph) DFS() ([]string, []int) { 7 | visited := make(map[string]bool) 8 | 9 | var result []string 10 | var weights []int 11 | 12 | if len(g) == 0 { 13 | fmt.Println("\n-- Graph is empty. --") 14 | return nil, nil 15 | } 16 | for i := range g { 17 | if !visited[i] { 18 | result, weights = g.dfsHelper(i, visited, result, weights) 19 | } 20 | } 21 | return result, weights 22 | } 23 | 24 | // dfsHelper recursively calls itself to solve dfs traversal 25 | func (g graph) dfsHelper(vtx string, visited map[string]bool, result []string, weights []int) ([]string, []int) { 26 | visited[vtx] = true 27 | result = append(result, vtx) 28 | for i := range g[vtx] { 29 | if !visited[g[vtx][i].name] { 30 | weights = append(weights, g[vtx][i].value) 31 | result, weights = g.dfsHelper(g[vtx][i].name, visited, result, weights) 32 | } 33 | } 34 | return result, weights 35 | } 36 | 37 | // BFS traverses a graph using dfs technique 38 | func (g graph) BFS() ([]string, []int) { 39 | 40 | if len(g) == 0 { 41 | fmt.Println("\n-- Graph is empty. --") 42 | return nil, nil 43 | } 44 | 45 | visited := make(map[string]bool) 46 | var queue []string 47 | var result []string 48 | var currentVtx string 49 | var weights []int 50 | 51 | for i := range g { 52 | if !visited[i] { 53 | visited[i] = true 54 | queue = append(queue, i) 55 | 56 | for len(queue) != 0 { 57 | currentVtx = queue[0] // get the element from the queue 58 | queue = queue[1:] // remove element from the queue 59 | result = append(result, currentVtx) // push the current vertex in result 60 | 61 | for j := range g[currentVtx] { 62 | if !visited[g[currentVtx][j].name] { 63 | visited[g[currentVtx][j].name] = true // mark as visited 64 | weights = append(weights, g[currentVtx][j].value) 65 | queue = append(queue, g[currentVtx][j].name) // push neighbors of current vertex in the queue 66 | } 67 | } 68 | 69 | } 70 | } 71 | } 72 | 73 | return result, weights 74 | } 75 | -------------------------------------------------------------------------------- /graphs/undirected_unweighted/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // DFS traverses a graph using dfs technique 6 | func (g graph) DFS(start string) []string { 7 | visited := make(map[string]bool) 8 | var result []string 9 | if g[start] == nil { 10 | fmt.Println("\n-- No vertex named " + start + " present in graph. --") 11 | return nil 12 | } 13 | result = g.dfsHelper(start, visited, result) 14 | return result 15 | } 16 | 17 | // dfsHelper recursively calls itself to solve dfs traversal 18 | func (g graph) dfsHelper(vtx string, visited map[string]bool, result []string) []string { 19 | visited[vtx] = true 20 | result = append(result, vtx) 21 | for i := range g[vtx] { 22 | if !visited[g[vtx][i]] { 23 | result = g.dfsHelper(g[vtx][i], visited, result) 24 | } 25 | } 26 | return result 27 | } 28 | 29 | // BFS traverses a graph using dfs technique 30 | func (g graph) BFS(start string) []string { 31 | 32 | if g[start] == nil { 33 | fmt.Println("\n-- No vertex named " + start + " present in graph. --") 34 | return nil 35 | } 36 | 37 | visited := make(map[string]bool) 38 | 39 | var queue []string 40 | queue = append(queue, start) 41 | 42 | var result []string 43 | var currentVtx string 44 | visited[start] = true 45 | 46 | for len(queue) != 0 { 47 | currentVtx = queue[0] // get the element from the queue 48 | queue = queue[1:] // remove element from the queue 49 | result = append(result, currentVtx) // push the current vertex in result 50 | 51 | for i := range g[currentVtx] { 52 | if !visited[g[currentVtx][i]] { 53 | visited[g[currentVtx][i]] = true // mark as visited 54 | queue = append(queue, g[currentVtx][i]) // push neighbors of current vertex in the queue 55 | } 56 | } 57 | 58 | } 59 | 60 | return result 61 | } 62 | -------------------------------------------------------------------------------- /graphs/undirected_weighted/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // DFS traverses a graph using dfs technique 6 | func (g graph) DFS(start string) ([]string, []int) { 7 | visited := make(map[string]bool) 8 | var result []string 9 | var weights []int 10 | if g[start] == nil { 11 | fmt.Println("\n-- No vertex named " + start + " present in graph. --") 12 | return nil, nil 13 | } 14 | result, weights = g.dfsHelper(start, visited, result, weights) 15 | return result, weights 16 | } 17 | 18 | // dfsHelper recursively calls itself to solve dfs traversal 19 | func (g graph) dfsHelper(vtx string, visited map[string]bool, result []string, weights []int) ([]string, []int) { 20 | visited[vtx] = true 21 | result = append(result, vtx) 22 | for i := range g[vtx] { 23 | if !visited[g[vtx][i].name] { 24 | weights = append(weights, g[vtx][i].value) 25 | result, weights = g.dfsHelper(g[vtx][i].name, visited, result, weights) 26 | } 27 | } 28 | return result, weights 29 | } 30 | 31 | // BFS traverses a graph using dfs technique 32 | func (g graph) BFS(start string) ([]string, []int) { 33 | 34 | if g[start] == nil { 35 | fmt.Println("\n-- No vertex named " + start + " present in graph. --") 36 | return nil, nil 37 | } 38 | 39 | visited := make(map[string]bool) 40 | 41 | var queue []string 42 | queue = append(queue, start) 43 | 44 | var result []string 45 | var weights []int 46 | var currentVtx string 47 | visited[start] = true 48 | 49 | for len(queue) != 0 { 50 | currentVtx = queue[0] // get the element from the queue 51 | queue = queue[1:] // remove element from the queue 52 | result = append(result, currentVtx) // push the current vertex in result 53 | 54 | for i := range g[currentVtx] { 55 | if !visited[g[currentVtx][i].name] { 56 | visited[g[currentVtx][i].name] = true // mark as visited 57 | weights = append(weights, g[currentVtx][i].value) 58 | queue = append(queue, g[currentVtx][i].name) // push neighbors of current vertex in the queue 59 | } 60 | } 61 | 62 | } 63 | 64 | return result, weights 65 | } 66 | -------------------------------------------------------------------------------- /heaps/max_binary_heap/max_binary_heap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // Insert inserts a node in a heap 9 | func Insert(value int) { 10 | heap = append(heap, value) 11 | maxHeapify() 12 | } 13 | 14 | func maxHeapify() { 15 | idx := len(heap) - 1 16 | element := heap[idx] 17 | for idx > 0 { 18 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 19 | parent := heap[parentIdx] 20 | if element <= parent { 21 | break 22 | } 23 | heap[parentIdx] = element 24 | heap[idx] = parent 25 | idx = parentIdx 26 | } 27 | } 28 | 29 | // ExtractMax will remove a node from heap 30 | func ExtractMax() int { 31 | if len(heap) == 0 || heap[0] == 0 { 32 | fmt.Println("\n-- Heap is empty. --") 33 | return 0 34 | } 35 | max := heap[0] 36 | end := heap[len(heap)-1] 37 | heap = heap[0 : len(heap)-1] 38 | if len(heap) > 0 { 39 | heap[0] = end 40 | bubbleDown() 41 | } 42 | return max 43 | } 44 | 45 | func bubbleDown() { 46 | idx := 0 47 | length := len(heap) 48 | element := heap[0] 49 | for { 50 | leftChildIdx := (2 * idx) + 1 51 | rightChildIdx := (2 * idx) + 2 52 | var leftChild, rightChild, swap int 53 | 54 | if leftChildIdx < length { 55 | leftChild = heap[leftChildIdx] 56 | if leftChild > element { 57 | swap = leftChildIdx 58 | } 59 | } 60 | if rightChildIdx < length { 61 | rightChild = heap[rightChildIdx] 62 | if (rightChild > element && swap == 0) || (rightChild > leftChild && swap != 0) { 63 | swap = rightChildIdx 64 | } 65 | } 66 | 67 | if swap == 0 { 68 | break 69 | } 70 | heap[idx] = heap[swap] 71 | heap[swap] = element 72 | idx = swap 73 | } 74 | } 75 | 76 | var heap []int 77 | 78 | func main() { 79 | i := 0 80 | for i == 0 { 81 | fmt.Println("\n1. INSERT") 82 | fmt.Println("2. REMOVE") 83 | fmt.Println("3. DISPLAY") 84 | fmt.Println("4. EXIT") 85 | var ch int 86 | fmt.Print("Enter your choice: ") 87 | fmt.Scanf("%d\n", &ch) 88 | switch ch { 89 | case 1: 90 | insertNode() 91 | case 2: 92 | ExtractMax() 93 | case 3: 94 | display() 95 | case 4: 96 | i = 1 97 | default: 98 | fmt.Println("Command not recognized.") 99 | } 100 | } 101 | } 102 | 103 | func insertNode() { 104 | var ch int 105 | fmt.Print("Enter the element that you want to insert: ") 106 | fmt.Scanf("%d\n", &ch) 107 | Insert(ch) 108 | } 109 | 110 | func display() { 111 | fmt.Println("") 112 | fmt.Println(heap) 113 | } 114 | -------------------------------------------------------------------------------- /heaps/min_binary_heap/min_binary_heap.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | // Insert inserts a node in a heap 9 | func Insert(value int) { 10 | heap = append(heap, value) 11 | minHeapify() 12 | } 13 | 14 | func minHeapify() { 15 | idx := len(heap) - 1 16 | element := heap[idx] 17 | for idx > 0 { 18 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 19 | parent := heap[parentIdx] 20 | if element >= parent { 21 | break 22 | } 23 | heap[parentIdx] = element 24 | heap[idx] = parent 25 | idx = parentIdx 26 | } 27 | } 28 | 29 | // ExtractMin will remove a node from heap 30 | func ExtractMin() int { 31 | if len(heap) == 0 || heap[0] == 0 { 32 | fmt.Println("\n-- Heap is empty. --") 33 | return 0 34 | } 35 | min := heap[0] 36 | end := heap[len(heap)-1] 37 | heap = heap[0 : len(heap)-1] 38 | if len(heap) > 0 { 39 | heap[0] = end 40 | bubbleDown() 41 | } 42 | return min 43 | } 44 | 45 | func bubbleDown() { 46 | idx := 0 47 | length := len(heap) 48 | element := heap[0] 49 | for { 50 | leftChildIdx := (2 * idx) + 1 51 | rightChildIdx := (2 * idx) + 2 52 | var leftChild, rightChild, swap int 53 | 54 | if leftChildIdx < length { 55 | leftChild = heap[leftChildIdx] 56 | if leftChild < element { 57 | swap = leftChildIdx 58 | } 59 | } 60 | if rightChildIdx < length { 61 | rightChild = heap[rightChildIdx] 62 | if (rightChild < element && swap == 0) || (rightChild < leftChild && swap != 0) { 63 | swap = rightChildIdx 64 | } 65 | } 66 | 67 | if swap == 0 { 68 | break 69 | } 70 | heap[idx] = heap[swap] 71 | heap[swap] = element 72 | idx = swap 73 | } 74 | } 75 | 76 | var heap []int 77 | 78 | func main() { 79 | i := 0 80 | for i == 0 { 81 | fmt.Println("\n1. INSERT") 82 | fmt.Println("2. REMOVE") 83 | fmt.Println("3. DISPLAY") 84 | fmt.Println("4. EXIT") 85 | var ch int 86 | fmt.Print("Enter your choice: ") 87 | fmt.Scanf("%d\n", &ch) 88 | switch ch { 89 | case 1: 90 | insertNode() 91 | case 2: 92 | ExtractMin() 93 | case 3: 94 | display() 95 | case 4: 96 | i = 1 97 | default: 98 | fmt.Println("Command not recognized.") 99 | } 100 | } 101 | } 102 | 103 | func insertNode() { 104 | var ch int 105 | fmt.Print("Enter the element that you want to insert: ") 106 | fmt.Scanf("%d\n", &ch) 107 | Insert(ch) 108 | } 109 | 110 | func display() { 111 | fmt.Println("") 112 | fmt.Println(heap) 113 | } 114 | -------------------------------------------------------------------------------- /linked_lists/pres_rev_single_ll/RGIF2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deveshptl/golang-data-structures-algorithms/8522c89d4e6ae1aa273754f1507cb75706784f6a/linked_lists/pres_rev_single_ll/RGIF2.gif -------------------------------------------------------------------------------- /notes/heaps/README.md: -------------------------------------------------------------------------------- 1 | # Heap 2 | 3 | Heap is a tree based data structure where the tree is a complete binary tree. This binary tree satisfies the properties of heap: 4 | 5 | 1. For max heap, any given node C, if P is a parent node of C, then the key (the value) of P is greater than or equal to the key of C. 6 | 2. For min heap, any given node C, if P is a parent node of C, then the key (the value) of P is less than or equal to the key of C. 7 | 8 | ### Representation 9 | 10 | Heap can be implemented using binary tree or array. 11 | 12 | ### Types 13 | 14 | 1. Min Binary Heap: Returns the least value node present in the heap. 15 | 2. Max Binary Heaps: Returns the max value node present in the heap. 16 | 17 | ### Operations 18 | 19 | 1. **Insert**: Inserts a node in the heap 20 | 2. **ExtractMin/ExtractMax**: Extracts the min or max value node depending on the type of the heap 21 | 3. **Delete**: Deletes a node from the heap 22 | 4. **Increase/Decrease Key**: Increases or decreases the key value of given node 23 | 24 | Main functions of heap are: 25 | 26 | 1. **MaxHeapify/MinHeapify (aka Bubble Up)**: This is called after inserting an element, which is inserted in the end of the heap. This function traverses the heap in upward direction while making necessary shifts between nodes. 27 | 2. **Bubble down**: This is called after deleting an element, which is the root of the heap and the last node of the heap is placed there instead. This function traverses downward in direction while making necessary shifts between nodes. 28 | 29 | ### Applications 30 | 31 | 1. Heap Sort: Used to sort the elements in an array 32 | 2. Priority Queue: Used to select the highest priority job 33 | 3. Graph Algorithms: Used in graph algorithms like Dijkstra’s Shortest Path and Prim’s Minimum Spanning Tree 34 | 35 | ## References 36 | 37 | - [https://en.wikipedia.org/wiki/Heap\_(data_structure)]() 38 | - [https://en.wikipedia.org/wiki/Binary_heap](https://en.wikipedia.org/wiki/Binary_heap) 39 | - [https://www.geeksforgeeks.org/binary-heap/](https://www.geeksforgeeks.org/binary-heap/) 40 | -------------------------------------------------------------------------------- /notes/stack/README.md: -------------------------------------------------------------------------------- 1 | ## Stack 2 | 3 | Stack is a linear data structure which follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). 4 | 5 | ### Operations 6 | 7 | 1. **PUSH** - Adds an item in the stack and increments the `top` pointer. If the stack is full, then it is said to be an Overflow condition. 8 | 2. **POP** - Removes an item from the stack and decrements the `top`. The items are popped in the reversed order in which they are pushed. If the stack is empty, then it is said to be an Underflow condition. 9 | 3. **PEEK** - Returns top element of stack. Does not remove any elements from stack. 10 | 4. **isEmpty** - Returns true if stack is empty, else false. 11 | 5. **DISPLAY** - Displays content of stack. 12 | 6. **getSize** - Returns the size of the stack irrespective of how many elements are in the stack. 13 | 14 | ### Implementation 15 | 16 | Stack can be implemented using arrays, linked list or queues. Implementation using arrays is the simplest one. 17 | 18 | ### Time Complexities 19 | 20 | - push(), pop(), isEmpty() and peek() all take O(1) time. We do not run any loop in any of these operations. 21 | 22 | ### Applications 23 | 24 | 1. Expression evaluation 25 | 2. Expression conversion 26 | 3. Syntax parsing 27 | 4. String reversal 28 | 5. Implementation of Tower of Hanoi Problem 29 | 6. Function call and Recursion 30 | 7. Parenthesis checking 31 | 8. Backtracking 32 | 9. File undo and redo operations 33 | 10. Depth First Search traversal in tree and graph data structure uses stack to store explored nodes and processes them later. 34 | 35 | ## References 36 | 37 | - [https://www.geeksforgeeks.org/stack-data-structure/](https://www.geeksforgeeks.org/stack-data-structure/) 38 | - [https://www.geeksforgeeks.org/stack-data-structure-introduction-program/](https://www.geeksforgeeks.org/stack-data-structure-introduction-program/) 39 | - [https://www.thecrazyprogrammer.com/2016/04/applications-of-stack.html](https://www.thecrazyprogrammer.com/2016/04/applications-of-stack.html) 40 | -------------------------------------------------------------------------------- /queues/cqueue/cqueue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // r - rear pointer 8 | // f - front pointer 9 | // n - size of circular queue 10 | // q - circular queue 11 | 12 | type queue []string 13 | 14 | var r, n, f int 15 | var q queue 16 | 17 | func init() { 18 | r = -1 19 | f = -1 20 | n = 4 21 | q = make(queue, 5) 22 | for i := range q { 23 | q[i] = "nil" 24 | } 25 | } 26 | 27 | func main() { 28 | i := 0 29 | for i == 0 { 30 | fmt.Println("\n1. INSERT") 31 | fmt.Println("2. DELETE") 32 | fmt.Println("3. DISPLAY") 33 | fmt.Println("4. EXIT") 34 | fmt.Print("Enter your choice: ") 35 | var choice int 36 | fmt.Scanf("%d\n", &choice) 37 | switch choice { 38 | case 1: 39 | q.insert() 40 | fmt.Println("\nValues after insertion - FRONT:", f, "REAR:", r) 41 | display() 42 | case 2: 43 | q.delete() 44 | fmt.Println("\nValues after deletion - FRONT:", f, "REAR:", r) 45 | display() 46 | case 3: 47 | fmt.Println("\nFRONT:", f, "REAR:", r) 48 | display() 49 | case 4: 50 | i = 1 51 | default: 52 | fmt.Println("Command not recognized.") 53 | } 54 | } 55 | } 56 | 57 | func (q queue) insert() { 58 | 59 | // reset rear pointer 60 | if r == n { 61 | r = 0 62 | } else { 63 | r++ 64 | } 65 | 66 | // check for overflow 67 | if f == r { 68 | fmt.Println("\n-- Overflow --") 69 | if r == 0 { 70 | r = n 71 | } else { 72 | r-- 73 | } 74 | return 75 | } 76 | 77 | // insert element 78 | var y string 79 | fmt.Print("Enter the element that you want to insert: ") 80 | fmt.Scanf("%s\n", &y) 81 | q[r] = y 82 | 83 | // set front pointer 84 | if f == -1 { 85 | f = 0 86 | } 87 | } 88 | 89 | func (q queue) delete() { 90 | 91 | // check for underflow 92 | if f == -1 { 93 | fmt.Println("\n-- Underflow --") 94 | return 95 | } 96 | 97 | // delete the element 98 | y := q[f] 99 | q[f] = "nil" 100 | 101 | // check if queue is empty 102 | if f == r { 103 | f = -1 104 | r = -1 105 | fmt.Println("\nElement deleted: ", y) 106 | return 107 | } 108 | 109 | // increment front pointer 110 | if f == n { 111 | f = 0 112 | } else { 113 | f++ 114 | } 115 | 116 | fmt.Println("\nElement deleted: ", y) 117 | 118 | } 119 | 120 | func display() { 121 | fmt.Println("Displaying elements: ") 122 | for i := range q { 123 | fmt.Print(q[i], " ") 124 | } 125 | fmt.Println("") 126 | } 127 | -------------------------------------------------------------------------------- /queues/priority_queue/priority_queue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Note - Lower priority value processes will be run first. Hence this is implemented using min heap. 4 | 5 | import ( 6 | "fmt" 7 | "math" 8 | ) 9 | 10 | // Node is a single node in a queue 11 | type Node struct { 12 | name string 13 | priority int 14 | } 15 | 16 | // Enqueue inserts a node in a heap 17 | func Enqueue(node *Node) { 18 | heap = append(heap, node) 19 | minHeapify() 20 | } 21 | 22 | func minHeapify() { 23 | idx := len(heap) - 1 24 | element := heap[idx] 25 | for idx > 0 { 26 | parentIdx := int(math.Floor(float64((idx - 1) / 2))) 27 | parent := heap[parentIdx] 28 | if element.priority >= parent.priority { 29 | break 30 | } 31 | heap[parentIdx] = element 32 | heap[idx] = parent 33 | idx = parentIdx 34 | } 35 | } 36 | 37 | // Dequeue will remove a node from heap 38 | func Dequeue() *Node { 39 | if len(heap) == 0 || heap[0] == nil { 40 | fmt.Println("\n-- Heap is empty. --") 41 | return nil 42 | } 43 | min := heap[0] 44 | end := heap[len(heap)-1] 45 | heap = heap[0 : len(heap)-1] 46 | if len(heap) > 0 { 47 | heap[0] = end 48 | bubbleDown() 49 | } 50 | return min 51 | } 52 | 53 | func bubbleDown() { 54 | idx := 0 55 | length := len(heap) 56 | element := heap[0] 57 | for { 58 | leftChildIdx := (2 * idx) + 1 59 | rightChildIdx := (2 * idx) + 2 60 | var leftChild, rightChild *Node 61 | var swap int 62 | 63 | if leftChildIdx < length { 64 | leftChild = heap[leftChildIdx] 65 | if leftChild.priority < element.priority { 66 | swap = leftChildIdx 67 | } 68 | } 69 | if rightChildIdx < length { 70 | rightChild = heap[rightChildIdx] 71 | if (rightChild.priority < element.priority && swap == 0) || (rightChild.priority < leftChild.priority && swap != 0) { 72 | swap = rightChildIdx 73 | } 74 | } 75 | 76 | if swap == 0 { 77 | break 78 | } 79 | heap[idx] = heap[swap] 80 | heap[swap] = element 81 | idx = swap 82 | } 83 | } 84 | 85 | var heap []*Node 86 | 87 | func main() { 88 | i := 0 89 | for i == 0 { 90 | fmt.Println("\n1. INSERT") 91 | fmt.Println("2. REMOVE") 92 | fmt.Println("3. DISPLAY") 93 | fmt.Println("4. EXIT") 94 | var ch int 95 | fmt.Print("Enter your choice: ") 96 | fmt.Scanf("%d\n", &ch) 97 | switch ch { 98 | case 1: 99 | insertNode() 100 | case 2: 101 | node := Dequeue() 102 | fmt.Println("Process removed: ", node) 103 | case 3: 104 | display() 105 | case 4: 106 | i = 1 107 | default: 108 | fmt.Println("Command not recognized.") 109 | } 110 | } 111 | } 112 | 113 | func insertNode() { 114 | var name string 115 | var priority int 116 | fmt.Print("Enter the name of the process: ") 117 | fmt.Scanf("%s\n", &name) 118 | fmt.Print("Enter the priority of the process: ") 119 | fmt.Scanf("%d\n", &priority) 120 | fmt.Println(name, priority) 121 | newNode := &Node{name: name, priority: priority} 122 | Enqueue(newNode) 123 | } 124 | 125 | func display() { 126 | if len(heap) == 0 { 127 | fmt.Println("\n-- Heap is empty. --") 128 | return 129 | } 130 | for i := range heap { 131 | fmt.Println(heap[i].name, heap[i].priority) 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /queues/simple_queue/simple_queue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // r - rear 8 | // n - length 9 | // f - front 10 | // q - queue 11 | 12 | type queue []string 13 | 14 | var r, n, f int 15 | var q queue 16 | 17 | func init() { 18 | r = -1 19 | f = -1 20 | n = 4 21 | q = make(queue, 5) 22 | for i := range q { 23 | q[i] = "nil" 24 | } 25 | } 26 | 27 | func main() { 28 | i := 0 29 | var choice int 30 | for i == 0 { 31 | fmt.Println("\n1. INSERT") 32 | fmt.Println("2. DELETE") 33 | fmt.Println("3. DISPLAY") 34 | fmt.Println("4. EXIT") 35 | fmt.Print("Enter your choice: ") 36 | fmt.Scanf("%d\n", &choice) 37 | switch choice { 38 | case 1: 39 | q.insert() 40 | fmt.Println("\nValues after insertion FRONT:", f, "REAR:", r) 41 | display() 42 | case 2: 43 | q.delete() 44 | fmt.Println("\nValues after deletion FRONT:", f, "REAR:", r) 45 | display() 46 | case 3: 47 | fmt.Println("\nFRONT:", f, "REAR:", r) 48 | display() 49 | case 4: 50 | i = 1 51 | default: 52 | fmt.Println("\nCommand not recognized") 53 | } 54 | } 55 | } 56 | 57 | func (q queue) insert() { 58 | 59 | // check for overflow 60 | if r >= n { 61 | fmt.Println("\n-- Overflow --") 62 | return 63 | } 64 | 65 | // increment rear pointer 66 | r++ 67 | 68 | // insert the element 69 | var y string 70 | fmt.Print("Enter the element that you want to insert: ") 71 | fmt.Scanf("%s\n", &y) 72 | q[r] = y 73 | 74 | // set front pointer 75 | if f == -1 { 76 | f = 0 77 | } 78 | } 79 | 80 | func (q queue) delete() { 81 | 82 | // check for underflow 83 | if f == -1 { 84 | fmt.Println("\n-- Underflow --") 85 | return 86 | } 87 | 88 | // delete element 89 | y := q[f] 90 | q[f] = "nil" 91 | 92 | // check if queue is empty 93 | if f == r { 94 | f = -1 95 | r = -1 96 | } else { 97 | f++ 98 | } 99 | 100 | // print deleted element 101 | fmt.Println("Element deleted", y) 102 | } 103 | 104 | func display() { 105 | for i := range q { 106 | fmt.Print(q[i], " ") 107 | } 108 | fmt.Println("") 109 | } 110 | -------------------------------------------------------------------------------- /resources.md: -------------------------------------------------------------------------------- 1 | ### Useful Websites 2 | 3 | The below list contains the list of websites or youtube channels that I referred while I was implementing this data structures and algorithms. 4 | 5 | 1. [William Fiset - youtube channel](https://www.youtube.com/channel/UCD8yeTczadqdARzQUp29PJw) 6 | 2. [Youtube playlist - A list of all DSA videos created so far by William Fiset](https://www.youtube.com/playlist?list=PLDd6ofQIcSMMc1fzkLYFwZT072DB0ZrMS) 7 | 3. [Geeks for Geeks](https://www.geeksforgeeks.org/) 8 | 4. [AVL Tree - Live Youtube Webinar](https://www.youtube.com/watch?v=a96JFhw5Ee4) 9 | 5. [Data Structures that I learnt during my CS degree](http://gtu-info.com/Subject/2130702/DS/Data_Structures/Syllabus) 10 | 6. [Algorithms that I learnt during my CS degree](http://gtu-info.com/Subject/2150703/ADA/Analysis_and_Design_of_Algorithms/Syllabus) 11 | 7. [A book on Introduction to the Design and Analysis of Algorithms](https://amzn.to/2WPFzuW) by Anany Levitin 12 | 13 | The following list contains some helpful links 14 | 15 | 1. [https://github.com/mtdvio/every-programmer-should-know](https://github.com/mtdvio/every-programmer-should-know) 16 | 2. [https://github.com/jwasham/coding-interview-university](https://github.com/jwasham/coding-interview-university) 17 | 3. [https://github.com/trekhleb/javascript-algorithms](https://github.com/trekhleb/javascript-algorithms) 18 | -------------------------------------------------------------------------------- /stack/stack.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // size - size of stack 6 | // top - top pointer 7 | // stack - stack array 8 | 9 | type stack []string 10 | 11 | var s stack 12 | var size, top int 13 | 14 | func init() { 15 | size = 4 16 | top = -1 17 | s = make(stack, 5) 18 | for i := range s { 19 | s[i] = "nil" 20 | } 21 | } 22 | 23 | func main() { 24 | i := 0 25 | for i == 0 { 26 | var choice int 27 | fmt.Println("\n1. PUSH") 28 | fmt.Println("2. POP") 29 | fmt.Println("3. PEEK") 30 | fmt.Println("4. DISPLAY") 31 | fmt.Println("5. isEmpty") 32 | fmt.Println("6. EXIT") 33 | fmt.Print("\nEnter you choice: ") 34 | fmt.Scanf("%d\n", &choice) 35 | 36 | switch choice { 37 | case 1: 38 | s.push() 39 | fmt.Println("\nValues after push TOP:", top) 40 | s.display() 41 | case 2: 42 | s.pop() 43 | fmt.Println("\nValues after pop TOP:", top) 44 | s.display() 45 | case 3: 46 | s.peek() 47 | fmt.Println("\nValues after peek TOP:", top) 48 | s.display() 49 | case 4: 50 | fmt.Println("\nTOP:", top) 51 | s.display() 52 | case 5: 53 | s.isEmpty() 54 | case 6: 55 | i = 1 56 | default: 57 | fmt.Println("Choice not recognized") 58 | } 59 | 60 | } 61 | } 62 | 63 | func (s stack) push() { 64 | 65 | // check for overflow 66 | if size == top { 67 | fmt.Println("\n-- Stack overflow --") 68 | return 69 | } 70 | 71 | // scan for element 72 | var val string 73 | fmt.Print("Enter the value that you want to PUSH: ") 74 | fmt.Scanf("%s\n", &val) 75 | 76 | // increment top pointer 77 | top++ 78 | 79 | // insert the element 80 | s[top] = val 81 | } 82 | 83 | func (s stack) pop() { 84 | 85 | // check for underflow 86 | if top == -1 { 87 | fmt.Println("\n-- Stack underflow --") 88 | return 89 | } 90 | 91 | // print popped value 92 | y := s[top] 93 | fmt.Println("\nValue popped:", y) 94 | 95 | // initialize to nil 96 | s[top] = "nil" 97 | 98 | // decrement top pointer 99 | top-- 100 | } 101 | 102 | func (s stack) peek() { 103 | // check for underflow 104 | if top == -1 { 105 | fmt.Println("\n-- Stack underflow --") 106 | return 107 | } 108 | 109 | // print the peeked value 110 | y := s[top] 111 | fmt.Println("\nValue peeked:", y) 112 | } 113 | 114 | func (s stack) isEmpty() { 115 | if top == -1 { 116 | fmt.Println("\ntrue") 117 | return 118 | } 119 | fmt.Println("\nfalse") 120 | } 121 | 122 | func (s stack) display() { 123 | for i := range s { 124 | fmt.Print(s[i], " ") 125 | } 126 | fmt.Println("") 127 | } 128 | -------------------------------------------------------------------------------- /trees/avl_tree_using_ll/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // BFS prints the tree using bfs traversal 6 | func (avl *AVLTree) BFS() []int { 7 | if avl.root == nil { 8 | fmt.Print("\n-- Tree is empty. --") 9 | return nil 10 | } 11 | var queue []*Node 12 | var data []int 13 | node := avl.root 14 | queue = append(queue, node) 15 | 16 | for len(queue) != 0 { 17 | node = queue[0] 18 | queue = queue[1:] 19 | count := node.freq 20 | for count != 0 { 21 | data = append(data, node.value) 22 | count-- 23 | } 24 | if node.left != nil { 25 | queue = append(queue, node.left) 26 | } 27 | if node.right != nil { 28 | queue = append(queue, node.right) 29 | } 30 | } 31 | return data 32 | } 33 | 34 | // DFS prints the tree using dfs traversal 35 | func (avl *AVLTree) DFS(traverseType string) []int { 36 | if avl.root == nil { 37 | fmt.Println("\n-- Tree is empty. --") 38 | return nil 39 | } 40 | 41 | var data []int 42 | current := avl.root 43 | if traverseType == "pre" { 44 | data = traversePre(data, current) 45 | } else if traverseType == "in" { 46 | data = traverseIn(data, current) 47 | } else if traverseType == "pos" { 48 | data = traversePos(data, current) 49 | } 50 | return data 51 | } 52 | 53 | // traverses a node in pre-order and recursively calls itself 54 | func traversePre(data []int, node *Node) []int { 55 | count := node.freq 56 | for count != 0 { 57 | data = append(data, node.value) 58 | count-- 59 | } 60 | if node.left != nil { 61 | data = traversePre(data, node.left) 62 | } 63 | if node.right != nil { 64 | data = traversePre(data, node.right) 65 | } 66 | return data 67 | } 68 | 69 | // traverses a node in in-order and recursively calls itself 70 | func traverseIn(data []int, node *Node) []int { 71 | if node.left != nil { 72 | data = traverseIn(data, node.left) 73 | } 74 | count := node.freq 75 | for count != 0 { 76 | data = append(data, node.value) 77 | count-- 78 | } 79 | if node.right != nil { 80 | data = traverseIn(data, node.right) 81 | } 82 | return data 83 | } 84 | 85 | // traverses a node in pos-order and recursively calls itself 86 | func traversePos(data []int, node *Node) []int { 87 | if node.left != nil { 88 | data = traversePos(data, node.left) 89 | } 90 | if node.right != nil { 91 | data = traversePos(data, node.right) 92 | } 93 | count := node.freq 94 | for count != 0 { 95 | data = append(data, node.value) 96 | count-- 97 | } 98 | return data 99 | } 100 | -------------------------------------------------------------------------------- /trees/bst_using_arr/bst_using_arr.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Node is a node of bst 6 | type Node struct { 7 | value int 8 | freq int 9 | height int 10 | } 11 | 12 | // Insert inserts a node in a bst 13 | func Insert(value, index int) { 14 | newNode := &Node{value: value, freq: 1} 15 | if index >= size { 16 | fmt.Println("\n-- Not enough space in array. --") 17 | return 18 | } 19 | if bst[index] == nil { 20 | bst[index] = newNode 21 | } else if bst[index].value == value { 22 | bst[index].freq++ 23 | } else { 24 | if value < bst[index].value { 25 | Insert(value, (index*2)+1) 26 | } else { 27 | Insert(value, (index*2)+2) 28 | } 29 | } 30 | } 31 | 32 | // Find finds a key and prints its information 33 | func Find(key int) { 34 | i := 0 35 | for { 36 | if bst[i] != nil { 37 | if bst[i].value == key { 38 | index := i 39 | var sibling *Node 40 | if i%2 == 0 { 41 | i = (i / 2) - 1 42 | sibling = bst[(i*2)+1] 43 | } else { 44 | i /= 2 45 | sibling = bst[(i*2)+2] 46 | } 47 | fmt.Println("\n-- Key found. --") 48 | fmt.Println("Key info is: ", bst[index]) 49 | fmt.Println("Parent is: ", bst[i]) 50 | fmt.Println("Sibling is: ", sibling) 51 | fmt.Println("Left Child is: ", bst[(index*2)+1]) 52 | fmt.Println("Right Child is: ", bst[(index*2)+2]) 53 | return 54 | } else if bst[i].value < key { 55 | i = (i * 2) + 2 56 | } else if bst[i].value > key { 57 | i = (i * 2) + 1 58 | } 59 | } else { 60 | fmt.Println("\n-- Key NOT found. --") 61 | return 62 | } 63 | } 64 | } 65 | 66 | var bst [100]*Node 67 | var size int 68 | 69 | func init() { 70 | size = 100 71 | } 72 | 73 | func main() { 74 | i := 0 75 | for i == 0 { 76 | fmt.Println("\n1. INSERT") 77 | fmt.Println("2. DISPLAY using BFS") 78 | fmt.Println("3. DISPLAY using DFS Pre-order") 79 | fmt.Println("4. DISPLAY using DFS In-order") 80 | fmt.Println("5. DISPLAY using DFS Post-order") 81 | fmt.Println("6. FIND") 82 | fmt.Println("7. EXIT") 83 | 84 | var choice int 85 | fmt.Print("Enter your choice: ") 86 | fmt.Scanf("%d\n", &choice) 87 | 88 | switch choice { 89 | case 1: 90 | insNode() 91 | case 2: 92 | fmt.Println("\n", BFS()) 93 | case 3: 94 | fmt.Println("\n", DFS("pre")) 95 | case 4: 96 | fmt.Println("\n", DFS("in")) 97 | case 5: 98 | fmt.Println("\n", DFS("pos")) 99 | case 6: 100 | findNode() 101 | case 7: 102 | i = 1 103 | default: 104 | fmt.Println("Command not recognized.") 105 | } 106 | } 107 | } 108 | 109 | func insNode() { 110 | var element int 111 | fmt.Print("Enter the node value that you want to insert: ") 112 | fmt.Scanf("%d\n", &element) 113 | Insert(element, 0) 114 | } 115 | 116 | func findNode() { 117 | var element int 118 | fmt.Print("Enter the value of the key: ") 119 | fmt.Scanf("%d\n", &element) 120 | Find(element) 121 | } 122 | -------------------------------------------------------------------------------- /trees/bst_using_arr/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // BFS is a bfs traversal technique 4 | func BFS() []int { 5 | var data []int 6 | for i := range bst { 7 | if bst[i] != nil { 8 | count := bst[i].freq 9 | for count != 0 { 10 | data = append(data, bst[i].value) 11 | count-- 12 | } 13 | } 14 | } 15 | return data 16 | } 17 | 18 | // DFS is a dfs traversal technique 19 | func DFS(traversalType string) []int { 20 | var data []int 21 | if traversalType == "pre" { 22 | data = traversePre(data, 0) 23 | } else if traversalType == "in" { 24 | data = traverseIn(data, 0) 25 | } else if traversalType == "pos" { 26 | data = traversePos(data, 0) 27 | } 28 | return data 29 | } 30 | 31 | // traverses a tree in pre-order and recursively calls itself 32 | func traversePre(data []int, index int) []int { 33 | if bst[index] != nil { 34 | count := bst[index].freq 35 | for count != 0 { 36 | data = append(data, bst[index].value) 37 | count-- 38 | } 39 | data = traversePre(data, (index*2)+1) 40 | data = traversePre(data, (index*2)+2) 41 | } 42 | return data 43 | } 44 | 45 | // traverses a tree in in-order and recursively calls itself 46 | func traverseIn(data []int, index int) []int { 47 | if bst[index] != nil { 48 | data = traverseIn(data, (index*2)+1) 49 | count := bst[index].freq 50 | for count != 0 { 51 | data = append(data, bst[index].value) 52 | count-- 53 | } 54 | data = traverseIn(data, (index*2)+2) 55 | } 56 | return data 57 | } 58 | 59 | // traverses a tree in post-order and recursively calls itself 60 | func traversePos(data []int, index int) []int { 61 | if bst[index] != nil { 62 | data = traversePos(data, (index*2)+1) 63 | data = traversePos(data, (index*2)+2) 64 | count := bst[index].freq 65 | for count != 0 { 66 | data = append(data, bst[index].value) 67 | count-- 68 | } 69 | } 70 | return data 71 | } 72 | -------------------------------------------------------------------------------- /trees/bst_using_ll/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // BFS prints the tree using bfs traversal 6 | func (bst *BinarySearchTree) BFS() []int { 7 | if bst.root == nil { 8 | fmt.Print("\n-- Tree is empty. --") 9 | return nil 10 | } 11 | var queue []*Node 12 | var data []int 13 | node := bst.root 14 | queue = append(queue, node) 15 | 16 | for len(queue) != 0 { 17 | node = queue[0] 18 | queue = queue[1:] 19 | count := node.freq 20 | for count != 0 { 21 | data = append(data, node.value) 22 | count-- 23 | } 24 | if node.left != nil { 25 | queue = append(queue, node.left) 26 | } 27 | if node.right != nil { 28 | queue = append(queue, node.right) 29 | } 30 | } 31 | return data 32 | } 33 | 34 | // DFS prints the tree using dfs traversal 35 | func (bst *BinarySearchTree) DFS(traverseType string) []int { 36 | if bst.root == nil { 37 | fmt.Println("\n-- Tree is empty. --") 38 | return nil 39 | } 40 | 41 | var data []int 42 | current := bst.root 43 | if traverseType == "pre" { 44 | data = traversePre(data, current) 45 | } else if traverseType == "in" { 46 | data = traverseIn(data, current) 47 | } else if traverseType == "pos" { 48 | data = traversePos(data, current) 49 | } 50 | return data 51 | } 52 | 53 | func traversePre(data []int, node *Node) []int { 54 | count := node.freq 55 | for count != 0 { 56 | data = append(data, node.value) 57 | count-- 58 | } 59 | if node.left != nil { 60 | data = traversePre(data, node.left) 61 | } 62 | if node.right != nil { 63 | data = traversePre(data, node.right) 64 | } 65 | return data 66 | } 67 | 68 | func traverseIn(data []int, node *Node) []int { 69 | if node.left != nil { 70 | data = traverseIn(data, node.left) 71 | } 72 | count := node.freq 73 | for count != 0 { 74 | data = append(data, node.value) 75 | count-- 76 | } 77 | if node.right != nil { 78 | data = traverseIn(data, node.right) 79 | } 80 | return data 81 | } 82 | 83 | func traversePos(data []int, node *Node) []int { 84 | if node.left != nil { 85 | data = traversePos(data, node.left) 86 | } 87 | if node.right != nil { 88 | data = traversePos(data, node.right) 89 | } 90 | count := node.freq 91 | for count != 0 { 92 | data = append(data, node.value) 93 | count-- 94 | } 95 | return data 96 | } 97 | -------------------------------------------------------------------------------- /trees/simple_bt_using_arr/simple_bt_using_arr.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Node is a node of bt 6 | type Node struct { 7 | value int 8 | height int 9 | } 10 | 11 | // Insert inserts a node in a bt 12 | func Insert(value, index int) { 13 | flag := 0 14 | newNode := &Node{value: value} 15 | for i := range bt { 16 | if bt[i] == nil { 17 | bt[i] = newNode 18 | flag = 1 19 | return 20 | } 21 | if i == 99 && flag == 0 { 22 | fmt.Println("\n-- Not enough space in array. --") 23 | return 24 | } 25 | } 26 | } 27 | 28 | // Find finds a key and prints its information 29 | func Find(key int) { 30 | for i := range bt { 31 | if bt[i] == nil { 32 | fmt.Println("\n-- Key NOT found. --") 33 | return 34 | } else if bt[(i*2)+1] != nil && bt[(i*2)+1].value == key { 35 | index := (i * 2) + 1 36 | fmt.Println("\n-- Key found. --") 37 | fmt.Println("Key info is:", bt[index]) 38 | fmt.Println("Parent is:", bt[i]) 39 | fmt.Println("Sibling is:", bt[(i*2)+2]) 40 | fmt.Println("Left Child is:", bt[(index*2)+1]) 41 | fmt.Println("Right Child is:", bt[(index*2)+2]) 42 | return 43 | } else if bt[(i*2)+2] != nil && bt[(i*2)+2].value == key { 44 | index := (i * 2) + 2 45 | fmt.Println("\n-- Key found. --") 46 | fmt.Println("Key info is:", bt[index]) 47 | fmt.Println("Parent is:", bt[i]) 48 | fmt.Println("Sibling is:", bt[(i*2)+1]) 49 | fmt.Println("Left Child is:", bt[(index*2)+1]) 50 | fmt.Println("Right Child is:", bt[(index*2)+2]) 51 | return 52 | } 53 | } 54 | } 55 | 56 | var bt [100]*Node 57 | var size int 58 | 59 | func init() { 60 | size = 100 61 | } 62 | 63 | func main() { 64 | i := 0 65 | for i == 0 { 66 | fmt.Println("\n1. INSERT") 67 | fmt.Println("2. DISPLAY using BFS") 68 | fmt.Println("3. DISPLAY using DFS Pre-order") 69 | fmt.Println("4. DISPLAY using DFS In-order") 70 | fmt.Println("5. DISPLAY using DFS Post-order") 71 | fmt.Println("6. FIND") 72 | fmt.Println("7. EXIT") 73 | 74 | var choice int 75 | fmt.Print("Enter your choice: ") 76 | fmt.Scanf("%d\n", &choice) 77 | 78 | switch choice { 79 | case 1: 80 | insNode() 81 | case 2: 82 | fmt.Println("\n", BFS()) 83 | case 3: 84 | fmt.Println("\n", DFS("pre")) 85 | case 4: 86 | fmt.Println("\n", DFS("in")) 87 | case 5: 88 | fmt.Println("\n", DFS("pos")) 89 | case 6: 90 | findNode() 91 | case 7: 92 | i = 1 93 | default: 94 | fmt.Println("Command not recognized.") 95 | } 96 | } 97 | } 98 | 99 | func insNode() { 100 | var element int 101 | fmt.Print("Enter the node value that you want to insert: ") 102 | fmt.Scanf("%d\n", &element) 103 | Insert(element, 0) 104 | } 105 | 106 | func findNode() { 107 | var element int 108 | fmt.Print("Enter the value of the key: ") 109 | fmt.Scanf("%d\n", &element) 110 | Find(element) 111 | } 112 | -------------------------------------------------------------------------------- /trees/simple_bt_using_arr/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // BFS is a bfs traversal technique 4 | func BFS() []int { 5 | var data []int 6 | for i := range bt { 7 | if bt[i] != nil { 8 | 9 | data = append(data, bt[i].value) 10 | } 11 | } 12 | return data 13 | } 14 | 15 | // DFS is a dfs traversal technique 16 | func DFS(traversalType string) []int { 17 | var data []int 18 | if traversalType == "pre" { 19 | data = traversePre(data, 0) 20 | } else if traversalType == "in" { 21 | data = traverseIn(data, 0) 22 | } else if traversalType == "pos" { 23 | data = traversePos(data, 0) 24 | } 25 | return data 26 | } 27 | 28 | // traverses a tree in pre-order and recursively calls itself 29 | func traversePre(data []int, index int) []int { 30 | if bt[index] != nil { 31 | data = append(data, bt[index].value) 32 | data = traversePre(data, (index*2)+1) 33 | data = traversePre(data, (index*2)+2) 34 | } 35 | return data 36 | } 37 | 38 | // traverses a tree in in-order and recursively calls itself 39 | func traverseIn(data []int, index int) []int { 40 | if bt[index] != nil { 41 | data = traverseIn(data, (index*2)+1) 42 | data = append(data, bt[index].value) 43 | data = traverseIn(data, (index*2)+2) 44 | } 45 | return data 46 | } 47 | 48 | // traverses a tree in post-order and recursively calls itself 49 | func traversePos(data []int, index int) []int { 50 | if bt[index] != nil { 51 | data = traversePos(data, (index*2)+1) 52 | data = traversePos(data, (index*2)+2) 53 | data = append(data, bt[index].value) 54 | } 55 | return data 56 | } 57 | -------------------------------------------------------------------------------- /trees/simple_bt_using_ll/traversal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // BFS prints the tree using bfs traversal 6 | func (bt *BinaryTree) BFS() []int { 7 | if bt.root == nil { 8 | fmt.Print("\n-- Tree is empty. --") 9 | return nil 10 | } 11 | var queue []*Node 12 | var data []int 13 | node := bt.root 14 | queue = append(queue, node) 15 | 16 | for len(queue) != 0 { 17 | node = queue[0] 18 | queue = queue[1:] 19 | data = append(data, node.value) 20 | if node.left != nil { 21 | queue = append(queue, node.left) 22 | } 23 | if node.right != nil { 24 | queue = append(queue, node.right) 25 | } 26 | } 27 | return data 28 | } 29 | 30 | // DFS prints the tree using dfs traversal 31 | func (bt *BinaryTree) DFS(traverseType string) []int { 32 | if bt.root == nil { 33 | fmt.Println("\n-- Tree is empty. --") 34 | return nil 35 | } 36 | 37 | var data []int 38 | current := bt.root 39 | if traverseType == "pre" { 40 | data = traversePre(data, current) 41 | } else if traverseType == "in" { 42 | data = traverseIn(data, current) 43 | } else if traverseType == "pos" { 44 | data = traversePos(data, current) 45 | } 46 | return data 47 | } 48 | 49 | func traversePre(data []int, node *Node) []int { 50 | data = append(data, node.value) 51 | if node.left != nil { 52 | data = traversePre(data, node.left) 53 | } 54 | if node.right != nil { 55 | data = traversePre(data, node.right) 56 | } 57 | return data 58 | } 59 | 60 | func traverseIn(data []int, node *Node) []int { 61 | if node.left != nil { 62 | data = traverseIn(data, node.left) 63 | } 64 | data = append(data, node.value) 65 | if node.right != nil { 66 | data = traverseIn(data, node.right) 67 | } 68 | return data 69 | } 70 | 71 | func traversePos(data []int, node *Node) []int { 72 | if node.left != nil { 73 | data = traversePos(data, node.left) 74 | } 75 | if node.right != nil { 76 | data = traversePos(data, node.right) 77 | } 78 | data = append(data, node.value) 79 | return data 80 | } 81 | --------------------------------------------------------------------------------