dsa_visualizer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +323 -0
  4. data/USAGE.md +359 -0
  5. data/bin/dsa_visualizer +5 -0
  6. data/lib/dsa_visualizer/algorithms/dynamic_programming.rb +23 -0
  7. data/lib/dsa_visualizer/algorithms/graph_algorithms.rb +23 -0
  8. data/lib/dsa_visualizer/algorithms/greedy.rb +11 -0
  9. data/lib/dsa_visualizer/algorithms/searching.rb +78 -0
  10. data/lib/dsa_visualizer/algorithms/sorting.rb +77 -0
  11. data/lib/dsa_visualizer/algorithms/string_algorithms.rb +11 -0
  12. data/lib/dsa_visualizer/cli.rb +281 -0
  13. data/lib/dsa_visualizer/comparator.rb +57 -0
  14. data/lib/dsa_visualizer/data_structures/array.rb +109 -0
  15. data/lib/dsa_visualizer/data_structures/binary_tree.rb +104 -0
  16. data/lib/dsa_visualizer/data_structures/bst.rb +11 -0
  17. data/lib/dsa_visualizer/data_structures/deque.rb +11 -0
  18. data/lib/dsa_visualizer/data_structures/doubly_linked_list.rb +11 -0
  19. data/lib/dsa_visualizer/data_structures/graph.rb +11 -0
  20. data/lib/dsa_visualizer/data_structures/hash_table.rb +61 -0
  21. data/lib/dsa_visualizer/data_structures/heap.rb +17 -0
  22. data/lib/dsa_visualizer/data_structures/linked_list.rb +197 -0
  23. data/lib/dsa_visualizer/data_structures/priority_queue.rb +11 -0
  24. data/lib/dsa_visualizer/data_structures/queue.rb +110 -0
  25. data/lib/dsa_visualizer/data_structures/stack.rb +207 -0
  26. data/lib/dsa_visualizer/data_structures/string.rb +11 -0
  27. data/lib/dsa_visualizer/data_structures/trie.rb +11 -0
  28. data/lib/dsa_visualizer/data_structures/union_find.rb +11 -0
  29. data/lib/dsa_visualizer/fundamentals/complexity.rb +264 -0
  30. data/lib/dsa_visualizer/fundamentals/memory.rb +285 -0
  31. data/lib/dsa_visualizer/fundamentals/pointers.rb +311 -0
  32. data/lib/dsa_visualizer/fundamentals/recursion.rb +63 -0
  33. data/lib/dsa_visualizer/memory_tracker.rb +49 -0
  34. data/lib/dsa_visualizer/notes_manager.rb +85 -0
  35. data/lib/dsa_visualizer/version.rb +3 -0
  36. data/lib/dsa_visualizer/visualizer.rb +58 -0
  37. data/lib/dsa_visualizer.rb +114 -0
  38. metadata +157 -0
@@ -0,0 +1,104 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class TreeNode
4
+ attr_accessor :value, :left, :right
5
+
6
+ def initialize(value)
7
+ @value = value
8
+ @left = nil
9
+ @right = nil
10
+ end
11
+ end
12
+
13
+ class BinaryTree
14
+ attr_reader :root
15
+
16
+ def initialize
17
+ @root = nil
18
+ end
19
+
20
+ def insert(value)
21
+ @root = insert_recursive(@root, value)
22
+ end
23
+
24
+ private
25
+
26
+ def insert_recursive(node, value)
27
+ return TreeNode.new(value) if node.nil?
28
+
29
+ if value < node.value
30
+ node.left = insert_recursive(node.left, value)
31
+ else
32
+ node.right = insert_recursive(node.right, value)
33
+ end
34
+ node
35
+ end
36
+
37
+ public
38
+
39
+ def self.learn
40
+ demo
41
+ end
42
+
43
+ def self.demo
44
+ Visualizer.print_header("BINARY SEARCH TREE - Core Level Visualization")
45
+
46
+ Visualizer.print_section("1. BST Concept")
47
+ puts "\nBinary Search Tree properties:"
48
+ puts " - Left subtree < node < right subtree"
49
+ puts " - Enables O(log n) search in balanced tree"
50
+ puts " - Can degrade to O(n) if unbalanced"
51
+
52
+ Visualizer.print_section("2. Implementation Comparison")
53
+
54
+ ruby_code = <<~RUBY
55
+ class TreeNode
56
+ attr_accessor :value, :left, :right
57
+ def initialize(value)
58
+ @value = value
59
+ @left = @right = nil
60
+ end
61
+ end
62
+
63
+ # Ruby: object references for children
64
+ # GC handles memory
65
+ RUBY
66
+
67
+ cpp_code = <<~CPP
68
+ struct TreeNode {
69
+ int value;
70
+ TreeNode *left, *right;
71
+ TreeNode(int v) : value(v),
72
+ left(nullptr), right(nullptr) {}
73
+ };
74
+
75
+ // C++: explicit pointers
76
+ // Manual memory management
77
+ CPP
78
+
79
+ explanation = "Both use pointer-based structure. Ruby uses object references with GC, C++ uses raw pointers requiring manual deletion. Tree traversal is same in both."
80
+
81
+ Visualizer.print_comparison(ruby_code, cpp_code, explanation)
82
+
83
+ tree = BinaryTree.new
84
+ values = [50, 30, 70, 20, 40, 60, 80]
85
+
86
+ Visualizer.print_step(1, "Inserting values: #{values.join(', ')}")
87
+ values.each { |v| tree.insert(v) }
88
+
89
+ puts "\nTree structure:"
90
+ puts " 50"
91
+ puts " / \\"
92
+ puts " 30 70"
93
+ puts " / \\ / \\"
94
+ puts " 20 40 60 80"
95
+
96
+ puts "\n\nšŸŽÆ Key Takeaways:".colorize(:green).bold
97
+ puts " 1. BST enables efficient searching: O(log n) average"
98
+ puts " 2. Insertion/deletion: O(log n) average"
99
+ puts " 3. Worst case O(n) for unbalanced tree"
100
+ puts " 4. Self-balancing trees (AVL, Red-Black) maintain O(log n)"
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,11 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class BST
4
+ def self.learn
5
+ Visualizer.print_header("BINARY SEARCH TREE - Ordered Binary Tree")
6
+ puts "\nšŸ“š Coming soon: BST properties, search, insert, delete"
7
+ puts "Topics: In-order traversal, balancing, AVL trees"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class Deque
4
+ def self.learn
5
+ Visualizer.print_header("DEQUE - Double-Ended Queue")
6
+ puts "\nšŸ“š Coming soon: Operations at both ends"
7
+ puts "Topics: Push/pop from front and back, circular buffer implementation"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class DoublyLinkedList
4
+ def self.learn
5
+ Visualizer.print_header("DOUBLY LINKED LIST - Bidirectional Navigation")
6
+ puts "\nšŸ“š Coming soon: Two-way traversal, prev and next pointers"
7
+ puts "Topics: Insertion, deletion, reverse traversal"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class Graph
4
+ def self.learn
5
+ Visualizer.print_header("GRAPH - Vertices and Edges")
6
+ puts "\nšŸ“š Coming soon: Graph representations"
7
+ puts "Topics: Adjacency matrix, adjacency list, directed vs undirected"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,61 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class HashTable
4
+ def self.learn
5
+ demo
6
+ end
7
+
8
+ def self.demo
9
+ Visualizer.print_header("HASH TABLE - Core Level Visualization")
10
+
11
+ Visualizer.print_section("1. Hash Table Concept")
12
+ puts "\nKey-Value storage with O(1) average access time"
13
+ puts "Uses hash function to map keys to array indices"
14
+
15
+ Visualizer.print_section("2. Implementation Comparison")
16
+
17
+ ruby_code = <<~RUBY
18
+ hash = { "name" => "Alice", "age" => 30 }
19
+
20
+ # Ruby Hash internals:
21
+ # - Uses MurmurHash
22
+ # - Open addressing with linear probing
23
+ # - Maintains insertion order (since Ruby 1.9)
24
+ # - Automatic resizing at 75% capacity
25
+ RUBY
26
+
27
+ cpp_code = <<~CPP
28
+ #include <unordered_map>
29
+ std::unordered_map<std::string, int> map;
30
+ map["name"] = "Alice";
31
+
32
+ // C++ unordered_map:
33
+ // - Uses hash function (std::hash)
34
+ // - Separate chaining (linked lists)
35
+ // - No order guarantee
36
+ // - Rehashing at load factor threshold
37
+ CPP
38
+
39
+ explanation = "Ruby Hash maintains insertion order and uses open addressing. C++ unordered_map uses separate chaining and doesn't maintain order. Both provide O(1) average case, O(n) worst case."
40
+
41
+ Visualizer.print_comparison(ruby_code, cpp_code, explanation)
42
+
43
+ Visualizer.print_section("3. Hash Function Demo")
44
+
45
+ keys = ["apple", "banana", "cherry"]
46
+ puts "\nHash values for keys:"
47
+ keys.each do |key|
48
+ hash_val = key.hash
49
+ bucket = hash_val % 10
50
+ puts " '#{key}' → hash: #{hash_val} → bucket: #{bucket}"
51
+ end
52
+
53
+ puts "\n\nšŸŽÆ Key Takeaways:".colorize(:green).bold
54
+ puts " 1. Hash tables provide O(1) average lookup"
55
+ puts " 2. Collision handling: chaining vs open addressing"
56
+ puts " 3. Ruby maintains order, C++ doesn't"
57
+ puts " 4. Load factor triggers resizing"
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,17 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class Heap
4
+ def self.learn_min
5
+ Visualizer.print_header("MIN HEAP - Complete Binary Tree")
6
+ puts "\nšŸ“š Coming soon: Heap property, heapify, extract-min"
7
+ puts "Topics: Array representation, priority queue implementation"
8
+ end
9
+
10
+ def self.learn_max
11
+ Visualizer.print_header("MAX HEAP - Complete Binary Tree")
12
+ puts "\nšŸ“š Coming soon: Max heap operations"
13
+ puts "Topics: Heap sort, building heap in O(n)"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,197 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class Node
4
+ attr_accessor :data, :next
5
+
6
+ def initialize(data)
7
+ @data = data
8
+ @next = nil
9
+ end
10
+ end
11
+
12
+ class LinkedList
13
+ attr_reader :head
14
+
15
+ def initialize
16
+ @head = nil
17
+ end
18
+
19
+ def append(data)
20
+ new_node = Node.new(data)
21
+
22
+ if @head.nil?
23
+ @head = new_node
24
+ return
25
+ end
26
+
27
+ current = @head
28
+ current = current.next while current.next
29
+ current.next = new_node
30
+ end
31
+
32
+ def visualize
33
+ return "Empty list" if @head.nil?
34
+
35
+ result = ""
36
+ current = @head
37
+ while current
38
+ result += "[#{current.data}|•]"
39
+ result += " -> " if current.next
40
+ current = current.next
41
+ end
42
+ result += " -> nil"
43
+ result
44
+ end
45
+
46
+ def self.learn
47
+ demo
48
+ end
49
+
50
+ def self.demo
51
+ Visualizer.print_header("LINKED LIST - Core Level Visualization")
52
+
53
+ # Memory Model
54
+ Visualizer.print_section("1. Memory Model Comparison")
55
+
56
+ ruby_code = <<~RUBY
57
+ class Node
58
+ attr_accessor :data, :next
59
+ def initialize(data)
60
+ @data = data
61
+ @next = nil
62
+ end
63
+ end
64
+ # Each node is a Ruby object
65
+ # @next stores reference to next node
66
+ RUBY
67
+
68
+ cpp_code = <<~CPP
69
+ struct Node {
70
+ int data;
71
+ Node* next;
72
+ Node(int d) : data(d), next(nullptr) {}
73
+ };
74
+ // Each node allocated on heap
75
+ // next is explicit pointer
76
+ CPP
77
+
78
+ explanation = "Ruby uses object references (implicit pointers), C++ uses explicit pointers. Both achieve same structure but Ruby adds GC overhead while C++ requires manual memory management."
79
+
80
+ Visualizer.print_comparison(ruby_code, cpp_code, explanation)
81
+
82
+ # Creation
83
+ Visualizer.print_section("2. Creating Linked List")
84
+ tracker = MemoryTracker.new
85
+ list = LinkedList.new
86
+
87
+ Visualizer.print_step(1, "Adding nodes: 10, 20, 30")
88
+
89
+ [10, 20, 30].each do |value|
90
+ list.append(value)
91
+ tracker.track_operation("Append", "Added node with value #{value}")
92
+ end
93
+
94
+ puts "\n" + list.visualize
95
+
96
+ puts "\nšŸ“¦ Memory Layout:"
97
+ current = list.head
98
+ index = 0
99
+ while current
100
+ puts " Node #{index}:"
101
+ puts " Address: 0x#{current.object_id.to_s(16)}"
102
+ puts " Data: #{current.data}"
103
+ puts " Next: #{current.next ? "0x#{current.next.object_id.to_s(16)}" : "nil"}"
104
+ current = current.next
105
+ index += 1
106
+ end
107
+
108
+ puts "\nšŸ” Ruby Internals:"
109
+ puts " - Each Node is a Ruby object (heap allocated)"
110
+ puts " - @next is object reference (managed by GC)"
111
+ puts " - No manual memory management needed"
112
+ puts " - Overhead: object header + reference tracking"
113
+
114
+ puts "\nšŸ” C++ Internals:"
115
+ puts " - Each Node allocated with 'new'"
116
+ puts " - next is raw pointer (8 bytes on 64-bit)"
117
+ puts " - Must manually delete nodes"
118
+ puts " - No overhead beyond struct size"
119
+
120
+ # Traversal
121
+ Visualizer.print_section("3. Traversal")
122
+ Visualizer.print_step(2, "Traversing to find value 20")
123
+
124
+ puts "\nProcess:"
125
+ current = list.head
126
+ position = 0
127
+ while current
128
+ if current.data == 20
129
+ puts " Position #{position}: [#{current.data}] ← FOUND!".colorize(:green)
130
+ else
131
+ puts " Position #{position}: [#{current.data}]"
132
+ end
133
+ current = current.next
134
+ position += 1
135
+ end
136
+
137
+ Comparator.compare_complexity(
138
+ "Linked List Traversal",
139
+ "O(n) - must follow references",
140
+ "O(n) - must follow pointers",
141
+ "Both require sequential access. No random access like arrays. Cache performance worse due to non-contiguous memory."
142
+ )
143
+
144
+ # Insertion
145
+ Visualizer.print_section("4. Insertion at Beginning")
146
+ Visualizer.print_step(3, "Inserting 5 at head")
147
+
148
+ puts "\nBefore: " + list.visualize
149
+
150
+ new_node = Node.new(5)
151
+ new_node.next = list.head
152
+ list.instance_variable_set(:@head, new_node)
153
+ tracker.track_operation("Insert", "Inserted 5 at head")
154
+
155
+ puts "After: " + list.visualize
156
+
157
+ puts "\nšŸ”„ Ruby Process:"
158
+ puts " 1. Create new Node object (GC manages)"
159
+ puts " 2. Set new_node.next = current head"
160
+ puts " 3. Update head reference"
161
+ puts " 4. O(1) operation"
162
+
163
+ puts "\nšŸ”„ C++ Process:"
164
+ puts " 1. Allocate: Node* new_node = new Node(5)"
165
+ puts " 2. Set: new_node->next = head"
166
+ puts " 3. Update: head = new_node"
167
+ puts " 4. O(1) operation"
168
+
169
+ # Memory comparison
170
+ Visualizer.print_section("5. Memory Comparison")
171
+
172
+ puts "\nšŸ“Š Array vs Linked List:"
173
+ puts "\nArray:"
174
+ puts " āœ“ Contiguous memory (better cache)"
175
+ puts " āœ“ O(1) random access"
176
+ puts " āœ— O(n) insertion/deletion (middle)"
177
+ puts " āœ— Fixed size (or expensive resize)"
178
+
179
+ puts "\nLinked List:"
180
+ puts " āœ“ O(1) insertion/deletion (at known position)"
181
+ puts " āœ“ Dynamic size (no resize needed)"
182
+ puts " āœ— O(n) random access"
183
+ puts " āœ— Poor cache locality"
184
+ puts " āœ— Extra memory for pointers/references"
185
+
186
+ tracker.print_summary
187
+
188
+ puts "\n\nšŸŽÆ Key Takeaways:".colorize(:green).bold
189
+ puts " 1. Linked lists trade random access for efficient insertion/deletion"
190
+ puts " 2. Ruby's GC simplifies memory management vs C++ manual management"
191
+ puts " 3. Non-contiguous memory means poor cache performance"
192
+ puts " 4. Each node has pointer/reference overhead"
193
+ puts " 5. Best for frequent insertions/deletions, not random access"
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,11 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class PriorityQueue
4
+ def self.learn
5
+ Visualizer.print_header("PRIORITY QUEUE - Heap-Based Queue")
6
+ puts "\nšŸ“š Coming soon: Priority-based dequeue"
7
+ puts "Topics: Min/max heap implementation, applications in scheduling"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,110 @@
1
+ module DSAVisualizer
2
+ module DataStructures
3
+ class Queue
4
+ def initialize
5
+ @items = []
6
+ end
7
+
8
+ def enqueue(item)
9
+ @items.push(item)
10
+ end
11
+
12
+ def dequeue
13
+ @items.shift
14
+ end
15
+
16
+ def front
17
+ @items.first
18
+ end
19
+
20
+ def empty?
21
+ @items.empty?
22
+ end
23
+
24
+ def size
25
+ @items.size
26
+ end
27
+
28
+ def visualize
29
+ return "Empty queue" if @items.empty?
30
+
31
+ result = "\nFRONT → "
32
+ @items.each_with_index do |item, idx|
33
+ result += "[ #{item} ]"
34
+ result += " → " unless idx == @items.size - 1
35
+ end
36
+ result += " ← REAR"
37
+ result
38
+ end
39
+
40
+ def self.learn
41
+ demo
42
+ end
43
+
44
+ def self.demo
45
+ Visualizer.print_header("QUEUE - Core Level Visualization")
46
+
47
+ Visualizer.print_section("1. Queue Concept (FIFO)")
48
+ puts "\nFirst In, First Out - like a line at a store"
49
+ puts "Operations: enqueue (add at rear), dequeue (remove from front)"
50
+
51
+ Visualizer.print_section("2. Implementation Comparison")
52
+
53
+ ruby_code = <<~RUBY
54
+ class Queue
55
+ def initialize
56
+ @items = []
57
+ end
58
+
59
+ def enqueue(item)
60
+ @items.push(item) # O(1)
61
+ end
62
+
63
+ def dequeue
64
+ @items.shift # O(n) - shifts all elements!
65
+ end
66
+ end
67
+ RUBY
68
+
69
+ cpp_code = <<~CPP
70
+ #include <queue>
71
+ std::queue<int> q;
72
+
73
+ q.push(10); // O(1)
74
+ q.pop(); // O(1)
75
+
76
+ // Internally uses deque (double-ended queue)
77
+ // Efficient operations at both ends
78
+ CPP
79
+
80
+ explanation = "Ruby's Array.shift is O(n) because it shifts all elements. C++'s std::queue uses deque internally for O(1) operations at both ends. For better Ruby performance, use a circular buffer or linked list."
81
+
82
+ Visualizer.print_comparison(ruby_code, cpp_code, explanation)
83
+
84
+ tracker = MemoryTracker.new
85
+ queue = Queue.new
86
+
87
+ Visualizer.print_step(1, "Enqueuing: 10, 20, 30")
88
+ [10, 20, 30].each do |val|
89
+ queue.enqueue(val)
90
+ tracker.track_operation("Enqueue", "Added #{val}")
91
+ puts queue.visualize
92
+ end
93
+
94
+ Visualizer.print_step(2, "Dequeuing")
95
+ dequeued = queue.dequeue
96
+ tracker.track_operation("Dequeue", "Removed #{dequeued}")
97
+ puts "\nRemoved: #{dequeued}".colorize(:red)
98
+ puts queue.visualize
99
+
100
+ tracker.print_summary
101
+
102
+ puts "\n\nšŸŽÆ Key Takeaways:".colorize(:green).bold
103
+ puts " 1. Queue is FIFO - First In, First Out"
104
+ puts " 2. Ruby Array.shift is O(n) - inefficient for large queues"
105
+ puts " 3. C++ std::queue uses deque for O(1) operations"
106
+ puts " 4. Use cases: task scheduling, BFS, buffering"
107
+ end
108
+ end
109
+ end
110
+ end