|
From: Jean-Christophe Helary <fusion@...>
Subject: Re: [QUIZ #1] Solution by Stuart Sierra Newsgroups: gmane.lisp.cl-quiz Date: 2006-05-03 16:37:29 GMT (3 years, 8 weeks, 6 days, 4 hours and 37 minutes ago) Is it possible to suggest that the CAPTCHA must be "easily" localizable ? By abstarcting the translatable strings for ex ? I would see another problem, namely the structure of the end string. This structure should be also abstracted to a certain point so that languages that do not use a structure similar to English (Japanese for ex) could still make use of the code. How hard would that be to have a "source" file including things like key=value for the localizable strings: initial-state-string_1="something in English" initial-state-string_1="something else in English" that would be parsed for display, and easily translatable to any other language and a "pattern" model that would be parsed to create the "generate- question" code ? (I am asking because I am not a programmer by any stretch of the imagination, I am just here to look at some short code and learn from it, and I don't intend to be disruptive with my questions, but it happens that I am also a translator in real life and that it is one of the reasons I got interested in Lisp) Sincere regards, Jean-Christophe Helary On 2006/05/04, at 0:07, Stuart Sierra wrote: > This is very similar to Joseph Abrahamson's solution. The main > difference is that I use separate databases for each part of the > question: the initial set-up, the operation (addition or > subtraction), and the final question. I also got a little silly > with the text of the questions. > > This code can be extended to other operations by adding to the > *operations* list and creating another *Xstrings* list, where X is > the symbol name of the operation (e.g. +, -, *, ...). > > My goal was to add enough "noise" to the question that it could not > be solved by simple text calculators such as Google. It's still > pretty easy to crack this once you know the algorithm -- just scan > the question string for numbers, add or subtract them, and you've > got a 50% chance of getting the right answer. > > Code attached. > -Stuart > ;; CAPTCHA.TEXT.ARITHMETIC > > ;; version 1, released 3 May 2006 > > ;; A text-based CAPTCHA (completely automated public Turing test to > ;; tell computers and humans apart) in ANSI Common Lisp. > > ;; This Lisp package has one public function, GENERATE-CAPTCHA, called > ;; with no arguments. It returns two strings, the first containing a > ;; question and the second containing the answer. The answer will > ;; always be in the form of numerical digits. > > ;; Example: > > ;; > (generate-captcha) > ;; "You started out with three Lisp Machines. You bought ten. In the > ;; end, how many did you have?" > ;; "13" > > > ;; Copyright 2006 Stuart Sierra > > ;; This program is free software; you can redistribute it and/or > modify > ;; it under the terms of the GNU General Public License as > published by > ;; the Free Software Foundation; either version 2 of the License, or > ;; (at your option) any later version. > > ;; This program is distributed in the hope that it will be useful, > ;; but WITHOUT ANY WARRANTY; without even the implied warranty of > ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > ;; GNU General Public License for more details. > > ;; You should have received a copy of the GNU General Public License > ;; along with this program; if not, write to the Free Software > ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA > 02110-1301 USA > > ;; CAPTCHA is a trademark of Carnegie Mellon University > > > (in-package :common-lisp-user) > > ;; package names should be descriptive ;) > (defpackage :com.stuartsierra.captcha.text.arithmetic > (:nicknames :captcha) > (:use :common-lisp) > (:export #:generate-captcha)) > > (in-package :com.stuartsierra.captcha.text.arithmetic) > > (defvar *min-initial-value* 12) > (defvar *max-initial-value* 50) > (defvar *min-delta-value* 2) > (defvar *max-delta-value* 10) > > (defvar *operations* > (list '+ '-)) > > (defvar *initial-state-strings* > (list "You started out with ~a." > "Before, you had ~a." > "In the beginning, there were ~a." > "Once upon a time, you had ~a." > "You were in possession of ~a." > "In the vague, distant past, ~a were your pride and joy.")) > > (defvar *+strings* > (list "Beneficent aliens from planet Grog gave you ~a." > "Your third cousin Warrl died and you inherited his ~a." > "By devious and suble means, you acquired an additional ~a." > "You quit your job and got ~a as part of your severance package." > "You lost them all in a stock deal, but then you got them all back > plus ~a." > "You bought ~a.")) > > (defvar *-strings* > (list "When you least expected it, your best friend turned on you > and stole ~a." > "Just as you were starting to enjoy them, ~a ran away." > "But, tragically, ~a went off to that big something-or-other in > the sky." > "However, ~a didn't feel like sticking around, and left." > "After a few years, ~a and you didn't get along any more, so they > left." > "Not through any fault of your own, you lost ~a.")) > > (defvar *question-strings* > (list "When all is said and done, what did you end up with?" > "How many did you have after that?" > "By the end of the story, you had how many?" > "Years later, when you were reflecting on this whole sordid > process, you counted up how many you had. What was the result?" > "What number did you have then, after you got over the emotional > shock?" > "Tell me how many you had when you finished.")) > > (defvar *nouns* > (list "apples" "ponies" "pieces of fruit" "PDP-10s" "laptops" > "clones of William Shatner" "Lisp Machines" "ice cream cones" > "lollipops" "oranges" "brown paper packages tied up with string" > "first-edition Superman comic books" "pairs of stiletto heels")) > > > > (defun pick-random (list) > (nth (random (length list)) list)) > > (defun random-range (min max) > (+ min (random (- max min)))) > > (defun format-quantity (number noun) > (format nil "~r ~a" number noun)) > > > > (defun generate-initial-state-string (initial-value noun) > (format nil (pick-random *initial-state-strings*) > (format-quantity initial-value noun))) > > (defun generate-change-string (operation delta-value noun) > (format nil (pick-random > (symbol-value > (find-symbol > (concatenate 'string "*" > (symbol-name operation) > (symbol-name :strings*)) ; to allow for lowercase readers > :com.stuartsierra.captcha.text.arithmetic))) > (format-quantity delta-value noun))) > > (defun generate-question (operation initial-value delta-value) > (let ((noun (pick-random *nouns*))) > (format nil "~a ~a ~a" > (generate-initial-state-string initial-value noun) > (generate-change-string operation delta-value noun) > (pick-random *question-strings*)))) > > (defun generate-answer (operation initial-value delta-value) > (format nil "~d" (funcall operation initial-value delta-value))) > > > > (defun generate-captcha () > (let ((initial-value (random-range *min-initial-value* *max- > initial-value*)) > (operation (pick-random *operations*)) > (delta-value (random-range *min-delta-value* *max-delta-value*))) > (values (generate-question operation initial-value delta-value) > (generate-answer operation initial-value delta-value)))) > _______________________________________________ > quiz mailing list > quiz@... > http://common-lisp.net/cgi-bin/mailman/listinfo/quiz |
|
|