Programming thread

  • 🐕 I am attempting to get the site runnning as fast as possible. If you are experiencing slow page load times, please report it.
After looking through the programming challenges from /g/ (can be found here) I decided to do the ROT-13 challenge in C and Python. ROT-13 is a cipher which changes each letter with the 13th letter after it in the Latin alphabet. Here is each implementation:
Python:
text = input("Enter the string you want to encrypt: ")
ascii_num = 0
encrypted_string = ""

for char in text:
    if char.isupper() == True:
        ascii_num = ord(char) + 13
        if ascii_num > 90:
            ascii_num -= 26
        encrypted_string += chr(ascii_num)
    elif char.islower() == True:
        ascii_num = ord(char) + 13
        if ascii_num > 122:
            ascii_num -= 32
        encrypted_string += chr(ascii_num)
print("The text is",text)
print("The encrypted string is",encrypted_string)
C:
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main() {
    char text[] = "Cake";
    char encrypted_str[10];
    int len = strlen(text);
    int ascii_num;
    int i;
  
    for(i = 0; i < len; i++) {
        if (isupper(text[i])) {
            ascii_num = text[i];
            ascii_num += 13;
            if (ascii_num > 90)
                ascii_num -= 26;
            char temp[2] = {(char)ascii_num, '\0'};
            strcat(encrypted_str, temp);
        }
        else if (islower(text[i])) {
            ascii_num = text[i];
            ascii_num += 13;
            if (ascii_num > 122)
                ascii_num -= 32;
            char temp[2] = {(char)ascii_num, '\0'};
            strcat(encrypted_str, temp);
        }
    }
  
    printf("The encrypted string is %s",encrypted_str);
    return 0;
}
Feedback on the code is apprciated.
 
printf("The encrypted string is %s",encrypted_str);
Don't forget the \n at the end.

The trick for ROT13 is to stick it through a substitution array. Something like this:

C:
void rot13(char* s) {
    static const char subst[] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 
        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 
        48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 
        64, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 65, 66, 
        67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 91, 92, 93, 94, 95, 
        96, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 97, 98, 
        99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 123, 124, 125, 126, 127, 
        128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 
        144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 
        160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 
        176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 
        192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 
        208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 
        224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 
        240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
    };
    
    while (*s) {
        *s = subst[*s];
        s++;
    }
}
 
strcat(encrypted_str, temp);
You never initialize encrypted_str so it will most likely be full of garbage and the C string functions won't work properly.
Besides which, you don't need to use them, you can just write characters directly to encrypted_str since you know exactly how long the output string is and what characters go where. (Don't forget to null-terminate)
 
Skull Gun is on point with substitution, so I'll be picky with what you've written.

use uint8_t instead of int for ascii, you know the range for that value and want to constrain it to something logical (within 128 for basic ascii) , and you can initialise iterator in the for loop e.g: for( int i = 0; i < len; i++) .

Lastly, for both solutions, you have duplicated code between the upper and lower cases but the only part that changes is the applied offset value of either 32 or 26 and the appropriate check. You could just change those values out with by checking the case of the the letter as the first thing in the loop.
 
Don't forget the \n at the end.

The trick for ROT13 is to stick it through a substitution array. Something like this:

C:
void rot13(char* s) {
    static const char subst[] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
        48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
        64, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 65, 66,
        67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 91, 92, 93, 94, 95,
        96, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 97, 98,
        99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 123, 124, 125, 126, 127,
        128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
        144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
        160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
        176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
        192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
        208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
        224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
        240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
    };
  
    while (*s) {
        *s = subst[*s];
        s++;
    }
}
Good advice. You can find a lot of tables like this in a large number of crypto and hashing libs. This reminds me of a CRC32 thing I wrote back before KiwiBomb progress stalled.
C:
static const u32 crc32Table[] = {
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

u32 checksum(u8 *data, uint size)
{
    u32 crc = 0xffffffff;
    for (uint i = 0; i < size; i++)
        crc = (crc >> 8) ^ crc32Table[(data[i] ^ crc) & 0xff];

    return ~crc;
}
It turns out I have used the bitwise complement in my C. I completely forgot.

int i;

for(i = 0; i < len; i++) {
Very small nitpick: There's no sense in declaring i outside of the loop definition unless you reuse its value outside of the loop later on, which you don't appear to.
 
use uint8_t instead of int for ascii
Or really, just work in-place in the output array - no need for a temp variable at all.

Also, on loops: RMSG's solution already has this but it's worth calling out in more detail: you don't need to calculate the string's length in advance since C strings are null-terminated. strlen() is really just a bit of code that does its own for loop to find the end of a string. And similarly, strcat() is "do a for loop on string 1, find the end, then do a for loop on string 2 to copy all of it to the end of string 1". If your strings are huge, this adds up.

Instead, you can just loop through with a pointer, starting at the beginning of the input string. If the underlying data is not 0, it's a character and you ROT13 it. If it is 0, you're at the end of the string and you're done. (Again, being sure to null-terminate your output)
 
Saw this pygame script on funnyjunk might aswell share.
Python:
import pygame
import sys
 
# Initialize Pygame
pygame.init()
 
# Set up display
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Mechanical Arm Thrusting")
 
# Define colors
white = (255, 255, 255)
 
# Define mechanical arm parameters
arm_length = 100
arm_thickness = 20
joint_radius = 10
thrust_distance = 50
thrust_speed = 5
 
# Initial arm angles
base_angle = 0
arm_angle = 45
 
# Main game loop
clock = pygame.time.Clock()
 
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
 
    # Update arm angles
    arm_angle += thrust_speed
    if arm_angle &gt;= 135 or arm_angle &lt;= 45:
        thrust_speed = -thrust_speed
 
    # Calculate arm positions
    base_x, base_y = width // 2, height // 2
    arm_x = base_x + arm_length * pygame.math.Vector2(1, 0).rotate(base_angle)
    arm_y = base_y + arm_length * pygame.math.Vector2(1, 0).rotate(base_angle + arm_angle)
 
    # Draw background
    screen.fill(white)
 
    # Draw base joint
    pygame.draw.circle(screen, white, (int(base_x), int(base_y)), joint_radius)
 
    # Draw arm
    pygame.draw.line(screen, white, (base_x, base_y), (arm_x, arm_y), arm_thickness)
 
    # Update display
    pygame.display.flip()
 
    # Cap the frame rate
    clock.tick(3)
 
  • Thunk-Provoking
Reactions: UERISIMILITUDO
Some positive news from me for once, I figured out how to create header files in C! Nothing amazing but hey I can make header files and make them work! Soon I’ll program robowaifus.
Great job! Now you can go back to making C files, except with a header file with only the function definitions so you can include the header from other C files and then link the implementation from the C file into your program so you don't have to recompile as much code when changing things in a specific part of your program. Then you get to have FUN™ with build systems, too!
 
I get having giant tables of magic constants for seed values in crypto/hashing applications, but I feel that it's kind of overkill to allocate a whole table of data for something like ROT-13. I'd really just do some if/else based on the char code.

Code:
if (c >= 'A' && c <= 'Z') {
  c = 'A' + ((c - 'A' + 13) % 26);
} else if (c >= 'a' && c <= 'z') {
  c = 'a' + ((c - 'a' + 13) % 26);
} else {
  // c is unchanged
}

or if you want to be clever you could even just inline it all with a couple of conditional expressions...

Code:
c += (c >= 'A' && c <= 'M' || c >= 'a' && c <= 'm' ? 13 : c >= 'N' && c <= 'Z' || c >= 'n' && c <= 'z' ? -13 : 0);
 
Getting rid of if's is practically the biggest performance optimization you can make though. Not that it matters for a toy algorithm, but even so.
That's fair. If you're processing gigabytes of data, allocating some space for a table of data constants to speed up a bottleneck at the core of the processing loop becomes a lot more reasonable.

Tables of magic constants are dense, unreadable, and non-self-documenting, so they might not always be worth the compromise.
 
Just curious, when should you create and use your own header files in C? As opposed to just writing something in the main code?
 
Just curious, when should you create and use your own header files in C? As opposed to just writing something in the main code?
Another reason besides pure organizational convenience is when you're writing a shared library. The user doesn't have to copy your source code into his project and build it himself, you just give him the compiled binaries and a header file that says "Here's what's in my library and how to call it from C".

You've already seen this when you include things like stdlib.h - the actual implementation of those functions is in your C runtime library, which you just link into your program and call in the way the .h file specifies.
 
Alright this might seem like a strange request but does anyone here have any tutorials/exercises I can view/do that can explain the structure of C#? Since they are so similar something for Java would also work.

Like I kind of understand how the language does stuff like types, variables and functions but it is hard for me to put it in my head and actually work with it. I need a bit more of an intuitive understanding of the language.

I've written stuff that works but it has taken me like 2 or 3 hours just to do something really simple. And I don't entirely understand it. I know enough about programming concepts that I can get a decent understanding of different languages. The brief amount of time I've looked at something like C or Rust or etc I could basically grasp what was going on. All the boilerplate just makes it really difficult for me to grasp everything on a line at once.

I think what I need to do is just do something that forces me to figure it out and I won't get good I'll be bad or decent but that'll be good enough.
 
any tutorials/exercises I can view/do that can explain the structure of C#
Freecodecamp is pretty good for beginners. Something that can really speed up your progress though is finding a project to build that will actually be useful to you. If it's something you use often, you'll get ideas with proper motivation to implement them and when something works well the info sticks much better
 
Getting rid of if's is practically the biggest performance optimization you can make though. Not that it matters for a toy algorithm, but even so.
Generally, yeah, but ROT13 using if statements will be faster on all lowercase or all uppercase text thanks to the magic of branch prediction. The only miss and reversion that will happen is at the end where it gets a null character.
 
Back