Tinkering with the source code for $language is also a great idea! That meshes with my empirical experience that the best way to learn is to "play". These days, it's rare for me to write code that isn't related to some specific personal project or business goal; maybe bringing back a bit of the "play" aspect is one of the keys to improving fluency.
You really start learning when you read the references, and have 5 or 6 browser windows open with web searches to things that either interested you and weren't referenced, or to terms that you didn't understand.
>That meshes with my empirical experience that the best way to learn is to "play".
It has actually been shown in educational studies that this is one of the best ways to learn; so social science seems to match up with your experience as well.
Later on I found some Stanford lectures, particularly Programming Abstractions by Julie Zelenski (around lecture 14). After watching that lecture I was able to classify my linked list sorting attempt as a selection sort. I was pretty excited that I wrote a selection sort without even knowing what kind of sorting I was doing. I have yet to use my newly acquired knowledge at work but I'm now confident I can spot certain sorting algorithms and I'm much more aware of when to use each.
If anyone is aware of any other resources like books, online tutorials or videos I would love to hear about them!
It helped a lot with basis for algorithms (terminology so you can understand what you are reading), but it didn't really teach me all of the data-structures and algorithms that I know. (There are really too many to cover everything properly/thoroughly in the extent of a course or two, even at graduate level). Also, I would have been sunk if I hadn't known a lot of it before applying to the program.
So I learned a lot of it through my own natural curiosity.
Everything concrete that I learned about data structures and algorithms started by reading Wikipedia. The CS articles are fairly accurate (it is hard to gain anything by spreading misinformation in them) and there are often times links at the bottom to the actual papers and code describing and implementing them. Start with the overview article and then read the paper. Look up any terms you don't know. Try implementing it in a language you like.
You can also Learn about data-structures in languages that you like (looks like ruby/python for you; you are in luck... those are both open source). Figure out how they are implemented, and performance characteristics. Go ahead and download the source tree and read the code.
Implement naive versions of various datastructures/algorithms yourself. See if you can play with them and improve them for various tasks. (Can I make this hash table use less memory? Give it a faster hash function? Make it a game).
I think flash cards would be a bad move, because then it starts to feel like a chore. Programming and reading and learning shouldn't be taken to like chores, they should be enjoyable and rewarding.