import java.util.Scanner;

/**
 * Details the intermediate steps of string folding (for hashing)
 * @author Hyrum D. Carroll (and OpenDSA Data Structures and Algorithms Modules Collection)
 * @version 0.1 (March 1, 2023)
 */
public class StringFoldingDemo{

    // Use folding on a string, summed 4 bytes at a time
    // Modified from: OpenDSA Data Structures and Algorithms Modules Collection, Section 15.3.2 (https://opendsa-server.cs.vt.edu/ODSA/Books/Everything/html/HashFuncExamp.html)
    public static int sfold(String s, int M) {
        long sum = 0;
        int mul = 1; // either 1, 256, 65636 or 16777216
        for (int i = 0; i < s.length(); i++) {
            mul = (i % 4 == 0) ? 1 : mul * 256;
            long shiftedWord = s.charAt(i) * mul;
            sum += shiftedWord;

            System.out.print("Shifting '"+s.charAt(i)+"' ");
            // display the ASCII value of the character in base-10 and has hexadecimal (base-16)
            System.out.print("(base-10: "+String.format("%3d", (int)s.charAt(i))+", 0x"+String.format("%02X", (int)s.charAt(i))+")");
            // display the multipler in base-10 and hexadecimal
            System.out.print(" by mul: " + String.format("%8d", mul) + " (0x"+String.format("%08X", mul)+")");
            // display the shifted word
            System.out.print(" to 0x"+String.format("%08X", shiftedWord));
            // display the sum
            System.out.println(" (sum: 0x" + String.format("%016X", sum)+")");

        }
        return (int)(Math.abs(sum) % M);
    }

    public static void main( String[] args ){
        Scanner stdin = new Scanner( System.in );
        System.out.print("Please enter a string to fold: ");
        sfold( stdin.nextLine(), 101 );
    }
}

/* Example output:
Please enter a string to fold: Hello, world
Shifting 'H' (base-10:  72, 0x48) by mul:        1 (0x00000001) to 0x00000048 (sum: 0x0000000000000048)
Shifting 'e' (base-10: 101, 0x65) by mul:      256 (0x00000100) to 0x00006500 (sum: 0x0000000000006548)
Shifting 'l' (base-10: 108, 0x6C) by mul:    65536 (0x00010000) to 0x006C0000 (sum: 0x00000000006C6548)
Shifting 'l' (base-10: 108, 0x6C) by mul: 16777216 (0x01000000) to 0x6C000000 (sum: 0x000000006C6C6548)
Shifting 'o' (base-10: 111, 0x6F) by mul:        1 (0x00000001) to 0x0000006F (sum: 0x000000006C6C65B7)
Shifting ',' (base-10:  44, 0x2C) by mul:      256 (0x00000100) to 0x00002C00 (sum: 0x000000006C6C91B7)
Shifting ' ' (base-10:  32, 0x20) by mul:    65536 (0x00010000) to 0x00200000 (sum: 0x000000006C8C91B7)
Shifting 'w' (base-10: 119, 0x77) by mul: 16777216 (0x01000000) to 0x77000000 (sum: 0x00000000E38C91B7)
Shifting 'o' (base-10: 111, 0x6F) by mul:        1 (0x00000001) to 0x0000006F (sum: 0x00000000E38C9226)
Shifting 'r' (base-10: 114, 0x72) by mul:      256 (0x00000100) to 0x00007200 (sum: 0x00000000E38D0426)
Shifting 'l' (base-10: 108, 0x6C) by mul:    65536 (0x00010000) to 0x006C0000 (sum: 0x00000000E3F90426)
Shifting 'd' (base-10: 100, 0x64) by mul: 16777216 (0x01000000) to 0x64000000 (sum: 0x0000000147F90426)
*/