/*
Java 17 -- Arrays
Declare and index, access with a loop, update by index, remove by shifting, copy with a loop.
No em dashes anywhere -- use plain hyphens or rewrite the sentence.
Line index comments mark each scenario's 0-based line numbers
(blank lines are not counted).
*/
STEPPER_REGISTRY.register("java-17/arrays", {
label: 'Arrays',
panelConfig: {
stack: true,
heap: false,
custom: false,
legend: [
{ color:'#1d5799', border:'#9dc0e8', label:'Currently running frame' },
{ color:'#a0540a', border:'#e8c070', label:'Variable just assigned' },
{ color:'#095e40', border:'#90d4b8', label:'Holding a value' },
{ color:'#3d3490', border:'#b0a8e0', label:'Reference (array)' },
]
},
scenarios: [
/* ------------------------------------------------------------------ */
/* 1. Declare and index (read) */
/* */
/* 0 static void main(String[] args) { */
/* 1 int[] nums = {10, 20, 30}; */
/* 2 int x = nums[0]; */
/* 3 int y = nums[2]; */
/* 4 } */
/* ------------------------------------------------------------------ */
{
label: 'Declare and index',
lines: [
{ code: [['tok-kw','static '],['tok-kw','void '],['tok-meth','main'],['tok-op','(String[] args) {']] },
{ code: [['',' '],['tok-type','int'],['tok-op','[] nums = {'],['tok-num','10'],['tok-op',', '],['tok-num','20'],['tok-op',', '],['tok-num','30'],['tok-op','};']] },
{ code: [['',' '],['tok-type','int '],['tok-op','x = nums['],['tok-num','0'],['tok-op','];']] },
{ code: [['',' '],['tok-type','int '],['tok-op','y = nums['],['tok-num','2'],['tok-op','];']] },
{ code: [['tok-op','}']] },
],
steps: [
{ line:0, stack:[{name:'main()',vars:[],active:true}],
expl:{label:'Program starts', text:'Java enters main() and pushes a new frame onto the call stack.'} },
{ line:1, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:true,cls:true}],active:true}],
expl:{label:'Array created', text:'int[] nums = {10, 20, 30} allocates a 3-element array and stores a reference to it in nums. The purple pill signals it is a reference, not a primitive value.'} },
{ line:2, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'x',v:'10',fresh:true,cls:false}],active:true}],
expl:{label:'Reading index 0', text:'nums[0] reads the element at index 0. Arrays are zero-indexed, so the first element is 10. That value is copied into x.'} },
{ line:3, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'x',v:'10',fresh:false,cls:false},{n:'y',v:'30',fresh:true,cls:false}],active:true}],
expl:{label:'Reading index 2', text:'nums[2] reads the last element. Index 2 holds 30, which is copied into y. Valid indices for a 3-element array are 0, 1, and 2.'} },
{ line:4, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'x',v:'10',fresh:false,cls:false},{n:'y',v:'30',fresh:false,cls:false}],active:true}],
expl:{label:'Program ends', text:'main() reaches its closing brace. All local variables go out of scope and the program finishes.'} },
]
},
/* ------------------------------------------------------------------ */
/* 2. Access with a loop */
/* */
/* 0 static void main(String[] args) { */
/* 1 int[] nums = {10, 20, 30}; */
/* 2 int sum = 0; */
/* 3 for (int i = 0; i < 3; i++) { */
/* 4 sum = sum + nums[i]; */
/* 5 } */
/* 6 } */
/* ------------------------------------------------------------------ */
{
label: 'Access with a loop',
lines: [
{ code: [['tok-kw','static '],['tok-kw','void '],['tok-meth','main'],['tok-op','(String[] args) {']] },
{ code: [['',' '],['tok-type','int'],['tok-op','[] nums = {'],['tok-num','10'],['tok-op',', '],['tok-num','20'],['tok-op',', '],['tok-num','30'],['tok-op','};']] },
{ code: [['',' '],['tok-type','int '],['tok-op','sum = '],['tok-num','0'],['tok-op',';']] },
{ code: [['',' '],['tok-kw','for '],['tok-op','('],['tok-type','int '],['tok-op','i = '],['tok-num','0'],['tok-op','; '],['tok-op','i < '],['tok-num','3'],['tok-op','; '],['tok-op','i++'],['tok-op',') {']] },
{ code: [['',' '],['tok-op','sum = sum + nums[i];']] },
{ code: [['',' '],['tok-op','}']] },
{ code: [['tok-op','}']] },
],
steps: [
{ line:0, stack:[{name:'main()',vars:[],active:true}],
expl:{label:'Program starts', text:'Java enters main() and pushes a frame onto the call stack.'} },
{ line:1, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:true,cls:true}],active:true}],
expl:{label:'Array created', text:'nums holds a reference to a 3-element array. We will visit each element using a loop.'} },
{ line:2, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'0',fresh:true,cls:false}],active:true}],
expl:{label:'Accumulator initialized', text:'sum starts at 0. Each loop iteration will read one element from nums and add it to sum.'} },
{ line:3, tokenRange:[3,5], stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'0',fresh:false,cls:false},{n:'i',v:'0',fresh:true,cls:false}],active:true}],
expl:{label:'Init', text:'int i = 0 creates the loop counter. i is set to 0. It will serve as the index into nums.'} },
{ line:3, tokenRange:[7,8], stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'0',fresh:false,cls:false},{n:'i',v:'0',fresh:false,cls:false}],active:true}],
expl:{label:'Condition: true', text:'Java checks i < 3. 0 < 3 is true -- first iteration begins.'} },
{ line:4, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'10',fresh:true,cls:false},{n:'i',v:'0',fresh:false,cls:false}],active:true}],
expl:{label:'Read index 0', text:'nums[i] is nums[0], which is 10. sum = 0 + 10 gives sum = 10.'} },
{ line:3, tokenRange:[10,10], stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'10',fresh:false,cls:false},{n:'i',v:'1',fresh:true,cls:false}],active:true}],
expl:{label:'Increment', text:'i++ runs. i goes from 0 to 1.'} },
{ line:3, tokenRange:[7,8], stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'10',fresh:false,cls:false},{n:'i',v:'1',fresh:false,cls:false}],active:true}],
expl:{label:'Condition: true', text:'Java checks i < 3. 1 < 3 is true -- next iteration.'} },
{ line:4, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'30',fresh:true,cls:false},{n:'i',v:'1',fresh:false,cls:false}],active:true}],
expl:{label:'Read index 1', text:'nums[1] is 20. sum = 10 + 20 gives sum = 30.'} },
{ line:3, tokenRange:[10,10], stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'30',fresh:false,cls:false},{n:'i',v:'2',fresh:true,cls:false}],active:true}],
expl:{label:'Increment', text:'i++ runs. i goes from 1 to 2.'} },
{ line:3, tokenRange:[7,8], stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'30',fresh:false,cls:false},{n:'i',v:'2',fresh:false,cls:false}],active:true}],
expl:{label:'Condition: true', text:'Java checks i < 3. 2 < 3 is true -- final iteration.'} },
{ line:4, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'60',fresh:true,cls:false},{n:'i',v:'2',fresh:false,cls:false}],active:true}],
expl:{label:'Read index 2', text:'nums[2] is 30. sum = 30 + 30 gives sum = 60. All elements have been visited.'} },
{ line:3, tokenRange:[10,10], stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'60',fresh:false,cls:false},{n:'i',v:'3',fresh:true,cls:false}],active:true}],
expl:{label:'Increment', text:'i++ runs. i goes from 2 to 3.'} },
{ line:3, tokenRange:[7,8], stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'60',fresh:false,cls:false},{n:'i',v:'3',fresh:false,cls:false}],active:true}],
expl:{label:'Condition: false', text:'Java checks i < 3. 3 < 3 is false. The loop exits and i goes out of scope.'} },
{ line:6, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:false,cls:true},{n:'sum',v:'60',fresh:false,cls:false}],active:true}],
expl:{label:'Program ends', text:'The loop visited every element once, using i as the index. The final value of sum is 60: 10 + 20 + 30.'} },
]
},
/* ------------------------------------------------------------------ */
/* 3. Update by index */
/* */
/* 0 static void main(String[] args) { */
/* 1 int[] nums = {10, 20, 30}; */
/* 2 nums[1] = 99; */
/* 3 } */
/* ------------------------------------------------------------------ */
{
label: 'Update by index',
lines: [
{ code: [['tok-kw','static '],['tok-kw','void '],['tok-meth','main'],['tok-op','(String[] args) {']] },
{ code: [['',' '],['tok-type','int'],['tok-op','[] nums = {'],['tok-num','10'],['tok-op',', '],['tok-num','20'],['tok-op',', '],['tok-num','30'],['tok-op','};']] },
{ code: [['',' '],['tok-op','nums['],['tok-num','1'],['tok-op','] = '],['tok-num','99'],['tok-op',';']] },
{ code: [['tok-op','}']] },
],
steps: [
{ line:0, stack:[{name:'main()',vars:[],active:true}],
expl:{label:'Program starts', text:'Java enters main().'} },
{ line:1, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:true,cls:true}],active:true}],
expl:{label:'Array created', text:'nums holds a reference to a 3-element array: [10, 20, 30].'} },
{ line:2, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 99, 30]',fresh:true,cls:true}],active:true}],
expl:{label:'Element updated', text:'nums[1] = 99 overwrites the element at index 1. The array goes from [10, 20, 30] to [10, 99, 30]. Index 0 and 2 are unchanged.'} },
{ line:3, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 99, 30]',fresh:false,cls:true}],active:true}],
expl:{label:'Program ends', text:'main() finishes. The array held [10, 99, 30] at the end.'} },
]
},
/* ------------------------------------------------------------------ */
/* 3. Remove by shifting */
/* */
/* 0 static void main(String[] args) { */
/* 1 int[] nums = {10, 20, 30}; */
/* 2 nums[1] = nums[2]; // shift left */
/* 3 nums[2] = 0; // clear last slot */
/* 4 } */
/* ------------------------------------------------------------------ */
{
label: 'Remove by shifting',
lines: [
{ code: [['tok-kw','static '],['tok-kw','void '],['tok-meth','main'],['tok-op','(String[] args) {']] },
{ code: [['',' '],['tok-type','int'],['tok-op','[] nums = {'],['tok-num','10'],['tok-op',', '],['tok-num','20'],['tok-op',', '],['tok-num','30'],['tok-op','};']] },
{ code: [['',' '],['tok-op','nums['],['tok-num','1'],['tok-op','] = nums['],['tok-num','2'],['tok-op','];'],['',' '],['tok-cmt','// shift left']] },
{ code: [['',' '],['tok-op','nums['],['tok-num','2'],['tok-op','] = '],['tok-num','0'],['tok-op',';'],['',' '],['tok-cmt','// clear last slot']] },
{ code: [['tok-op','}']] },
],
steps: [
{ line:0, stack:[{name:'main()',vars:[],active:true}],
expl:{label:'Program starts', text:'Java enters main(). We will "remove" the middle element by shifting elements down.'} },
{ line:1, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 20, 30]',fresh:true,cls:true}],active:true}],
expl:{label:'Array created', text:'nums is [10, 20, 30]. Arrays in Java have a fixed length -- we cannot shrink them. "Removing" an element means shifting values to fill the gap, then zeroing the tail.'} },
{ line:2, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 30, 30]',fresh:true,cls:true}],active:true}],
expl:{label:'Shift: overwrite index 1', text:'nums[1] = nums[2] reads the value at index 2 (30) and writes it over index 1. The old value 20 is gone. Both slots now hold 30.'} },
{ line:3, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 30, 0]',fresh:true,cls:true}],active:true}],
expl:{label:'Clear: zero the tail', text:'nums[2] = 0 resets the last slot to the default int value. The array is now [10, 30, 0] -- logically the element at index 1 has been removed.'} },
{ line:4, stack:[{name:'main()',vars:[{n:'nums',v:'[10, 30, 0]',fresh:false,cls:true}],active:true}],
expl:{label:'Program ends', text:'main() finishes. The array still has length 3 -- only its contents changed.'} },
]
},
/* ------------------------------------------------------------------ */
/* 4. Copy with a for loop */
/* */
/* 0 static void main(String[] args) { */
/* 1 int[] src = {1, 2, 3}; */
/* 2 int[] copy = new int[3]; */
/* 3 for (int i = 0; i < 3; i++) { */
/* 4 copy[i] = src[i]; */
/* 5 } */
/* 6 } */
/* ------------------------------------------------------------------ */
{
label: 'Copy with a loop',
lines: [
{ code: [['tok-kw','static '],['tok-kw','void '],['tok-meth','main'],['tok-op','(String[] args) {']] },
{ code: [['',' '],['tok-type','int'],['tok-op','[] src = {'],['tok-num','1'],['tok-op',', '],['tok-num','2'],['tok-op',', '],['tok-num','3'],['tok-op','};']] },
{ code: [['',' '],['tok-type','int'],['tok-op','[] copy = '],['tok-kw','new '],['tok-type','int'],['tok-op','['],['tok-num','3'],['tok-op','];']] },
{ code: [['',' '],['tok-kw','for '],['tok-op','('],['tok-type','int '],['tok-op','i = '],['tok-num','0'],['tok-op','; '],['tok-op','i < '],['tok-num','3'],['tok-op','; '],['tok-op','i++'],['tok-op',') {']] },
{ code: [['',' '],['tok-op','copy[i] = src[i];']] },
{ code: [['',' '],['tok-op','}']] },
{ code: [['tok-op','}']] },
],
steps: [
{ line:0, stack:[{name:'main()',vars:[],active:true}],
expl:{label:'Program starts', text:'Java enters main(). We will copy one array into a separate, independent array.'} },
{ line:1, stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:true,cls:true}],active:true}],
expl:{label:'Source array created', text:'src holds a reference to [1, 2, 3]. This is the array we want to copy from.'} },
{ line:2, stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[0, 0, 0]',fresh:true,cls:true}],active:true}],
expl:{label:'Destination array created', text:'new int[3] allocates a fresh 3-element array. Java automatically fills it with 0. copy is a separate array in memory -- not the same object as src.'} },
{ line:3, tokenRange:[3,5], stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[0, 0, 0]',fresh:false,cls:true},{n:'i',v:'0',fresh:true,cls:false}],active:true}],
expl:{label:'Init', text:'The initializer int i = 0 runs exactly once. i is created and set to 0.'} },
{ line:3, tokenRange:[7,8], stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[0, 0, 0]',fresh:false,cls:true},{n:'i',v:'0',fresh:false,cls:false}],active:true}],
expl:{label:'Condition: true', text:'Java checks i < 3. 0 < 3 is true -- first iteration begins.'} },
{ line:4, stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 0, 0]',fresh:true,cls:true},{n:'i',v:'0',fresh:false,cls:false}],active:true}],
expl:{label:'Copy index 0', text:'copy[0] = src[0] reads 1 from src and writes it to copy. copy is now [1, 0, 0].'} },
{ line:3, tokenRange:[10,10], stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 0, 0]',fresh:false,cls:true},{n:'i',v:'1',fresh:true,cls:false}],active:true}],
expl:{label:'Increment', text:'i++ runs. i goes from 0 to 1.'} },
{ line:3, tokenRange:[7,8], stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 0, 0]',fresh:false,cls:true},{n:'i',v:'1',fresh:false,cls:false}],active:true}],
expl:{label:'Condition: true', text:'Java checks i < 3. 1 < 3 is true -- next iteration.'} },
{ line:4, stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 2, 0]',fresh:true,cls:true},{n:'i',v:'1',fresh:false,cls:false}],active:true}],
expl:{label:'Copy index 1', text:'copy[1] = src[1] copies 2. copy is now [1, 2, 0].'} },
{ line:3, tokenRange:[10,10], stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 2, 0]',fresh:false,cls:true},{n:'i',v:'2',fresh:true,cls:false}],active:true}],
expl:{label:'Increment', text:'i++ runs. i goes from 1 to 2.'} },
{ line:3, tokenRange:[7,8], stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 2, 0]',fresh:false,cls:true},{n:'i',v:'2',fresh:false,cls:false}],active:true}],
expl:{label:'Condition: true', text:'Java checks i < 3. 2 < 3 is true -- final iteration.'} },
{ line:4, stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 2, 3]',fresh:true,cls:true},{n:'i',v:'2',fresh:false,cls:false}],active:true}],
expl:{label:'Copy index 2', text:'copy[2] = src[2] copies 3. All elements are now copied. copy is [1, 2, 3].'} },
{ line:3, tokenRange:[10,10], stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 2, 3]',fresh:false,cls:true},{n:'i',v:'3',fresh:true,cls:false}],active:true}],
expl:{label:'Increment', text:'i++ runs. i goes from 2 to 3.'} },
{ line:3, tokenRange:[7,8], stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 2, 3]',fresh:false,cls:true},{n:'i',v:'3',fresh:false,cls:false}],active:true}],
expl:{label:'Condition: false', text:'Java checks i < 3. 3 < 3 is false. The loop exits and i goes out of scope.'} },
{ line:6, stack:[{name:'main()',vars:[{n:'src',v:'[1, 2, 3]',fresh:false,cls:true},{n:'copy',v:'[1, 2, 3]',fresh:false,cls:true}],active:true}],
expl:{label:'Two separate arrays', text:'src and copy each hold a reference to a different array object. Changing one will not affect the other.'} },
]
},
]
});