From 9ff7468e9e1f5b84b23dd7749ed3f6b8eae72795 Mon Sep 17 00:00:00 2001 From: Serg Gini Date: Fri, 2 May 2025 02:24:42 +0300 Subject: [PATCH] D solutions (#305) * Added 1 and 2 chapters for D lang * [D] Added recursion code All examples were ported from the Python code directly to D. Naming convention of Dlang is not allowing to run code files, which started with numbers. To run examples rename the files * [D] quicksort code * [D] Added hashtable example Based on the Python code * Create 01_breadth_first_search.d Added D example for breadth-first search * Create 01_filesystem_dfs.d Filesystem example in D * Create 01_dijkstras_algorithm.d Added Dijkstras algorithm implementation for D * Create 01_set_covering.d Added greedy algorythm for D * Create 01_longest_common_sub.d Added dynamic programming example for D language. The code is based on Rust example * Added modules definition Required to run code with names starting with numbers * Fixed proper unsigned handling --- .../d/01_binary_search.d | 27 ++++++++ 02_selection_sort/d/01_selection_sort.d | 32 ++++++++++ 03_recursion/d/01_countdown.d | 18 ++++++ 03_recursion/d/02_greet.d | 22 +++++++ 03_recursion/d/03_factorial.d | 14 +++++ 03_recursion/d/04_count.d | 9 +++ 03_recursion/d/05_binary_search_recursive.d | 23 +++++++ 03_recursion/d/06_find_max.d | 10 +++ 03_recursion/d/07_sum_array.d | 5 ++ 03_recursion/d/08_look_for_key.d | 61 ++++++++++++++++++ 04_quicksort/d/01_loop_sum.d | 14 +++++ 04_quicksort/d/02_recursive_sum.d | 13 ++++ 04_quicksort/d/03_recursive_count.d | 13 ++++ 04_quicksort/d/04_recursive_max.d | 19 ++++++ 04_quicksort/d/05_quicksort.d | 18 ++++++ 05_hash_tables/d/01_price_of_groceries.d | 8 +++ 05_hash_tables/d/02_check_voter.d | 21 +++++++ .../d/01_breadth_first_search.d | 42 +++++++++++++ 07_trees/d/01_filesystem_dfs.d | 19 ++++++ .../d/01_dijkstras_algorithm.d | 63 +++++++++++++++++++ 10_greedy_algorithms/d/01_set_covering.d | 40 ++++++++++++ .../d/01_longest_common_sub.d | 53 ++++++++++++++++ 22 files changed, 544 insertions(+) create mode 100644 01_introduction_to_algorithms/d/01_binary_search.d create mode 100644 02_selection_sort/d/01_selection_sort.d create mode 100644 03_recursion/d/01_countdown.d create mode 100644 03_recursion/d/02_greet.d create mode 100644 03_recursion/d/03_factorial.d create mode 100644 03_recursion/d/04_count.d create mode 100644 03_recursion/d/05_binary_search_recursive.d create mode 100644 03_recursion/d/06_find_max.d create mode 100644 03_recursion/d/07_sum_array.d create mode 100644 03_recursion/d/08_look_for_key.d create mode 100644 04_quicksort/d/01_loop_sum.d create mode 100644 04_quicksort/d/02_recursive_sum.d create mode 100644 04_quicksort/d/03_recursive_count.d create mode 100644 04_quicksort/d/04_recursive_max.d create mode 100644 04_quicksort/d/05_quicksort.d create mode 100644 05_hash_tables/d/01_price_of_groceries.d create mode 100644 05_hash_tables/d/02_check_voter.d create mode 100644 06_breadth-first_search/d/01_breadth_first_search.d create mode 100644 07_trees/d/01_filesystem_dfs.d create mode 100644 09_dijkstras_algorithm/d/01_dijkstras_algorithm.d create mode 100644 10_greedy_algorithms/d/01_set_covering.d create mode 100644 11_dynamic_programming/d/01_longest_common_sub.d diff --git a/01_introduction_to_algorithms/d/01_binary_search.d b/01_introduction_to_algorithms/d/01_binary_search.d new file mode 100644 index 0000000..7d9e137 --- /dev/null +++ b/01_introduction_to_algorithms/d/01_binary_search.d @@ -0,0 +1,27 @@ +module app; + +import std.stdio: writeln; +import std.range: assumeSorted, SortedRange; + +long binary_search(T)(SortedRange!(T[]) list, T item) { + long low = 0; + long high = list.length - 1; + + while (low <= high) { + auto mid = (low + high) / 2; + T guess = list[mid]; + if (guess == item) + return mid; + else if (guess > item) + high = mid - 1; + else + low = mid + 1; + } + return -1; +} + +void main() { + auto my_list = [1, 3, 5, 7, 9]; + writeln(binary_search(assumeSorted(my_list), 3)); + writeln(binary_search(assumeSorted(my_list), -1)); +} diff --git a/02_selection_sort/d/01_selection_sort.d b/02_selection_sort/d/01_selection_sort.d new file mode 100644 index 0000000..53d81bb --- /dev/null +++ b/02_selection_sort/d/01_selection_sort.d @@ -0,0 +1,32 @@ +module app; + +import std.stdio: writeln; +import std.algorithm: minIndex, remove; + + +// or it is possible to use minIndex +T findSmallest(T)(T[] arr) { + auto smallest = arr[0]; + auto smallest_index = 0; + foreach(i; 0 .. cast(int)arr.length) { + if (arr[i] < smallest) { + smallest = arr[i]; + smallest_index = i; + } + } + return smallest_index; +} + +T[] selectionSort(T)(T[] arr) { + T[] newArr = []; + foreach(i; 0 .. cast(int)arr.length) { + auto smallest = findSmallest(arr); // or use minIndex(arr); + newArr ~= arr[smallest]; + arr = arr.remove(smallest); + } + return newArr; +} + +void main() { + writeln(selectionSort([5, 3, 6, 2, 10])); +} diff --git a/03_recursion/d/01_countdown.d b/03_recursion/d/01_countdown.d new file mode 100644 index 0000000..6662a76 --- /dev/null +++ b/03_recursion/d/01_countdown.d @@ -0,0 +1,18 @@ +module app; + +import std; + +void countdown(int i) { + // base case + if (i <= 0) + return 0; + // recursive case + else { + writeln(i); + return countdown(i-1); + } +} + +void main() { + countdown(5); +} diff --git a/03_recursion/d/02_greet.d b/03_recursion/d/02_greet.d new file mode 100644 index 0000000..e1d5865 --- /dev/null +++ b/03_recursion/d/02_greet.d @@ -0,0 +1,22 @@ +module app; + +import std; + +void greet2(string name) { + writeln(i"how are you $(name)?"); +} + +void bye() { + writeln("ok bye!"); +} + +void greet(string name) { + writeln(i"hello, #(name)!"); + greet2(name); + writeln("gettin ready to say bye..."); + bye(); +} + +void main() { + greet("adit"); +} diff --git a/03_recursion/d/03_factorial.d b/03_recursion/d/03_factorial.d new file mode 100644 index 0000000..aa360c5 --- /dev/null +++ b/03_recursion/d/03_factorial.d @@ -0,0 +1,14 @@ +module app; + +import std; + +T fact(T x) { + if (x == 1) + return 1; + else + return x * fact(x-1); +} + +void main() { + writeln(fact(5)); +} diff --git a/03_recursion/d/04_count.d b/03_recursion/d/04_count.d new file mode 100644 index 0000000..65ce37f --- /dev/null +++ b/03_recursion/d/04_count.d @@ -0,0 +1,9 @@ +module app; + +import std; + +int count(T[] arr) { + if (arr.empty) + return 0; + return 1 + count(arr[1..$]); +} diff --git a/03_recursion/d/05_binary_search_recursive.d b/03_recursion/d/05_binary_search_recursive.d new file mode 100644 index 0000000..261b2e6 --- /dev/null +++ b/03_recursion/d/05_binary_search_recursive.d @@ -0,0 +1,23 @@ +module app; + +import std; + +int binary_search(T)(T[] arr, T target) { + if (arr.length == 0) + return -1; + + int mid = cast(int)arr.length / 2; + if (arr[mid] == target) + return mid; + else if (arr[mid] > target) + return binary_search(arr[0..mid], target); + else { + int recursive_response = binary_search(arr[mid + 1 .. $], target); + return recursive_response == -1 ? recursive_response : (mid + 1) + recursive_response; + } +} + +void main() { + writeln(binary_search([6, 7, 8, 9, 10], 8)); + writeln(binary_search([6, 7, 8, 9, 10], 6)); +} diff --git a/03_recursion/d/06_find_max.d b/03_recursion/d/06_find_max.d new file mode 100644 index 0000000..d09a145 --- /dev/null +++ b/03_recursion/d/06_find_max.d @@ -0,0 +1,10 @@ +T find_max(T)(T[] arr) { + if (arr.length == 0) + return 0; + else if (arr.length == 1) + return arr[0]; + else if (arr.length == 2) + return arr[0] > arr[1] ? arr[0] : arr[1]; + auto sub_max = find_max(arr[1..$]); + return arr[0] > sub_max ? arr[0] : sub_max; +} diff --git a/03_recursion/d/07_sum_array.d b/03_recursion/d/07_sum_array.d new file mode 100644 index 0000000..22e5e34 --- /dev/null +++ b/03_recursion/d/07_sum_array.d @@ -0,0 +1,5 @@ +T sum_array(T)(T[] arr) { + if (arr.empty) + return 0; + return arr[0] + sum_array(arr[1..$]); +} diff --git a/03_recursion/d/08_look_for_key.d b/03_recursion/d/08_look_for_key.d new file mode 100644 index 0000000..68c7ecb --- /dev/null +++ b/03_recursion/d/08_look_for_key.d @@ -0,0 +1,61 @@ +modeul app; + +import std; + +class Item { + bool is_key = false; + Item[] items_in_box; + + this() { + this.is_key = false; + } + + this(bool key) { + this.is_key = key; + } + + bool is_a_box() { + return !this.is_key; + } + + bool is_a_key() { + return this.is_key; + } +} + +void look_for_key(Item box) { + foreach(item; box.items_in_box) + if (item.is_a_box()) + // recursive case + look_for_key(item); + else if (item.is_a_key()) + // base case + writeln("found the key!"); +} + +/* +main_box +├── box_A +│ ├── box_B +│ └── box_C +└── box_D + └── box_E + └── key +*/ +void main() { + auto main_box = new Item(); + auto box_A = new Item(); + auto box_B = new Item(); + auto box_C = new Item(); + box_A.items_in_box = [box_B, box_C]; + + auto box_D = new Item(); + auto box_E = new Item(); + auto key = new Item(true); + box_E.items_in_box = [key]; + box_D.items_in_box = [box_E]; + + main_box.items_in_box = [box_A, box_D]; + + look_for_key(main_box); +} diff --git a/04_quicksort/d/01_loop_sum.d b/04_quicksort/d/01_loop_sum.d new file mode 100644 index 0000000..df5bc29 --- /dev/null +++ b/04_quicksort/d/01_loop_sum.d @@ -0,0 +1,14 @@ +module app; + +import std; + +T loop_sum(T[] arr) { + T total; + foreach(x; arr) + total += x; + return total; +} + +void main() { + writeln(loop_sum([1,2,3,4])); +} diff --git a/04_quicksort/d/02_recursive_sum.d b/04_quicksort/d/02_recursive_sum.d new file mode 100644 index 0000000..891b686 --- /dev/null +++ b/04_quicksort/d/02_recursive_sum.d @@ -0,0 +1,13 @@ +module app; + +import std; + +T rec_sum(T[] list) { + if (list.empty) + return 0; + return list[0] + sum(list[1..$]); +} + +void main() { + writeln(rec_sum([1,2,3,4])); +} diff --git a/04_quicksort/d/03_recursive_count.d b/04_quicksort/d/03_recursive_count.d new file mode 100644 index 0000000..b197479 --- /dev/null +++ b/04_quicksort/d/03_recursive_count.d @@ -0,0 +1,13 @@ +module app; + +import std; + +T rec_count(T[] list) { + if (list.empty) + return 0; + return 1 + rec_count(list[1..$]); +} + +void main() { + writeln(rec_count([1,2,3,4])); +} diff --git a/04_quicksort/d/04_recursive_max.d b/04_quicksort/d/04_recursive_max.d new file mode 100644 index 0000000..2f176d1 --- /dev/null +++ b/04_quicksort/d/04_recursive_max.d @@ -0,0 +1,19 @@ +module app; + +import std; + +T rec_max(T)(T[] list) { + if (list.empty) + return T.init; + if (list.length == 1) + return list[0]; + else { + auto max_num = rec_max(list[1..$]); + return list[0] > max_num ? list[0] : max_num; + } +} + +void main() { + writeln(rec_max([1,2,3])); +} + diff --git a/04_quicksort/d/05_quicksort.d b/04_quicksort/d/05_quicksort.d new file mode 100644 index 0000000..7b943a7 --- /dev/null +++ b/04_quicksort/d/05_quicksort.d @@ -0,0 +1,18 @@ +module app; + +import std; + +T[] quicksort(T[] arr) { + if (arr.length < 2) + return arr; + else { + auto pivot = arr[0]; + auto less = arr.filter!(el => el < pivot).array; + auto greater = arr.filter!(el => el > pivot).array; + return quicksort(less) ~ arr.filter!(el => el == pivot).array ~ quicksort(greater); + } +} + +void main() { + writeln(quicksort([10, 5, 2, 3])); +} diff --git a/05_hash_tables/d/01_price_of_groceries.d b/05_hash_tables/d/01_price_of_groceries.d new file mode 100644 index 0000000..04f0b6b --- /dev/null +++ b/05_hash_tables/d/01_price_of_groceries.d @@ -0,0 +1,8 @@ +module app; + +import std; + +void main() { + float[string] book = ["apple": 0.67, "milk": 1.49, "avocado": 1.49]; + writeln(book); +} diff --git a/05_hash_tables/d/02_check_voter.d b/05_hash_tables/d/02_check_voter.d new file mode 100644 index 0000000..e723227 --- /dev/null +++ b/05_hash_tables/d/02_check_voter.d @@ -0,0 +1,21 @@ +module app; + +import std; + +bool[string] voted; + +void check_voter(string name) { + auto p = name in voted; + if (p !is null) + writeln("Kick them out!"); + else { + voted[name] = true; + writeln("Let them vote!"); + } +} + +void main() { + check_voter("tom"); + check_voter("mike"); + check_voter("mike"); +} diff --git a/06_breadth-first_search/d/01_breadth_first_search.d b/06_breadth-first_search/d/01_breadth_first_search.d new file mode 100644 index 0000000..6fdae87 --- /dev/null +++ b/06_breadth-first_search/d/01_breadth_first_search.d @@ -0,0 +1,42 @@ +module app; + +import std; + +bool personIsSeller(string name) { + return name[name.length - 1] == 'm'; +} + +bool search(string name) { + auto search_queue = DList!string(); + search_queue.insertBack(name); + bool[string] searched; + while (!search_queue.empty) { + auto person = search_queue.front(); + search_queue.removeFront(); + auto found = person in searched; + if (found !is null) + continue; + if (personIsSeller(person)) { + writeln(person, " is a mango seller!"); + return true; + } + search_queue.insertBack(graph[person]); + searched[person] = true; + } + return false; +} + +string[][string] graph; + +void main() { + graph["you"] = ["alice", "bob", "claire"]; + graph["bob"] = ["anuj", "peggy"]; + graph["alice"] = ["peggy"]; + graph["claire"] = ["thom", "jonny"]; + graph["anuj"] = []; + graph["peggy"] = []; + graph["thom"] = []; + graph["jonny"] = []; + + search("you"); +} diff --git a/07_trees/d/01_filesystem_dfs.d b/07_trees/d/01_filesystem_dfs.d new file mode 100644 index 0000000..1974b49 --- /dev/null +++ b/07_trees/d/01_filesystem_dfs.d @@ -0,0 +1,19 @@ +module app; + +import std; + +void printnames(string dir) +{ + foreach(DirEntry name; dirEntries(dir, SpanMode.shallow)) + { + if (name.isFile) + writeln(name); + else + printnames(name); + } +} + +void main() +{ + printnames("test1"); +} diff --git a/09_dijkstras_algorithm/d/01_dijkstras_algorithm.d b/09_dijkstras_algorithm/d/01_dijkstras_algorithm.d new file mode 100644 index 0000000..be548ea --- /dev/null +++ b/09_dijkstras_algorithm/d/01_dijkstras_algorithm.d @@ -0,0 +1,63 @@ +module app; + +import std; + +alias Costs = double[string]; +alias Graph = Costs[string]; + +Graph graph; +string[] processed; + +string find_lowest_cost_node(const Costs costs) +{ + double lowestCost = double.infinity; + string lowestCostNode; + foreach(node; costs.byPair) + { + auto cost = node.value; + if (cost < lowestCost && (!processed.canFind(node.key))) + { + lowestCost = cost; + lowestCostNode = node.key; + } + } + return lowestCostNode; +} + +void main() +{ + graph["start"] = ["a": 6, "b": 2]; + graph["a"] = ["finish": 1]; + graph["b"] = ["a": 3, "finish": 5]; + graph["finish"] = new Costs; + + Costs costs; + costs["a"] = 6; + costs["b"] = 2; + costs["finish"] = double.infinity; + + string[string] parents; + parents["a"] = "start"; + parents["b"] = "start"; + + auto node = find_lowest_cost_node(costs); + while (!node.empty) + { + double cost = costs[node]; + auto neighbors = graph[node]; + foreach(n; neighbors.byKey()) + { + double newCost = cost + neighbors[n]; + if (costs[n] > newCost) + { + costs[n] = newCost; + parents[n] = node; + } + } + processed ~= node; + node = find_lowest_cost_node(costs); + } + + writeln("Cost from the start to each node:"); + writeln(costs); +} diff --git a/10_greedy_algorithms/d/01_set_covering.d b/10_greedy_algorithms/d/01_set_covering.d new file mode 100644 index 0000000..837233a --- /dev/null +++ b/10_greedy_algorithms/d/01_set_covering.d @@ -0,0 +1,40 @@ +module app; + +import std; + +alias Set = bool[string]; + +void main() +{ + Set statesNeeded = assocArray(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"], true.repeat); + Set[string] stations; + stations["kone"] = assocArray(["id", "nv", "ut"], true.repeat); + stations["ktwo"] = assocArray(["wa", "id", "mt"], true.repeat); + stations["kthree"] = assocArray(["or", "nv", "ca"], true.repeat); + stations["kfour"] = assocArray(["nv", "ut"], true.repeat); + stations["kfive"] = assocArray(["ca", "az"], true.repeat); + + Set finalStations; + + while (!statesNeeded.empty) + { + string bestStation; + Set statesCovered; + foreach(station; stations.byPair) + { + auto coverage = setIntersection(station.value.keys.sort, statesNeeded.keys.sort).array; + if (coverage.length > statesCovered.keys.length) + { + bestStation = station.key; + statesCovered = assocArray(coverage, true.repeat); + } + } + if (statesCovered.length) + { + foreach(st; statesCovered.keys) + statesNeeded.remove(st); + } + finalStations[bestStation] = true; + } + writeln(finalStations.keys); +} diff --git a/11_dynamic_programming/d/01_longest_common_sub.d b/11_dynamic_programming/d/01_longest_common_sub.d new file mode 100644 index 0000000..35f9aa3 --- /dev/null +++ b/11_dynamic_programming/d/01_longest_common_sub.d @@ -0,0 +1,53 @@ +module app; + +import std; + +alias DpTable = ulong[][]; + +DpTable longest_common_substring(T)(T[] table1, T[] table2) +{ + DpTable dp_table = new DpTable(table1.length, table2.length); + + foreach(i, c1; table1) + foreach(j, c2; table2) + { + if (c1 == c2) + dp_table[i][j] = dp_table[i > 0 ? i - 1 : 0][j > 0 ? j - 1 : 0] + 1; + else + dp_table[i][j] = 0; + } + return dp_table; +} + + +DpTable longest_common_subsequence(T)(T[] table1, T[] table2) +{ + DpTable dp_table = new DpTable(table1.length, table2.length); + + foreach(i, c1; table1) + foreach(j, c2; table2) + { + if (c1 == c2) + dp_table[i][j] = dp_table[i > 0 ? i-1 : 0][j > 0 ? j-1 : 0] + 1; + else + { + dp_table[i][j] = max(dp_table[i > 0 ? i-1 : 0][j], + dp_table[i][j > 0 ? j-1 : 0]); + } + } + return dp_table; +} + +void main() +{ + auto dp_table_blue = "blue"; + auto dp_table_clues = "clues"; + + writeln("Longest substring:"); + foreach(line; longest_common_substring(dp_table_blue.array, dp_table_clues.array)) + writeln(line); + + writeln("Longest subsequence:"); + foreach(line; longest_common_subsequence(dp_table_blue.array, dp_table_clues.array)) + writeln(line); +}