I'm not sure I would call it the most challenging class, but it's the one where the most amount of people failed to learn anything. If I had to guess then 90% of the students (or more) ended up not being able to do anything with prolog.
I haven't seen any other class that had such an abysmally low rate of successful learning. I think the only knowledge most people took away from this class is to not use prolog.
This was my only 100% final exam module with no continuous assessment/midterm papers or exams/projects to pick up slack if I failed, so I was nervous going into it. Kinda felt like my whole degree weighed on it. That night before, I just *got it* and it made all the difference in the world. I got how powerful it is, and why to use it.
I haven't used prolog since.
Either people loved the whole different paradigm of logical programming and were really invested or they just didn't want to touch it. There wasn't much in-between.
I think it is great to expose people to different things and I loved it, but I agree for many people that sent prolog straight to their blacklist
> Logical programming (prolog) ... but it's the one where the most amount of people failed to learn anything
I think the implication is that hnthrow098767 would like useful experience at the end of the course.
That being said: 25 years after my prolog course, and 21 years into my career, I wonder if I would take something away from it now.
https://kurser.ku.dk/course/ndaa09013u/2023-2024
The course teaches Haskell, Erlang and Prolog over half a semester (7.5 ECTS).
It mainly focuses on Haskell (7 weeks?) and covers Monad/Applicative/Functor bottom-up (i.e. you define your own, rather than use mtl/transformers), property-based testing (QuickCheck, generators, shrinking), parser generators (ReadP, minus points for parsing whitespace ambiguously). It is the 1st MSc course, so those who didn't have an FP-heavy bachelor's degree will have quite a shock. The Haskell part of the exam is writing a parser and interpreter for a non-trivial DSL.
The Haskell part already blasts most people. Then comes the Erlang part (3-4 weeks), where you learn about OTP, supervisors, process hierarchies, map/reduce, or similar problems. I remember one exam was implementing a quad tree where each level in the tree was controlled by a process.
The third part is Prolog, of which only a week of the course is dedicated to. While Prolog is a little mind-blowing in itself, the fact that it's only for one week also means the Prolog part of the exam is typically only a small set of exercises, where the Haskell and Erlang parts can be hard to complete given the allocated time.
When I took the course, I started learning Haskell in the summer break before the course started. Having two months of Haskell under my belt meant I survived the course quite fine (and ended up TA'ing it several times). But I saw lots of people way smarter than me (some of whom are now CS professors) struggle quite a lot with the pace and learning style.
Definitely the hardest course. To some unreasonably.
Moreover in the same class we also had exams, in one exercise you had to write more SIMD code in x86_64 (over images, strings of utf-8 characters, etc.) this was all in paper and no reference was allowed except the Intel Manuals; that was just one exercise there were more in systems programming, etc.
I also had a bad time with Prolog and Haskell in a Paradigms class though those exercises were a bit more bite-sized and streamlined.
Non-programming wise, I'm having the hardest time right now with a Numerical Methods class which involves a lot of proof-based linear algebra, induction over matrices, etc. I also had a bad time with a Logic and Computability class.
The kernel development one was pretty much what you can find in the Intel Manuals + osdev wiki [1] or some of the many osdev tutorials [2].
For SIMD I'm not aware of good tutorials or books, we did use again Intel manuals for reference and also [3]. For the image filters I assume you can search algorithms for basic filters such as pixelate, edges, etc. expressed as matrix operations and see how you can write that as SIMD ops.
[1]: https://wiki.osdev.org/Expanded_Main_Page [2]: https://os.phil-opp.com/ [3]: https://www.felixcloutier.com/x86/
Spoiler, I did not succeed at that, but neither did most of the class.
It honestly strikes me as too trivial an exercise for masters-level.
It did force me to get decent with bitshifts, which is always a useful skill. I found this [0] article about doing so with the 68000, and adapted it.
[0]: https://web.archive.org/web/20210225221011/https://www.atari...
My prof maintained a notable SML compiler, so the language we developed our compiler for was an SML style language that was statically typed, type inferred, and functional (very capable language). From parsing, to type checking, to code gen, to optimization, every project in that class was so much fun. I hate a lot of late nights with four or five tmux windows open tracking down errors, but I don't regret any of those. Aced everything in that class except the exam on parser algos (did not study as well as I should have).
That class made me realized that I can probably write any code I needed to, assuming I had some reading on the existing domain. Huge confidence booster.
[1]: https://merlot.usc.edu/cs402-s23/ [2]: https://pdos.csail.mit.edu/6.824/
The first was to implement a search algorithm that combines binary search and interleaving search which was pretty easy.
The second was to implement a prime number generator that generates >=1024-bit prime numbers without relying on bignum library. I miserably failed at this, been meaning to revisit this (over 15 years since).
The third was to implement a huffman encoder/decoder and an lz77 compressor/decompressor. Huffman was easy, but I found lz77 pretty difficult to implement efficiently (poor choice of data structure for the dictionary and phrase search on my part). I got a very minor deduction for the implementation not being quick.
Despite not doing well I hold the course in high regard.
The OCaml part is free, well structured and does not take long to complete.
It wasn't one of those "memorize the textbook and you'll be fine" type of classes. It was a "do a bunch of independent research and figure a whole lot of things out for yourself" type of class.
When I took it, the teacher taught LISP to start with, then taught us about compilers, BNF grammar, tokenizing, lex, yacc etc. We had write a compiler (translator) to compile the BNF code we were given. The BNF was a stripped down Pascal. Think ints, for loops, if statements, long expressions (abc * bxy - (delta/time .... I think variable names where like normal. Implementing BNF was very much a recursion exercise.
I did not like the teacher, but it really upped my programming skills.
It's ofcourse, about low level programming, but since, the lower levels underpin the higher ones, for me the most useful thing was this book.
It was a super challenge for me personally (no degree in computing or anything), and working through it i felt more things click than any other resource i tapped into before. I feel i understand much better in any language now, what actually happens on the PC, and how to go about investigating what happens if i do not. (finding specifications, isa documents, documentation on interpreters of scripts etc. etc., learning to read code/sources.)
That being said, do you have a specific direction in which you want to improve? Because this obviously leans towards a specific flavor of programming, where it's maybe not as useful if you want a different flavor. I know many good/professional programmers who know nothing of this stuff and are really really good in their own domains.
I haven't delved into low level programming much but I will give it a shot. I do mostly scripting and automation - I want to improve my programming skills to the next level.
These different types will likely have very different learning paths and things for you to explore that will get you to a practical skill level in the areas you want quicker than going the assembly -> c -> c++ -> script engines route for example. This last one is really a long journey (to me atleast), and it will bare fruits only near the end unless you're into embedded stuff because hardly any apps these days are written in such languages (c++ being a bit more common).
Networking: Not really "difficult" concepts, but the teacher had a chip on his shoulder. The programming assignments were "fun challenging", and I think if the course was taught at a slower pace, it would have sunk in better.
Assembly: I personally didn't struggle too much, but a lot of the class did. My secret was that I had read a little bit about assembly programming in high school, and realized that I had to force myself to follow "structured programming patterns." (If true goto true else goto false.) (I also programmed with a lot of GOTOs as a kid, so I knew enough not to make a mess.) I remember showing one of my high-score assignments to another kid in class, it "clicked," and they told me that if they realized that they could make their code kinda look like normal structured code it would be much easier.
(Also, I forgot that I really, really struggled with the first assignment, which was to write "hello world" using the DOS debugger. That was the angriest I ever got in college.)
As far as "not limited to programming courses":
Foundations of Computer Science: This was difficult because of the professor. They really didn't click or empathize with the class. Most of the class was about regular expressions. They never made sense to me, so now I just have ChatGPT write them for me.
Compilers: I really, really enjoyed the homework, but again, difficult because of the professor. It basically picks up the theory from Foundations of Computer Science.
One thing I noticed was that theoretical CS classes at my school had professors who didn't really understand the students and their goals. Most of us were targeting software engineering careers: The professors would often get us lost in the theory and not bring it back to concrete terms.
Automata is a good one to give you some understanding of how things work 'underneath'. The different algorithm ones are good because by implementing algorithms from scratch you learn how they actually work and that helps inform when you'd choose specific ones. I find that a decent background in algorithms is what really separates the self taught folks from the college educated ones.
Database programming was kinda tough, at least the theory side of it, because relational algebra and relational calculus are complicated and the whole normalizing databases during the design stage of things.
Lots of Turing Machines and constructing proofs. I'm not sure I would have passed if it wasn't for my friend who worked with me on the homework.
If you want to learn about applying your skills more successfully, look into an area where you think you'll be working. Most people don't graduate with a CS degree and start working on compilers. I worked at a network vendor where we made firewalls/routers, a lot of our programmers didn't have a clue how customers implemented our products in the real world. In that case, taking networking and security courses would be beneficial.
What's great about it vs other courses is you had to understand an extremely complex thing and learn to modify it, instead of building something from scratch. In the real world, many things are not documented or misdocumented, so it's a vital skill to be able to understand how something works from the code.
Programming is something you will get better at as you do it, so I wouldn't worry too much about it. Instead I would look for computer science courses that interest you and a course outside of comp sci that requires a lot of writing. Although technical writing is probably what you will be mostly doing, consider taking a creative writing or a critical reading course.
edit: I wasn't looking for programming courses exactly but I thought they might suffice. I haven't graduated yet and I love to work on challenging stuff in my free time.
Most work in terms of hours spent: compilers (you had to write one from scratch)
Hardest due to inherent difficulty of the material: theory of computation. Turing Machines and the Halting Problem and such weren't too bad (well, duh) but some of the more advanced stuff was pretty challenging, at least to me.
Hardest due to the material being a collection of bizarre recipes and jumping all over the mathematical map: tie between an undergrad numerical methods course and a graduate modeling and simulations course. It wasn't conceptually difficult to write the code, but understanding exactly why it worked was a different story. I've never been good at memorizing stuff unless I understand how it works (advanced statistics suffers from a similar glut of "magic recipes", in my experience).
Edit: the compilers class was the one that's proven to be the most useful over the rest of my life. I've written specialized parsers and so on a bunch of times.
I've never used the stuff from theory of computation again, nor can I imagine that anyone would who wasn't a researcher in that area.
I could see numerical methods being useful if I did a lot of down and dirty work with the physical world, but I mostly haven't done that..
When you move up a level or two, you'll see that making games can be pretty fun!
Hardware security (implementing rowhammer in JS powered by WebGL)
These were by far my hardest courses. One course that comes somewhat close is a course in Buddhism (meditatie en paychologie - meditation and psychology). The issue is that I didn’t have prerequisite knowledge. The psych part was easy. Reading a 1000 year old Burmese text on Buddhism/meditation at that time had so many crazy traps that it was just fascinating how wrong I interpreted that text.
Easiest course that I took: social psychology
Best course that I took: a teacher that said “I am too lazy to teach. Just make a cool project.” I taught myself iOS development and made an iPhone app that led to a job for a year creating an iPad app
All at the Vrije Universiteit Amsterdam
Most fun course: technology & games. Creating a game with unity3d and publishing a paper, that was fun. This was at the Universiteit van Amsterdam. The course doesn’t exist anymore sadly
Hardware security (implementing rowhammer in JS powered by WebGL)
At the Vrije Universiteit Amsterdam
These were by far my hardest courses. One course that comes somewhat close is a course in Buddhism (meditatie en paychologie - meditation and psychology). The issue is that I didn’t have prerequisite knowledge. The psych part was easy. Reading a 1000 year old Burmese text on Buddhism/meditation at that time had so many crazy traps that it was just fascinating how wrong I interpreted that text.
Easiest course that I took: social psychology
Best course that I took: a teacher that said “I am too lazy to teach. Just make a cool project.” I taught myself iOS development and made an iPhone app that led to a job for a year creating an iPad app
Edit: noticed that it’s not just about programming. Then it’s complex analysis and theoretical physics at MIPT. Most computer science problems felt simple compared to that stuff.
https://ocw.mit.edu/courses/6-001-structure-and-interpretati...
[1]: https://en.wikipedia.org/wiki/Abstract_interpretation
It was much more interesting/useful the other compiler class I took which actually had me create a parser+compiler for a made-up language. Still somewhat challenging to think in that way, as it's not the usual way to process data.
I didnt enjoy it at all nor found it very useful, meanwhile practice was really useful and satisfying
I really had to work for that class, but the payoff was tremendous.
The Pavlov course is good.
My first year of uni also had a pretty evil pure maths course which was worth a high percentage of the year. Not much fun.
I would appreciate anything that's challenging and helps me improve my programming skills.
It will significantly improve your understanding of programming langs, how some of them suck, what is possible, etc, etc.
A course being challenging is not a good indicator of its quality I think.