Skip to content

Instantly share code, notes, and snippets.

@mudassaralichouhan
Last active December 19, 2024 20:12
Show Gist options
  • Save mudassaralichouhan/178bfd172f6745a53b4543275645d11e to your computer and use it in GitHub Desktop.
Save mudassaralichouhan/178bfd172f6745a53b4543275645d11e to your computer and use it in GitHub Desktop.
bool isEven(int n) {
return (n & 1) == 0;
}
/*
* Sieve of Eratosthenes: An efficient algorithm to find all prime numbers up to a given limit.
* Time complexity: O(n log(log n))
* Space complexity: O(n)
*/
#include <iostream>
#include <vector>
#include <cstdlib>
std::vector<bool> sieveOfEratosthenes(int n) {
std::vector<bool> primes(n + 1, true);
primes[0] = primes[1] = false;
for (int i = 2; i * i <= n; i++) {
if (primes[i]) {
for (int j = i * i; j <= n; j += i) {
primes[j] = false;
}
}
}
return primes;
}
bool isPrime(int number) {
if (number <= 1) return false;
for (int i = 2; i * i <= number; i++) {
if (number % i == 0) return false;
}
return true;
}
int main() {
{
int n = 100, i = 1, count = 0;
std::vector<bool> primes = sieveOfEratosthenes(n);
for (int i = 2; i <= primes.size(); i++) {
if (primes[i]) {
std::cout << i << ' ';
}
}
}
std::cout << std::endl;
{
int n = 100, count = 0, number = 2;
while (count < n) {
if (isPrime(number)) {
std::cout << number << " ";
count++;
}
number++;
}
}
std::cout << std::endl;
return EXIT_SUCCESS;
}
void swap(int &a, int &b) {
a ^= b;
b ^= a;
a ^= b;
}
@mudassaralichouhan
Copy link
Author

Certainly! Here's a structured outline for your Custom Image Editor project in C++. This structure includes classes, functions, and their relationships, which will help you organize your code effectively.

Project Structure

1. ImageEditor Class

  • Responsibilities: Manage image loading, saving, and application of bitwise operations.

  • Attributes:

    • imageData: A 2D array or vector holding pixel data (RGB values).
    • width, height: Dimensions of the image.
  • Methods:

    • loadImage(const std::string& filePath): Load image from file.
    • saveImage(const std::string& filePath): Save image to file.
    • applyXor(const Image& otherImage): Apply XOR operation with another image.
    • applyOr(const Image& otherImage): Apply OR operation with another image.
    • applyAnd(const Image& maskImage): Apply AND operation using a mask image.
    • applyNot(): Apply NOT operation to invert colors.
    • applyLeftShift(int shiftAmount): Apply left shift to adjust brightness.
    • applyRightShift(int shiftAmount): Apply right shift to adjust darkness.

2. Image Class

  • Responsibilities: Represent and manipulate image data.

  • Attributes:

    • pixels: A 1D or 2D array/vector of RGB values.
    • width, height: Dimensions of the image.
  • Methods:

    • getPixel(int x, int y): Get the RGB value of a specific pixel.
    • setPixel(int x, int y, uint32_t color): Set the RGB value of a specific pixel.
    • applyOperation(const std::function<uint32_t(uint32_t)>& operation): Apply a custom operation to all pixels.

3. ImageLoader Class

  • Responsibilities: Handle image file loading and saving.

  • Methods:

    • loadBMP(const std::string& filePath, Image& image): Load BMP file into Image object.
    • saveBMP(const std::string& filePath, const Image& image): Save Image object to BMP file.
    • loadPNG(const std::string& filePath, Image& image): Load PNG file into Image object (if applicable).
    • savePNG(const std::string& filePath, const Image& image): Save Image object to PNG file (if applicable).

4. BitwiseOperation Class

  • Responsibilities: Encapsulate bitwise operations that can be applied to images.

  • Methods:

    • xorOperation(uint32_t color1, uint32_t color2): Perform XOR operation on two colors.
    • orOperation(uint32_t color1, uint32_t color2): Perform OR operation on two colors.
    • andOperation(uint32_t color1, uint32_t color2): Perform AND operation on two colors.
    • notOperation(uint32_t color): Perform NOT operation on a color.
    • leftShiftOperation(uint32_t color, int shiftAmount): Perform left shift operation on a color.
    • rightShiftOperation(uint32_t color, int shiftAmount): Perform right shift operation on a color.

5. Main Driver (main.cpp)

  • Responsibilities: Handle user input and interact with the ImageEditor class to perform actions.

  • Methods:

    • main(): Entry point of the application.
      • Tasks:
        • Parse command-line arguments or GUI input for file paths and operations.
        • Create instances of ImageEditor, ImageLoader, and BitwiseOperation.
        • Load images using ImageLoader.
        • Apply bitwise operations using ImageEditor.
        • Save the processed images using ImageLoader.
        • Display results or errors to the user.

Example Class Diagram

+------------------+
|   ImageEditor    |
+------------------+
| - imageData      |
| - width          |
| - height         |
+------------------+
| + loadImage()    |
| + saveImage()    |
| + applyXor()     |
| + applyOr()      |
| + applyAnd()     |
| + applyNot()     |
| + applyLeftShift()|
| + applyRightShift()|
+------------------+

+------------------+
|    Image         |
+------------------+
| - pixels         |
| - width          |
| - height         |
+------------------+
| + getPixel()     |
| + setPixel()     |
| + applyOperation()|
+------------------+

+------------------+
| ImageLoader      |
+------------------+
| + loadBMP()      |
| + saveBMP()      |
| + loadPNG()      |
| + savePNG()      |
+------------------+

+------------------+
| BitwiseOperation |
+------------------+
| + xorOperation() |
| + orOperation()  |
| + andOperation() |
| + notOperation() |
| + leftShiftOperation()|
| + rightShiftOperation()|
+------------------+

+------------------+
| main()           |
+------------------+
| + main()         |
+------------------+

This structure should give you a good starting point for organizing your project. You can adjust and expand upon this structure as needed based on your specific requirements and design choices.

@mudassaralichouhan
Copy link
Author

Certainly! Here's another project idea where bitwise operators are essential: A Custom Data Compression Tool. This project involves creating a tool that compresses and decompresses data using bitwise operations to encode and decode information efficiently.

Project: Custom Data Compression Tool

Project Overview

Develop a data compression tool that utilizes bitwise operations to encode and decode data. You’ll implement basic compression algorithms such as Run-Length Encoding (RLE) or a simple version of Huffman coding. The tool will read data from a file, compress it, and save the compressed data to another file. It will also support decompression of compressed data.

Features and Bitwise Operator Usage

  1. Bitwise XOR (^):

    • Simple Obfuscation: Apply XOR to obfuscate data as a simple form of encryption.
    • Example: XOR each byte of the data with a key byte to make the data less readable.
  2. Bitwise OR (|):

    • Combine Flags: Combine multiple binary flags into a single byte or integer for efficient storage.
    • Example: Use OR to combine several single-bit flags into a byte for a header or metadata.
  3. Bitwise AND (&):

    • Bit Masking: Extract specific bits from data or filter out unwanted bits.
    • Example: Use AND to isolate bits of interest from a byte or integer, such as extracting certain fields from compressed data.
  4. Bitwise NOT (~):

    • Bit Inversion: Invert bits for certain compression techniques or checksums.
    • Example: Use NOT to invert bits for error detection or to create a simple checksum.
  5. Bitwise Left Shift (<<):

    • Bit Packing: Pack multiple smaller data elements into a larger data element.
    • Example: Shift bits to the left to align data for compression or to create packed data formats.
  6. Bitwise Right Shift (>>):

    • Bit Unpacking: Extract smaller data elements from a larger data element.
    • Example: Shift bits to the right to decode data from a packed format or to retrieve original values from compressed data.

Implementation Steps

  1. Data Representation:

    • Use byte arrays or vectors to hold raw data. Each byte can be treated as 8 bits for compression and decompression.
  2. Compression Algorithms:

    • Run-Length Encoding (RLE):
      • Encode sequences of repeating bytes by storing the byte and the count of its repetitions.
      • Use bitwise operations to efficiently store and retrieve counts.
    • Simple Huffman Coding (optional):
      • Build a Huffman tree and use bitwise operations to encode and decode variable-length codes.
      • Use OR, AND, and shifting to pack and unpack Huffman codes.
  3. Compression and Decompression Functions:

    • Implement functions for compressing and decompressing data using the chosen algorithm(s).
  4. File I/O:

    • Implement functionality to read data from a file, compress it, save the compressed data, and vice versa.
  5. User Interface:

    • Build a simple command-line or graphical user interface (GUI) for users to load files, choose compression/decompression options, and save results.
  6. Testing and Optimization:

    • Test the tool with various data files to ensure correct compression and decompression.
    • Optimize the algorithm and code for performance and efficiency.

Example Class Structure

1. DataCompressor Class

  • Responsibilities: Handle the compression and decompression of data.

  • Attributes:

    • data: Byte array or vector holding the raw data.
  • Methods:

    • compress(const std::vector<uint8_t>& inputData): Compress data using the chosen algorithm.
    • decompress(const std::vector<uint8_t>& compressedData): Decompress data using the chosen algorithm.

2. CompressionAlgorithm Class

  • Responsibilities: Encapsulate specific compression algorithms.

  • Attributes:

    • compressedData: Data after compression.
  • Methods:

    • applyRLE(const std::vector<uint8_t>& inputData): Apply Run-Length Encoding.
    • applyHuffmanCoding(const std::vector<uint8_t>& inputData): Apply Huffman Coding (if implemented).

3. FileHandler Class

  • Responsibilities: Handle file operations for reading and writing compressed data.

  • Methods:

    • readFile(const std::string& filePath): Read data from a file.
    • writeFile(const std::string& filePath, const std::vector<uint8_t>& data): Write data to a file.

4. Main Driver (main.cpp)

  • Responsibilities: Provide the entry point and handle user interaction.

  • Methods:

    • main(): Entry point of the application.
      • Tasks:
        • Parse command-line arguments or GUI input for file paths and operation modes.
        • Create instances of DataCompressor, CompressionAlgorithm, and FileHandler.
        • Read input data from files using FileHandler.
        • Compress or decompress data using DataCompressor and CompressionAlgorithm.
        • Save processed data using FileHandler.
        • Display results or errors to the user.

Example Class Diagram

+------------------+
|  DataCompressor  |
+------------------+
| - data           |
+------------------+
| + compress()     |
| + decompress()   |
+------------------+

+------------------+
| CompressionAlgorithm |
+------------------+
| - compressedData |
+------------------+
| + applyRLE()     |
| + applyHuffmanCoding() |
+------------------+

+------------------+
|    FileHandler   |
+------------------+
| + readFile()     |
| + writeFile()    |
+------------------+

+------------------+
| main()           |
+------------------+
| + main()         |
+------------------+

This project provides practical experience with bitwise operations in a data compression context, allowing you to understand how these operations can be applied to optimize data storage and manipulation.

@mudassaralichouhan
Copy link
Author

Certainly! A more complex project involving bitwise operations could be a Custom File System Implementation. This project involves designing and implementing a basic file system that operates on a virtual disk, managing file storage, directories, and metadata.

Project: Custom File System

Project Overview

Create a custom file system that operates on a simulated virtual disk. This file system will support basic operations such as creating, reading, writing, and deleting files, as well as managing directories. Bitwise operations will be used extensively for managing file metadata, permissions, and file allocation.

Features and Bitwise Operator Usage

  1. Bitwise XOR (^):

    • Error Detection: Implement simple error detection mechanisms such as checksums.
    • Example: XOR data blocks or metadata to create a checksum for detecting data corruption.
  2. Bitwise OR (|):

    • Permission Flags: Combine multiple permission flags for files and directories.
    • Example: Use OR to combine read, write, and execute permissions into a single integer flag.
  3. Bitwise AND (&):

    • Permission Checking: Check for specific permissions by masking bits.
    • Example: Use AND to determine if a file has a specific permission by masking the permission bits.
  4. Bitwise NOT (~):

    • Permission Inversion: Invert permissions or flags for specific operations.
    • Example: Use NOT to disable all permissions and then selectively enable certain ones.
  5. Bitwise Left Shift (<<):

    • File Allocation: Encode file sizes or metadata in a compact format.
    • Example: Use left shift to create space-efficient representations of file sizes or block indices.
  6. Bitwise Right Shift (>>):

    • File Indexing: Retrieve specific parts of metadata or data blocks.
    • Example: Use right shift to decode file indices or to retrieve specific fields from metadata.

Implementation Steps

  1. Virtual Disk Representation:

    • Use a large byte array or file to simulate the virtual disk where all files and metadata will be stored.
  2. File System Metadata:

    • Superblock: Contains information about the file system, such as total disk size, number of blocks, and pointers to the root directory.
    • Inodes: Store metadata for each file (e.g., size, permissions, block pointers).
    • Directory Entries: Map file names to inode numbers.
  3. File Allocation:

    • Implement a mechanism to allocate and deallocate blocks on the virtual disk.
    • Use bitwise operations to manage free block lists or bitmaps.
  4. Permission Management:

    • Use bitwise operations to manage and check file and directory permissions.
    • Implement functionality to set and check permissions.
  5. File Operations:

    • Create File: Allocate space, create an inode, and update directory entries.
    • Read/Write File: Read from or write to file blocks using the allocated inode information.
    • Delete File: Deallocate blocks, remove the inode, and update directory entries.
  6. Directory Management:

    • Implement functionality to create and manage directories.
    • Support directory listings and path resolution.
  7. File System Commands:

    • Provide command-line or GUI commands for interacting with the file system (e.g., create, delete, read, write, list).
  8. Error Handling and Testing:

    • Implement error handling for file system operations and test with various scenarios to ensure robustness.

Example Class Structure

1. FileSystem Class

  • Responsibilities: Manage the overall file system operations.

  • Attributes:

    • virtualDisk: Byte array or file representing the virtual disk.
    • superblock: Metadata about the file system.
  • Methods:

    • createFile(const std::string& fileName, const std::vector<uint8_t>& data): Create a new file with the specified data.
    • readFile(const std::string& fileName, std::vector<uint8_t>& data): Read data from a file.
    • writeFile(const std::string& fileName, const std::vector<uint8_t>& data): Write data to a file.
    • deleteFile(const std::string& fileName): Delete a file from the file system.
    • createDirectory(const std::string& dirName): Create a new directory.
    • listDirectory(const std::string& dirName, std::vector<std::string>& files): List files in a directory.

2. Inode Class

  • Responsibilities: Represent and manage file metadata.

  • Attributes:

    • fileSize: Size of the file.
    • permissions: Permissions for the file.
    • blockPointers: Pointers to data blocks on the virtual disk.
  • Methods:

    • setPermissions(uint8_t permFlags): Set permissions using bitwise operations.
    • getPermissions(): Get permissions and check them using bitwise operations.
    • allocateBlocks(int numBlocks): Allocate data blocks for the file.

3. DirectoryEntry Class

  • Responsibilities: Represent a file or directory entry in a directory.

  • Attributes:

    • fileName: Name of the file or directory.
    • inodeNumber: Associated inode number.
  • Methods:

    • createEntry(const std::string& name, int inode): Create a new directory entry.
    • removeEntry(const std::string& name): Remove an entry from the directory.

4. VirtualDisk Class

  • Responsibilities: Handle operations on the virtual disk.

  • Attributes:

    • diskData: Byte array or file data.
  • Methods:

    • readBlock(int blockNumber, std::vector<uint8_t>& buffer): Read a block from the virtual disk.
    • writeBlock(int blockNumber, const std::vector<uint8_t>& buffer): Write a block to the virtual disk.
    • allocateBlock(): Find and allocate a free block.
    • deallocateBlock(int blockNumber): Free up a block.

5. Main Driver (main.cpp)

  • Responsibilities: Provide the entry point and handle user interactions.

  • Methods:

    • main(): Entry point of the application.
      • Tasks:
        • Parse command-line arguments or GUI input for file system operations.
        • Create instances of FileSystem, VirtualDisk, and other necessary classes.
        • Handle user commands for creating, reading, writing, and deleting files and directories.
        • Display results or errors to the user.

Example Class Diagram

+------------------+
|   FileSystem     |
+------------------+
| - virtualDisk    |
| - superblock     |
+------------------+
| + createFile()   |
| + readFile()     |
| + writeFile()    |
| + deleteFile()   |
| + createDirectory()|
| + listDirectory()|
+------------------+

+------------------+
|      Inode        |
+------------------+
| - fileSize       |
| - permissions    |
| - blockPointers  |
+------------------+
| + setPermissions()|
| + getPermissions()|
| + allocateBlocks()|
+------------------+

+------------------+
|  DirectoryEntry  |
+------------------+
| - fileName       |
| - inodeNumber    |
+------------------+
| + createEntry()  |
| + removeEntry()  |
+------------------+

+------------------+
|  VirtualDisk     |
+------------------+
| - diskData       |
+------------------+
| + readBlock()    |
| + writeBlock()   |
| + allocateBlock()|
| + deallocateBlock()|
+------------------+

+------------------+
| main()           |
+------------------+
| + main()         |
+------------------+

Key Points

  • Complexity: This project involves managing file and directory structures, file allocation, and permissions, which provides a deep understanding of how file systems operate.
  • Bitwise Operations: Essential for managing file metadata, permissions, and space allocation efficiently.
  • Scalability: You can extend this project by adding more features such as journaling, file compression, or advanced permissions.

This project will give you hands-on experience with complex systems programming and a deeper understanding of file systems, memory management, and data handling.

@mudassaralichouhan
Copy link
Author

Project: "Binary Image Steganography"

Objective:
Create a program that hides a secret message within an image using bitwise operations.

Description:
Steganography is the practice of hiding secret information within a non-secret message, image, or other medium. In this project, you will create a program that takes a binary image (e.g., a black and white image) and a secret message as input. The program will then use bitwise operations to hide the secret message within the image.

Requirements:

  1. The program should take a binary image as input (e.g., a 2D array of 0s and 1s).
  2. The program should take a secret message as input (e.g., a string of characters).
  3. The program should use bitwise XOR (^) to encrypt the secret message.
  4. The program should use bitwise OR (|) to combine the encrypted message with the image pixels.
  5. The program should use bitwise AND (&) to extract the hidden message from the modified image.
  6. The program should use bitwise NOT (~) to invert the image pixels (optional).
  7. The program should use bitwise left shift (<<) and right shift (>>) to manipulate the bits of the image pixels and the secret message.

Implementation:

  1. Read the Binary Image:

    • Load the binary image into a 2D array where each element is either 0 or 1.
  2. Convert the Secret Message:

    • Convert the secret message into a binary string (e.g., using ASCII codes).
  3. Encrypt the Secret Message:

    • Use bitwise XOR (^) to encrypt the secret message with a key (e.g., a random number).
  4. Embed the Encrypted Message:

    • Iterate through the image pixels and use bitwise OR (|) to combine the encrypted message with the pixel values.
  5. Extract the Hidden Message:

    • To extract the hidden message, iterate through the modified image pixels and use bitwise AND (&) to retrieve the encrypted message.
  6. Decrypt the Hidden Message:

    • Decrypt the extracted message using bitwise XOR (^) with the same key used in the encryption step.
  7. Optional - Invert Image Pixels:

    • Use bitwise NOT (~) to invert the image pixels, creating a visually appealing effect.
  8. Manipulate Bits:

    • Use bitwise left shift (<<) and right shift (>>) to manipulate the bits of the image pixels and the secret message as needed.

    Here's the code with the comments for the "Binary Image Steganography" project, utilizing all 6 bitwise operators in C++:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

// Function to encrypt the secret message using bitwise XOR
string encryptMessage(const string& message, int key) {
    string encryptedMessage;
    for (char c : message) {
        encryptedMessage += (c ^ key);
    }
    return encryptedMessage;
}

// Function to hide the encrypted message within the image
void hideMessage(vector<vector<int>>& image, const string& encryptedMessage) {
    int messageIndex = 0;
    for (int i = 0; i < image.size(); i++) {
        for (int j = 0; j < image[0].size(); j++) {
            // Use bitwise OR to combine the encrypted message with the image pixels
            image[i][j] |= (encryptedMessage[messageIndex++] << 1);
            if (messageIndex >= encryptedMessage.size()) return; // Ensure we don't go out of bounds
        }
    }
}

// Function to extract the hidden message from the modified image
string extractMessage(const vector<vector<int>>& image) {
    string extractedMessage;
    string tempMessage;
    
    for (int i = 0; i < image.size(); i++) {
        for (int j = 0; j < image[0].size(); j++) {
            // Use bitwise AND to extract the hidden bits from the image
            tempMessage += (image[i][j] & 1);
        }
    }

    // Convert the extracted bits back to characters
    for (size_t i = 0; i < tempMessage.size(); i += 8) {
        char byte = 0;
        for (int bit = 0; bit < 8; ++bit) {
            byte |= ((tempMessage[i + bit] - '0') << (7 - bit));
        }
        extractedMessage += byte;
    }
    
    return extractedMessage;
}

int main() {
    // Input image and secret message
    vector<vector<int>> image = {{0, 1, 0, 1}, {1, 0, 1, 0}, {0, 1, 0, 1}, {1, 0, 1, 0}};
    string message = "Hello, World!";

    // Encrypt the secret message
    int key = 123;
    string encryptedMessage = encryptMessage(message, key);

    // Hide the encrypted message within the image
    hideMessage(image, encryptedMessage);

    // Extract the hidden message from the modified image
    string extractedMessage = extractMessage(image);

    // Decrypt the extracted message
    string decryptedMessage = encryptMessage(extractedMessage, key);

    cout << "Original Message: " << message << endl;
    cout << "Decrypted Message: " << decryptedMessage << endl;

    return 0;
}

Summary of Bitwise Operators Used:

  1. Bitwise XOR (^): Used for encrypting and decrypting the secret message.
  2. Bitwise OR (|): Used to combine the encrypted message with the image pixels.
  3. Bitwise AND (&): Used to extract the hidden message from the modified image.
  4. Bitwise NOT (~): Optional; can be used to invert the image pixels (not shown in this example).
  5. Bitwise Left Shift (<<): Used to manipulate the position of bits in the encrypted message when hiding it in the image.
  6. Bitwise Right Shift (>>) (not explicitly used in this example): Can be used for manipulating bits if needed.

@mudassaralichouhan
Copy link
Author

@mudassaralichouhan
Copy link
Author

Sure! I'd be happy to provide detailed information on both the Blockchain Prototype and the Maze Solver Visualization projects. Below, I'll break down each project, explain how the data structures are utilized, and provide implementation details to help you get started.


1. Blockchain Prototype

Project Overview

  • Objective: Build a simplified blockchain model where each block is a node in a linked list.
  • Key Data Structures:
    • Linked List: To chain the blocks together, forming the blockchain.
    • Stack: To manage a pool of pending transactions.
    • Merkle Tree: To efficiently store and verify transactions within a block.

Understanding the Components

a. Blockchain as a Linked List

  • Blocks: Each block contains data, a timestamp, a nonce (for mining), a hash of its contents, and the hash of the previous block.
  • Chaining Blocks: The blockchain is essentially a linked list where each block points to the previous block via the previous hash.
  • Genesis Block: The first block in the chain, which has no previous hash.

b. Transaction Pool as a Stack

  • Transaction Pool: A stack where new transactions are added (pushed) to the top.
  • Mining Process: Transactions are popped from the stack when creating a new block.
  • LIFO Behavior: Ensures that the most recent transactions are prioritized.

c. Merkle Trees for Transaction Verification

  • Merkle Tree Structure: A binary tree where each leaf node is a hash of a transaction, and non-leaf nodes are hashes of their child nodes.
  • Root Hash: The topmost hash that represents all transactions in the block.
  • Verification: Efficiently verify the presence of a transaction without storing all transaction data.

Implementation Details

1. Define the Block Structure

class Block:
    def __init__(self, index, timestamp, transactions_root, previous_hash, nonce=0):
        self.index = index
        self.timestamp = timestamp
        self.transactions_root = transactions_root
        self.previous_hash = previous_hash
        self.nonce = nonce
        self.hash = self.compute_hash()

    def compute_hash(self):
        # Combine the block's contents and hash them
        block_string = f"{self.index}{self.timestamp}{self.transactions_root}{self.previous_hash}{self.nonce}"
        return hashlib.sha256(block_string.encode()).hexdigest()

2. Implement the Linked List (Blockchain)

class Blockchain:
    def __init__(self):
        self.chain = []
        self.create_genesis_block()

    def create_genesis_block(self):
        genesis_block = Block(0, datetime.now(), "0", "0")
        self.chain.append(genesis_block)

    def add_block(self, new_block):
        new_block.previous_hash = self.chain[-1].hash
        new_block.hash = new_block.compute_hash()
        self.chain.append(new_block)

3. Transaction Pool Using Stack

class TransactionPool:
    def __init__(self):
        self.stack = []

    def add_transaction(self, transaction):
        self.stack.append(transaction)

    def get_transactions(self, num_transactions):
        transactions = []
        for _ in range(num_transactions):
            if self.stack:
                transactions.append(self.stack.pop())
            else:
                break
        return transactions

4. Implement the Merkle Tree

class MerkleTree:
    def __init__(self, transactions):
        self.transactions = transactions
        self.root = self.build_merkle_tree(transactions)

    def build_merkle_tree(self, transactions):
        # Base case
        if len(transactions) == 1:
            return hashlib.sha256(transactions[0].encode()).hexdigest()

        # Recursive case
        new_level = []
        for i in range(0, len(transactions), 2):
            left = transactions[i]
            right = transactions[i + 1] if i + 1 < len(transactions) else transactions[i]
            combined_hash = hashlib.sha256((left + right).encode()).hexdigest()
            new_level.append(combined_hash)
        return self.build_merkle_tree(new_level)

5. Block Creation and Mining

def mine_block(blockchain, transaction_pool):
    index = len(blockchain.chain)
    timestamp = datetime.now()
    transactions = transaction_pool.get_transactions(5)  # Get 5 transactions
    merkle_tree = MerkleTree(transactions)
    transactions_root = merkle_tree.root
    previous_hash = blockchain.chain[-1].hash

    new_block = Block(index, timestamp, transactions_root, previous_hash)
    blockchain.add_block(new_block)

Additional Considerations

  • Hashing and Security: Use cryptographic hashing functions like SHA-256.
  • Proof-of-Work: Implement a simple PoW algorithm by finding a nonce that results in a hash with a certain number of leading zeros.
  • Validation: Ensure that each block's previous_hash matches the hash of the previous block.

Extensions

  • User Interface: Create a simple CLI or GUI to interact with the blockchain.
  • Network Simulation: Simulate multiple nodes adding blocks to the blockchain.
  • Consensus Mechanism: Implement basic consensus algorithms to handle forks.

2. Maze Solver Visualization

Project Overview

  • Objective: Implement a maze-solving algorithm (DFS or BFS) and visualize the pathfinding process.
  • Key Data Structures:
    • 2D Array or Linked List: To represent the maze grid.
    • Stack (for DFS) or Queue (for BFS): To keep track of the nodes to visit.

Understanding the Components

a. Maze Representation

  • Grid-Based Maze: Represent the maze as a 2D grid where cells can be walls or paths.
  • Cells:
    • 0: Open path.
    • 1: Wall or obstacle.

b. Pathfinding Algorithms

  • Depth-First Search (DFS):
    • Explores as far as possible along each branch before backtracking.
    • Uses a stack to keep track of the path.
  • Breadth-First Search (BFS):
    • Explores all neighbors at the current depth before moving to the next level.
    • Uses a queue and is guaranteed to find the shortest path in an unweighted maze.

c. Visualization

  • Real-Time Updates: Show the algorithm's progress as it explores the maze.
  • Color Coding:
    • Unvisited Cells: Default color (e.g., white).
    • Visited Cells: Marked with a different color (e.g., blue).
    • Current Path: Highlighted (e.g., green).
    • Solution Path: Final path from start to finish (e.g., red).

Implementation Details

1. Maze Grid Creation

  • Static Maze: Use a predefined maze for simplicity.
  • Random Maze Generation (Optional): Implement algorithms like Recursive Division or Prim's Algorithm.
maze = [
    [0, 1, 0, 0, 0],
    [0, 1, 0, 1, 0],
    [0, 0, 0, 1, 0],
    [1, 1, 0, 0, 0],
]

2. Implement DFS Algorithm Using a Stack

def dfs(maze, start, end):
    stack = [start]
    visited = set()
    parent = {}

    while stack:
        current = stack.pop()
        if current == end:
            break
        visited.add(current)
        neighbors = get_neighbors(maze, current)
        for neighbor in neighbors:
            if neighbor not in visited and neighbor not in stack:
                stack.append(neighbor)
                parent[neighbor] = current
                visualize_step(maze, current, neighbor)  # Visualization function

    return reconstruct_path(parent, start, end)

3. Implement BFS Algorithm Using a Queue

def bfs(maze, start, end):
    queue = deque([start])
    visited = set()
    parent = {}

    while queue:
        current = queue.popleft()
        if current == end:
            break
        visited.add(current)
        neighbors = get_neighbors(maze, current)
        for neighbor in neighbors:
            if neighbor not in visited and neighbor not in queue:
                queue.append(neighbor)
                parent[neighbor] = current
                visualize_step(maze, current, neighbor)  # Visualization function

    return reconstruct_path(parent, start, end)

4. Neighbor Retrieval Function

def get_neighbors(maze, position):
    rows, cols = len(maze), len(maze[0])
    row, col = position
    neighbors = []
    for delta_row, delta_col in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
        new_row, new_col = row + delta_row, col + delta_col
        if 0 <= new_row < rows and 0 <= new_col < cols:
            if maze[new_row][new_col] == 0:
                neighbors.append((new_row, new_col))
    return neighbors

5. Path Reconstruction

def reconstruct_path(parent, start, end):
    path = [end]
    while path[-1] != start:
        path.append(parent[path[-1]])
    path.reverse()
    return path

6. Visualization

  • Using Libraries: Libraries like matplotlib, pygame, or tkinter can be used for visualization.
  • Visualization Function:
def visualize_step(maze, current, neighbor):
    # Update the display to show the current cell and neighbor
    # Implement a short delay to visualize the process
    time.sleep(0.1)
    draw_maze(maze, current, neighbor)
  • Drawing the Maze:
def draw_maze(maze, current=None, neighbor=None, path=None):
    for row in range(len(maze)):
        for col in range(len(maze[0])):
            cell = maze[row][col]
            # Determine the color based on the cell state
            # Draw the cell using the chosen library

Additional Considerations

  • Handling Large Mazes: Optimize visualization updates to handle larger mazes without significant lag.
  • User Interaction:
    • Start/Stop/Pause: Allow users to control the simulation.
    • Maze Editing: Enable users to design their own mazes.
  • Algorithm Selection: Provide options to switch between DFS and BFS.

Extensions

  • Heuristic Search (A* Algorithm):
    • Implement A* for faster pathfinding using heuristics.
  • 3D Mazes:
    • Extend the project to handle three-dimensional mazes.
  • Mobile App:
    • Develop the project as a mobile application for interactive learning.

Next Steps

  1. Choose a Programming Language:

    • Python: Excellent for rapid development and has rich libraries for GUI (tkinter, pygame) and cryptography (hashlib).
    • Java: Offers strong object-oriented features and GUI capabilities with Swing or JavaFX.
    • C++: Provides fine-grained control over memory and performance.
  2. Set Up the Development Environment:

    • Install necessary tools and libraries.
    • Set up version control with Git.
  3. Plan the Project Structure:

    • Break down the project into modules (e.g., data structures, algorithms, visualization).
    • Define classes and interfaces.
  4. Implement Incrementally:

    • Start with core functionalities.
    • Test each component thoroughly before moving on.
  5. Documentation and Testing:

    • Write clear documentation for your code.
    • Implement unit tests to ensure reliability.
  6. Seek Feedback:

    • Share your progress with peers or mentors.
    • Participate in forums or communities related to your project.

Additional Resources

  • Blockchain Resources:

  • Maze Solver Resources:

    • Red Blob Games: In-depth guides on pathfinding algorithms.
    • Mazegen: A maze generator and solver in Python.

Feel free to ask if you need more specific code examples, explanations on certain parts, or guidance on how to proceed with any aspect of these projects. Good luck with your implementation!

@mudassaralichouhan
Copy link
Author

function findMatchingWords(words, pattern) {
    // Convert the pattern to a regular expression
    // Replace '?' with '.' (matches any single character)
    // Replace '_' with '.' (matches any single character)
    const regexPattern = pattern.replace(/\?/g, '.').replace(/_/g, '.');
    const regex = new RegExp(`^${regexPattern}$`); // Anchors the regex to match the whole word

    // Filter the words that match the regex
    return words.filter(word => regex.test(word));
}

// Example usage
const wordsList = ['cat', 'bat', 'hat', 'heat', 'helt', 'help', 'hell', 'he'll', 'heatwave'];
const pattern1 = '?at'; // Matches 'cat', 'bat', 'hat'
const pattern2 = 'he_l'; // Matches 'help', 'hell'

const matches1 = findMatchingWords(wordsList, pattern1);
const matches2 = findMatchingWords(wordsList, pattern2);

console.log(`Matches for '${pattern1}':`, matches1);
console.log(`Matches for '${pattern2}':`, matches2);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment