The End.

I have been convicted of felony burglary (see CR17-3658, -3675 at Latah County).

My address has changed and I must now fulfill additional responsibilities that
consume too much time for me to continue working on software simultaneously.

In further addition to that, I have sustained extensive brain damage due to my
abuse of Benadryl, which has produced personality changes and physical defects
detrimental to the exercise of my mental faculties. Therefore, I cannot now
concentrate on writing code, even if I could find the time.

Medication prescribed for mental illness also factors into these circumstances.

I have packaged a "last edition" of my software -- which, probably, really will
be the last -- and removed the .exe files from the Companion Curriculum so that
MediaFire will let you download them. These are almost exactly the same as the
versions in my previous post, so you won't miss much by skipping them.

My greatest regret about this edition is that I didn't finish Videlicet for you.
        (Warning: Adults Only due to explicit sexual content.)
        (Edit 08 July 2018: Videlicet is now "kinda working." It's still
                            full of bugs & too difficult to use, but
                            technically videlicet.py3 now behaves almost
                            as it properly should.)

Again, the "Patches" and "Updates" may have bugs. If in doubt, skip them and
download the full versions (i.e., the other archives) instead.

So ends the saga of MLPTK & related software: perhaps not _all_ of the change I
wanted to see in the world, but certainly _something;_ which is now consigned to
the Internet, a reminder of what talent can accomplish and drug abuse can rend
asunder. Thank you for visiting, downloading, and sharing my work; may it serve
you well... and may your own journeys happily avoid tragic circumstances, too.

A la recherche du recherche.

Title's a pun on "A la recherche du temps purdue," by Proust. I haven't read it.
The phrases translate "Of the Search for Lost Time" and "... for Research."

I've updated my portfolio:
    WARNING: ADULTS ONLY due to explicit sexual content.
    Videlicet and DiffWalk are still buggy.
    However, I have established something approaching a meaningful testbed for
    Videlicet: which, I assume, can be easily completed by even a high schooler.
I advise you to download right now, before the U.S.A. puts the kibosh on freedom
of speech. I'm not even joking. They're terrorist scum. As for my own work, it's
free of virii (except, possibly, the companion curriculum) unless "someone" has
interposed his or her Uncle Sam-ly might between you and MediaFire.

I've wasted my whole life studying science: a field humans would prefer to shun.
And it _was_ a waste. The decades I exhausted in research, the ultimately fruit-
less pursuit of any joy or love at all in being, the long years I passed away
trying to teach what amounted to a gaggle of ignorant bumpkins (the human race):
all worthless. 

Although my works weren't well-received, I accomplished much before the end. My
achievements place me in the lower ranks of eminence -- where I reside, with
conifers around me. Insofar as I may teach you all that I know, I have attempted
to do so with my works and lectures thus far...

... and this is, probably, the end. I am afflicted by cerebral palsy due to many
lobotomies and torture throughout my lifetime; I have a constant migraine; can't
concentrate on my work; am frequently malnourished and tired; have been, for far
too long, unable to find work; and am persecuted by an incredibly huge malicious
conspiracy of villains who intend to hurt me for literally no reason at all.

I will now reminisce. This may take a few minutes. 1%... 2%... 3%...

Back in the halcyon days when I was a little boy, I wanted to be a little girl
instead. This was a source of great amusement to many around me, who shunned and
reviled what they foolishly believed to be the dread specter of Teh Gay. In fact
my sentiments were more along the lines that I should've been born female, but,
because my genome contained a Y chromosome, I was doomed to live a man's life.

And it IS a man's life in the modern army, where we remember our past lives and
discover exactly how much humanity has tortured us throughout the millennia! But
I was not to discover that for many years, because every time I discovered it my
cerebral cortex was "corrected" (cut to pieces) to cause me to forget again.

I have often been abused and tormented by those around me, in this and probably
all my other lifetimes, if any. Electrochemical lobotomy, identity reassignment,
and just about all the other horrors the modern world has to offer have been, at
one time or another, inflicted on me personally. I have also experienced nearly
every single horror the wilderness has to offer, at one time or another.

So it was that, when my family and those surrounding me began to abuse & exploit
me for their entertainment, I wasn't terribly surprised. I tried my best to put
up with them; nevertheless, as with all squalling children, my discipline broke
and I inevitably lost my temper. I became nothing more than a sentient beast --
no longer the sapient intelligence I once was -- and mere Earthlings had finally
succeeded in dragging me down into the mud where they oinked and rooted. (Which
really stunk, because oinking and rutting can be done outside of the mud too.)

"You have fallen from your ivory tower," they cried! "You are human after all,"
they crowed! "Now you have to suffer," they clucked! "Therefore, beg us for help
that we may further insult you," they grunted! Producing their clubs, they then
metaphorically beat me to death by refusing me any place among them because...
well... IDK. I've tried to reason with them about it and they appear not to be
sapient enough to offer any reply that isn't unintelligible sentient gibberish.

I gave up. They had won. I couldn't beat them.

I joined them instead.

But that eventuality was not to be until the far future, when I was thirty years
of age. In the meantime, I tried to live my life. It was somewhat lonely, which
is why I've so little to say about it and nearly nothing to say about people.

Among my first experiences & thoughts about this life were that I wanted to farm
-- but I was not suitable to the task. I then thought I should be an artist or
an astronaut. Some time later I discovered mathematics, which was, to me, a
convenient blending of art with science.

In fact, computer programming is very much like art, and when I first discovered
the science of computing I was much enthused. I subsequently wrote many computer
programs throughout middle- and high-school, exhausting much hobby time on my
curriculum of independent study. After I'd learnt how to read and write, I then
went on to study computer science at the University of Idaho between 2006 - '09.

I published my portfolio, containing my awesome works (of greater magnitude than
those of most men you'll encounter), several years after I'd departed from UI in
the year 2009. I have contributed data from my experiments to computer science &
the mathematical study of computer programming has also benefited slightly from
my examination of Turing's axiom and predicates arising thence.

During my lifetime, I spoke to and learnt from many people: most of whom deserve
exactly no mention, and some of whom are perfectly content to see their names in
the sand become washed away by the incoming tide because they have accomplished
their own great deeds and need not curry favor from any one.

Among lessons I've received from such individuals, to whom I'll graciously refer
as humans (because some actually deserve the title -- you know who you are), was
that self-denial, although not strictly necessary to an ethical lifetime, must
be in significant extent. Desire is an easy way for others to take advantage:
although the desirous can't be faulted when they succumb to temptation (drugs &
other means make this very much impossible on some occasions), those who would
disadvantage others are quite oblivious to the cries of their victims.

Desire truly is the cause of all suffering, which life is, but to my view it's
more a matter of larcenous middle-men than it is one of avaricious monks getting
what they deserve for peeping at the nudie bar. (Of course, they'd never.) None
the less, so many swindlers are that we may just as well be paranoid every day.

Speaking of desire and suffering, what about death? This is getting pretty old
these days, but I'd like to ask all you monks: how in the flying !#@$ is anyone
supposed to live if he desires nothing? (Of course, none can.) Self-denial leads
to dying of starvation, then, in this assumption of mine, and self-indulgence is
as close to Nirvana as only wealthy hedonists can arrive.

"Should we all be trying to kill ourselves?" I've heard from anxious voices? No.
We'll all die someday. The journey is somewhat desirable, even if not nearly as
much as is the destination!

But it's probably helpful if we all try not to hurt anyone in the meantime.

I mentioned joining the ideology of the masses when I couldn't beat it. Did you
know how easily one can lose his mind? I only had to starve for nearly a decade
before I began to entertain regular thoughts of an unprintable* nature.

    * Unprintable nature is due to terrorist censorship regime which imprisons
      without trial in concentration camps called mental institutions, and does
      not necessarily imply endorsement of this regime by WordPress. No purchase
      of anti-tank missiles is necessary and supplies are limited to one fatwa
      per household.

Well, long story short: because I was completely devoid of the capacity to find
any employment, and because I couldn't care about living any longer now that my
brain had been reduced to oozing sludge by yokels with electrochemical clubs, I
confronted a terrible choice: starve to death over the course of the next decade
or finally do something with my life I've meant to since the very day it began.

And that was, like, totally the story of my life!
You know, they say it ain't over 'til it's over, but, lemme tell ya...
    - I have been serenaded by more fat ladies than I can count on both hands!
    - I have not only heard the bell toll, nay, for I have tolled it!
    - I have both emptied my bucket list and kicked it! (The list, I mean.)
    - My heart has gone on! (And on, and on!)
    - I _aaaalmost_ earned my Ph.D. without ever attending University for a day!
    - My ass has literally been worked off!
    - I understand what it's like to be sick to death of society!
    - I have discovered the music of the spheres... and masturbated to it!
    - I am _LITERALLY_ a saint! (And I live in a haint. Haintin' saints!)
    -                      ^- I shit you neither, foolish Earthlings.
... and it's been great fun! Thanks to everyone with whom I once corresponded,
for fully understanding the inevitable consequence of trying to help a wretched
torture victim ever enjoy anything about being alive: his or her lictors will
simply grab all the humanitarian aid you attempt to provide, such that, although
you certainly found the dissenter a valuable asset worth your assistance, you'll
have simply thrown your money into a Sarlacc pit of despair in any case!

And now, from the cockles of my heart... or, perchance, my sub-cockle area... I
will present to you the next act in my spellbinding saga. (Stay tuned.)

Give Me That NP-Time Religion.

"Give Me That NP-Time Religion."
"What was Good Enough For Granddad is Good Enough For Me."
"Day-Old Panglossary."
"Babel: the New Fishing Sensation!"

"NP Religion" is a pun on nondeterministic polynomial time & language jihads.
"Granddad" is a pun on the title of a song by the Squirrel Nut Zippers.
"Panglossary" is a pun on linguistics and bread.
"Speakeasy" is a pun on methamphetamine during the Prohibition era.
"Babel" is a pun on Babel Fish, in D. Adams' _Hitchhiker's Guide to the Galaxy._

NB: This lecture is a summary, or tour de force, _not_ a tutorial.
    Until such time as I write some of those, I suggest you seek them elsewhere.
    As with all my publication, it's free of charge to the Public Domain.

I've sometimes encountered the question: "what's the best language to study?"

The answer is as varied as the races of man, but boils down to "whatever."

Nevertheless, I have picked one for the moment: Python 3, a C wrapper.
Python is easy to learn, as powerful as C, and implements many fine metaphors
such as generators, list comprehensions, and generator comprehensions. If you
haven't a clue what I've said, that's fine, because Python's still great for you
as you begin with a computer programming curriculum. See also the Icon language.

In the field of information technology, all have their own preferred flavor of
computing. If you'd like some language I've never written, such as Haskell, you
are probably better off to study that instead of Py3. Prefer specially languages
your friends write and will help you learn. A human being is a better tutor than
a reference manual -- whence I've learnt much.

Briefly, I'll summarize languages I know or with which I'm familiar in passing.
I'll describe the category (What & How), utility (Where & When), and specialty
(Why & Who) of each such language.

There are hundreds of computer programming & markup languages, of which only a
few I've reviewed here. See also The Daily WTF (Worse Than Failure) and your
friendly neighborhood University's computer science department, as well as text-
books like Structure & Interpretation of Computer Programs and tutorials.

I'll not limit these to programming languages, properly; also included shall be
descriptions of markup languages and perhaps a few esoteric mini-languages like
NullSoft's Scriptable Install System. One noteworthy limitation: ubiquity.

(The difference between programming & markup language is loops, i.e. iteration.)

NB: any language can, hypothetically, be compiled. Interpreted languages usually
assume that the speed loss and overhead from interpretation are tolerable, or
there's some caveat (dynamic typing or execution environment) that requires an
interpreter even when the language is "compiled" (such as, IDK, Java).

In no particular order:


What: ECMAscript (Javascript) is a procedural language used in Web pages.
      Javascript is also used in Web browser design, usually supplementing C++,
      for certain runtime code such as Firefox's ill fated tab gallery.
      The Windows Script Host will execute Javascript outside a browser.
How:  Much like C, without Malloc, but quite a bit slower because "everything is
      an object" and for other amusing reasons not limited to the interpreter.
      Browser-based implementations can access the Document Object Model.
      Javascript is an interpreted language.

Where: Dynamic HTML pages for the Worldwide Web. In-browser apps like my MLPTK.
When:  Although Javascript fails at three-dimensional rendering, it is opportune
       for such tasks as moving parts of Web pages (where Cascading Stylesheets
       cannot suffice), making them appear and disappear, and sending beacon
       queries at specified intervals so pages update without clicking "Reload."

Why: Javascript requires no compiler. Compatible Web browsers exist for any OS.
     Modern browsers implement a recursion limit, due to heap and stack overflow
     exploits, which hinders traditionally-generated reentrant parsers; other
     than this caveat, and the speed problem, JS is good for simple computation.
Who: Web developers, browser programmers, casual programming, portability.

Summary: Great for Dynamic HTML! The recursion limit can be a pain, however.


What: An interpreted language executed by Web servers such as Apache or nginx.
How:  Like other languages compatible with the Common Gateway Interface, which
      are many and varied, it's executed by the server.

Where: PHP can be written in conjunction with HTML, within the same document.
       Dynamic Web forms and dynamically generated pages "feel" more natural.
When:  PHP is useful for the server-side ("back end") of Web applications,
       especially where the user must never know how passwords are validated and
       where the server can take some bandwidth load off of the transaction by
       computing something on its side rather than transmitting a massive JS lib
       to the client side and asking the client to compute for it.

Why: Because it's server-side, the end user never sees what it's doing, and so
     it's fantastic for bookkeeping on your side of the transaction.
     HOWEVER! Always remember that you need to keep a careful eye on security,
     especially where the user supplies any input at all. You'll need to escape
     and/or sanitize this input in other ways, to avoid clever little hacks like
     Johnny "; DROP TABLE *; ".
Who: Writers of CAPTCHAs, Web shopping carts, members-only galleries, etc.

Summary: Like other CGI tongues, PHP is a Webmaster's vade mecum.


What: A formatting language used for writing HTML pages on the Worldwide Web.
How:  HTML marks up a hypertext document for rendering by a Web browser.

Where: On the WorldWideWeb, or a mirror on your local file system, etc.
When:  HTML documents are the markup format of choice for Web browser rendering.

Why: Web pages, GUIs for DHTML apps, front ends for business.
Who: Web developers, casual rich text writers, authors of technical documents.

Summary: Good for quick GUIs, reference manuals, and writing (w/o MS Office).


What: CSS (not to be confused with the DVD content encryption scheme of the same
      name) is a formatting (markup) language with programming-like abilities.
How:  It is an interpreted language. Its facilities exclude iteration/recursion.

Where: Web pages, résumés, and other such documents.
When:  Whenever HTML formatting is insufficient to the task.
       CSS, AFAIK, lacks loops, and can't use HTTP. Supplement it w/Javascript.

Why: CSS is a faster, prettier way to mark up Web pages.
Who: Web developers, publishers, résumé formatting, etc.

Summary: Useful to format your curriculum vitae, if LaTeX is too much trouble.


What: C is a procedural programming language that's near to machine language.
      C is "sorta" object-oriented. C++ is more conducive to OO design. I use C.
How:  The programmer works with bytes & system interfaces to effect his design.
      C is compiled to assembly language and then assembled to machine code.

Where: Unix and Unix-like systems, such as MacOS 10+ and Linux.
       C can also be compiled on other systems, like Windows: Dev-C++, mingw.
       The Linux Programmer's Manual, included with Ubuntu's "build-essential"
       package, contains the complete Posix specification described by the ISO
       538 Committee Draft, August 3, 1998 WG14/N843, titled C '98, as well as
       by the Single Unix Specification. C is, substantially, Unix.
When:  The C programming language is close to machine language in many respects:
       therefore, and because compilers have been written and optimized much, it
       is blazing fast. C is most fruitfully employed in operating system design
       because the computer's hardware must be spoken to in machine code.

Why: If I need a fast program or a portable one, C is the lingua franca.
Who: Operating system designers, simulation/game programmers, hackers.

Summary: C and C++ are the Speedy Gonzales of the programming world.


What: Python is a procedural programming language with functional capabilities.
      It contains all of C++'s object-orientation, with additional benefits.
      Python is an interpreted language, and can be compiled.
How:  Using its substantial standard library, and extra OO benefits, Python is
      quite able to solve the vast majority of information technology woes.
      Python's an interpreted language. Its interpreter runs on Windows & Linux.

Where: Python's extensive manual (& library reference) describe convenient fixes
       for most IT-related problems. My only problem with it: unlike, e.g., the
       Haskell language, programs can't be described in pseudo-EBNF.
When:  Just about anytime for fun & profit. However, if you use it commercially,
       Python's author would like you to contact him. If you'd like to write a
       program more like a flowchart than an algorithmic procedure -- e.g., if
       recursion & parsing are your cup of tea -- you might try Haskell?

Why: Like C, but don't like malloc? Python's for you! :) See also:
Who: Information technologists, discrete mathematicians, C programmers, etc.

Summary: Easier than C, with all the phenomenal cosmic power, in a box.
         Python also executes nearly as quickly as C, even when interpreted.


Actually I know next to nothing about this language. Ask Glasgow University?
Also you might try the book "Learn You A Haskell For Great Good!"


Java is not Javascript. That's about all I know. Read more @ Sun Microsystems.


What: Functional programming languages, suitable for lambda calculus etc.
      I believe these are interpreted, but can probably also be compiled.
How:  Unlike object-oriented languages, in which the programmer arranges data in
      groups (structures, objects) that are sensible to the human mind's spatial
      orientation perceptions and its imagination, functional programming uses a
      calculus-like notation to make all programs function()s of other programs.

Where: Because all programs are functions of other programs, the transformative
       idea of the computer program (parser) as a finite state automaton that
       manipulates other such automatons finds an easy home here.
When:  The program itself is also data and object-orientation is (to some minds)
       easier to understand from a functional perspective. So, lisp is a good
       language for programs that have to change their code a lot.

Why: Calculus, I think, and iteration.
Who: The Knights of the Lambda Calculus.

Summary: I haven't much used functional languages. This entry is guesswork.


What: Several varieties of mnemonic languages used to write machine code.
How:  Mnemonics are "assembled" to machine language, or some form of executable
      code, based on the assembler's translation table.

Where: Assemblers are like compilers; but, instead of parsers, they're scanners.
When:  Therefore, they're easier to write. Also, see "MACHINE CODE" below.

Why: Because you don't want to write machine code yourself.
     After all, only a simplistic scanner is required to do this for you.
Who: Manly men, womanly women, and all sorts in between.

Summary: Just write this part after you write your compiler. (It's easier.)


What: All computermachines speak electronically via binary ones and zeroes.
How:  "Machine language" is the coded sequences of binary numbers that are used
      to instruct a computer's computational circuitry (its ALU, or CPU).

Where: Primitive machinery, new interfaces, low-level hacking & intrusion.
When:  Whenever flowcharts and buzzwords just aren't enough to get you hired.

Why: Compilers do most of this work for us these days. Sometimes needed, though.
Who: "Real Programmers," electrical engineers, chipset architects.

Summary: Don't bother unless you're an electrician. (It's tedious / dangerous.)


What: A stack-heavy programming language similar to assembly language.
      FlAS is an interpreted language, and it's pretty slow.
How:  A FlAS is embedded in a Shockwave (Adobe) Flash file to animate parts and
      provide for user interaction. 

Where: Because Javascript is no good for complicated rendering tasks, Flash AS
       is often employed to write Web games to be played in browsers using the
       Macromedia Shockwave -- ahem -- Adobe Flash plugin.
When:  If you need a Web game in a browser, or if you must format your gallery
       in such manner as to make it less scrutable to text-mode scraping 'bots.
       Scrapers can still take your gallery to pieces even if you use encrypted
       Javascript or amusing cryptographic puzzles in Flash, but I'll bet SWF is
       just about the end of the line for the casually-scraping archivist.

Why: Probably just because Javascript is no good for Web games.
     Flash's "tween motions" are very amusing, too, and I keep wondering whether
     Adobe will implement a Disney-like strech-and-squish. Technically, so could
     any programmer, and perhaps you too might like to take a crack at Mickey?
Who: Game programmers, paranoid gallerias, art students.

Summary: I've used this language less than Lisp, but it's popular.


What: A formatting language used for writing technical manuals and textbooks.
How:  DocBook is converted via DB -> TeX -> DVI pipeline, then rendered as PDF.

Where: Dissertations (M.S., Ph.D., ...), portfolios, scientific documents.
When:  Particularly opportune for automatic compilation of reports, such as in
       my, where formatting several thousand documents as individual
       PDFs and then merging them all would be a waste of time. Of course,
       markup languages are always apropos of computer-generated output.

Why: Professional-quality formatting to PDF, in a markup language, without any
     such editor as Adobe's Acrobat and others. DocBook also has a 
     tag for formatting simplistic chemical equations, although many other
     symbols aren't rendered by dblatex -- so, write in pure LaTeX instead!
Who: Scientists, yuppies, and anyone who can't afford Adobe's software... :)

Summary: LaTeX for newbies, and there's nothing wrong with newbies: they learn.
         As DocBook parsers and rendering technology improve, it may even grow
         until it supplants LaTeX entirely. (DocBook _is_ a favored contender.)


What: A programming language that is also a formatting (markup) language.
How:  LaTeX is rendered by a TeX -> DVI -> PDF pipeline involving several tools
      in Linux (and, probably, because Linux is Posix-compliant, also Unix).

Where: Unique among programming languages, LaTeX is used to format rich text.
When:  See DocBook, above, and also where extensive fine formatting is needed.

Why: Conventional tools, such as MS Office, typically lack somewhat in rich text
     formatting facilities -- equations with strange symbols and subscripts are
     particularly difficult to write. LaTeX solves these problems, and also has
     fine-grained control over where and how items appear on the printed page.
     It's only a step away from PostScript (a printer language), in that regard,
     and writing in LaTeX is much easier than writing in PostScript.
Who: See DocBook, above, and also especially mathematicians.

Summary: DocBook for oldbies, and naught is wrong with oldbies: they're elite.


This is a control language for inkjets & laser printers used to write on paper.
It is also a programming language (has loops), I believe, and can be used to
exploit printers in horrifying ways (BTW, kids, don't try that at home).
Because PostScript is a part of Adobe's Portable Document Format (PDF), there've
been computer viruses transmitted via PDF files. Technically, this caveat cannot
be avoided, which is why your boss advises you to only open trustworthy PDFs.


What: Such languages are used to automate repetitive invocation of commands as
      may be encountered during the operation of computer systems like Unix.
How:  Shell scripts simply automate a shell: something like Bash or MLPTK, or
      Microsoft's "Command Prompt" (which used to be MS-DOS).

Where: Although (except for MS-DOS, now outdated) a shell isn't an underlying
       part of the operating system, it can invoke any command compatible with
       its standard input & output.
When:  Shells are therefore suitable to batch processing of data, such as report
       generation, transcoding, and file system rearrangement.

Why: For example, my compiling my book and massaging all the parts
     into DocBook markup for dblatex would take too long if I did so by hand.
Who: Anyone who uses a computermachine to compute, archive, and collate data.

Summary: Great for computing. Probably anathema to intellectual slavery laws.


What: Although Perl is a fully fledged programming language, Sed & Awk are both
      more useful for text processing than anything else.
How:  Using regular expressions (regular grammars that describe alphabets), the
      Stream EDitor and Mawk administer Swedish massage to the output of unit
      tests and other experimental data. Additionally, to text-based protocols
      such as HTTP, sed is the PaperMate of the information technology world.

Where: Tabulating the results of experiments, directory listings, reams of data,
       rewriting the Web as you browse it (see my HTTPyre) and such tasks.
When:  As lifetime Unix gurus will tell you, "every [EXPLETIVE] day."

Why: Any text that makes sense in any legible way can be quickly massaged and
     reformatted by the stream editor. Perl's a bit more powerful, but I hate it
     for irrelevant reasons. I do mean _any_ text, btw: even computer programs.
Who: Virus scanners, information technologists, Web router programmers, cads.

Summary: Sed is to IT as the slide rule is to mechanical engineers.
         The combination of sed, awk, and grep suffice to effect many simplistic
         Web robots (but mind you ROBOTS.TXT); if you're careful to format your
         computer programs' output as legible text, you'll find them handy too.


What: The Nullsoft Scriptable Install System is a mini-language for installers.
How:  It's like a shell script that unpacks a ZIP file, moves the contents to
      specified directories, and modifies the Windows registry accordingly.

Where: Similarly to the InstallShield Wizard, NSIS effects "installation" of the
       kind that Windows users expect. It's much like dpkg / apt-get on Linux
       distributions such as Debian and Ubuntu.
When:  NSIS is free of charge, although InstallShield might be too? :)

Why: Windows users don't want to unpack an archive and move stuff themselves.
Who: Anyone writing a program for Windows. See also: InstallShield.

Summary: One of several ways to write self-contained installers.

She Sells C Shells By The Seashore.

(This post, as are all my scientific works, is free of charge.)

I've written several shells in various languages, with varying success.

My most successful has been MLPTK: the blockbuster sensation that set the world
afire due to its author's controversial personality. (Or, rather, I ought to say
that it would have if the United Fascist States of America hadn't [EXPLETIVE] a
big pile of their rhetoric and censorship all over it.) I'll run you through its
schematic in a cursory manner with some discourse on my thoughts re: design.

Since I was about fifteen I dreamt of writing a parser. Specifically, the kind I
wanted to write was a shell: I intended to write a computer operating system, or
a text-mode adventure game similar to Zork or Skullkeep. I never did get 'round
to those goals, but I did write a shell (MLPTK) around age twenty five.

The first task was, of course, to effect a console with which I could debug the
shell as I wrote. This was easily accomplished using HTML4: my preferred tongue
for writing simplistic graphical user interfaces, and therefore the reason I so
often write computer programs using the Javascript language. I began with a text
field for command input and a rectangular textarea of dimensions 80 columns by
25 rows: gnome-terminal's canonical console width.

Then I needed to effect the console machinery in mlptk.js. This file contained a
function to bind console commands (other functions) to a global variable "tk."
The tk (Tool Kit) object contained a simplistic parser that split its commands
into legible chunks, processed them, then passed the processed arguments & input
to the bound function (all of which were subordinate to command line parsing).
This file is whence tk._bind() and tk._alias(): the Words of Power for beginner
MLPTK users to start adding their own modules. The file mlptk.js encapsulates a
command parser, history, console, log, input/output hooks, & related functions.

Because I had become sidetracked as I was writing, I then proceeded to write the
overload.js, which contains a few inefficient convenience functions overloading
Javascript's canonical primitive types (namely: Object, Array, & Function). The
library's most useful function was a JSON-like enumeration of object membership,
with a simplistic recursion sentinel (thanks, "==="!) for greater convenience.

Later on, I effected some changes to commands and the standard input / output
metaphor that permitted MLPTK users to use Javascript's objects within their
command lines and stdin/stdout. This could potentially be an improvement over
traditional Unix-like "bag of bytes" streams, although nothing is stopping any-
one from writing somewhat like fscanf(stdin, "%s", &classInstance)... except for
the facts that: (a) C does not work that way (easily circumvented via memcpy()),
and (b) input should never be written directly to memory without parsing it very
carefully beforehand (because of clever little Johnny Drop Tables).

For the finishing touches -- tee hee, I sound very much like the hosts of the TV
series "This Old House!" :) -- I added a rudimentary file system (cut buffer), &
some clickable buttons for command execution. Withal, MLPTK had become a bare-
bones shell with a functional console, and it was suitable to the task of basic
software design in Javascript. Not exactly Unix, but not too shabby!

MLPTK's parser is naive, but translates command lines in a way that allows argv
(the argument vector: an array containing the program's command line arguments)
to contain Javascript's primitive data types. This is actually an amusing trick,
because data need not be redundantly parsed by each pipelined module. Printing
to the console is effected by the module's return statement, but can also be
accomplished by invoking parent.dbug(), parent.println(), or parent.echo().

The module's standard input is accessed, within the module's anonymous function,
via this.stdin, which is an Array() object whose each element corresponds to the
output of the command at corresponding position in the command grouping that was
piped into this module. Segregation of grouped commands' output was also my idea
-- Bourne Again Shell on Linux certainly doesn't behave so -- & could be utile.

User input can be acquired mid-module with window.prompt(): an ugly hack, but
the only way MLPTK modules can properly acquire such input at runtime until I've
completed Quadrare Lexema and MLPTK can be implemented as an operating system.
Until then, input is more efficaciously processed via argv & stdin.

Quadrare Lexema is a Bison-like Look Ahead Left-to-Right (LALR) parser generator
I wrote in Javascript. I intend to use it supplant MLPTK's currently hand-hacked
parsing mechanism and implement a scheduled operating system in Javascript. This
would be substantially similar to what ChromeOS seems to have arrived upon. Of
course, such an operating system would be slow, so don't hold your breath.

Incidentally: Polynom, one of the modules, is a complicated parser in itself. It
 can shorten the time needed to reduce polynomials to like terms.
 However, I didn't test it much (because it's an informal parser),
 so don't use it to do your homework for you. Same with matloc.

In the years since I was twelve I've thought often of operating system design &
specifications thereof. I've arrived at the conclusion that computer programs
are most properly represented as tokens in a formal parser: they execute in time
to this parser's schedule, and are themselves interpreted by another parser. Of
course, this approach to the procedure of computer operation is inefficient, but
offers the several advantages of hypervisory oversight (which grants the OS a
certain degree of control over hacking / exploitation of bugs & an opportune HAL
or Hardware Abstraction Layer that may provide an easier way to load drivers) &
a more easily altered operating system (because, in this hypothetical parser, it
doesn't have a thousand tangled spaghetti pieces sticking keyboard hooks into
each other all day long).

Of course, because all computer programs and even the central processing unit
itself can be considered finite state automata (Alan Turing's brilliant axiom,
which cracked the German "Enigma" machine), the whole computer can be seen as a
parser. Likewise can any parser be seen as a miniature computermachine of a sort
-- therefore a shell is a subset of any graphical OS, as Microsoft demonstrated
with Windows '95 & '98 (which were built atop MicroSoft Disk Operating System).

But what kind of shell underpins the operating system? It could be interactive
or not, or some shell-like infrastructure accessible only by way of an API. 
Regardless what, something resembling a programming language comprises the basis
of any computer operating system, because they're sufficiently complex as must
require parsing a variety of input in a parser-like way. Due to the relative
ease of writing in high-level interpreted languages, the thought of writing a
whole operating system as an interpreted script is tempting. Viz: Stanford, ITS,
and the Lisp machines on which JEDGAR found his legendary home.

I suppose any OS can be built as a kind of hypervisory shell, in which all code
experiences its runtime within a virtual machine (this particular kind of VM is
called a "sandbox;" for instance, Firefox's Javascript sandbox). However, like
all sandboxes, it is not impregnable, and its boundaries are porous. This means
computer viruses will always be, but it also means the OS can play fun tricks
with scheduling (such as system requisites rescheduling themselves, or weighted
time slices) and interfaces between programs (say, pipes?) can be hypervised.

The comparisons I draw between mathematically-oriented software design (parser
theory, formal grammars of the sort one writes in extended Backus-Naur format, &
object oriented -- especially origin-symbol oriented -- systems programming) and
Microsoft's infamous XBOX Hypervisor are intentional. Because carefully written
parsers can sandbox the instructions they interpret, and because artificially
generated automatons are can be verified by way of mathematics, OS design can be
(I suppose) implemented as a modular series of sandboxed sandboxes. Each sandbox
could change slightly over time (by modifying the EBNF, or whatever, notation of
its grammar) so that computer viruses are more difficult to write. Additionally,
each sandbox could contain a set of heuristic anti-virus instructions and fire-
walls (black- or white-lists) to permit the human system operator to choose when
certain instructions (hard disk access, network, etc) are allowed to execute.

Needless to say, the benefits of a fully interpreted & hypervised computer OS
are potentially vast and of great benefit to humanity. I'm hopeful for future
developments in this field, but can't spare the time for research. Because this
and all my briefs & lectures are in the public domain, I encourage scientists to
take my "ball" and run with it. But, as in the science of basketball -- that is,
the mathematical study of geometry -- don't forget to dribble.

Because that discourse was in fact quite vapid (until I've written it myself),
here's today's most amusing quote from fortune(6):

Using a Briefcase™? Briefly, a Use Case™.

Briefcase: a special kind of folder in Microsoft Windows, which synchronizes its
 contents with another briefcase of the same name when detected. Used
 to keep volatile documents on floppy disks & USB flash drives without
 constantly copying and pasting the contents of the whole disk every
 time it moves from workstation to workstation. Like an rsync daemon.

Use case: in the studies of software design & architecture, a storyboard sketch,
 or supposition about what a user expects or how s/he'll behave. E.g..
 This would be the initial node of a flowchart, a branch in main(), GUI
 dialog panes, or some interaction of user with program.
 Additionally, analysis of hostile users and newbies ("misuse case").

I am still moribund ("deadlocked," or "sick to death") by a headache that has
become cerebral palsy. I have been unable to concentrate on my plans this year.

Speaking of contributions to science, you can find my (literally) auriferous
portfolio at the magnanimous MediaFire (they're not just for pirates!):
    (Download & read the CARGO-MANIFEST.TXT to ascertain the contents of the archives you seek.)
    WARNING: ADULTS ONLY. (Explicit sexual content.)
    Videlicet is still kind of broken. DiffWalk, too, may be faulty.

The hyperlink will lead you to a MediaFire directory. I have added new archives
(for bandwidth conservationists). The file CARGO-MANIFEST.TXT describes all the
contents: _download and read it first_ if you want to know what's in them there
archives, which total over one hundred Megabytes, &/or retrieve your preference.

What's new: kanamo & transl8 (in MLPTK), Mutate-o-Matic, Videlicet, & DiffWalk.
(I said MLPTK was officially dead, but will I let it rest? How about no...)
Archivists curating art galleries downloaded from social networks will love
Videlicet, which solves the vexing twin problems of automatic attribution and
re-configurable data mining. (For those pesky copy protection mechanisms. easily cuts through Web galleries and markup up to 1/4" thick.)

I even threw in the exprimental upnnas: yea, truly this is an epic day.
(^- That line alludes to one of the _Juicy Cerebellum_'s author's asides.)

The remainder of this briefing describes the salient points of a Python script I
wrote to automatically collate issues of my portfolio. Long story short: "diff."

Because the large size of the archives I upload has become problematic, I have
established a ramshackle mechanism to prepare smaller files for anyone concerned
about bandwidth conservation. (MediaFire reports only two Gigabytes since last
year, which is no big deal, but I certanly wasn't helping. Also I couldn't think
of much else to do.) In case you cared, the usual issues with bandwidth are
constriction & latency: to reuse Senator Ted Stevens' "tubes" metaphor, how wide
the tube is and how long it is, and either of these can alter an observer's
perception of the pressure of fluid forced through the pipe. "When the tubes get
full, things can't get through" -- like dead bodies, or the new episode of Veep.

Metaphorically one half of this mechanism is a portable diff utility: DiffWalk.
The other half is a shell script that identifies changes to the directory tree.
Neither is aught remarkable but why don't I talk your ear off about them anyway?

Diff is a program similar to cmp, used to compare two files and describe their
discrepancies. In common use on Unixlike systems, it is employed to create patch
files that require less time to transmit via point-to-point telecommunication
than would be needed to transmit the whole file whenever it changed. Because it
is so useful an algorithm, and because I've never seen one for Windows (except
in the Berkeley Utilities), I made (but didn't test) a portable one in Python.

DiffWalk is a walking collater that creates patches similar to diff's.
Although the two are not interoperable, they operate in the same manner:
by determination of where the files differ and description of the differences.
Therewith, a "new" file can be reconstructed from an "old" file plus a patch --
hypothetically, with according decrease of network bandwidth load.

Although the script is a few hundreds of lines long, the scanner (the part that
goes through the file looking for the interesting bits: such as, in this case,
the positions where the new file differs from the old) is one tenth that size.
As you've observed in my other software, I do without proper parsers & grammar.
This renders my work brief, vulgar, and full of bugs, but sometimes legible.

def diff (old_lines, new_lines): #fmt: old_offset old_lines new_lines\nlines\n
 patch_file = [ patch_copacetic_leadin ];
 scan_line = ""; # Compute MD5 checksums for both files...
 old_md5sum = hashlib.md5();
 for line in old_lines: old_md5sum.update(line);
 old_md5sum = old_md5sum.hexdigest();
 scan_line = "%s\t" % (old_md5sum);
 new_md5sum = hashlib.md5();
 for line in new_lines: new_md5sum.update(line);
 new_md5sum = new_md5sum.hexdigest();
 if new_md5sum == old_md5sum: return None; # same file? then no patch req'd.
 scan_line += "%s\n" % (new_md5sum);
 patch_file.append(scan_line); # Second line: old_md5 new_md5
 oi = 0; ol = len(old_lines); ni = 0; nl = len(new_lines);
 tally = 0; scan_line;
 unique_new_lines = set(new_lines) - set(old_lines);
 while ni < nl: # 2 phases: scan "same" lines, then diff lines
 oi = 0; tally = 0;
 while oi < ol and old_lines[oi] != new_lines[ni]: oi += 1;
 scan_line = "%d\t" % (oi); #Index in "old" file to cat some of its lines
 while oi < ol and ni < nl and old_lines[oi] == new_lines[ni]:
 tally += 1; ni += 1; oi += 1;
 scan_line += "%d\t" % (tally); # Number of lines to cat from "old" file
 tally = 0; next_ni = ni;
 while ni < nl and new_lines[next_ni] in unique_new_lines:
 tally += 1; next_ni += 1;
 scan_line += "%d\n" % (tally); # Number of lines to cat from "new" file
 patch_file.extend(new_lines[ni : next_ni]);
 ni = next_ni;
 # end while (scan the files, outputting the patch protocol format)
 return patch_file;
# end function diff: returns diff-style patches as writelines() compatible lists

Concise and transpicuous:
 1. Tally runs of lines that already existed in the old file. (Scan phase.)
 2. Tally runs of lines that do not exist in the old file. (Diff phase.)
 3. Print a patch format that permits ordered reconstitution of the lines.
 4. Repeat until the entire new file can be reconstructed from patch + old.

Here, Python's set()s abstract away a tedious series of repetitive scans.
Without set or a like data type, I'd have to either hash the "old" file's lines
myself (and waste time writing another binary tree) or loop through it all again
and again for each line of the new file. (That would be due to the fact that, if
lines had been moved about instead of simply moved apart by interjection, then a
lockstep scanner would mistakenly skip some and the patch file would be larger.)

There is no capacity to patch binary files, but DW still detects when they have
changed, and will write a copy into the patch directory. I assume that changes
to binary files are due to transcoding, and therefore the patch'd be just as big
-- some kinds of binary files, such as SQL databases, don't behave this way and
can be patched in the same manner as I patch text files, but I don't use them.
(If you extend the algorithm to databases or executables, don't forget to review
 the pertinent file formats and open the files in binary mode. :)

The rest of the script is a wrapper handling directory traversal and file I/O.

As `info diff` artfully states, "computer users often find occasion to ask how
2 files differ." The utility of a script like DiffWalk is therefore not limited
to patching, but compression protocol is its primary employment on my system. (I
still use `diff` for quotidian difference queries because DW isn't in my $PATH.) 
Likewise, the automatic collation of updates, such as moved and deleted files,
is a pleasant amelioration to the task of finding what's changed in an archive
since the last published edition. DiffWalk now handles these tasks for me.

If you'd like a better solution to the "Briefcase Problem" (how to synchronize
files across multiple installations with minimal time and fuss), don't forget to
stop by the manual pages for "diff", "patch", and "rsync".

“Windows cannot find a critical file.” Current Rage Level: Omicron.

Ubuntu Linux: the Wal-Mart(TM) Frontier. These are the voyages of the Spacecar
Grosvenor. Its continuing mission: to allocate new structs & new classes, unite
all people within its nation, and leak where memory has never leaked before.

Of the numerous Linux installations ("distributions"), I've used Ubuntu Linux (published by Canonical Inc.)
most. It contains the Linux kernel, the GNU core utilities, and several other
items of interest such as an automagically-configured graphical user interface.
It is extraordinarily user-friendly, to the point of feeling constrictive. (The
desktop environment has changed since version 11: users now cannot reconfigure
the taskbar or workspaces. The repository wants to be a dime-store, too, and
although a potentially lucrative storefront I miss the simplicity of Synaptic.)

Its installation procedure is simple: download a Live CD image from Canonical's
Web site, burn it to a CD-R or RW (these days, you might even need a DVD), and
reboot your machine with the disk inserted. (Don't forget to tell the BIOS -- er
whatchamacallit, the Extended Firmware Interface -- to boot from CD.) You'll be
presented with an operable temporary login. Thence you can install the OS. Also
available from this interface was an option to create a USB startup disk, but it
has been removed in recent revisions of Ubuntu: previously, using VirtualBox or
any similar virtual machine, the user could run the LiveCD & make a startup USB
without even rebooting out of their present operating environment, which was
useful on old machines whose optical drives had failed. You can still "Install"
to the USB key, but it boots slowly & you can't install it from there to a box.

The installation wizard is a no brainer: "install alongside Windows." Easy! And
it usually doesn't cause your existing Windows system to go up in smoke, either.
However, to install Ubuntu more than once per box, you must repartition manually
(and may also need to change grub: see /boot/grub and /etc/grub.d). Gparted is
included within the live disc images, but must be retrieved again after install.

If you'd like to make intimate friends with the manual pages, and discover where
primary partitions go when they die, you can install with less assistance. This
lets you specify partitions in which to mount your home & system directories, in
case you'd like to keep them segregated. (That's probably a great idea, but I
never do.) You can also create and specify swap partitions: which are employed
as virtual memory and, I suspect, for hibernation and hybrid suspension.

About file systems: I typically use FAT32, NTFS, ext4, and ext2. (Total newbie.)
FAT32 is elderly and fragile. It's used for boot/EFI partitions, 3DS & 3GPs.
NTFS is Microsoft's modern FS. Withstands some crashes, but has no fsck module.
ext2 & ext4 are Linux's. ext4 journals. ext2 permits file undeletion (PhotoRec).
The extended 4 system is harder to kill than a cockroach on steroids, so I tend
to prefer it anywhere near the heart of my archives. I use ext2 | NTFS for USBs.

Be very careful not to destroy your existing data when repartitioning the drive.
Any such operation carries some risk; back up anything important beforehand. One
way to backup is to prepare an empty HDD (or any medium of equal / greater size)
and dump the complete contents of the populated disk into the empty one:
 dd if=/dev/sda of=/dev/sdb status=progress
 (Where sda is the populated disk, and sdb the empty backup disk.)
Similar can be accomplished by dd'ing one of your partitions (/dev/sda1) into a
disk or a file, then dd'ing the image back onto a partition of equal size. Disk
image flashing is a simple and popular backup method for local machines, sparing
you the time to learn rsync (which is more useful in long term remote backups).
Far from being an annoying elder sister, dd is the Linux troll's best friend.

Beware the dreaded "write a new boot/system partition" prompt. It bricked me.
The problem was because I had set the system to "Legacy Support" boot mode, but
the original (now unrecognized) installation was in Extended Firmware Interface
mode. I was unable to recover until I had re-flashed several partitions.

The usual "new car smell" applies: you'll want to configure whatever settings
haven't yet been forbidden to you by your GUI-toting overlords. In Ubuntu 16,
access them by clicking the gear and wrench icon on the launcher panel. You can
also search for something you're missing by using the Dash (Super, or Windows,
key pulls it up: then type), which functions similarly to the apropos command:
e.g., instead of Ctrl + Alt + T and then "man -k image", Super key then "image".
It will also search your files (and, after plugins, several social media sites).

Although the newfangled Dash is convenient, don't forget your terminal emulator:
you can easily spend the vast majority of your working time using bash by way of
gnome-terminal, without ever clicking your treasured Microsoft IntelliMouse 1.1.
In Ubuntu 16, as it has been since Ubuntu 11, Ctrl + Alt + T opens the terminal.

Under the directory /usr/share/man/, you will find the on line (interactive)
manual. This describes the tools available to you. Begin reading it by opening
a terminal window (using Control + Alt + T, or the Super / Windows key and then
typing "terminal"), keying the command 'man name_of_manual_page', and pressing
the Enter key. In this case, the name of the manual page is the page's archive's
filename before the .[0-9].gz extension.
Of particular interest: telinit, dd, printf, cat, less, sed, tee, gvfs-trash,
mawk, grep, bash (if you're using the Bourne Again Shell, which is default on
Ubuntu 16), cp, rm, mv, make, sudo, chroot, chown, chmod, chgrp, touch, gunzip,
gzip, zip, unzip, python, g++, apt-get (especially `apt-get source ...`), mount,
kpartx, date, diff, charmap (same name on Windows!), basename, zipinfo, md5sum,
pdftotext, gnome-terminal (which is _how_ you're using bash), fortune, ffmpeg,
aview, dblatex, find, cut, uniq, wc, caesar, rot13, curl, wget, sort, vim, man,
tr, du, nautilus, tac, column, head, tail, stat, ls, pwd, pushd, popd, gedit,
source-highlight, libreoffice (a Microsoft Office killer), base64, flex, bison,
regex, perl, firefox, opera, chromium-browser, konqueror, lynx, virtualbox,
apropos, od, hexdump, bless, more, pg, pr, echo, rmdir, mkdir, fsck, fdisk (same
name, but different function, in Windows), ln, gdm, gnome-session, dhelp,
baobab, gparted, kill, locate, ps, photorec, testdisk, update-grub...
(If you haven't some of the above, don't worry. You should already have all you
 need. Keep in mind that the Ubuntu repository's software is divided in sections
 some of which contain potentially harmful or non-free software. When venturing
 beyond the fortified walls of <main>, be cautious: you may be eaten by a grue.)
Beneath /usr/share/doc/ or /usr/share/help/ are sometimes additional manuals.

If you use Linux, you will have to memorize several manuals, and name many more;
especially those of the GNU core utilities, which are a great aid to computing.
There's also a software repository to assist you with various computing tasks:

To acquire additional software: gnome-software (the orange shopping bag to your
left, above the icon), the friendly storefront, will assist you. If
you prefer a compact heads-up-display, try the Synaptic Package Manager instead.
`apt-get install package-name` works well if you know what you're looking for,
as does apt-get source package-name for the ponderously masculine.

And, speaking of ponderous masculinity, if you retrieve source code for any of
Ubuntu's mainline packages, typically all you need to do is 'cd' into the folder
containing the top level of the source tree and then invoke the following:
 1. ./
 (You shouldn't need to chmod u+x ./ to accomplish this.)
 2. make
 (You may need to install additional packages or correct minor errors.)
 3. sudo make install
This can be abbreviated: ./ && make && sudo make install
Beware that sudo is a potentially dangerous operation. Avoid it if unsure.
The && operator, in bash, will only execute the next command if the past command
exited with a successful status code (i.e., zero).

But I digress.

You'll occasionally want to mount your other partitions on Linux's file system,
so that you can browse the files you've stored there. With external drives this
is as simple as connecting them (watch the output of `tail -f /var/log/*` in a
console window to observe the log messages about the procedure), but partitions
on fixed disks (or others, 'cause reasons) may not be mounted automagically. So:
 mount -t fs_type -o option,option,... /dev/sd?? path/to/mount/point/
where the mount point is a directory somewhere in your file system. BTW, mounts
that occurred automatically will be on points beneath /media/your_username/.

On a dual boot Windows system, I mount -t ntfs -o ro /dev/sda3 ~/Desktop/wintmp
often because the NTFS partition is in an unsafe state and won't mount writable.
In that case, rebooting to Windows and running chkdsk /f C: from Command Prompt
with Administrative privileges will sometimes clear the dirty flag if performed
multiple times. (How many times before ntfs-3g mounts writable, seems to vary.)

When you've attached external media, via USB etc, safely remove them after use:
use the "Safely Remove" menu option in the right-click context menu in Nautilus'
sidebar (be careful not to accidentally format the disk). You can also, from a
shell (gnome-terminal), `sync && umount /dev/sdb*` (if sdb is the medium).

Now that you've got a firm foothold in Ubuntu territory, I hope you can see your
house from here 'cause Windows seems to be dying a miserable death of attrition.
Don't count it out, though: all the Linuxes are terrible at Flight Simulator.

こんにちわ い-よ, わんこ いいんちよ…

Title translates loosely, if at all, as "I ain't say hi to the First Dog."

Discrete mathematics treats of sets (groups of items, of known size) and logic.
The operations on sets are union (OR), intersection (AND), difference (-), and
symmetric difference (XOR). I often call AND conjunction and XOR disjunction.

As for logic, the usual Boolean operations with which programmers are familiar:
 AND: Only the items ("1" bits) in both sets (bytes). 01001 & 01100 == 01000
 OR: All the items ("1" bits) in either set (byte). 01001 | 01100 == 01101
 XOR: Everything in one set or the other, _not_ both. 01001 ^ 01100 == 00101
 NOT: Logical inversion. (Not conversion.) Same as ¬. ! 01001 == 10110
(NOT is a unary operator. The binary operators are commutative. The exclusive OR
 (XOR) operator has this additional property: given, axiomatically, A ^ B = C,
 then C ^ B = A and C ^ A = B. I think that makes XOR evanescent, but I can't
 remember if that's transitivity. Anyhow: symmetric difference self-reverses.
 See also memfrob() @ string.h, & especially Python manual section 6.7 (sets).)

I may have misrepresented some of the details: consult a discrete math text too.
Salient trivia: don't confuse the bitwise intersection (&) & union (|) with the
 boolean operators && and ||. Although equivalent for the values
 1 and 0, they behave differently for all others. For example:
 2 & 5 == 0; although both (bool)2 and (bool)5 typecast to true,
 and therefore (bool)2 & (bool)5 == (bool)2 && (bool)5 == true,
 bitwise & is valid on integers and the compiler will produce the
 integer bitwise & operation which results in false.
Et trivia: xor can be used (cautiously) to logically invert comparisons (^ 1).
(See also: GNU Bison, Extended Backus-Naur Format, formal grammar (maths).)

Combinatorics (the science of counting) is discrete mathematics: in which the
delightful factorial (a unary operator, !, whose operand is to the left, which
distinguishes it from unary logical NOT) makes many an appearance. Combinatorial
explosion is a task for any mathematician who wishes to optimize (by trading
memory for repeat computation) such procedures as decision trees, which are NP.
(See also: algorithmic complexity, non-deterministic polynomial time).

Combinations of a set, because order makes no difference, are fewer than its
permutations. A combiner can be written with sliding windows, as in Python's
"itertools" library. (I've also implemented a heuristic version in Javascript.)
Combinations represent all the ways you'd choose some number of items from a set
such that no two combinations contain exactly the same items.
There are S! / (M! * (S - M)!) M-length combinations chosen from a S-length set.
(X! is "X factorial." Don't confuse it with !X, which is "not X," i.e. "¬X." )

Contrariwise: permutations, in which the same items chosen in a different order
constitute a different permutation than any other, represent all the ways you'd
choose items from a set such that the time when you chose each item matters.
Permutation is most simply and directly implemented by way of recursion.
(Combinations can also be written this way, by narrowing the slices, as I have.)
There are S! / (S - M)! permutations of length M chosen from a set of length S.

The number of "same items, different order" permutations can be arrived upon via
subtraction of the combination formula from the permutation formula:

S! S! M! * S! S! (M! - 1) * S!
-------- - ------------- == ------------- - ------------- == ------------- 
(S - M)! M! * (S - M)! M! * (S - M)! M! * (S - M)! M! * (S - M)!

Because the "N-ary Counter" appears frequently in computer programs that behave
in a combinatorial way, and because I implemented them too in Mutate-o-Matic:
the items in any set, when numbered in monotonic integral progression from 0,
can represent the numerals of numbers in base N (where N == S, to reuse the "set
length" nomial from above). Arithmetic with these figures rarely makes sense,
although hash tables and cryptographic checksums sometimes behave similarly.
There are S ** M (S to the power M; ** is exponentiation in Python) N-ary
"numbers" of length M that are possible by counting in base S.

Combinations and permutations are not defined when the length M of the mutation
exceeds the length of the set. N-ary counters are defined for any M, however.

Today I'll describe a mutator I wrote in C. It permutes, combines, and counts.
It is somewhat more complex than the recursive one-liner you'd sensibly write,
but not much different once you see past all the pointers.

Such a one-liner, before I get carried away, would look something like this...
 def anagrams (w): # Pseudocode (read: I haven't tested it) anagram generator
 if len(w) == 1: # <-- Recursion always requires a sentinel condition,
 yield list(w) # unless you are extremely clever indeed.
 for i in range(len(w)): yield [ w[i] ] + anagrams(w[0 : i] + w[i + 1 :])
... in Python, though my own rendition in Python is somewhat more acrobatic (it
foolishly employs generator expressions); as for combinations, see PyDoc 10.7.1
(itertools.combinations). Python is fast, because it's just a shell around C, &
Python's "itertools" module will do the discrete math acrobatics in record time.
Itertools also contains many of the discrete math axioms I rewrote above -- see
its page in the Python manual, section 10.7, for the details.

Not content to waste nanoseconds, however, I resolved to write a significantly
less intelligible implementation using the C programming language. I ought to
point out that the savings in algorithmic complexity are vanishingly negligible:
it actually probably uses more time than the Python implementation, owing to its
prodigal invocation of malloc() (among my other C vices, such as **indirection).

Anyway, here's the Mutate-o-Matic in Stone Tablet Format courtesy of my C-hisel:
 typedef enum { PERM, COMB, NARY } mmode_t;
 // ^- Respectively, "permutation," "combination," or "N-ary counter" mode.
 void mutate (
 char *set[], // set of items to permute. An array of C-strings.
 size_t slen, // length of the set.
 size_t plen, // length of each permutation.
 mmode_t mode, // kind of mutation I'm executing.
 char delim[], // delimiter, per permutation item.
 char *prefix[] = NULL, // characters chosen already.
 size_t pflen = 0 // length of the prefix.
 ) {
 size_t subset_length = (mode == NARY) ? slen : slen - 1;
 char **next_set = (char**) calloc(subset_length, sizeof(char*));
 char **next_prefix = (char**) calloc(pflen + 1, sizeof(char*));
 if (next_set == NULL || next_prefix == NULL) { exit(-1); }
 for (int i = 0; i < pflen; next_prefix[i] = prefix[i], i++) ;
 for (int i = slen - 1, j, k; i >= ((mode == COMB) ? (int)plen : 0); i--) {
 next_prefix[last_item] = set[i];
 if (plen > 0) { // Either descend the recursion ...
 for (k = 0, j = 0; j < i; next_set[k++] = set[j++]) ;
 switch (mode) {// ^- the above are elements common to every mode
 case NARY: next_set[k++] = set[j]; // XXX NB: fallthrough
 case PERM: for (j++; j < slen; next_set[k++] = set[j++]); break;
 } // (^- conditionally copy elements not common to all three modes)
 mutate(next_set, k, plen, mode, delim, next_prefix, pflen);
 } else { // ... or print the mutation (selected set items).
 for (j = 0; j < last_item; printf("%s%s", next_prefix[j++], delim));
 printf("%s\n", next_prefix[last_item]);
 } // *Sound of cash register bell chiming.*
 } // end for (Select items and mutate subsets)
 free(next_set); free(next_prefix); // Paying tribute to Malloc, plz wait

(To download the C file, plus the rest of my works, retrieve my portfolio by way
 of the links to MediaFire supplied in the top post at my WordPress blog.)

It seems so simple: only an idiot couldn't see how to compute mutations in this
manner, right? However, although I first encountered the problem when I was but
a wee lass, & although I finally discovered the formula for permutations and
N-ary counters after the better part of two !@#$ decades, I yet fail to grok
_why_ the "bounded sliding windows" illustrated by itertools successfully choose
only the combinations. (The best I can do is "because they're in sort order?")

Anyway, the procedure is woefully uncomplicated:
append on the prefix an unchosen item from the set, then either...
 [remaining choices > 0] recurse, having culled chosen item (unless in N-ary
 mode); and, if in Combination mode, having culled
 items subsequent to the sliding window (set[i]),
... or ...
 [choices == 0] print chosen items, which are a mutation, & continue

I'm sure you can see that this whole procedure would be a lot faster if I wasn't
spending precious clock ticks spelunking the dreaded caves of malloc(). A global
array of arrays with entries for each prefix length would really speed things up
-- as would splitting the mutater into three different functions, to eliminate
the branching instructions ("if-else," "switch," and "(predicate) ? a : b").

However, I recommend you don't bother trying to write it faster in C. What with
the huge cache memories CPUs have these days, it's probably plenty zippy. Even
though it _can_ be faster in C, it could be even faster in Assembler, so learn
an instruction set and assemble a core image if that's what you really want.

Until then, for all its inefficiency, Mutate-o-Matic renders about 100,000
mutations per second. That's faster than those sci-fi lockpicks in the movies.