public static void main(String[] args)
    {
        // initialize all data 
        try
        {
            // start reading the input txt file
            String  fname = "Assignment03.txt";
            Scanner scnr  = new Scanner(new File(fname));
            int numpatch  = scnr.nextInt();
            int numit     = scnr.nextInt();
            
            // create array of patches
            Patch[] patch = new Patch[numpatch];
            
            System.out.printf("%-5s %7s    %7s\n", "Id", "ePwr", "Reflect");
            System.out.println("========================");
            
            // loop over patches and gather info
            for(int i = 0; i < numpatch; i++)
            {
                // assign variables
                patch[i] = new Patch(scnr.nextInt(),      // patch id
                                     scnr.nextFloat(),    // emission pwr
                                     scnr.nextFloat(),    // reflectance
                                     scnr.nextInt()       // num vis patch
                                     );
                                       
                // loop over num visible patches
                for(int j = 0; j < patch[i].numVisPatch; j++)
                {
                    // update patch objects
                    patch[i].visIds[j]    = scnr.nextInt();
                    patch[i].formfacts[j] = scnr.nextFloat();
                }
                
                // print id, reflectance and emission power
                System.out.printf("[%3d] %7.2f %7.2f\n", patch[i].patchId,
                                                        patch[i].emissionPower,
                                                        patch[i].reflectance
                                                        );
            }
            
            // start main shooting algorithm
            // initialize unshot power
            float[] pwrVals = new float[numpatch];
            for(int i = 0; i < numpatch; i++)
            {
                patch[i].unshotPower = patch[i].emissionPower;
                patch[i].totalPower  = patch[i].unshotPower;
                pwrVals[i]           = patch[i].unshotPower;
            }
            
            // initialize indirect heap helper arrays
            int[] outof = new int[pwrVals.length];
            int[] into  = new int[pwrVals.length];
            for(int i = 0; i < outof.length; i++)
            {
                outof[i] = i;   // arrays of indices
                into[i]  = i;
            }
           
            // initialize indirect heap
            buildIndirectHeap(pwrVals, outof, into, pwrVals.length);
            
            // start iterative solution
            int converged = 0;
            while(converged != numit)
            {
                // find patch k with max unshot pwr in O(1)
                int k = getMaxPwrInd(outof);
                
                // shoot unshotPower to all adjacent patches
                for(int j = 0; j < patch[k].visIds.length; j++)
                {
                    int i = patch[k].visIds[j] - 1;
                    patch[i].totalPower  += patch[i].reflectance*
                                            patch[k].formfacts[j]*
                                            patch[k].unshotPower;
                                               
                    patch[i].unshotPower += patch[i].reflectance*
                                            patch[k].formfacts[j]*
                                            patch[k].unshotPower;
                                            
                    // restore heap property
                    increasePatchValue(pwrVals, into, outof, i, patch[i].unshotPower);
                }
                patch[k].unshotPower = 0;
                // restore heap property
                decreasePatchValue(pwrVals, into, outof, k, patch[k].unshotPower);
                converged++;
            }
            System.out.println("\n");
            System.out.printf("RESULTS AFTER %d ITERATIONS:\n", numit);
            System.out.printf("===========================\n");
            // print status after the iteration
            for(int i = 0; i < numpatch; i++)
            {
                System.out.printf("[%d] %f\n", 
                                  patch[i].patchId,
                                  patch[i].totalPower);
                printPatchInfo(patch[i]);
                System.out.println("\n");
            }
        }
        catch(Exception ioe)
        {
            System.out.println("Error: " + ioe.getMessage());
        }
    }