Given some text you suspect has been encrypted with a Vigenère cipher, extract the key and plaintext. There are several methods for doing this. See the Wikipedia entry for more information. Use the following encrypted text:

MOMUD EKAPV TQEFM OEVHP AJMII CDCTI FGYAG JSPXY ALUYM NSMYH
VUXJE LEPXJ FXGCM JHKDZ RYICU HYPUS PGIGM OIYHF WHTCQ KMLRD
ITLXZ LJFVQ GHOLW CUHLO MDSOE KTALU VYLNZ RFGBX PHVGA LWQIS
FGRPH JOOFW GUBYI LAPLA LCAFA AMKLG CETDW VOELJ IKGJB XPHVG
ALWQC SNWBU BYHCU HKOCE XJEYK BQKVY KIIEH GRLGH XEOLW AWFOJ
ILOVV RHPKD WIHKN ATUHN VRYAQ DIVHX FHRZV QWMWV LGSHN NLVZS
JLAKI FHXUF XJLXM TBLQV RXXHR FZXGV LRAJI EXPRV OSMNP KEPDT
LPRWM JAZPK LQUZA ALGZX GVLKL GJTUI ITDSU REZXJ ERXZS HMPST
MTEOE PAPJH SMFNB YVQUZ AALGA YDNMP AQOWT UHDBV TSMUE UIMVH
QGVRW AEFSP EMPVE PKXZY WLKJA GWALT VYYOB YIXOK IHPDS EVLEV
RVSGB JOGYW FHKBL GLXYA MVKIS KIEHY IMAPX UOISK PVAGN MZHPW
TTZPV XFCCD TUHJH WLAPF YULTB UXJLN SIJVV YOVDJ SOLXG TGRVO
SFRII CTMKO JFCQF KTINQ BWVHG TENLH HOGCS PSFPV GJOKM SIFPR
ZPAAS ATPTZ FTPPD PORRF TAXZP KALQA WMIUD BWNCT LEFKO ZQDLX
BUXJL ASIMR PNMBF ZCYLV WAPVF QRHZV ZGZEF KBYIO OFXYE VOWGB
BXVCB XBAWG LQKCM ICRRX MACUO IKHQU AJEGL OIJHH XPVZW JEWBA
FWAML ZZRXJ EKAHV FASMU LVVUT TGK

Letter frequencies for English can be found here.

Specifics for this task:

 Take only the ciphertext as input. You can assume it's all capitalized and has no punctuation, but it might have whitespace.
 Assume the plaintext is written in English.
 Find and output the key.
 Use that key to decrypt and output the original plaintext. Maintaining the whitespace from the ciphertext is optional.
 The algorithm doesn't have to be perfect (which may not be possible) but it should work when given enough ciphertext. The example above is fairly long, and should be plenty for any algorithm.
// (1) Copy text into tmp buffer and remove non-alpha chars.
 
Chdir(PATH_ONLY)
BOF
Reg_Copy(10, ALL)                       // copy text to new buffer
Buf_Switch(Buf_Free)
Reg_Ins(10)
BOF
Replace ("|!|A", "", BEGIN+ALL+NOERR)   // remove non-alpha chars
Reg_Copy_Block(10,0,EOB_pos)            // @10 = text to be analysed
 
#20 = Buf_Num                           // buffer for text being analyzed
#21 = Buf_Free                          // buffer for English frequency list (A-Z)
Buf_Switch(#21)
Ins_Text("8167 1492 2782 4253 12702 2228 2015 6094 6966 153 772 4025 2406 6749 7507 1929 95 5987 6327 9056 2758 978 2360 150 1974 74")
File_Open("unixdict.txt")               // or use "|(MACRO_DIR)\scribe\english.vdf"
#23 = Buf_Num                           // buffer for dictionary
#24 = Buf_Free                          // buffer for key canditates
 
Buf_Switch(#24)
for (#1=0; #1<5; #1++) {                // Fill table for 5 keys of 50 chars
    Ins_Char('.', COUNT, 50)
    Ins_Newline
}
#22 = Buf_Free                          // buffer for results
 
#25 = Reg_Size(10)                      // number of letters in the text
#26 = 26                                // number of characters in the alphabet
#61 = min(#25/10, 50)                   // max key length to try
 
// (2) Check Index of coincidence (or Kp) for each key length
 
Buf_Switch(#22)                         // buffer for results
Ins_Text("KeyLen Kp   dist ") Ins_Newline
Ins_Text("-----------------") Ins_Newline
#13 = Cur_Pos
#7 = 0                                  // no Caesar encryption
for (#5=1; #5<=#61; #5++) {
    Buf_Switch(#20)                     // text being analyzed
    BOF
    #54 = 0;                            // sum of Kp's
    for (#6=0; #6<#5; #6++) {           // for each slide
        Goto_Pos(#6)
        Call("CHARACTER_FREQUENCIES")
        Call("INDEX_OF_COINCIDENCE")    // #51 = Kp * 10000
        #54 += #51
    }
    #54 /= #5                           // average of Kp's
    Buf_Switch(#22)
    Num_Ins(#5, COUNT, 3)               // write key length
    IT(": ")
    Num_Ins(#54, NOCR)                  // average Kp
    Num_Ins(670-#54)                    // distance to English Kp
}
Buf_Switch(#22)
Sort_Merge("5,12", #13, Cur_Pos, REVERSE)  // sort the results by Kp value
Ins_Newline
 
// (3) Check the best 4 key lengths to find which one gives the best decrypt result
 
#38 = 0                                 // max number of correct characters found
#19 = 1                                 // best key length
for (#14 = 0; #14<4; #14++) {           // try 4 best key lengths
    Buf_Switch(#22)                     // results buffer
    Goto_Pos(#13) Line(#14)
    #5 = Num_Eval(SUPPRESS)             // #5 = key length
    Call("FIND_KEYS")                   // find Caesar key for each key character
    #4 = -1                             // try best match key chars only
    Call("BUILD_KEY")
    EOF
    Ins_Text("Key length ")
    Num_Ins(#5, LEFT)
    Reg_Ins(10)                         // encrypted text
    BOL
    Call("DECRYPT_LINE")
    BOL
    Call("FIND_ENGLISH_WORDS")          // #37 = number of English chars
    EOL Ins_Newline
    Ins_Text("Correct chars: ")
    Num_Ins(#37)
    if (#37 > #38) {
        #38 = #37
        #19 = #5
    }
    Update()
}
 
Ins_Text("Using key length: ") Num_Ins(#19) Ins_Newline
#5 = #19
Call("FIND_KEYS")                       // find Caesar key for each key character
 
// (4) Decrypt with different key combinations and try to find English words.
//     Try key combinations where max one char is taken from 2nd best Caesar key.
 
#38 = 0                                 // max number of chars in English words found
#39 = -1                                // best key number found
for (#4 = -1; #4 < #19; #4++)
{
    Call("BUILD_KEY")
    Buf_Switch(#22)                     // results
    Reg_Ins(10)                         // encrypted text
    BOL
    Call("DECRYPT_LINE")
    BOL
    Update()
    Call("FIND_ENGLISH_WORDS")          // #37 := number of correct letters in text
    if (#37 > #38) {
        #38 = #37                       // new highest number of correct chars
        #39 = #4                        // new best key
    }
 
    EOL IT(" -- ")                      // display results
    Num_Ins(#4, COUNT, 3)               // key number
    Ins_Text(": ")
    for (#6=0; #6<#19; #6++) {          // display key
        #9 = 130 + #6
        Ins_Char(#@9)
    }
    Ins_Text("  correct chars =")
    Num_Ins(#37)
}
Ins_Text("Best key = ")
Num_Ins(#39, LEFT)
#4 = #39
Ins_Newline
 
// Display results
//
Buf_Switch(#24)                         // table for key canditates
BOF
Reg_Copy_Block(14, Cur_Pos, Cur_Pos+#19)  // best Caesar key chars
Line(1)
Reg_Copy_Block(15, Cur_Pos, Cur_Pos+#19)  // 2nd best Caesar key chars
Call("BUILD_KEY")
Buf_Switch(#22)
Ins_Text("Key 1: ") Reg_Ins(14) Ins_Newline
Ins_Text("Key 2: ") Reg_Ins(15) Ins_Newline
Ins_Text("Key:   ")
for (#6=0; #6 < #19; #6++) {
    #9 = #6+130
    Ins_Char(#@9)
}
Ins_Newline
Ins_Newline
 
// decrypt the text with selected key
Ins_Text("Decrypted text:") Ins_Newline
Reg_Ins(10)
BOL
Call("DECRYPT_LINE")
BOL Reg_Copy(13,1)
EOL Ins_Newline
 
// Find English words from the text
Reg_Ins(13)
Call("FIND_ENGLISH_WORDS")
EOL
Ins_Newline
Num_Ins(#37, NOCR) IT(" of ")
Num_Ins(#25, NOCR) IT(" characters are English words. ")
Ins_Newline
 
Buf_Switch(#20) Buf_Quit(OK)
Buf_Switch(#21) Buf_Quit(OK)
Buf_Switch(#23) Buf_Quit(OK)
Buf_Switch(#24) Buf_Quit(OK)
 
Statline_Message("Done!")
Return
 
/////////////////////////////////////////////////////////////////////////////
//
// Caesar decrypt current line and count character frequencies.
//   in: #5 = step size, #7 = encryption key, #26 = num of chars in alphabet
//  out: #65...#90 = frequencies, #60 = number of chars
 
:CHARACTER_FREQUENCIES:
    Save_Pos
    for (#8 = 'A'; #8<='Z'; #8++) {
        #@8 = 0                         // reset frequency counters
    }
    #60 = 0                             // total number of chars
    while (!At_EOL) {
        if (Cur_Char >= 'A' && Cur_Char <= 'Z') {
            #8 = (Cur_Char-'A'+#26-#7) % #26 + 'A'  // decrypted char
            #@8++
            #60++
        }
        Char(#5)
    }
    Restore_Pos
Return
 
// Calculate Index of Coincidence (Kp).
//   in: character frequencies in #65...#90, #60 = num of chars
//  out: #51 = IC * 10000
//
:INDEX_OF_COINCIDENCE:
    Num_Push(10,15)
    #10 = 0
    for (#11 = 'A'; #11<='Z'; #11++) {
        #10 += (#@11 * (#@11-1))        // Calculate sigma{ni * (ni-1)}
    }
    #12 = #60 * (#60-1)                 // #12 = N * (N-1)
    #51 = #10 * 10000 / #12             // #51 = Kp * 10000
    Num_Pop(10,15)
Return
 
// Find best and 2nd best Caesar key for each character position of Vigenère key.
//   in: #5=step size (key length)
//  out: keys in buffer #24
//
:FIND_KEYS:
    for (#6 = 0; #6 < #5; #6++) {               // for each char position in the key
        #30 = -1                                // best key char found so far
        #31 = -1                                // 2nd best key char
        #32 = MAXNUM                            // smallest error found so far
        #33 = MAXNUM                            // 2nd smallest error found so far
        for (#7 = 0; #7 < #26; #7++) {          // for each possible key value
            #35 = 0                             // total frequency error compared to English
            Buf_Switch(#20)                     // text being analyzed
            Goto_Pos(#6)
            Call("CHARACTER_FREQUENCIES")
            Buf_Switch(#21)                     // English frequency table
            BOF
            for (#8 = 'A'; #8<='Z'; #8++) {     // calculate total frequency error
                #34 = Num_Eval(SUPPRESS+ADVANCE)
                #35 += abs((#@8*100000+50000)/#60-#34)
            }
 
            if (#35 < #32) {                    // found better match?
                #33 = #32
                #32 = #35
                #31 = #30
                #30 = #7
            } else {
                if (#35 < #33) {                // 2nd best match?
                    #33 = #35
                    #31 = #7
                }
            }
        }
        Buf_Switch(#24)                         // table for key canditates
        BOF
        Goto_Col(#6+1)
        Ins_Char(#30+'A', OVERWRITE)            // save the best match
        Line(1)
        Goto_Col(#6+1)
        Ins_Char(#31+'A', OVERWRITE)            // save 2nd best match
    }
    Buf_Switch(#22)                             // results buffer
Return
 
// Combine actual key from 1st and 2nd best Caesar key characters
// Use 1st key chars and (possibly) one character from 2nd key.
//  #4 = index of the char to be picked from 2nd key, -1 = none.
//  #5 = key length
//
:BUILD_KEY:
    Buf_Switch(#24)                     // table for key canditates
    BOF
    for (#6=0; #6<#5; #6++) {           // copy 1st key
        #8 = 130 + #6
        #@8 = Cur_Char
        Char(1)
    }
    if (#4 >= 0) {
        #8 = 130 + #4                   // pick one char from 2st key
        Line(1)
        Goto_Col(#4+1)
        #@8 = Cur_Char
    }
    Buf_Switch(#22)                     // results buffer
Return
 
// Decrypt text on current line
//   in: #5 = key length, #130...#189 = key
//
:DECRYPT_LINE:
    Num_Push(6,9)
    #6 = 0
    While (!At_EOL) {
       #9 = #6+130
       #7 = #@9
       #8 = (Cur_Char - #7 + #26) % #26 + 'A'   // decrypted char
       Ins_Char(#8, OVERWRITE)
       #6++
       if (#6 >= #5) {
           #6 = 0
       }
    }
    Num_Pop(6,9)
Return
 
// Find English words from text on current line
//  out: #37 = number of chars matched
//
:FIND_ENGLISH_WORDS:
    Buf_Switch(#23)                     // dictionary
    BOF
    While (!At_EOF) {
        Reg_Copy_Block(12, Cur_Pos, EOL_Pos)
        if (Reg_Size(12) > 2) {
            Buf_Switch(#22)             // buffer for results
            BOL
            while (Search_Block(@12, Cur_Pos, EOL_Pos, NOERR)) {
                Reg_Ins(12, OVERWRITE)
            }
            Buf_Switch(#23)
        }
        Line(1, ERRBREAK)
    }
 
    Buf_Switch(#22)
    BOL
    #37 = Search_Block("|V", Cur_Pos, EOL_Pos, ALL+NOERR)
Return 