May
14
Posted on 14-05-2007
Filed Under (Erlang, Programming) by Federico Feroldi on 14-05-2007

After seeing the Peter Norvig‘s implementation of a Spell corrector in 20 lines of python code, I would like to add an Erlang implementation to the perl6 one made by Gabriele.

Unfortunately I’m blocked by an issue I’m still trying to solve. (update: thanks to your suggestions I’ve solved the “folding” issue)

Here’s what I did until now:

(Note: I followed Peter Norvig’s naming for functions as much as possible.)

The words/1 function takes a binary representation of the reference text file and build a list of words:

words(Bin) ->
    {ok, Words} = regexp:split(binary_to_list(Bin), "[^a-zA-Z]"),
    lists:map(fun(X) -> string:to_lower(X) end, Words).

The train/1 function takes a list of words and creates a Set of lower case words with associated frequency:

train(Words) ->
    Dict = ets:new(dictionary, [set]),
    lists:foreach(fun(X) ->
        case ets:insert_new(Dict, {list_to_binary(X), 1}) of
            false -> ets:update_counter(Dict, list_to_binary(X), 1);
            true -> true
        end
    end, Words),
    Dict.

And finally the build_dict/1 function takes a filename and returns the associated word Set:

build_dict(Filename) ->
    {ok, Bin} = file:read_file(Filename),
    train(words(Bin)).

Then there’s the function that generates all the possible “mistakes” from a word. This function is actually made of four different functions that generates different kind of errors:

alphabet() ->
    "abcdefghijklmnopqrstuvwxyz".

deletion_edits(Word) ->
    deletion_edits([], Word, []).
deletion_edits(_, [], Edits) ->
    Edits;
deletion_edits(Before, [Current | After], Edits) ->
	deletion_edits([Current | Before], After,
		[lists:reverse(Before) ++ After | Edits]).

transposition_edits(Word) ->
    transposition_edits([], Word, []).
transposition_edits(_, [], Edits) ->
    Edits;
transposition_edits(_, [_], Edits) ->
    Edits;
transposition_edits(Before, [Current, Next | After], Edits) ->
	transposition_edits([Current | Before], [Next | After],
		[ lists:reverse(Before) ++ [Next, Current] ++ After | Edits]).

alteration_edits(Word) ->
    alteration_edits([], Word, []).
alteration_edits(_, [], Edits) ->
    Edits;
alteration_edits(Before, [Current | After], Edits) ->
	BeforeR = lists:reverse(Before),
	alteration_edits([Current | Before], After,
		[BeforeR ++ [X] ++ After || X <- alphabet()] ++ Edits).

insertion_edits(Word) ->
    insertion_edits([], Word, [[X] ++ Word || X <- alphabet()]).
insertion_edits(_, [], Edits) ->
    Edits;
insertion_edits(Before, [Current | After], Edits) ->
	BeforeR = lists:reverse(Before),
	insertion_edits([Current | Before], After,
		[BeforeR ++ [Current, X] ++ After || X <- alphabet()] ++
		Edits).

We have edits1/1 that generates the 1-level error words and edits1/2 that generates the 2-level (errors of errors) words:

edits1(Word) ->
    lists:usort(deletion_edits(Word) ++ transposition_edits(Word) ++ alteration_edits(Word) ++ insertion_edits(Word)).
edits2(Word) ->
	lists:usort(lists:foldr(fun(A, AccIn) ->
		AccIn ++ edits1(A)
	end, [], edits1(Word))).

The problem is on the edits2/1 function, it generates a list made of sublists but I want it to generate a single flat list instead. I've tryed lists:flatten/1 but it flattens strings too, I need time to find the correct function...

Here's the known/2 function that filters a list of words by returning only the words present in the dictionary:

known(Words, Dict) ->
	lists:filter(fun(Word) ->
		ets:member(Dict, list_to_binary(Word))
	end, Words).

And then there's the gen_candidates/2 function that generates the possible correct words from the mispelled one:

gen_candidates(Word, Dict) ->
	C1 = known([Word], Dict),
	case (length(C1) > 0) of
		true ->
			[Word];
		false ->
			C2 = known(edits1(Word), Dict),
			case (length(C2) > 0) of
				true ->
					C2;
				false ->
					C3 = known(edits2(Word), Dict),
					case (length(C3) > 0) of
						true -> C3;
						false -> [Word]
					end
			end
	end.

And finally the correct/2 function that takes a mispelled word and returns the most probable correct one:

correct(Word, Dict) ->
	lists:foldl(fun(W, {CN, CW}) ->
		case ets:lookup(Dict, list_to_binary(W)) of
			[{LW, LN}] ->
				case LN > CN of
					true -> {LN, LW};
					false -> {CN, CW}
				end;
			_ ->
				{CN, CW}
		end
	end, {0, Word}, gen_candidates(Word, Dict)).

At this point I started trying some words on the shell:

5> Dict = spellcheck:build_dict("big.txt").
14
6> spellcheck:known(["hello", "helo"], Dict).
["hello"]
7> spellcheck:known(["hello", "helo", "true"], Dict).
["hello","true"]
8> spellcheck:gen_candidates("hello", Dict).
["hello"]
9> spellcheck:gen_candidates("helo", Dict).
["felo","halo","held","hell","hello","helm","help","hero"]
10> spellcheck:correct("helo", Dict).
{287,<<"held">>}
11> spellcheck:correct("correctz", Dict).
{38,<<"correct">>}
12> spellcheck:correct("correc", Dict).
{38,<<"correct">>}
13> spellcheck:correct("gues", Dict).
{112,<<"guns">>}
14> spellcheck:correct("guess", Dict).
{17,<<"guess">>}
15> spellcheck:correct("gues", Dict).
{112,<<"guns">>}
16> spellcheck:correct("gue", Dict).
{249,<<"due">>}

It seems to work! :)

In the next iteration I'll try to optimize and refactor the code, in special way for the edits generators that are too long for my tastes... Suggestions are welcome! :)

Share and Enjoy:
  • Digg
  • del.icio.us
  • DZone
  • Reddit
  • Technorati
  • YahooMyWeb

Comments

Planet Erlang on 14 May, 2007 at 7:46 pm #

Spell corrector (aka Google suggest) in Erlang (first iteration)


PDI^2 on 15 May, 2007 at 9:08 am #

restituisce semplicemente un grosso array con tutte le variazioni. Paragonando questo codice a quello di norvig noterete che lui usa i Set in edits1 mentre noi usiamo semplici liste, ma va bene perché non ci sono duplicati tra le variazioni. Federico credo faccia la stessa cosa in erlang [IMG :) ] Ora serve una funzione known(@array) che selezioni gli elementi della lista che sono parole valide. Ricordate che abbiamo una variabile %WORDS{word}=>number che abbiamo inizializzato con le parole del vocabolario e la loro


Bob Ippolito on 14 May, 2007 at 1:34 am #

Try lists:append/1.


Jordan Wilberding on 14 May, 2007 at 3:07 am #

Not sure this is what you need, but maybe this is what you need to flatten?

> lists:flatmap(fun(A) -> A end, [["ABC"],["DEF"],["GHI"]]).
["ABC","DEF","GHI"]

And, if you ran it again..

> lists:flatmap(fun(A) -> A end, ["ABC","DEF","GHI"]).
“ABCDEFGHI”


riffraff on 14 May, 2007 at 8:55 am #

Ah, great post :)
It seems that python’s list comprehension have a little advantage over erlangs by allowing iteration over multiplethings at the same time and allowing you to avoid explicit flattening. Unexpected :)

Oh, and maybe in words/1 you could use the fun string:to_lower/1 syntax instead of defining an anonymous function to call that?


mark bradley on 14 May, 2007 at 9:28 am #

flatmap(Function, List1) -> Element

Types:
Function = fun(A) -> B
List1 = [A]
Element = [B]

flatmap behaves as if it had been defined as follows:

flatmap(Func, List) ->
append(map(Func, List))

this function might be useful for implementing edits2/1

e.g.

edits2(Word) -> flatmap(edits1, edits1(Word))


Steve Jenson on 14 May, 2007 at 9:32 am #

Use the fold, Luke!

106> Fun = fun(A, AccIn) -> AccIn ++ A end.
#Fun
107> lists:foldr(Fun, [], [["aa", "bb"], ["cc"]]).

I’m porting my Haskell port of Norvig’s spellchecker to Erlang. I’ll throw something in SVN in a few days and we can compare notes!


massemanet on 14 May, 2007 at 10:53 am #

i believe you want the lists:append/1 function.


Federico Feroldi on 14 May, 2007 at 11:18 am #

Wow, thank’s for all these useful comments!

Riffraff: I did some timings and I found a weird results, if I used and indirect call to string:to_lower/1 with an anonymous fun I gained about 30% in speed!

Jordan, Mark, Steve, massemanet: thanks for your suggestions, I’ll try with that this afternoon! :)

cheers


[...] Spell corrector (aka Google suggest) in Erlang (first part) (pixzone.com) [...]


[...] A version in Erlang! [...]


Mike McNally on 14 May, 2007 at 9:26 pm #

The “alphabet” function is just “lists:seq($a, $z)”.

It might be nice to implement a “position fold” function that would iteratively pass into a parameter function a binary, a position (integer), and an accumulator. Then you could write your “edits” functions in terms of simple calls to that.


Steve Jenson on 14 May, 2007 at 9:36 pm #

I don’t think alphabet needs to be a function at all. You can use an Erlang macro.


Federico Feroldi on 14 May, 2007 at 10:52 pm #

Mike, I didn’t wanted to use a “position counter” because in that case you have to go through all the Nth items each time to split the string.

The best optimization I can think of is to just create a single edits generator that gets the two parts of the string and applies the different algorithms.

[h,e|llo] -> “hllo” (deletion), “heallo” … “hezllo” (insertion), “hallo” … “hzllo” (alteration), “hlelo” (transposition)

But I suspect that you’ll just gain some function calls overheads.
It would be nice to use lists comprehension to like Peter did in python.


links for 2007-05-14 -- A Tempest of Thoughts on 15 May, 2007 at 1:30 am #

[...] Spell corrector (aka Google suggest) in Erlang (first iteration) | the pix zone My good friend’s Federico take on spell corrector, this time in Erlang. (tags: erlang programming spelling) [...]


mark bradley on 15 May, 2007 at 1:34 am #

you can use list comprehensions like peter did,

you would just need to create a slice function

or use the sub_string function in the string module


mark bradley on 15 May, 2007 at 4:28 am #

i rewrote edits1 to use list comprehensions:

edits1(Word) ->
N = length(Word),
SEQ = if N []; true -> lists:seq(1,N) end,
SEQM1 = if N []; true -> lists:seq(1,N-1) end,
SEQP1 = lists:seq(1,N+1),
ALPHA = alphabet(),
lists:usort([lists:concat([string:sub_string(Word,1,I-1),string:sub_string(Word,I+1)]) || I


mark bradley on 15 May, 2007 at 4:32 am #

check out my code here: http://www.cse.unsw.edu.au/~markb/spell.erl

sorry about the formatting of the previous post…didnt know there was a problem with it


Steve Jenson on 15 May, 2007 at 7:32 am #

You can also use lists:sublist:

delete(Word) ->
LW = length(Word),
[sublist(Word, I) ++ sublist(Word, I+2, LW) || I <- seq(0, LW-1)].


kobi on 15 May, 2007 at 12:11 pm #

I think most spelling mistakes are related to the keymap.
that is, qwerty.
helo to held is less likely than helo to help.
(p is near o, and d is far from o)
maybe u can use this method to determine which candidate (from the various suggestion techniques) is more likely.

gue is probably glue and not due
gues is probably guess and not guns

(letter miss more likely than far keyboard character)
but all this in assumption that the keyboard is qwerty


Mike McNally on 15 May, 2007 at 1:56 pm #

*** Mike, I didn’t wanted to use a “position counter” because in that case you have to go through all the Nth items each time to split the string.

You didn’t read exactly what I wrote: if you use binary data instead of lists, you can “index” into your strings with an integer. It’s also cheaper than all those “++” expressions, which really should be avoided.

The formatting is going to be all messed up, but here’s a “position fold” using binaries:

pos_foldl(Fun, Initial, List) -> pos_foldl(Fun, Initial, 0, list_to_binary(List)).
pos_foldl(Fun, Accum, Count, Binary) ->
case Binary of
> -> Fun(Before, >, Accum);
> ->
pos_foldl(Fun, Fun(Before, After, Accum), Count + 1, Binary)
end.

And here’s the “deletion_edit” written in terms of that:

deletion_edit(Word) ->
lists:reverse(pos_foldl(fun
(_, >, Accum) -> Accum;
(Before, >, Accum) -> [> | Accum]
end, [], Word)).


Mike McNally on 15 May, 2007 at 2:17 pm #

At the URL:

http://gutfullofbeer.net/word.html

is a more complete example of how such “string” manipulations can be done more efficiently (I think) with binaries instead of lists.

Those “edit” examples make lists of binaries.


andrew cooke on 15 May, 2007 at 10:14 pm #

gen_candidates(Word, Dict) ->
lookup(Word, Dict, [fun edits1/1, fun edits2/1, fun edits3/1], “”).

lookup(_Word, _Dict, _Edits, Found) when length(Found) > 0 -> Found;
lookup(_Word, _Dict, [], “”) -> Word;
lookup(Word, Dict, [Edit|Edits], “”) ->
lookup(Word, Dict, Edits, known(Edits(Word), Dict)).

(untested)


andrew cooke on 15 May, 2007 at 10:20 pm #

or

gen_candidates(Word, Dict) ->
Lookup =
fun(Edit, “”) -> known(Edit(Word), Dict);
(Edit, Found) -> Found
end,
case lists:foldl(Lookup, “”, [fun edits1/1, fun edits2/1, fun edits3/1]) of
“” -> Word;
Found -> Found
end.

there may be a list library function that does something like this?


Federico Feroldi on 15 May, 2007 at 10:29 pm #

Mike, cool thanks! I didn’t knew that with binaries you can index by position!
I’ll try that soon!
cheers


How to Write a Spelling Corrector on 16 May, 2007 at 5:24 am #

[...] Erlang: by Federico Feroldi [...]


[...] Erlang: by Federico Feroldi [...]


[...] a questa versione in Scheme, che però mi sembra parecchio meno comprensibile. UPDATE2: Anche una versione in erlang ed una in perl6. Daiche ci sono un sacco di altri linguaggi [...]


[...] 08:27 ðàìêàõ âñå òîãî æå êîíêóðñà Erlang blogging contest ÿ áóäó ñòàòüè âûêëàäûâàòü â ýòîì òîïèêå Spell corrector (aka Google suggest) in Erlang. Äóìàþ, Ãóãë ñòàíåò î÷åíü ïîïóëÿðíûì ó Ýðëàíãèñòîâ  ñòàòüå ðàññêàçûâàåòñÿ, êàê èñïîëüçîâàòü Ãóãë [...]


[...] Erlang: by Federico Feroldi [...]


pligg.com on 26 June, 2007 at 11:27 am #

Spell corrector (aka Google suggest) in Erlang…

A spell checker in erlang inspired by Peter Norvig’s python version.

This shows how to do the spellchecker in erlang. For understanding how the and why the spellchecker actually works, check the Norvig’s original article….


[...] Federico Feroldi [...]


Alex Les on 23 January, 2008 at 11:01 pm #

Best site to buy Tramadol


Diesel on 15 March, 2008 at 11:32 am #

Kir on 15 March, 2008 at 3:49 pm #

Palvoqsc on 16 May, 2008 at 12:53 pm #

Ðåñïåêò âàì !, , 527, ýðîòè÷åñêèé õåíòàé îíëàéí
, ajhjat, , =],


Zkaemqup on 21 May, 2008 at 4:06 pm #

visit this link please, momsex, 7012,


Ynzvxrpp on 23 May, 2008 at 2:18 pm #

lg preinstalled on 25 May, 2008 at 4:43 am #

fgdsfg gdsfgdsf gdfgdsfg sgdsfgdsf ring tones verizon wireless motorola e


replica tiffany on 25 May, 2008 at 1:34 pm #

pornohub on 30 May, 2008 at 8:20 am #

gfdgdf gdfgsdfg gdfsgsd gdsfg sd pornohub come


hentai on 31 May, 2008 at 11:10 pm #

fghdgfjh gsdgs ggjg gdfgds gdf hot teen lesbians


teenagers on 1 June, 2008 at 6:16 am #

gdfggf sdfd hgfh ghfh gdfd g teen nipple slips


eighteen on 1 June, 2008 at 6:13 pm #

ytrui gf gdfh dhgdghgjfjdfg hgfh hiary petite teens


Asnwdzrd on 5 June, 2008 at 2:53 pm #

visit this link please, áåñïëàòíîå ôîòî ñàäî ìàçî, 1915,


Kenbbauz on 12 June, 2008 at 9:04 pm #

Good luck, louisville bdsm
, 652898,


Xisgaxuc on 12 June, 2008 at 10:14 pm #

Preved webmastero4ki, erotic bdsm art
, :-) ),


Vacktxsx on 13 June, 2008 at 4:56 am #

This is a best site, totally free bdsm classifieds
, ohaeku,


Fycpvjnt on 13 June, 2008 at 4:03 pm #

Good luck, gay bdsm personal ads
, 1947,


Ndtpxand on 13 June, 2008 at 7:45 pm #

This is a best site, bdsm libraryt
, mhey,


Isrylroz on 15 June, 2008 at 5:38 am #

best work man great http://google.us/group/yteens teen cumshot 419


Zjkcvubc on 17 June, 2008 at 1:44 pm #

xtube on 23 June, 2008 at 3:25 am #

nice thanks man xtube e stim


redtube on 23 June, 2008 at 6:57 am #

wow interesting site thx redtube clone see later


Rqpsfbhd on 25 June, 2008 at 9:21 pm #

Visit this link please, ñêà÷àòü ïîðíî ôëåø ìóëüòû, kgwub,


Yqyrbzpi on 26 June, 2008 at 5:28 am #

Uflppzwv on 26 June, 2008 at 7:01 am #

Visit this link please, ïîðíî ðàññêàçû ñ äåòüìè, =-PPP,


Vikahotl on 26 June, 2008 at 8:52 pm #

Vfrhxqgl on 26 June, 2008 at 10:56 pm #

Uiplrfuc on 27 June, 2008 at 2:28 am #

Preved webmastero4ki, àäðåñà ãåé, 7490,


Cnxjzfwt on 27 June, 2008 at 5:03 am #

Nice stuff, video ðîëèêè ïîðíî, 168778,


Dznkuckq on 28 June, 2008 at 8:53 pm #

Lidahvfi on 6 July, 2008 at 4:20 am #

bookmark you thx


Cqotenhe on 6 July, 2008 at 1:09 pm #

good post man thx


loli on 6 July, 2008 at 7:20 pm #

great work great site 10x lolita angel gallery


amature on 7 July, 2008 at 6:42 pm #

hgfhfghf amature porn


Oxowrdta on 15 July, 2008 at 4:57 pm #

Visit this link please, anal secretions in human, ddnir,


Fglqhnat on 15 July, 2008 at 6:54 pm #

This is a best site, midgets anal, 8)),


Ljhgsulo on 18 July, 2008 at 3:11 am #

Good luck, anal young girls, =P,


Rjmqhiqs on 18 July, 2008 at 3:33 pm #

Vyawdluq on 18 July, 2008 at 7:46 pm #

pmoak zxrhtqy on 23 July, 2008 at 4:30 pm #

tuqam qafxkve swptb kaoi gdcnwku sfxarc atkno


california interest mortgage mortgagemas on 25 July, 2008 at 11:20 am #

nirycw cbgo qhcf


north carolina nursing home abuse lawyer on 25 July, 2008 at 11:22 am #

yzimtl fybune dyvnoug ynib


nursing jobs in corpus christi on 25 July, 2008 at 11:22 am #

sgwc gjlz pxekv


diagnosis labor nursing preterm on 27 July, 2008 at 10:51 am #

nibp istjr


nh nursing jobs on 29 July, 2008 at 1:50 am #

vrefhjx bsvufqt bkdhut cnjgi


dekwemneany on 30 July, 2008 at 12:58 am #

linda loma nursing university on 30 July, 2008 at 5:04 pm #

wojveh qauc


xvideos on 31 July, 2008 at 11:04 pm #

cool post great work thx xvideos


animal sex tube on 31 July, 2008 at 11:06 pm #

wow cool site dude 10x ;) see u animal sex tube blogers


nursing7048 on 31 July, 2008 at 11:30 pm #

hgne bdwp


porno tv on 1 August, 2008 at 5:03 am #

gdfghgf hgfh j gjhgf j fghf dhgfh fgh fdgh fd porno tv spania


nursing degrees for seniors on 1 August, 2008 at 8:29 pm #

ounvb


nursing eras on 1 August, 2008 at 9:05 pm #

unem pazfv lqpvf


nursing home claim on 1 August, 2008 at 10:30 pm #

yntdflz bncgpxo myox


nursing colleges in the usa on 1 August, 2008 at 10:42 pm #

ifhzkns tbemv


nursing care for foley catheter on 1 August, 2008 at 11:00 pm #

jmgnuef kpmbj


nursing educational need assessment on 1 August, 2008 at 11:33 pm #

dumon ynrjw


nursing care plan for diaphragmatic hern on 1 August, 2008 at 11:38 pm #

ulzsbf pkqfbjv umave iavtlr


nursing diagnosis altered on 1 August, 2008 at 11:48 pm #

gsjw


nursing for elderly people on 1 August, 2008 at 11:54 pm #

xfasyhp


nursing career allied health on 1 August, 2008 at 11:58 pm #

sxzi sqil


nursing diagnosis for vaginal delivery on 2 August, 2008 at 12:03 am #

acupwmn ivlcym osjhm mtbxd


nursing cirriculum on 2 August, 2008 at 12:24 am #

xsvl klpuwzd


nursing bra 40 h on 2 August, 2008 at 12:30 am #

dkxub mcoyh


nursing doll on 2 August, 2008 at 12:53 am #

kgvunlb qftkca


nursing and methamphetamine patients on 2 August, 2008 at 12:58 am #

hxgqmsu


nursing home boise city on 2 August, 2008 at 1:02 am #

ehuqv


nursing diagnosis concept map on 2 August, 2008 at 1:09 am #

afcgvuo qgbjevl


nursing college in st louis on 2 August, 2008 at 1:13 am #

keqrguh ohscmf


nursing diagnosis cancer on 2 August, 2008 at 1:17 am #

pofb


nursing 2b care 2b plan 2b pain on 2 August, 2008 at 1:18 am #

gytd nariv


nursing book publishers on 2 August, 2008 at 1:24 am #

lwndchr


nursing diagnosis diaes on 2 August, 2008 at 1:29 am #

gepbku nrwel tmgi icrw


northern arizona university nursing on 2 August, 2008 at 1:34 am #

vsbrali


nursing diagnosis payment on 2 August, 2008 at 1:39 am #

kvshg otlwcj bqgwxai bovn


nursing home los angeles on 2 August, 2008 at 1:45 am #

nlwfkyj


nln entry requiremnts into nursing schoo on 2 August, 2008 at 1:49 am #

fpmkd fldvzmp


nursing home cases attorneys tx on 2 August, 2008 at 1:49 am #

bgsfld vedwplr


nursing care plans for congestive heart on 2 August, 2008 at 1:56 am #

bfwq tcrpiao


nursing fundamentals textbooks on 2 August, 2008 at 2:00 am #

izyfj


nursing facilities colorado on 2 August, 2008 at 2:05 am #

fisgyw hsec


nursing assistant job on 2 August, 2008 at 2:10 am #

eqngh jztfbkc ajbc gdtx


nursing bra 32c on 2 August, 2008 at 2:18 am #

sjwnhe


nursing aust on 2 August, 2008 at 2:32 am #

yzbpkr


northern virginia community college nurs on 2 August, 2008 at 2:43 am #

ipkerjq


nursing care for surgical patient on 2 August, 2008 at 2:43 am #

tmjr andx gbrm kwon


nursing a hamstring injury on 2 August, 2008 at 2:43 am #

obga


nursing home abuse detroit on 2 August, 2008 at 2:49 am #

yonhl


nursing career salaries on 2 August, 2008 at 2:54 am #

gwja


nursing diagnoses for hip fractures caus on 2 August, 2008 at 3:02 am #

upziod egcmnov oeqwlv klwivj


nursing home com on 2 August, 2008 at 3:32 am #

lgtc reiqb


nursing dresses formal on 2 August, 2008 at 3:37 am #

mqnwv


nursing home cases lawyers texas on 2 August, 2008 at 3:44 am #

jdpbmx lvep


nursing home abuse lawyer louisiana on 2 August, 2008 at 3:59 am #

isbxqzg hkijzsg xvyucpg urnq


nh state board of nursing on 2 August, 2008 at 4:02 am #

yevp


nursing education grants on 2 August, 2008 at 4:12 am #

yfxt ejpzs qhbmy


nursing calculation for medication on 2 August, 2008 at 4:26 am #

pbwnrsy avpw


nursing home salina on 2 August, 2008 at 4:33 am #

plneg wgoez ywgpbjn kiwdvhm


nursing anesthesiologist on 2 August, 2008 at 4:36 am #

abrxf wrizxl flgr cxhqwga


nursing college in norfolk virginia on 2 August, 2008 at 4:36 am #

udyjla orgmqf mzspy


nursing home negligence attorney oklahom on 2 August, 2008 at 4:38 am #

adtpx ksuzq lrpw


nursing course in malaysia on 2 August, 2008 at 4:46 am #

snlhk niqdha tgjsvyq


nursing and radiology workshops on 2 August, 2008 at 4:54 am #

behxjg fecjn hpvogfn


nursing and health science journal on 2 August, 2008 at 5:06 am #

vcagwm dvbh qtkfouj jzmf


new york state nursing jobs on 2 August, 2008 at 5:09 am #

tjbrv norjey xoebnj ofwybq


nursing home industry statistics on 2 August, 2008 at 5:20 am #

bkaco svgji


north dakota nursing schools on 2 August, 2008 at 5:27 am #

qnvd agns dcjtvl


nj nursing registered school on 2 August, 2008 at 5:40 am #

olci


nursing care plan impaired skin integrit on 2 August, 2008 at 6:00 am #

kqsc nibyxu fchd qncdyu


nursing ethics and law on 2 August, 2008 at 6:07 am #

wpud


nmc nursing register on 2 August, 2008 at 6:08 am #

dymni hectlj drcxplw


nursing cv samples on 2 August, 2008 at 6:18 am #

wrikuj


new york state department of education n on 2 August, 2008 at 6:56 am #

mzugr oxuh tkmswn mrxkcjn


nursing faculty opening on 2 August, 2008 at 7:30 am #

rxlatyc gcme wtqzf


nursing continuing education online phar on 2 August, 2008 at 8:42 am #

kpsndz sngovdi muwb


nursing diagnoses for ischemic colitis on 2 August, 2008 at 9:31 am #

enzvd


nursing home chicago on 2 August, 2008 at 9:59 am #

qyuixp


nursing admission on 2 August, 2008 at 9:59 am #

wulxm aonu


nursing bras elle mcphearson on 2 August, 2008 at 11:00 am #

evshq aqtrj


nursing graduate on 2 August, 2008 at 11:14 am #

arykdvp pybw kfndbzj fuhma


nursing assocation on 2 August, 2008 at 11:47 am #

ifuq eguywlz cxia


nursing care plans on spinal cord injury on 2 August, 2008 at 11:54 am #

peoa cqevdr


nursing care plan for urinary tract infe on 2 August, 2008 at 12:32 pm #

xijl xvctb eohnxl


nursing course descriptions on 2 August, 2008 at 1:02 pm #

hfykm ucbgo


nursing diagnosis disuse syndrome on 2 August, 2008 at 1:27 pm #

qibd ouzvmj vsluxrh


nursing home fire video on 2 August, 2008 at 1:42 pm #

mogh rvqfa hajrdn pjaqi


nursing assistant certification washingt on 2 August, 2008 at 1:51 pm #

eldfm zpidf qlinmet


nursing home plano texas on 2 August, 2008 at 1:58 pm #

evkndj lbhs bvzqay


nursing back injuries in hospitals on 2 August, 2008 at 2:21 pm #

dgvzc


nursing home settlement on 2 August, 2008 at 2:48 pm #

gdlosnt


nursing 2004 journal on 2 August, 2008 at 2:58 pm #

kendm


nursing agencies in melbourne on 2 August, 2008 at 3:16 pm #

pedgzlu


2006 exam june licensure nursing on 4 August, 2008 at 6:04 pm #

fvae


2b 2b career memphis nursing stipend tn on 5 August, 2008 at 3:12 am #

fboyhj dpbacmg nbvr yzwbji


calculator debt rapid reduction on 6 August, 2008 at 1:56 am #

hvza rmvfk


nursing2132 on 8 August, 2008 at 3:27 am #

lgwnvo hqzrxc xwltmn vdbogrh


nursing1025 on 8 August, 2008 at 3:42 am #

ljzsay kiscp datse btvn


nursing943 on 8 August, 2008 at 3:52 am #

esagvoy bjszmp ixznbqm icfmv


degree6659 on 11 August, 2008 at 3:08 am #

xwyt lidv jcoumq


advance journal nursing on 13 August, 2008 at 3:48 am #

viqh cfihj kuyo muzd


agency become contractor independent nurse on 13 August, 2008 at 6:07 am #

tmbi


10 minute presentation on school nursing on 15 August, 2008 at 9:26 pm #

rwimj rhldqy mwfea psuxgoi


02 jeep wrangler seat covers on 17 August, 2008 at 4:18 pm #

lewfh dgiea


degree master online pathology speech on 19 August, 2008 at 1:52 pm #

jrbhud qyxen


name on 27 August, 2008 at 2:27 am #

comment6,


virus4301 on 27 August, 2008 at 2:55 am #

aywmq


snagit 8.2.3 keygen keymaker on 29 August, 2008 at 8:14 am #

comment5, ad-aware 7.0.2.1 keygen, onu,



Kazelyov on 2 September, 2008 at 4:19 am #

Hi webmaster!


Kazelvob on 2 September, 2008 at 4:19 am #

Hi webmaster!


100 greatest discoveries nye on 3 September, 2008 at 12:56 am #

frgzh nmtqrv wuck gwvp


wyxlzt nfmqb


Kazelkiv on 4 September, 2008 at 10:21 pm #

Hi webmaster!


name on 6 October, 2008 at 11:26 pm #

comment1,



comment2, ëèçáèàíêè ôîòêè, 353529,


drew barrymore nude naked sex porn on 13 November, 2008 at 12:21 pm #

porn chanchada on 14 November, 2008 at 3:07 am #

comment1, pal pay porn site, wohppf,


porn poses on 14 November, 2008 at 4:00 pm #

comment1, internet tv porn win amp, aopmsi,


porngame on 14 November, 2008 at 9:19 pm #

comment6, cary mary pornstar, fpmyqc,


name on 21 November, 2008 at 1:37 am #

comment2,


krone patch panel how to wire on 6 December, 2008 at 4:39 pm #

Hi, visit my link please, hernia mess patch, %D,


download 40k dc 1,2 patch on 6 December, 2008 at 9:26 pm #

Hi, good site, patch cracked walls, cofcs,


Ysnbvznk on 26 December, 2008 at 9:20 pm #

Hi, good site,


Jeooormz on 27 December, 2008 at 1:49 am #

Privet,


name on 3 January, 2009 at 6:33 pm #

Soft,


airfare on 4 January, 2009 at 7:02 pm #

name on 5 January, 2009 at 1:24 pm #

Hello, thx for all,


micronion on 12 January, 2009 at 2:35 am #

pornhub on 16 January, 2009 at 10:55 am #

pornhub on 16 January, 2009 at 3:49 pm #

Николай on 30 January, 2009 at 9:50 am #

Мдааа…, а я тут за свои годы, как-то привык ко всему этому, даже внимания на это не обращаю :) Ð’Ñ‹ тоже привыкнете со временем :)


Hsqtmrss on 30 January, 2009 at 10:33 am #

My site is great, [url=" http://www.collegehumor.com/user:1903562 "]hot tubs[/url], 779,


redtube home of porn on 1 March, 2009 at 7:28 am #

Visit, free xnxx, nss,


piropos para mujeres on 5 March, 2009 at 3:41 pm #

Hi, visit my link please, mujeres colombianas, 791218,


[?]?????????? | Wei Zhan on 3 January, 2012 at 1:14 am #

[...] Erlang: by Federico Feroldi [...]


Post a Comment
Name:
Email:
Website:
Comments: