Цитата:
Дан большой текст input.txt.
Нужно посчитать, сколько раз в нём встречается каждое слово.
Разделителями считаются все символы, кроме a-z и A-Z.
Заглавные буквы превращать в строчные. 
Откровенно простая задача, это всё равно что сравнивать сапёрную лопатку и бульдозер для вскапывания клумбы. Объём "служебных" операций, типа всякого рода циклов и операций ввода/вывода, которые во всех языках примерно одинаковы, будет сравним с самой логикой. Попробуй вместо этого более другую задачу, например трансляцию математических формул, записаную в человечьем стиле, в вид, пригодный для вычислений на компьютере, последующую компиляцию и выполнение полученного. В зависимости от "фичастости" такого транслятора, я думаю объём кода и скорость выполнения будет разниться на порядки.
Цитата:
Был бы рад увидеть хорошие решения на Лиспе и Питоне
(или на других языках, подходящих к этой задачке). 
Советую потеребить знатоков Перла. На нём должно в пару строк решаться.
Цитата:
Есть ли ассоциативные массивы в стандартных библиотеках чистого Си?
Есть. Что-то вроде такого:
Код:
struct {
  char * key;
  int value;
} assoc;
struct assoc assocar [];
Цитата:
В текстах программ не считал пустые строки и комментарии.
Считать строки вообще - неполезное развлечение. В Лисп-программу можно при желании в одну строку записать, в С - почти всю. А ещё есть obfuscated code  
 
 Цитата:
C++ - 50 строк, работает 0.6 секунды.
Ну запости сюда тоже, для "зверинца" 

Вот один из вариантов на Лиспе:
Код:
(defmacro how-many (obj ha) `(values (gethash ,obj ,ha 0)))
(defmacro 2list (h) `(let ((l nil)) (progn (maphash (lambda (k v) (setq l (cons (list k v) l))) ,h) l)))
(defun count-it (obj ha) (unless (null obj) (incf (how-many obj ha))))
(defun get-words (instr words &optional cur-word)
    (let ((c (read-char instr nil)))
        (cond 
            ((null c) words)
            ((alpha-char-p c) (get-words instr words (concatenate 'string cur-word (string (char-downcase c)))))
            (t (progn (count-it cur-word words) (get-words instr words))))))
   
(let ((ostr (open "output.txt" :direction :output :if-exists :rename-and-delete :if-does-not-exist :create)))
    (dolist (x (sort 
        (2list (get-words (open "input.txt" :direction :input) (make-hash-table :test 'equal)))
        (lambda (a b) (string< (first a) (first b))))) 
    (format ostr "~A ~D~%" (first x) (second x)))
    (close ostr))
(quit)
И заодно на С:
Код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct word {char * it; int cnt;};
int mystrcmp (char ** a, char ** b) {
    return  strcmp (*a, *b);
}
int main (int argc, char * argv []) {
    int bufsize = 1024;
    int wordsize = 256;
    int bufcnt = 0, wordcnt = 0;
    FILE * f = fopen ("input.txt", "r");
    char * buf = malloc (1024), ** words = (char **) malloc (256 * sizeof (char *));
    char inword = 0;
    int i, cnt;
    char * prev;
    buf [0] = 0;
    while (EOF != (i = fgetc (f))) {
        if (isalpha (i)) inword = 1, buf [bufcnt++] = (char) tolower (i);
        else if (inword) inword = 0, buf [bufcnt++] = 0;
        if (bufsize == bufcnt) bufsize += 1024, buf = realloc (buf, bufsize);
    }
    fclose (f);
    if (inword) inword = 0, buf [bufcnt++] = 0;
    words [0] = buf;
    bufcnt--;
    for (i = 1; i < bufcnt ; i++) {
        if (!buf [i]) words [wordcnt++] = &buf [i + 1];
        if (wordcnt == wordsize) wordsize += 256, words = realloc (words, wordsize * sizeof (char *));
    }
    qsort (words, wordcnt, sizeof (char *), (int (*)(const void*,const void*)) mystrcmp);
    inword = 1;
    cnt = 0;
    prev = "";
    for (i = 0; i < wordcnt; i++) {
        inword = strcmp (prev, words [i]);
        if (inword) {
            if (i) printf (" %i\n", cnt);
            cnt = 1;
            prev = words [i];
            printf ("%s", prev);
        } else cnt++;
    }
    printf (" %i\n", cnt);
    return 0;
}
ЗЫ Выяснили, что код на Лиспе ниже, но шире кода на Питоне  
