diff --git a/config.json b/config.json index 1a6f661..8204ffc 100644 --- a/config.json +++ b/config.json @@ -910,6 +910,14 @@ "practices": [], "prerequisites": [], "difficulty": 5 + }, + { + "slug": "parallel-letter-frequency", + "name": "Parallel Letter Frequency", + "uuid": "3daf3903-1eb0-49b9-827a-76e6b7ca25fb", + "practices": [], + "prerequisites": [], + "difficulty": 10 } ] }, diff --git a/exercises/practice/parallel-letter-frequency/.docs/instructions.append.md b/exercises/practice/parallel-letter-frequency/.docs/instructions.append.md new file mode 100644 index 0000000..b58c60a --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.docs/instructions.append.md @@ -0,0 +1,9 @@ +# Instructions append + +## Using Parallelism + +The goal of this exercise is to practice parallelism with Emacs Lisp. + +In Emacs Lisp this can be achieved by using [`asynchronous processes`](https://www.gnu.org/software/emacs/manual/html_node/elisp/Asynchronous-Processes.html#:~:text=An%20asynchronous%20process%20is%20controlled,%2Dtype%20(see%20below)). + +You may also want to look at the documentation for [`batch mode`](https://www.gnu.org/software/emacs/manual/html_node/elisp/Batch-Mode.html), [`sentinels`](https://www.gnu.org/software/emacs/manual/html_node/elisp/Sentinels.html) and [`receiving output from processes`](https://www.gnu.org/software/emacs/manual/html_node/elisp/Output-from-Processes.html). diff --git a/exercises/practice/parallel-letter-frequency/.docs/instructions.md b/exercises/practice/parallel-letter-frequency/.docs/instructions.md new file mode 100644 index 0000000..6147b90 --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.docs/instructions.md @@ -0,0 +1,7 @@ +# Instructions + +Count the frequency of letters in texts using parallel computation. + +Parallelism is about doing things in parallel that can also be done sequentially. +A common example is counting the frequency of letters. +Employ parallelism to calculate the total frequency of each letter in a list of texts. diff --git a/exercises/practice/parallel-letter-frequency/.meta/config.json b/exercises/practice/parallel-letter-frequency/.meta/config.json new file mode 100644 index 0000000..4372e34 --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.meta/config.json @@ -0,0 +1,21 @@ +{ + "authors": [ + "kmarker1101" + ], + "contributors": [ + "fapdash", + "BNAndras" + ], + "files": { + "solution": [ + "parallel-letter-frequency.el" + ], + "test": [ + "parallel-letter-frequency-test.el" + ], + "example": [ + ".meta/example.el" + ] + }, + "blurb": "Count the frequency of letters in texts using parallel computation." +} diff --git a/exercises/practice/parallel-letter-frequency/.meta/example.el b/exercises/practice/parallel-letter-frequency/.meta/example.el new file mode 100644 index 0000000..11123bf --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.meta/example.el @@ -0,0 +1,77 @@ +;;; parallel-letter-frequency.el --- Parallel Letter Frequency (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + +(require 'cl-lib) + + +(defun clean-text (text) + (downcase (replace-regexp-in-string "[^[:alpha:]]" "" text))) + + +(defun combine-frequencies (freqs-list) + (let ((combined-freqs (make-hash-table :test 'equal))) + (dolist (freqs freqs-list) + (maphash (lambda (key value) + (puthash key (+ value (gethash key combined-freqs 0)) combined-freqs)) + freqs)) + combined-freqs)) + + +(defun calculate-frequencies (texts) + (let ((cleaned-texts (mapcar #'clean-text texts))) + (if (cl-every #'string-empty-p cleaned-texts) + (make-hash-table :test 'equal) + (let* ((num-processes (min (length cleaned-texts) (max 1 (string-to-number (shell-command-to-string "nproc"))))) + (texts-per-process (ceiling (/ (float (length cleaned-texts)) num-processes))) + (results (make-hash-table :test 'equal)) + (pending num-processes) + (final-result (make-hash-table :test 'equal)) + (processes nil)) + (dotimes (i num-processes) + (let* ((start-index (* i texts-per-process)) + (end-index (min (* (1+ i) texts-per-process) (length cleaned-texts))) + (process-texts (if (< start-index (length cleaned-texts)) + (cl-subseq cleaned-texts start-index end-index) + '()))) + (when (not (null process-texts)) + (let* ((command (prin1-to-string `(calculate-frequencies-in-subprocess ',process-texts))) + (process (make-process + :name (format "letter-freq-process-%d" i) + :buffer (generate-new-buffer (format " *letter-freq-process-%d*" i)) + :command (list "emacs" "--batch" "-l" "parallel-letter-frequency.el" "--eval" command) + :sentinel (lambda (proc _event) + (when (eq (process-status proc) 'exit) + (with-current-buffer (process-buffer proc) + (let ((result (read (buffer-string)))) + (maphash (lambda (key value) + (puthash key (+ value (gethash key results 0)) results)) + result)) + (setq pending (1- pending)) + (when (= pending 0) + (setq final-result (combine-frequencies (list results)))))))))) + (push process processes))))) + (while (> pending 0) + (sleep-for 0.1)) + final-result)))) + + +(defun calculate-frequencies-in-subprocess (texts) + (let ((freqs (make-hash-table :test 'equal))) + (dolist (text texts) + (let ((text-freqs (make-hash-table :test 'equal))) + (dolist (char (string-to-list text)) + (when (string-match-p "[[:alpha:]]" (char-to-string char)) + (puthash + char (1+ (gethash char text-freqs 0)) text-freqs))) + (maphash + (lambda (key value) + (puthash key (+ value (gethash key freqs 0)) freqs)) + text-freqs))) + (prin1 freqs))) + + +(provide 'parallel-letter-frequency) +;;; parallel-letter-frequency.el ends here diff --git a/exercises/practice/parallel-letter-frequency/.meta/tests.toml b/exercises/practice/parallel-letter-frequency/.meta/tests.toml new file mode 100644 index 0000000..0c974f7 --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.meta/tests.toml @@ -0,0 +1,49 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[c054d642-c1fa-4234-8007-9339f2337886] +description = "no texts" + +[818031be-49dc-4675-b2f9-c4047f638a2a] +description = "one text with one letter" + +[c0b81d1b-940d-4cea-9f49-8445c69c17ae] +description = "one text with multiple letters" + +[708ff1e0-f14a-43fd-adb5-e76750dcf108] +description = "two texts with one letter" + +[1b5c28bb-4619-4c9d-8db9-a4bb9c3bdca0] +description = "two texts with multiple letters" + +[6366e2b8-b84c-4334-a047-03a00a656d63] +description = "ignore letter casing" + +[92ebcbb0-9181-4421-a784-f6f5aa79f75b] +description = "ignore whitespace" + +[bc5f4203-00ce-4acc-a5fa-f7b865376fd9] +description = "ignore punctuation" + +[68032b8b-346b-4389-a380-e397618f6831] +description = "ignore numbers" + +[aa9f97ac-3961-4af1-88e7-6efed1bfddfd] +description = "Unicode letters" + +[7b1da046-701b-41fc-813e-dcfb5ee51813] +description = "combination of lower- and uppercase letters, punctuation and white space" + +[4727f020-df62-4dcf-99b2-a6e58319cb4f] +description = "large texts" + +[adf8e57b-8e54-4483-b6b8-8b32c115884c] +description = "many small texts" diff --git a/exercises/practice/parallel-letter-frequency/parallel-letter-frequency-test.el b/exercises/practice/parallel-letter-frequency/parallel-letter-frequency-test.el new file mode 100644 index 0000000..520254f --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/parallel-letter-frequency-test.el @@ -0,0 +1,289 @@ +;;; parallel-letter-frequency-test.el --- Parallel Letter Frequency (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + + +(load-file "parallel-letter-frequency.el") +(declare-function calculate-frequencies "parallel-letter-frequency.el" (texts)) + + +(defun hash-table-contains (expected actual) + (let ((result t)) + (maphash (lambda (key value) + (unless (equal (gethash key actual) value) + (setq result nil))) + expected) + result)) + + +(ert-deftest no-texts () + (let ((expected (make-hash-table :test 'equal))) + (should (hash-table-contains expected (calculate-frequencies '()))))) + + +(ert-deftest one-text-with-one-letter () + (let ((expected (make-hash-table :test 'equal))) + (puthash ?a 1 expected) + (should (hash-table-contains expected (calculate-frequencies '("a")))))) + + +(ert-deftest one-text-with-multiple-letters () + (let ((expected (make-hash-table :test 'equal))) + (puthash ?b 2 expected) + (puthash ?c 3 expected) + (puthash ?d 1 expected) + (should (hash-table-contains expected (calculate-frequencies '("bbcccd")))))) + + +(ert-deftest two-texts-with-one-letter () + (let ((expected (make-hash-table :test 'equal))) + (puthash ?e 1 expected) + (puthash ?f 1 expected) + (should (hash-table-contains expected (calculate-frequencies '("e" "f")))))) + + +(ert-deftest two-texts-with-multiple-letters () + (let ((expected (make-hash-table :test 'equal))) + (puthash ?g 2 expected) + (puthash ?h 3 expected) + (puthash ?i 1 expected) + (should (hash-table-contains expected (calculate-frequencies '("ggh" "hhi")))))) + + +(ert-deftest ignore-letter-casing () + (let ((expected (make-hash-table :test 'equal))) + (puthash ?m 2 expected) + (should (hash-table-contains expected (calculate-frequencies '("m" "M")))))) + + +(ert-deftest ignore-whitespace () + (let ((expected (make-hash-table :test 'equal))) + (should (hash-table-contains expected (calculate-frequencies '(" " "\t" "\r\n")))))) + + +(ert-deftest ignore-punctuation () + (let ((expected (make-hash-table :test 'equal))) + (should (hash-table-contains expected (calculate-frequencies '("!" "?" ";" "," ".")))))) + + +(ert-deftest ignore-numbers () + (let ((expected (make-hash-table :test 'equal))) + (should (hash-table-contains expected (calculate-frequencies '("1" "2" "3" "4" "5" "6" "7" "8" "9")))))) + + +(ert-deftest unicode-letters () + (let ((expected (make-hash-table :test 'equal))) + (puthash ?ø 1 expected) + (puthash ?φ 1 expected) + (puthash ?ほ 1 expected) + (puthash ?本 1 expected) + (should (hash-table-contains expected (calculate-frequencies '("ø" "φ" "ほ" "本")))))) + + +(ert-deftest combination-of-lower-and-uppercase-letters-punctuation-and-white-space () + (let ((expected (make-hash-table :test 'equal))) + (puthash ?a 32 expected) + (puthash ?b 4 expected) + (puthash ?c 6 expected) + (puthash ?d 14 expected) + (puthash ?e 37 expected) + (puthash ?f 7 expected) + (puthash ?g 8 expected) + (puthash ?h 29 expected) + (puthash ?i 19 expected) + (puthash ?k 6 expected) + (puthash ?l 12 expected) + (puthash ?m 7 expected) + (puthash ?n 19 expected) + (puthash ?o 22 expected) + (puthash ?p 7 expected) + (puthash ?r 17 expected) + (puthash ?s 16 expected) + (puthash ?t 30 expected) + (puthash ?u 9 expected) + (puthash ?v 2 expected) + (puthash ?w 9 expected) + (puthash ?y 4 expected) + (should (hash-table-contains expected (calculate-frequencies '("There, peeping among the cloud-wrack above a dark tower high up in the mountains, Sam saw a white star twinkle for a while. The beauty of it smote his heart, as he looked up out of the forsaken land, and hope returned to him. For like a shaft, clear and cold, the thought pierced him that in the end, the shadow was only a small and passing thing: there was light and high beauty forever beyond its reach.")))))) + + +(defvar large-text + '("I am a sick man.... I am a spiteful man. I am an unattractive man." + "I believe my liver is diseased. However, I know nothing at all about my disease, and do not" + "know for certain what ails me. I don't consult a doctor for it," + "and never have, though I have a respect for medicine and doctors." + "Besides, I am extremely superstitious, sufficiently so to respect medicine," + "anyway (I am well-educated enough not to be superstitious, but I am superstitious)." + "No, I refuse to consult a doctor from spite." + "That you probably will not understand. Well, I understand it, though." + "Of course, I can't explain who it is precisely that I am mortifying in this case by my spite:" + "I am perfectly well aware that I cannot \"pay out\" the doctors by not consulting them;" + "I know better than anyone that by all this I am only injuring myself and no one else." + "But still, if I don't consult a doctor it is from spite." + "My liver is bad, well - let it get worse!" + "I have been going on like that for a long time - twenty years. Now I am forty." + "I used to be in the government service, but am no longer." + "I was a spiteful official. I was rude and took pleasure in being so." + "I did not take bribes, you see, so I was bound to find a recompense in that, at least." + "(A poor jest, but I will not scratch it out. I wrote it thinking it would sound very witty;" + "but now that I have seen myself that I only wanted to show off in a despicable way -" + "I will not scratch it out on purpose!) When petitioners used to come for" + "information to the table at which I sat, I used to grind my teeth at them," + "and felt intense enjoyment when I succeeded in making anybody unhappy." + "I almost did succeed. For the most part they were all timid people - of course," + "they were petitioners. But of the uppish ones there was one officer in particular" + "I could not endure. He simply would not be humble, and clanked his sword in a disgusting way." + "I carried on a feud with him for eighteen months over that sword. At last I got the better of him." + "He left off clanking it. That happened in my youth, though. But do you know," + "gentlemen, what was the chief point about my spite? Why, the whole point," + "the real sting of it lay in the fact that continually, even in the moment of the acutest spleen," + "I was inwardly conscious with shame that I was not only not a spiteful but not even an embittered man," + "that I was simply scaring sparrows at random and amusing myself by it." + "I might foam at the mouth, but bring me a doll to play with, give me a cup of tea with sugar in it," + "and maybe I should be appeased. I might even be genuinely touched," + "though probably I should grind my teeth at myself afterwards and lie awake at night with shame for" + "months after. That was my way. I was lying when I said just now that I was a spiteful official." + "I was lying from spite. I was simply amusing myself with the petitioners and with the officer," + "and in reality I never could become spiteful. I was conscious every moment in myself of many," + "very many elements absolutely opposite to that. I felt them positively swarming in me," + "these opposite elements. I knew that they had been swarming in me all my life and craving some outlet from me," + "but I would not let them, would not let them, purposely would not let them come out." + "They tormented me till I was ashamed: they drove me to convulsions and - sickened me, at last," + "how they sickened me!" + "Gentlemen, I am joking, and I know myself that my jokes are not brilliant" + "but you know one can take everything as a joke. I am, perhaps, jesting against the grain." + "Gentlemen, I am tormented by questions; answer them for me. You, for instance, want to cure men of their" + "old habits and reform their will in accordance with science and good sense." + "But how do you know, not only that it is possible, but also that it is" + "desirable to reform man in that way? And what leads you to the conclusion that man's" + "inclinations need reforming? In short, how do you know that such a reformation will be a benefit to man?" + "And to go to the root of the matter, why are you so positively convinced that not to act against" + "his real normal interests guaranteed by the conclusions of reason and arithmetic is certainly always" + "advantageous for man and must always be a law for mankind? So far, you know," + "this is only your supposition. It may be the law of logic, but not the law of humanity." + "You think, gentlemen, perhaps that I am mad? Allow me to defend myself. I agree that man" + "is pre-eminently a creative animal, predestined to strive consciously for an object and to engage in engineering -" + "that is, incessantly and eternally to make new roads, wherever" + "they may lead. But the reason why he wants sometimes to go off at a tangent may just be that he is" + "predestined to make the road, and perhaps, too, that however stupid the \"direct\"" + "practical man may be, the thought sometimes will occur to him that the road almost always does lead" + "somewhere, and that the destination it leads to is less important than the process" + "of making it, and that the chief thing is to save the well-conducted child from despising engineering," + "and so giving way to the fatal idleness, which, as we all know," + "is the mother of all the vices. Man likes to make roads and to create, that is a fact beyond dispute." + "But why has he such a passionate love for destruction and chaos also?" + "Tell me that! But on that point I want to say a couple of words myself. May it not be that he loves" + "chaos and destruction (there can be no disputing that he does sometimes love it)" + "because he is instinctively afraid of attaining his object and completing the edifice he is constructing?" + "Who knows, perhaps he only loves that edifice from a distance, and is by no means" + "in love with it at close quarters; perhaps he only loves building it and does not want to live in it," + "but will leave it, when completed, for the use of les animaux domestiques -" + "such as the ants, the sheep, and so on. Now the ants have quite a different taste." + "They have a marvellous edifice of that pattern which endures for ever - the ant-heap." + "With the ant-heap the respectable race of ants began and with the ant-heap they will probably end," + "which does the greatest credit to their perseverance and good sense. But man is a frivolous and" + "incongruous creature, and perhaps, like a chess player, loves the process of the game, not the end of it." + "And who knows (there is no saying with certainty), perhaps the only goal on earth" + "to which mankind is striving lies in this incessant process of attaining, in other words," + "in life itself, and not in the thing to be attained, which must always be expressed as a formula," + "as positive as twice two makes four, and such positiveness is not life, gentlemen," + "but is the beginning of death." + "But these are all golden dreams. Oh, tell me, who was it first announced," + "who was it first proclaimed, that man only does nasty things because he does not know his own interests;" + "and that if he were enlightened, if his eyes were opened to his real normal interests," + "man would at once cease to do nasty things, would at once become good and noble because," + "being enlightened and understanding his real advantage, he would see his own advantage in the" + "good and nothing else, and we all know that not one man can, consciously, act against his own interests," + "consequently, so to say, through necessity, he would begin doing good? Oh, the babe! Oh, the pure," + "innocent child! Why, in the first place, when in all these thousands of years has there been a time" + "when man has acted only from his own interest? What is to be done with the millions of facts that bear" + "witness that men, consciously, that is fully understanding their real interests, have left them in the" + "background and have rushed headlong on another path, to meet peril and danger," + "compelled to this course by nobody and by nothing, but, as it were, simply disliking the beaten track," + "and have obstinately, wilfully, struck out another difficult, absurd way, seeking it almost in the darkness." + "So, I suppose, this obstinacy and perversity were pleasanter to them than any advantage...." + "Advantage! What is advantage? And will you take it upon yourself to define with perfect accuracy in what the" + "advantage of man consists? And what if it so happens that a man's advantage, sometimes, not only may," + "but even must, consist in his desiring in certain cases what is harmful to himself and not advantageous." + "And if so, if there can be such a case, the whole principle falls into dust. What do you think -" + "are there such cases? You laugh; laugh away, gentlemen, but only answer me: have man's advantages been" + "reckoned up with perfect certainty? Are there not some which not only have not been included but cannot" + "possibly be included under any classification? You see, you gentlemen have, to the best of my knowledge," + "taken your whole register of human advantages from the averages of statistical figures and" + "politico-economical formulas. Your advantages are prosperity, wealth, freedom, peace - and so on, and so on." + "So that the man who should, for instance, go openly and knowingly in opposition to all that list would to your thinking," + "and indeed mine, too, of course, be an obscurantist or an absolute madman: would not he? But, you know, this is" + "what is surprising: why does it so happen that all these statisticians, sages and lovers of humanity," + "when they reckon up human advantages invariably leave out one? They don't even take it into their reckoning" + "in the form in which it should be taken, and the whole reckoning depends upon that. It would be no greater matter," + "they would simply have to take it, this advantage, and add it to the list. But the trouble is, that this strange" + "advantage does not fall under any classification and is not in place in any list. I have a friend for instance ..." + "Ech! gentlemen, but of course he is your friend, too; and indeed there is no one, no one to whom he is not a friend!" + "Yes, but here I come to a stop! Gentlemen, you must excuse me for being over-philosophical;" + "it's the result of forty years underground! Allow me to indulge my fancy. You see, gentlemen, reason is an excellent thing," + "there's no disputing that, but reason is nothing but reason and satisfies only the rational side of man's nature," + "while will is a manifestation of the whole life, that is, of the whole human life including reason and all the impulses." + "And although our life, in this manifestation of it, is often worthless, yet it is life and not simply extracting square roots." + "Here I, for instance, quite naturally want to live, in order to satisfy all my capacities for life, and not simply my capacity" + "for reasoning, that is, not simply one twentieth of my capacity for life. What does reason know? Reason only knows what it has" + "succeeded in learning (some things, perhaps, it will never learn; this is a poor comfort, but why not say so frankly?)" + "and human nature acts as a whole, with everything that is in it, consciously or unconsciously, and, even it if goes wrong, it lives." + "I suspect, gentlemen, that you are looking at me with compassion; you tell me again that an enlightened and developed man," + "such, in short, as the future man will be, cannot consciously desire anything disadvantageous to himself, that that can be proved mathematically." + "I thoroughly agree, it can - by mathematics. But I repeat for the hundredth time, there is one case, one only, when man may consciously, purposely," + "desire what is injurious to himself, what is stupid, very stupid - simply in order to have the right to desire for himself even what is very stupid" + "and not to be bound by an obligation to desire only what is sensible. Of course, this very stupid thing, this caprice of ours, may be in reality," + "gentlemen, more advantageous for us than anything else on earth, especially in certain cases. And in particular it may be more advantageous than" + "any advantage even when it does us obvious harm, and contradicts the soundest conclusions of our reason concerning our advantage -" + "for in any circumstances it preserves for us what is most precious and most important - that is, our personality, our individuality." + "Some, you see, maintain that this really is the most precious thing for mankind; choice can, of course, if it chooses, be in agreement" + "with reason; and especially if this be not abused but kept within bounds. It is profitable and some- times even praiseworthy." + "But very often, and even most often, choice is utterly and stubbornly opposed to reason ... and ... and ... do you know that that," + "too, is profitable, sometimes even praiseworthy? Gentlemen, let us suppose that man is not stupid. (Indeed one cannot refuse to suppose that," + "if only from the one consideration, that, if man is stupid, then who is wise?) But if he is not stupid, he is monstrously ungrateful!" + "Phenomenally ungrateful. In fact, I believe that the best definition of man is the ungrateful biped. But that is not all, that is not his worst defect;" + "his worst defect is his perpetual moral obliquity, perpetual - from the days of the Flood to the Schleswig-Holstein period.")) + + +(ert-deftest large-texts () + (let ((expected (make-hash-table :test 'equal))) + (puthash ?a 845 expected) + (puthash ?b 155 expected) + (puthash ?c 278 expected) + (puthash ?d 359 expected) + (puthash ?e 1143 expected) + (puthash ?f 222 expected) + (puthash ?g 187 expected) + (puthash ?h 507 expected) + (puthash ?i 791 expected) + (puthash ?j 12 expected) + (puthash ?k 67 expected) + (puthash ?l 423 expected) + (puthash ?m 288 expected) + (puthash ?n 833 expected) + (puthash ?o 791 expected) + (puthash ?p 197 expected) + (puthash ?r 432 expected) + (puthash ?q 8 expected) + (puthash ?s 700 expected) + (puthash ?t 1043 expected) + (puthash ?u 325 expected) + (puthash ?v 111 expected) + (puthash ?w 223 expected) + (puthash ?x 7 expected) + (puthash ?y 251 expected) + (should (hash-table-contains expected (calculate-frequencies (split-string (mapconcat 'identity large-text "\n") "\n")))))) + + +(ert-deftest many-small-texts () + (let ((expected (make-hash-table :test 'equal))) + (puthash ?a 50 expected) + (puthash ?b 100 expected) + (puthash ?c 150 expected) + (should (hash-table-contains expected (calculate-frequencies '("abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc" "abbccc")))))) + + +(provide 'parallel-letter-frequency-test) +;;; parallel-letter-frequency-test.el ends here diff --git a/exercises/practice/parallel-letter-frequency/parallel-letter-frequency.el b/exercises/practice/parallel-letter-frequency/parallel-letter-frequency.el new file mode 100644 index 0000000..2bda046 --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/parallel-letter-frequency.el @@ -0,0 +1,14 @@ +;;; parallel-letter-frequency.el --- Parallel Letter Frequency (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + + +(defun calculate-frequencies (texts) + (error "Delete this S-Expression and write your own implementation")) + + +(provide 'parallel-letter-frequency) +;;; parallel-letter-frequency.el ends here +