Japanese in one year?! - Not your usual study log

I’m still alive :slight_smile:

Not too much happened Japanese wise, tbh. I let my reviews on Bunpro pile up to 200+, but today, I finally had the time to get all of my reviews done! I’ve kept up with WaniKani, but still have ~100 lessons to be done, so I will tackle that next before leveling up, and this time for real :sweat_smile: I think my reviews have generally gone down (on WaniKani about 120 every day, instead of previously 180), and now that I had a slight adjustment in my daily schedule, I can also get more out of the two hours I have for Japanese every day since today (which is why I had time for my 200 reviews on Bunpro). Regarding Bunpro, I also unfortunately lost my streak…

Anyway, now that I can use more of my two hours, I can get faster done with my reviews and get more into reading again, so I think I will try to translate the rest of the TWC next week, and this time for real :sweat_smile: Time to build up a normal schedule again!

Aaaaaand, I’m pretty much finished with the CS50P course, which means I’m definitely a Python pro now :wink: (spoiler alert: I’m not). The only thing I need to submit now is my final project, but that is gonna take me some time, so I also started the next one, CS50x, and of course, I made a whole freaking game in the first week already :rofl: It was only Scratch, though, so nothing too exciting. What is exciting, however, is that I started C yesterday, which means I can now write stuff like this :stuck_out_tongue:

void void(void)
{
    printf("void");
}

I already had to experience how C is much less comfortable than Python in quite a few ways lol. For example, if I want to print a variable in Python, all I need to do is litteraly write

print(variable_name)

I tried to do the same in C, but the compiler didn’t like that, and the only way of printing a variable’s value that I currently know is something like this

printf("%s\n", variable_name);

(this is when the variable is a text, you use something different than %s for integers, floats etc.)

C is definitely a lot more sensible than Python, but I think it’s fun so far :slight_smile:

12 Likes

Welcome back!

Would that work? I bet your compiler would complain about the repetition of void!

error: cannot combine with previous 'void' declaration specifier
void void(void)

It’s all, uh, downhill from here! Learning C will definitely make you a much better programmer, but it’s always painful to write (as someone who likes strings and doesn’t like thinking about memory).

4 Likes

Yeah, you’re right, the compiler did indeed not like it :sweat_smile: Perhaps I should’ve tested it beforehand lol

I think I know what you mean, I, for example tend to use commas instead of semi-colons when making a for loop lol

Speaking of C, I today made an experiment to test whether C or Python is faster, by writing a program in both languages that prints every twin prime pair in a certain range. (Inspired by one of the problems from my course)

Here is the code that I wrote:

Python
def main():
    while True:
        try:
            # Get valid range from user
            min = int(input("Minimum: "))
            if min < 1:
                raise ValueError
            max = int(input("Maximum: "))
            if max < min:
                raise ValueError
        except ValueError:
            pass
        else:
            # Print all twin prime pairs in given range
            i = min
            while i <= max:
                if prime(i) and prime(i-2):
                    print(f"{i-2} and {i}")
                i += 1
            break


# Determines whether given number is a prime
def prime(n):
    match n:
        # Handle "special" cases
        case 1:
            return False
        case 2:
            return True
        case _:
            if n % 2 == 1:
                i = 3
                while i < n:
                    if n % i == 0:
                        return False
                    i += 2
                return True
            else:
                return False


main()
C
#include <cs50.h>
#include <stdio.h>

bool prime(int number);

int main(void)
{
    // Get valid range from user
    int min;
    do
    {
        min = get_int("Minimum: ");
    }
    while (min < 1);

    int max;
    do
    {
        max = get_int("Maximum: ");
    }
    while (min >= max);

    // Print all twin prime pairs in given range
    for (int i = min; i <= max; i++)
    {
        if (prime(i) && prime(i - 2))
        {
            printf("%i and %i\n", i - 2, i);
        }
    }
}

// Determines whether given number is a prime
bool prime(int number)
{
    switch (number)
    {
        // Handle "special" cases
        case 1:
            return false;
        case 2:
            return true;
        default:
            if (number % 2 == 1)
            {
                int factor_counter = 0;

                for (int i = 3; i < number; i += 2)
                {
                    if (number % i == 0)
                    {
                        factor_counter++;
                    }
                }

                if (factor_counter == 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
    }
}

My code probably isn’t the most efficient (especially because I’m not that knowledgable in C yet), but I hope they’re about the same in efficiency so that’s still a fair comparison. Also, the code should work, as I tested it a few times, and both programs had the same output.

I let both programs calculate every twim prime pair from 1 to 200000, and what do you think was faster?

Answer

It was C, and by a looooooot, C was more than twice as fast than Python, despite the code having more lines

5 Likes

Yeah, code in C will be faster most of the time.
However, for many practical usages the difference in speed would be unnoticable.
So, I think it would be best to learn both. Where you need performance – use C or Rust.
Where the performance is not so critical – use Python.

In any case, best of luck with your studies! wricat

4 Likes

Thank you! Yeah, I didn’t notice any difference for ranges like 1 to 8 or 1 to 30, since it isn’t that many calculations that the computer has to make, but for a range like 1 to 200000, there are millions of calculations, which is why the difference was so noticable. I don’t think that printing all prime twin pairs from 1 to 200000 is something I would need a lot though lol

4 Likes

The number of lines doesn’t really matter! You could write a program with a million lines and it could be faster than a program with one line; all that matters is what the program is doing. C has great performance because it’s compiled and the compiler can make a lot of optimizations.

Python is nice because you can write scripts quickly and make adjustments easily.

7 Likes

So true, I need at least four lines in C to print a string (though I personally prefer using six lines because of formatting), while in Python, I need only one lol

3 Likes

That’s just printing a string! Wait until you want to make a plot or work with a database, for example. It’s much easier to get something working in Python, even if it’s not as efficient as it could be.


Python needs to interpret your program every time it runs, so it’s slower than most compiled languages. Also, compiled languages can be a lot faster because of optimizations. This is a bit of a silly example, but it’s illustrative:

int main(void)
{
    int x = 0;
    if (x < 5) if (x < 4) if (x < 3) if (x < 2) if (x < 1) return 0;
    return 1;
}

You could add a million of these comparisons. Your C compiler is pretty smart, though, and the actual instructions (with an optimization flag set) are going to end up as something like

main:
        mov     eax, 0
        ret

which is actually equivalent to

int main(void)
{
    return 0;
}

and is clearly going to be faster than an interpreted language where all of the comparisons will be completed at runtime.

5 Likes

Wow, you can put multiple if statements and even the result in one line? :astonished: And what is the return 1; doing there? (Sorry for spamming questions, as I said, I just started out with C, and I certainly don’t even nearly know all the ways to do something like, for example, a conditional, only a few :sweat_smile:)

Oh, so it makes part of my inefficient code, if it is inefficient, efficient? Or is that only in some specific cases like making multiple conditionals where one is true anyway if another one is true? (like if x is less than 1, it’s obviously less than 2 as well etc.)

4 Likes

You sure can! This only works with a few things, like if, for, and while. Generally, you should only really do it if it’s clear what’s happening. Some people avoid this entirely and use curly braces every time for the sake of clarity. I just didn’t want to type them in my example. :laughing:


It is conventional to define the main function as one that returns an int. This number is called the status code. By convention, a value of 0 means the execution was successful, while any other number indicates something went wrong or was unexpected. The operating system knows about this status. As an example, with the program

#include <stdio.h>

int main(void) {
    printf("Hi, NeoArcturus!\n");
    return 0;
}

I can run (on Linux or macOS; I’m not sure about Windows)

northpilot@bluebird:/tmp$ ./test
Hi, NeoArcturus!
northpilot@bluebird:/tmp$ echo $?
0

and know that the program exited normally from the 0. If I had returned any other number (usually just 1), it would be a hint that something had gone wrong. (This really is a commonly followed standard. My compiler returns 1 when it fails and 0 when it succeeds.)

As for the return keyword, it indicates that the function will stop executing there and the output value (not output as in what you see on the screen, but output as in what another part of the code would see when calling the function) is what is returned.

Here, we are indicating that the main function will give a value that is an int when it is called. Think about this as something like what you might have seen in a math class mixed with the limitations of computers and the requirement of having a data type so it knows how much space the value takes up in memory. In math, you might expect the value of f(x) to be a number. In C, you might expect the value of int f(int x) to be an int.

In your previous example, you were using

where void indicates the function doesn’t return anything at all. The math analogy is not quite as obvious here because you’re basically saying the function has no value. It makes sense in C, though, because you can still change the state of things in memory or print to output, for example.


Well, compilers can’t fix an inefficient algorithm, but they can definitely help a bit with speed. The compiler can make a lot of optimizations like this if you tell it to. You can set a compiler flag for this and there are usually a whole lot of options.

3 Likes

Thank you for your detailed explanation! I already knew that this exit code existed and that main usually returns 0, but I didn’t know that you can tell main to return a specific exit code, like 1, instead of the default zero. Is it possbile that you could use that to see where something goes wrong in your code if you have a bug (in other words, could that be helpful for debugging)?

They mentioned in the course that it’s possible that 2038 will “turn” into 1901 because of how a computer stores the time (using 32 bits for the integer counting the seconds) (aka the problem of truncation (wait, trunkie??? :exploding_head:)). I don’t remember the exact dates anymore, but it could get pretty funny if they don’t “fix” that before 2038 lol

5 Likes

Yes, you could do that if you wanted to!

Yes, this was a problem on some systems because the time was stored as seconds after January 1, 1970 in an integer with 32 bits. This has already been addressed for most systems. I think it’s been patched since 2020 in Linux (kernel 5.6?).

3 Likes

Segmentation fault


Context: There are certain types of mistake that will cause a segmentation fault and until you learn about tools like debuggers and valgrind, that’ll be all the information you’ll have to understand what went wrong :stuck_out_tongue:

4 Likes

The story is a little more complicated than that. Those .pyc files (maybe in __pycache__ depending on your interpreter and OS) files that Python leaves behind are the bytecode generated for those files, which is sort of an intermediate state between the python source code. So it’s not going back to the source file every time and doing all that string parsing etc. again.

In Neo’s case, the slower performance of the Python code is likely due to all the indirection that is happening. With C, the compiler knows something is an int and can just spit out the machine instructions to use the processor’s inbuilt modulus instruction for example. With Python, there’s some amount of “Ok, we have a PyObject, let’s look at it’s type marker, ok it’s of type long, ok, let’s go look up the implementation of x.__mod__(), ok now let’s look in case someone has hooked this with a decorator or something, ok they haven’t, ok now let’s go run it”. And then the implementation of x.__mod__() for a long is rather more complicated because of all the dynamism anyway: cpython/Objects/longobject.c at main · python/cpython · GitHub

The good news is that there’s a proper JIT in the works for Python which should improve performance, but it’s never going to be as fast as something like C or Rust. But in the real world, there is a certain amount of tradeoff between execution time, server count, and implementation time.

Not to mention: "No way to prevent this" say users of only language where this regularly happens - Xe Iaso


The sad thing is I’ve already encountered year 2k38 bugs in real software. Think of trying to store the end date of a mortage in a database from the 90s/00s. :frowning:

5 Likes

Well, a debugger won’t really help me I can’t even compile the file, which is the case when I try to use “,” instead of “;” :sweat_smile: What’s valgrind, though? :eyes:

3 Likes

I am impressed by your resilience and tenacity in the face of changing circumstances.

Personally I am constantly struggling to manage my Japanese study time with other learning goals. I would love to hear more about your new strategy. How are you planning to use your two hours? Have you made a new daily checklist?

8 Likes

Valgrind is a debugging and profiling tool that’s most commonly used to check for bugs related to memory. With a language like Python, you don’t really ever need to think about memory management. Python handles that for you; for example, it cleans up after you with the “garbage collector” and automatically frees memory once it’s no longer needed.

In C, there are legitimate cases where you might need to manage memory yourself. You probably won’t encounter this for a while as a beginner, but it’s on the horizon if you continue with C. Manual memory management opens the door for a whole new class of bugs! These bugs can be hard to find because they might only occur under specific conditions. These bugs can be very serious, too. In fact, they can be so serious that is the official position of the “U.S. Cybersecurity and Infrastructure Security Agency (CISA), National Security Agency (NSA), Federal Bureau of Investigation (FBI), and the cybersecurity authorities of Australia, Canada, the United Kingdom, and New Zealand” (and the White House) that software development should transition to memory-safe languages instead of languages like C or C++.


This is one of the primary reasons I prefer to use

instead of C. There’s an attribute in Fortran called allocatable that allows you to dynamically set the size in memory. Every allocatable is automatically deallocated when going out of scope, so unless you really try, it’s impossible to create a memory leak. Another brilliant part of the language is the intent specifier, which lets you mark a variable as in, out, or inout. You cannot change a variable with intent(in), and you can specify multiple variables with intent(out) or intent(inout), so you can write a single subroutine with multiple outputs (and even outputs of unknown size with assumed-shape arrays, which was like magic coming from C) and no need for pointers.


Likewise! I am curious about how you’re handling this change in priorities while continuing to learn Japanese.

6 Likes

私も! But also I’m glad that you started with cutting back on everything. My first instinct is always to “try to do the same amount of things in less time” and it’s a big frustration point that I always feel like I’m not meeting enough goals.

I’m assuming you’re basically dropping iKnow, or at least dropping the SRS aspect of it since it’s just too intense? It’s possible to put all the words into WK with custom SRS but that would be a lot of work…The sentence training aspect is pretty good though, but I’m pretty slow at it so I can easily spend 20 minutes on 20 sentences so I’m not sure if that’s worth training either.

7 Likes

I’m currently working on it, yes :slight_smile: I’m currently just trying to slowly build up a schedule that I’m sure I can consistently follow. For now, my goal is to bring daily reading in again with at least one NHK easy article per day, then I will try two articles, then perhaps implementing some iKnow again etc., so I certainly don’t have a set schedule yet, but I’m building one. I will write more details about my schedule when I know more about how much I can do in two hours.

I was thinking about learning C# as well, after I finished my course (which does not include C# btw), does C# have that same “problem”?

Yeah, it would’ve been completely stupid to believe that I can do everything I did previously in just two hours, so I have to come up with a new plan, which I’m currently doing! Challenges are fun, and this one is a big challenge :slight_smile:

I would’ve preferred not dropping iKnow, but as for now, I unfortunately don’t see any other way than at least temporarily dropping it. I will indeed try to continue using the sentence builder, but it’s currently not among my highest priorities.

That being said, I will post an update soon when I have a bit more to say than just “I’m working on it” lol

Also @Hubbit200 I will try to test your script throughout the next few days :slight_smile: (responding to your ping)
I haven’t worked with drive until now, so I’ll first have to set that up :sweat_smile: I already (re)tested the conjugations practice, though, and it seems to work perfectly fine. One thing I’d like to point out, though, is that if I use Jitai, the text that tells which form is asked for is also being “Jitai’d”, if you know what I mean. Nothing really serious, but I’m not sure if that is the intended behavior.

9 Likes

Thank you! Sorry for the trouble, but luckily a Google account does tend to be nice and quick to set up.

Yeah, I was having some trouble getting the text in the conjugations to not all be Jitai’d - and I just gave up for now :sweat_smile: I’ll revisit it and fix it soon once I get too annoyed with it…

3 Likes