The way I initially thought I'd go about this was in a general sense, "How could I classify the things to be learned?" - and after a couple of minutes of just slamming my head into that wall I crumbled, and decided to just write about 30 things I'm interested in learning and then find the most general way to classify them. Seems to have worked.
Then I got sidetracked by some guitar I heard on the radio into playing with mine, and from there I got angry about not knowing simple musical theory like what the subdominant chord in the key of E would be - or even what the notes in the tonic chord would be. So I made a bunch of little pieces of paper I could slide around with the notes listed chromatically on them, and a counter and that was neat. Really clunky though. Then I streamlined it by cutting some well-spaced holes in a piece of paper and putting one of the thin pieces of paper I'd written scales on to slide into it. If I put an E in the top hole, it shows a G# and a B on the other two holes. It's quick and easy, and I could go on to make a slide for minor chords, for all the different chords in a particular key, for interesting intervals - but that's when I got smart.
I brushed up on my more-than-adequately rusty Turing skills and wrote myself a little program that tells me what information I would like to know. I made it very expandable, but off the bat I programmed in (for any given note) the major and minor tonic, subdominant, and dominant chords, as well as the perfect 4th and 5th interval to be shown. It isn't much, and in the long run it's something I should simply know - but doing it helped me learn a fair bit of theory and it was a lot of fun. I also learned a good deal about wrapping things into a range with a mod statement. That is now what this post is about.
I spent about 25 minutes kind of staring at the screen before making any real good work - I'd written the shell of a function and gotten it into my head I needed some kind of loop because I'd be repeatedly subtracting from a number. The situation was:
- 12 elements, 0-11 of an array, values 'A','Bb','B'...'G#'
- A function should take in a 'current' position in the array, and
- a 'modifier', the number of chromatic steps up or down to take, and
- should return an index to the desired note
Anyway I sucked at this. I spent a long time doing nothing, then spent a much longer time watching Lawrence of Arabia for the first time (that movie is amazing) then I went back to not succeeding. After a long, long period of time, I'd worked to this point:
if (modifier < MINNOTES) and ((current + modifier) < MINNOTES) then
current := (modifier + current) mod (MAXNOTES)
elsif (modifier < MINNOTES) and ((current + modifier) >= MINNOTES) then
current += modifier
elsif (modifier > MINNOTES) and ((current + modifier) > MAXNOTES) then
current := ((modifier + current) mod (MAXNOTES))
elsif (modifier > MINNOTES) and ((current + modifier) <= MAXNOTES) then
current += modifier
end if
After trying to write this small snippet of code in Blogger and spinning my wheels for a very long time, I've grown frustrated but learned a good deal. There are some issues that occur when moving between 'Compose' and 'HTML' mode that make newlines disappear and cause evaluation of symbols. For example, &-lt appears as <, but when you move to composition mode, the HTML is rendered and thus the symbol-text is replaced. Moving back to HTML leaves you with just an angle-bracket, and then moving into Compose will kill a large section of your post.
It's ugly.
Anyway, hopefully this works out (I've simply resolved to not switch back to Compose mode - who needs WYSIWYG) and you can read the code I posted in. Note that it's hideous. It took me over 3 hours to come up with that code which does actually work, during which time I went through off-by-one errors and modulo arithmetic problems and all sorts of hairy guff. Fortunately it finally worked, and once I saw that if-statement I saw it could be further reduced:
if isBetween (MINNOTES, current + modifier, MAXNOTES) then
result (current + modifier)
else
result ((modifier + current) mod (MAXNOTES))
end if
is the final rendition of that code - I wrote a small 'isBetween(low,target,high)' function that returns true when target is above-or-equal-to low and below-or-equal-to high, inclusive.
After hours of pounding away at what's really a simple problem, I finally ended up with a simple solution. From there the program wrote itself, and the ability to simply say "5 steps up from whatever the input is" without any error-checking or external wrapper statements made it all worthwhile.
It was a good coding experience.
Anyway, goodnight.