This repository has been archived by the owner on Dec 13, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
32 changed files
with
849 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,15 @@ | ||
{ | ||
"name": "Graphs and Algorithmic Complexity", | ||
"image": "mcr.microsoft.com/devcontainers/base:alpine", | ||
|
||
"postCreateCommand": "sudo apk update && sudo apk add just typst gdb", | ||
|
||
"postCreateCommand": "sudo apk update && sudo apk add just typst gdb zig", | ||
"customizations": { | ||
"vscode": { | ||
"extensions": [ | ||
"ms-vscode.cpptools", | ||
"vadimcn.vscode-lldb", | ||
"ziglang.vscode-zig", | ||
"myriad-dreamin.tinymist" | ||
] | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,7 @@ | |
|
||
# C++ | ||
*.out | ||
*.exe | ||
*.exe | ||
|
||
# Output | ||
output/ |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
const std = @import("std"); | ||
const print = std.debug.print; | ||
|
||
/// Number of vertices in the graph | ||
const N = 5; | ||
/// Maximum length of the path | ||
const MAX_PATH_LENGTH = 20; | ||
|
||
/// Find Eulerian Path in a graph | ||
/// | ||
/// # Parameters | ||
/// | ||
/// - `graph`: Adjacency matrix of the graph | ||
fn findPath(graph: *[N][N]i32) void { | ||
var numofadj: [N]i32 = [_]i32{0} ** N; | ||
var stack: [N]i32 = [_]i32{0} ** N; | ||
var path: [MAX_PATH_LENGTH]i32 = [_]i32{0} ** MAX_PATH_LENGTH; | ||
var top: usize = 0; | ||
var path_length: usize = 0; | ||
|
||
// Find out number of edges each vertex has | ||
for (0..N) |i| { | ||
for (0..N) |j| { | ||
numofadj[i] += graph.*[i][j]; | ||
} | ||
} | ||
|
||
// Find out how many vertices have an odd number of edges | ||
var startpoint: usize = 0; | ||
var numofodd: i32 = 0; | ||
var idx_i: usize = N; | ||
while (idx_i > 0) : (idx_i -= 1) { | ||
const idx = idx_i - 1; | ||
if (@mod(numofadj[idx], 2) == 1) { | ||
numofodd += 1; | ||
startpoint = idx; | ||
} | ||
} | ||
|
||
// If the number of vertices with odd number of edges is greater than two, return "No Solution". | ||
if (numofodd > 2) { | ||
print("No Solution\n", .{}); | ||
return; | ||
} | ||
|
||
// Initialize empty stack and path; take the starting current as discussed | ||
var cur: usize = startpoint; | ||
|
||
// Loop will run until there is an element in the stack or current vertex has some neighbor. | ||
while (top > 0 or numofadj[cur] > 0) { | ||
// If current node has no neighbors, add it to path and pop stack; set new current to the popped element | ||
if (numofadj[cur] == 0) { | ||
path[path_length] = @intCast(cur); | ||
path_length += 1; | ||
if (top > 0) { | ||
top -= 1; | ||
cur = @intCast(stack[top]); | ||
} else { | ||
break; | ||
} | ||
} | ||
// If the current vertex has at least one neighbor, add the current vertex to stack, | ||
// remove the edge between them, and set the current to its neighbor. | ||
else { | ||
for (0..N) |j| { | ||
if (graph.*[cur][j] == 1) { | ||
stack[top] = @intCast(cur); | ||
top += 1; | ||
graph.*[cur][j] = 0; | ||
graph.*[j][cur] = 0; | ||
numofadj[cur] -= 1; | ||
numofadj[j] -= 1; | ||
cur = j; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Add the last vertex to the path | ||
path[path_length] = @intCast(cur); | ||
path_length += 1; | ||
|
||
// Print the path | ||
var idx: usize = path_length; | ||
while (idx > 0) : (idx -= 1) { | ||
print("{d} -> ", .{path[idx - 1]}); | ||
} | ||
print("\n", .{}); | ||
} | ||
|
||
/// Main function | ||
pub fn main() !void { | ||
// Test case 1: | ||
// 0 --- 1 | ||
// | | \ | ||
// | 2--3 | ||
// 4 | ||
var graph1: [N][N]i32 = .{ | ||
.{ 0, 1, 0, 0, 1 }, | ||
.{ 1, 0, 1, 1, 0 }, | ||
.{ 0, 1, 0, 1, 0 }, | ||
.{ 0, 1, 1, 0, 0 }, | ||
.{ 1, 0, 0, 0, 0 }, | ||
}; | ||
|
||
print("Test Case 1:\n", .{}); | ||
findPath(&graph1); | ||
|
||
// Test case 2: | ||
// 0 -- 1 -- 2 | ||
// /| / \ | \ | ||
// 3--4 5 | ||
var graph2: [N][N]i32 = .{ | ||
.{ 0, 1, 0, 1, 1 }, | ||
.{ 1, 0, 1, 0, 1 }, | ||
.{ 0, 1, 0, 1, 1 }, | ||
.{ 1, 0, 1, 0, 0 }, | ||
.{ 1, 1, 1, 0, 0 }, | ||
}; | ||
|
||
print("Test Case 2:\n", .{}); | ||
findPath(&graph2); | ||
|
||
// Test case 3: | ||
// 0 --- 1 | ||
// /|\ |\ | ||
// 2 4---5 3 | ||
var graph3: [N][N]i32 = .{ | ||
.{ 0, 1, 1, 0, 1 }, | ||
.{ 1, 0, 0, 1, 1 }, | ||
.{ 1, 0, 0, 1, 0 }, | ||
.{ 0, 1, 1, 0, 1 }, | ||
.{ 1, 1, 0, 1, 0 }, | ||
}; | ||
|
||
print("Test Case 3:\n", .{}); | ||
findPath(&graph3); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
const std = @import("std"); | ||
const print = std.debug.print; | ||
|
||
/// Number of vertices in the graph | ||
const N = 5; | ||
|
||
/// A utility function to print the solution | ||
fn printSolution(path: [N]i32) void { | ||
print("Solution Exists: ", .{}); | ||
for (0..N) |i| { | ||
print("{d} ", .{path[i]}); | ||
} | ||
// Print the first vertex again to show the complete cycle | ||
print("{d}\n\n", .{path[0]}); | ||
} | ||
|
||
/// A utility function to check if the vertex `v` can be added at index `pos` | ||
/// in the Hamiltonian cycle constructed so far (stored in `path`) | ||
fn isSafe(v: i32, graph: *[N][N]i32, path: [N]i32, pos: usize) bool { | ||
// Check if this vertex is an adjacent vertex of the previously added vertex. | ||
if (graph.*[@intCast(path[pos - 1])][@intCast(v)] == 0) return false; | ||
|
||
// Check if the vertex has already been included. | ||
for (0..pos) |i| { | ||
if (path[i] == v) return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/// A recursive utility function to solve the Hamiltonian cycle problem | ||
fn hamiltonianCycleUtil(graph: *[N][N]i32, path: *[N]i32, pos: usize) bool { | ||
// Base case: If all vertices are included in the Hamiltonian cycle | ||
if (pos == N) { | ||
// And if there is an edge from the last included vertex to the first vertex | ||
if (graph.*[@intCast(path[pos - 1])][@intCast(path[0])] == 1) { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
// Try different vertices as the next candidate in the Hamiltonian cycle. | ||
// We don't try for 0 as we included 0 as the starting point in hamiltonianCycle() | ||
for (1..N) |v| { | ||
const v_int: i32 = @intCast(v); | ||
// Check if this vertex can be added to the Hamiltonian cycle | ||
if (isSafe(v_int, graph, path.*, pos)) { | ||
path.*[pos] = v_int; | ||
|
||
// Recur to construct the rest of the path | ||
if (hamiltonianCycleUtil(graph, path, pos + 1)) | ||
return true; | ||
|
||
// If adding vertex `v` doesn't lead to a solution, then remove it | ||
path.*[pos] = -1; | ||
} | ||
} | ||
|
||
// If no vertex can be added to the Hamiltonian cycle constructed so far, | ||
// then return false | ||
return false; | ||
} | ||
|
||
/// This function solves the Hamiltonian cycle problem using backtracking. | ||
/// It mainly uses `hamiltonianCycleUtil()` to solve the problem. | ||
/// It returns false if there is no Hamiltonian cycle possible, | ||
/// otherwise returns true and prints the path. | ||
fn hamiltonianCycle(graph: *[N][N]i32) bool { | ||
var path: [N]i32 = [_]i32{-1} ** N; | ||
|
||
// Let us put vertex 0 as the first vertex in the path. | ||
// If there is a Hamiltonian cycle, | ||
// then the path can be started from any point | ||
// of the cycle as the graph is undirected | ||
path[0] = 0; | ||
if (!hamiltonianCycleUtil(graph, &path, 1)) { | ||
print("Solution does not exist\n\n", .{}); | ||
return false; | ||
} | ||
|
||
printSolution(path); | ||
return true; | ||
} | ||
|
||
/// Main function | ||
pub fn main() !void { | ||
// Test case 1: | ||
// (0)--(1)--(2) | ||
// | / \ | | ||
// | / \ | | ||
// | / \ | | ||
// (3)-------(4) | ||
var graph1: [N][N]i32 = .{ | ||
.{ 0, 1, 0, 1, 0 }, | ||
.{ 1, 0, 1, 1, 1 }, | ||
.{ 0, 1, 0, 0, 1 }, | ||
.{ 1, 1, 0, 0, 1 }, | ||
.{ 0, 1, 1, 1, 0 }, | ||
}; | ||
|
||
_ = hamiltonianCycle(&graph1); | ||
|
||
// Test case 2: | ||
// (0)--(1)--(2) | ||
// | / \ | | ||
// | / \ | | ||
// | / \ | | ||
// (3) (4) | ||
var graph2: [N][N]i32 = .{ | ||
.{ 0, 1, 0, 1, 0 }, | ||
.{ 1, 0, 1, 1, 1 }, | ||
.{ 0, 1, 0, 0, 1 }, | ||
.{ 1, 1, 0, 0, 0 }, | ||
.{ 0, 1, 1, 0, 0 }, | ||
}; | ||
|
||
print("Test Case 2:\n", .{}); | ||
_ = hamiltonianCycle(&graph2); | ||
} |
Oops, something went wrong.