Цитата:
Дан большой текст 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;
}
ЗЫ Выяснили, что код на Лиспе ниже, но шире кода на Питоне