8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# File 'lib/dsa_visualizer/data_structures/array.rb', line 8
def self.demo
Visualizer.("ARRAY - Core Level Visualization")
Visualizer.print_section("1. Memory Model")
Comparator.compare_memory_model(:array)
Visualizer.print_section("2. Array Creation")
tracker = MemoryTracker.new
Visualizer.print_step(1, "Creating array in Ruby")
arr = [10, 20, 30, 40, 50]
tracker.track_allocation("Array", arr.size, arr)
puts "\nRuby internals:"
puts " - Array object created on heap"
puts " - Stores references to Integer objects"
puts " - Dynamic resizing capability"
Visualizer.visualize_memory_layout("Ruby Array", arr)
puts "\nC++ equivalent:"
puts " int arr[5] = {10, 20, 30, 40, 50};"
puts " - Contiguous memory block"
puts " - Each int: 4 bytes"
puts " - Total: 20 bytes (5 × 4)"
puts " - Stack allocated (if local)"
Visualizer.print_section("3. Element Access")
Visualizer.print_step(2, "Accessing element at index 2")
element = arr[2]
tracker.track_operation("Access", "arr[2] = #{element}")
Visualizer.visualize_array(arr, 2)
puts "\n🔍 Ruby Process:"
puts " 1. Check bounds (raises error if out of range)"
puts " 2. Calculate: base_address + (index × pointer_size)"
puts " 3. Dereference pointer to get object"
puts " 4. Return object reference"
puts "\n🔍 C++ Process:"
puts " 1. Calculate: base_address + (index × sizeof(int))"
puts " 2. Direct memory access"
puts " 3. Return value (no indirection)"
Comparator.compare_complexity(
"Array Access",
"O(1) - with bounds checking overhead",
"O(1) - direct memory access",
"Both are constant time, but C++ is faster due to no bounds checking and direct value access"
)
Visualizer.print_section("4. Insertion")
Visualizer.print_step(3, "Inserting 25 at index 2")
puts "\nBefore:"
Visualizer.visualize_array(arr)
arr.insert(2, 25)
tracker.track_operation("Insert", "Inserted 25 at index 2")
puts "\nAfter:"
Visualizer.visualize_array(arr, 2)
puts "\n🔄 Ruby Process:"
puts " 1. Check if resize needed (capacity vs size)"
puts " 2. If needed: allocate new array (2× capacity)"
puts " 3. Shift elements right from index 2"
puts " 4. Insert new element"
puts " 5. Update size"
puts "\n🔄 C++ Process (std::vector):"
puts " 1. Check capacity"
puts " 2. If needed: allocate new memory"
puts " 3. Copy elements to new location"
puts " 4. Shift elements using memmove"
puts " 5. Insert element"
Comparator.compare_complexity(
"Array Insertion (middle)",
"O(n) - must shift elements",
"O(n) - must shift elements",
"Both require shifting elements. Ruby has additional overhead from object reference management."
)
tracker.print_summary
puts "\n\n🎯 Key Takeaways:".colorize(:green).bold
puts " 1. Ruby arrays are dynamic and store object references"
puts " 2. C++ arrays can be static (fixed) or dynamic (std::vector)"
puts " 3. Ruby provides safety (bounds checking) at cost of performance"
puts " 4. C++ provides speed at cost of safety (manual management)"
puts " 5. Both use contiguous memory, but Ruby adds indirection layer"
end
|