Skip to content

Fix failing tests involving unicode chars #88

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ RUN apk update && \

RUN rm /var/cache/apk/*

ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8

WORKDIR /opt/test-runner
COPY . .
ENTRYPOINT ["/opt/test-runner/bin/run.sh"]
31 changes: 31 additions & 0 deletions tests/example-unicode/example-unicode-test.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
;;; example-unicode-test.el --- Parallel Letter Frequency (exercism) -*- lexical-binding: t; -*-

;;; Commentary:

;;; Code:


(load-file "example-unicode.el")
(declare-function calculate-frequencies "example-unicode.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 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 '("ø" "φ" "ほ" "本"))))))


(provide 'example-unicode-test)
;;; example-unicode-test.el ends here
77 changes: 77 additions & 0 deletions tests/example-unicode/example-unicode.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
;;; example-unicode.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" "example-unicode.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 'example-unicode)
;;; example-unicode.el ends here
13 changes: 13 additions & 0 deletions tests/example-unicode/expected_results.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": 2,
"status": "pass",
"message": null,
"tests": [
{
"name": "unicode-letters",
"test_code": "(let ((expected (make-hash-table :test 'equal)))\n (puthash ?ø 1 expected)\n (puthash ?φ 1 expected)\n (puthash ?ほ 1 expected)\n (puthash ?本 1 expected)\n (should (hash-table-contains expected (calculate-frequencies '(\"ø\" \"φ\" \"ほ\" \"本\")))))",
"status": "pass",
"message": null
}
]
}