Generating a quiz in Emacs Lisp?
Forgive the "duplicate" question. I'd like to see this solved in Emacs Lisp too, and if I just tagged it for both topics, I probably would have only gotten one answer. The Emacs answer should be sufficiently different that it's probably worthwhile to have it.
I want to teach myself Spanish and I've got several word lists like the data show below. How can I generate a quiz from th开发者_JAVA百科e data that looks like this?
amarillo? [ ] blue [ ] yellow [ ] gray [ ] pink azul? [ ] red [ ] blue [ ] green [ ] orange . . . verde? [ ] purple [ ] gold [ ] green [ ] black
The idea is to randomly include the answer with 3 randomly chosen incorrect answers. Ideally, the incorrect answers would not be too repetitive.
amarillo|yellow azul|blue blanco|white dorado|golden gris|gray marrón|brown naranja|orange negro|black oro|gold púrpura|purple rojo|red rosa|pink verde|green
Ok, so I'm assuming that you have the input in a file opened in an Emacs buffer.
(defun insert-quiz (a-buffer) (interactive "bBuffer name: ") (let* ((question-pairs (split-string (with-current-buffer a-buffer (buffer-string)))) (quiz-answers (mapcar (lambda (x) (cadr (split-string x "|"))) question-pairs))) (insert (apply #'concat (mapcar (lambda (x) (let ((q-pair (split-string x "|"))) (make-question (car q-pair) (answers-list quiz-answers (cadr q-pair))))) question-pairs)))))
insert-quiz is an interactive function that takes a buffer name, and uses the stuff in that buffer to generate a quiz for you, then insert that quiz at point as a side-effect. It calls some smaller functions which I'll explain below.
(defun make-question (question answers) (apply #'format "%-16s[ ] %-16s[ ] %-16s[ ] %-16s[ ] %s \n" (append (list (concat question "?")) answers)))
make-question takes a question and a list of answers, and formats them as one line of the quiz.
(defun answers-list (quiz-answers right-answer) (replace (n-wrong-answers quiz-answers right-answer) (list right-answer) :start1 (random 3)))
answers-list takes a list of all possible answers in the quiz, and the right answer and uses n-wrong-answers to create a list of four answers, one of which is the correct one.
(defun n-wrong-answers (answer-list right-answer &optional answers) (if (= 4 (list-length answers)) answers (n-wrong-answers answer-list right-answer (add-to-list 'answers (random-wrong-answer answer-list right-answer)))))
n-wrong-answers takes a list of all possible answers in the quiz, and the right answer, then uses random-wrong-answer to return a list of four unique incorrect answers.
(defun random-wrong-answer (answer-list right-answer) (let ((gen-answer (nth (random (list-length answer-list)) answer-list))) (if (and gen-answer (not (string= gen-answer right-answer))) gen-answer (random-wrong-answer answer-list right-answer))))
Finally, at the lowest level, random-wrong-answer takes a list of all possible answers in the quiz, and returns a single wrong answer.
After you load the above functions into Emacs, use M-x insert-quiz and type the name of the buffer you have your input loaded into (you'll get tab completion). It wouldn't be too difficult to change the insert-quiz function so that it takes a filename rather than an open buffer-name.
The input you list above will yield:
amarillo? [ ] yellow [ ] orange [ ] gray [ ] red azul? [ ] gold [ ] purple [ ] blue [ ] orange blanco? [ ] pink [ ] red [ ] white [ ] black dorado? [ ] yellow [ ] golden [ ] red [ ] orange gris? [ ] red [ ] pink [ ] gray [ ] green marrón? [ ] brown [ ] yellow [ ] white [ ] golden naranja? [ ] orange [ ] gold [ ] black [ ] golden negro? [ ] pink [ ] black [ ] blue [ ] white oro? [ ] red [ ] gold [ ] purple [ ] brown púrpura? [ ] purple [ ] orange [ ] gray [ ] black rojo? [ ] gray [ ] red [ ] black [ ] pink rosa? [ ] red [ ] green [ ] pink [ ] yellow verde? [ ] green [ ] purple [ ] red [ ] brown
Hope that helps.
精彩评论