:function! s:Random(n)
: if has('win32')
:   let r = libcallnr("msvcrt", "rand", 0)
: else
:   let r = libcallnr("libc", "rand", 0)
: endif
: return r % a:n
:endfunction

:function! s:MakeRandom()
: let res = ''
: for i in range(strlen(s:goal))
:   let res = res . nr2char(char2nr('A')+s:Random(26))
: endfor
: return res
:endfunction

:function! s:CheckScore(line, goal)
: let score = 0
: for i in range(strlen(a:goal))
:   let a = char2nr(strpart(s:goal,i,1))
:   let b = char2nr(strpart(a:line,i,1))
:   let d = a < b ? b - a : a - b
:   let score = score + d
: endfor
: return score
:endfunction

:function! s:SortLines(num)
: for i in range(a:num)
:   let line = getline(i+1)
:   let score = s:CheckScore(line, s:goal)
:   let line = printf("%05d:%s", score, line)
:   call setline(i+1,line)
: endfor
": %!sort
: let lines = sort(getline(1,a:num))
: for i in range(a:num)
:   call setline(i+1,strpart(lines[i],6,strlen(s:goal)))
: endfor
:endfunction

:function! s:ChangeLine(line_num, idx_num, var_num)
: for i in range(a:line_num)
:   let line = getline(i+1)
:   for j in range(a:var_num)
:     let vline = line
:     for k in range(a:idx_num)
:       let split_idx = s:Random(strlen(s:goal))
:       let head = strpart(vline,0,split_idx)
:       let tail = strpart(vline,split_idx+1,strlen(s:goal))
:       let vline = head .nr2char(char2nr('A')+s:Random(26)) . tail
:     endfor
:     call setline(a:line_num*(j+1)+i,vline)
:   endfor
: endfor
:endfunction

:let s:initial_line_num = 300
:let s:change_idx_num = 1
:let s:variaty_num = 5
:let s:goal = "METHINKSITISAWEASEL"

:let s:start_time = localtime()
:new
:for s:i in range(s:initial_line_num)
: call setline(s:i+1, s:MakeRandom())
:endfor
:call s:SortLines(s:initial_line_num)

:let s:break_flag = 0
:while s:break_flag == 0
: call s:ChangeLine(s:initial_line_num,s:change_idx_num,s:variaty_num)
: call s:SortLines(s:initial_line_num * s:variaty_num)
: let s:line = getline(1)
: if s:line ==# s:goal
:   let s:break_flag = 1
: endif
: echo getline(1)
:endwhile
:1
:let s:end_time = localtime()
:call append(0, (s:end_time - s:start_time) . " seconds elapsed")
