// Arup Guha
// 9/28/2026
// Practice with bitwise operators.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int numBitsOn(int block);
int cyclicLeftShift(int block);
int cyclicRightShift(int block);
int* encrypt(int* plain, int length, int key);

int main() {

    srand(time(0));

    for (int i=0; i<5; i++) {
        int val = (rand()<<17) + rand();
        //printf("%x %d %d\n", val, val, numBitsOn(val));
        int newval = cyclicLeftShift(val);
        int third = cyclicRightShift(val);
        printf("%x %x %x\n", val, newval, third);

    }

    int msg[20];
    for (int i=0; i<20; i++)
        msg[i] = (rand()<<17) + rand();

    int key = 123456789;

    int* cipher = encrypt(msg, 20, key);

    for (int i=0; i<20; i++) {
        printf("%x\n%x\n%x", msg[i], key, cipher[i]);
        printf("\n\n");
    }

    free(cipher);
    return 0;
}

// Returns the number of bits that are on in block.
int numBitsOn(int block) {

    int res = 0;
    for (int i=0; i<32; i++)
        if (block & (1<<i))
            res++;

    return res;
}

int cyclicLeftShift(int block) {

    // Since the right shift pulls 1s into the most signficant bits, I can get rid
    // of those by ANDing with 11111111.
    return (block<<8) + ( (block>>24) & ( (1<<8)-1)  );
}

int cyclicRightShift(int block) {

    // Since the right shift pulls 1s into the most signficant bits, I can get rid
    // of those by ANDing with 11111111.
    return (block<<24) + ( (block>>8) & ( (1<<24)-1)  );
}

int* encrypt(int* plain, int length, int key) {

    // Store answer here.
    int* cipher = calloc(length, sizeof(int));

    for (int i=0; i<length; i++) {
        cipher[i] = plain[i] ^ key;
        key = cyclicLeftShift(key);
    }

    return cipher;
}
